scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | Submodules | README | LICENSE

sethi.c (3599B)


      1 #include <scc/scc.h>
      2 
      3 #include "cc2.h"
      4 
      5 static Node *
      6 assignnode(Type *tp, Node *lhs, Node *rhs)
      7 {
      8 	Node *np;
      9 
     10 	np = node(OASSIG);
     11 	np->type = *tp;
     12 	np->left = lhs;
     13 	np->right = rhs;
     14 	return sethi(np);
     15 }
     16 
     17 static Node *
     18 branchnode(Node *cond, Symbol *sym)
     19 {
     20 	Node *np;
     21 	int op = cond ? OBRANCH : OJMP;
     22 
     23 	np = node(op);
     24 	np->op = op;
     25 	np->left = sethi(cond);
     26 	np->u.sym = sym;
     27 	sym->refcnt++;
     28 
     29 	return np;
     30 }
     31 
     32 static Node *
     33 bool(Node *cond, Symbol *true, Symbol *false)
     34 {
     35 	Symbol *label;
     36 	Node *p, *l = cond->left, *r = cond->right;
     37 
     38 	switch (cond->op) {
     39 	case ONEG:
     40 		l = bool(l, false, true);
     41 		break;
     42 	case OAND:
     43 		label = newlabel();
     44 		l = bool(l, label, false);
     45 		prestmt(labelstmt(NULL, label));
     46 		r = bool(r, true, false);
     47 		break;
     48 	case OOR:
     49 		label = newlabel();
     50 		l = bool(l, true, label);
     51 		prestmt(labelstmt(NULL, label));
     52 		r = bool(r, true, false);
     53 		break;
     54 	default:
     55 		prestmt(branchnode(cond, true));
     56 		prestmt(branchnode(NULL, false));
     57 		return NULL;
     58 	}
     59 
     60 	cond->left = l;
     61 	cond->right = r;
     62 	return cond;
     63 }
     64 
     65 Node *
     66 logicexpr(Node *np)
     67 {
     68 	Node *tmpvar, *p, *zero, *one;
     69 	Type *tp = &np->type;
     70 	Symbol *true, *false, *phi, *tmpsym;
     71 
     72 	true = newlabel();
     73 	false = newlabel();
     74 	phi = newlabel();
     75 
     76 	bool(np, true, false);
     77 
     78 	tmpvar = tmpnode(tp, NULL);
     79 	tmpsym = tmpvar->u.sym;
     80 	zero = constnode(NULL, 0, tp);
     81 	one = constnode(NULL, 1, tp);
     82 
     83 	p = assignnode(tp, tmpnode(tp, tmpsym), one);
     84 	prestmt(labelstmt(p, true));
     85 
     86 	prestmt(branchnode(NULL, phi));
     87 
     88 	p = assignnode(tp, tmpnode(tp, tmpsym), zero);
     89 	prestmt(labelstmt(p, false));
     90 
     91 	prestmt(labelstmt(NULL, phi));
     92 
     93 	return sethi(tmpvar);
     94 }
     95 
     96 static void
     97 comma(Node *np)
     98 {
     99 	if (np->op != OCOMMA) {
    100 		prestmt(sethi(np));
    101 	} else {
    102 		comma(np->left);
    103 		prestmt(sethi(np->right));
    104 		delnode(np);
    105 	}
    106 }
    107 
    108 static Node *
    109 ternary(Node *np)
    110 {
    111 	Type *tp;
    112 	Node *tmpvar, *colon, *p;
    113 	Symbol *tmpsym, *true, *false, *phi;
    114 
    115 	true = newlabel();
    116 	false = newlabel();
    117 	phi = newlabel();
    118 	bool(np->left, true, false);
    119 
    120 	tp = &np->type;
    121 	colon = np->right;
    122 	tmpvar = tmpnode(tp, NULL);
    123 	tmpsym = tmpvar->u.sym;
    124 
    125 	prestmt(labelstmt(NULL, true));
    126 	p = assignnode(tp, tmpnode(tp, tmpsym), sethi(colon->left));
    127 	prestmt(p);
    128 	prestmt(branchnode(NULL, phi));
    129 
    130 	prestmt(labelstmt(NULL, false));
    131 	p = assignnode(tp, tmpnode(tp, tmpsym), sethi(colon->right));
    132 	prestmt(p);
    133 
    134 	prestmt(labelstmt(NULL, phi));
    135 
    136 	return sethi(tmpvar);
    137 }
    138 
    139 static Node *
    140 replace(Node *what, Node *with)
    141 {
    142 	Node *prev, *next;
    143 
    144 	next = what->next, prev = what->prev;
    145 	*what = *with;
    146 	delnode(with);
    147 	what->next = next, what->prev = prev;
    148 
    149 	return sethi(what);
    150 }
    151 
    152 Node *
    153 sethi(Node *np)
    154 {
    155 	int op;
    156 	Node *next, *l, *r;
    157 
    158 	if (!np)
    159 		return np;
    160 
    161 	np->complex = 0;
    162 	np->address = 0;
    163 
    164 	switch (np->op) {
    165 	case OBSWITCH:
    166 		np = swtch(np);
    167 		break;
    168 	case OBRANCH:
    169 		next = np->next;
    170 		if (!next->label)
    171 			labelstmt(next, NULL);
    172 
    173 		op = np->left->op;
    174 		if (op != ONEG && op != OOR && op != OAND) {
    175 			sethi(np->left);
    176 			return np;
    177 		}
    178 
    179 		bool(np->left, np->u.sym, next->label);
    180 		np->u.sym->refcnt--;
    181 		return NULL;
    182 	case OCOMMA:
    183 		r = np->right;
    184 		comma(np->left);
    185 		return replace(np, r);
    186 	case OASK:
    187 		return replace(np, ternary(np));
    188 	case ONEG:
    189 	case OAND:
    190 	case OOR:
    191 		return replace(np, logicexpr(np));
    192 	default:
    193 		np = tsethi(np);
    194 		break;
    195 	}
    196 
    197 	l = np->left;
    198 	r = np->right;
    199 
    200 	if (np->address > 10)
    201 		return np;
    202 	if (l)
    203 		np->complex = l->complex;
    204 	if (r) {
    205 		int d = np->complex - r->complex;
    206 
    207 		if (d == 0)
    208 			++np->complex;
    209 		else if (d < 0)
    210 			np->complex = r->complex;
    211 	}
    212 	if (np->complex == 0)
    213 		++np->complex;
    214 
    215 	return np;
    216 }
    217 
    218 void
    219 genaddr(void)
    220 {
    221 	apply(sethi);
    222 	PRTREE("after sethi");
    223 }