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 }