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 }