scc

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

sethi.c (3758B)


      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 	Symbol *label;
    144 
    145 	label = what->label;
    146 	next = what->next, prev = what->prev;
    147 
    148 	*what = *with;
    149 	delnode(with);
    150 	what->next = next, what->prev = prev;
    151 	what->label = label;
    152 
    153 	return sethi(what);
    154 }
    155 
    156 Node *
    157 sethi(Node *np)
    158 {
    159 	int op;
    160 	Node *next, *l, *r;
    161 
    162 	if (!np)
    163 		return np;
    164 
    165 	np->complex = 0;
    166 	np->address = 0;
    167 
    168 	switch (np->op) {
    169 	case OBSWITCH:
    170 		np = swtch(np);
    171 		break;
    172 	case OBRANCH:
    173 		next = np->next;
    174 		if (!next->label)
    175 			labelstmt(next, NULL);
    176 
    177 		op = np->left->op;
    178 		if (op != ONEG && op != OOR && op != OAND) {
    179 			sethi(np->left);
    180 			return np;
    181 		}
    182 
    183 		bool(np->left, np->u.sym, next->label);
    184 		np->u.sym->refcnt--;
    185 		return NULL;
    186 	case OCOMMA:
    187 		r = np->right;
    188 		comma(np->left);
    189 		return replace(np, r);
    190 	case OASK:
    191 		return replace(np, ternary(np));
    192 	case ONEG:
    193 	case OAND:
    194 	case OOR:
    195 		return replace(np, logicexpr(np));
    196 	default:
    197 		np = tsethi(np);
    198 		break;
    199 	}
    200 
    201 	l = np->left;
    202 	r = np->right;
    203 
    204 	if (np->address > 10)
    205 		return np;
    206 	if (l)
    207 		np->complex = l->complex;
    208 	if (r) {
    209 		int d = np->complex - r->complex;
    210 
    211 		if (d == 0)
    212 			++np->complex;
    213 		else if (d < 0)
    214 			np->complex = r->complex;
    215 	}
    216 	if (np->complex == 0)
    217 		++np->complex;
    218 
    219 	return np;
    220 }
    221 
    222 static Node *
    223 presethi(Node *np)
    224 {
    225 	/* just in case ... */
    226 	savelabel();
    227 	return sethi(np);
    228 }
    229 
    230 void
    231 genaddr(void)
    232 {
    233 	apply(presethi);
    234 	PRTREE("after sethi");
    235 }