00001 #include "c.h"
00002
00003
00004 #define iscall(op) (generic(op) == CALL \
00005 || IR->mulops_calls \
00006 && (generic(op)==DIV||generic(op)==MOD||generic(op)==MUL) \
00007 && ( optype(op)==U || optype(op)==I))
00008 static Node forest;
00009 static struct dag {
00010 struct node node;
00011 struct dag *hlink;
00012 } *buckets[16];
00013 int nodecount;
00014 static Tree firstarg;
00015 int assignargs = 1;
00016 int prunetemps = -1;
00017 static Node *tail;
00018
00019 static int depth = 0;
00020 static Node replace(Node);
00021 static Node prune(Node);
00022 static Node asgnnode(Symbol, Node);
00023 static struct dag *dagnode(int, Node, Node, Symbol);
00024 static Symbol equated(Symbol);
00025 static void fixup(Node);
00026 static void labelnode(int);
00027 static void list(Node);
00028 static void kill(Symbol);
00029 static Node node(int, Node, Node, Symbol);
00030 static void printdag1(Node, int, int);
00031 static void printnode(Node, int, int);
00032 static void reset(void);
00033 static Node tmpnode(Node);
00034 static void typestab(Symbol, void *);
00035 static Node undag(Node);
00036 static Node visit(Node, int);
00037 static void unlist(void);
00038 void walk(Tree tp, int tlab, int flab) {
00039 listnodes(tp, tlab, flab);
00040 if (forest) {
00041 Node list = forest->link;
00042 forest->link = NULL;
00043 if (!IR->wants_dag)
00044 list = undag(list);
00045 code(Gen)->u.forest = list;
00046 forest = NULL;
00047 }
00048 reset();
00049 deallocate(STMT);
00050 }
00051
00052 static Node node(int op, Node l, Node r, Symbol sym) {
00053 int i;
00054 struct dag *p;
00055
00056 i = (opindex(op)^((unsigned long)sym>>2))&(NELEMS(buckets)-1);
00057 for (p = buckets[i]; p; p = p->hlink)
00058 if (p->node.op == op && p->node.syms[0] == sym
00059 && p->node.kids[0] == l && p->node.kids[1] == r)
00060 return &p->node;
00061 p = dagnode(op, l, r, sym);
00062 p->hlink = buckets[i];
00063 buckets[i] = p;
00064 ++nodecount;
00065 return &p->node;
00066 }
00067 static struct dag *dagnode(int op, Node l, Node r, Symbol sym) {
00068 struct dag *p;
00069
00070 NEW0(p, FUNC);
00071 p->node.op = op;
00072 if ((p->node.kids[0] = l) != NULL)
00073 ++l->count;
00074 if ((p->node.kids[1] = r) != NULL)
00075 ++r->count;
00076 p->node.syms[0] = sym;
00077 return p;
00078 }
00079 Node newnode(int op, Node l, Node r, Symbol sym) {
00080 return &dagnode(op, l, r, sym)->node;
00081 }
00082 static void kill(Symbol p) {
00083 int i;
00084 struct dag **q;
00085
00086 for (i = 0; i < NELEMS(buckets); i++)
00087 for (q = &buckets[i]; *q; )
00088 if (generic((*q)->node.op) == INDIR &&
00089 (!isaddrop((*q)->node.kids[0]->op)
00090 || (*q)->node.kids[0]->syms[0] == p)) {
00091 *q = (*q)->hlink;
00092 --nodecount;
00093 } else
00094 q = &(*q)->hlink;
00095 }
00096 static void reset(void) {
00097 if (nodecount > 0)
00098 memset(buckets, 0, sizeof buckets);
00099 nodecount = 0;
00100 }
00101 Node listnodes(Tree tp, int tlab, int flab) {
00102 Node p = NULL, l, r;
00103 int op;
00104
00105 assert(tlab || flab || tlab == 0 && flab == 0);
00106 if (tp == NULL)
00107 return NULL;
00108 if (tp->node)
00109 return tp->node;
00110 op = tp->op + sizeop(tp->type->size);
00111 switch (generic(tp->op)) {
00112 case AND: { if (depth++ == 0) reset();
00113 if (flab) {
00114 listnodes(tp->kids[0], 0, flab);
00115 listnodes(tp->kids[1], 0, flab);
00116 } else {
00117 listnodes(tp->kids[0], 0, flab = genlabel(1));
00118 listnodes(tp->kids[1], tlab, 0);
00119 labelnode(flab);
00120 }
00121 depth--; } break;
00122 case OR: { if (depth++ == 0)
00123 reset();
00124 if (tlab) {
00125 listnodes(tp->kids[0], tlab, 0);
00126 listnodes(tp->kids[1], tlab, 0);
00127 } else {
00128 tlab = genlabel(1);
00129 listnodes(tp->kids[0], tlab, 0);
00130 listnodes(tp->kids[1], 0, flab);
00131 labelnode(tlab);
00132 }
00133 depth--;
00134 } break;
00135 case NOT: { return listnodes(tp->kids[0], flab, tlab); }
00136 case COND: { Tree q = tp->kids[1];
00137 assert(tlab == 0 && flab == 0);
00138 if (tp->u.sym)
00139 addlocal(tp->u.sym);
00140 flab = genlabel(2);
00141 listnodes(tp->kids[0], 0, flab);
00142 assert(q && q->op == RIGHT);
00143 reset();
00144 listnodes(q->kids[0], 0, 0);
00145 if (forest->op == LABEL+V) {
00146 equatelab(forest->syms[0], findlabel(flab + 1));
00147 unlist();
00148 }
00149 list(jump(flab + 1));
00150 labelnode(flab);
00151 listnodes(q->kids[1], 0, 0);
00152 if (forest->op == LABEL+V) {
00153 equatelab(forest->syms[0], findlabel(flab + 1));
00154 unlist();
00155 }
00156 labelnode(flab + 1);
00157
00158 if (tp->u.sym)
00159 p = listnodes(idtree(tp->u.sym), 0, 0); } break;
00160 case CNST: { Type ty = unqual(tp->type);
00161 assert(ty->u.sym);
00162 if (tlab || flab) {
00163 assert(ty == inttype);
00164 if (tlab && tp->u.v.i != 0)
00165 list(jump(tlab));
00166 else if (flab && tp->u.v.i == 0)
00167 list(jump(flab));
00168 }
00169 else if (ty->u.sym->addressed)
00170 p = listnodes(cvtconst(tp), 0, 0);
00171 else
00172 p = node(op, NULL, NULL, constant(ty, tp->u.v)); } break;
00173 case RIGHT: { if ( tp->kids[0] && tp->kids[1]
00174 && generic(tp->kids[1]->op) == ASGN
00175 && (generic(tp->kids[0]->op) == INDIR
00176 && tp->kids[0]->kids[0] == tp->kids[1]->kids[0]
00177 || (tp->kids[0]->op == FIELD
00178 && tp->kids[0] == tp->kids[1]->kids[0]))) {
00179 assert(tlab == 0 && flab == 0);
00180 if (generic(tp->kids[0]->op) == INDIR) {
00181 p = listnodes(tp->kids[0], 0, 0);
00182 list(p);
00183 listnodes(tp->kids[1], 0, 0);
00184 }
00185 else {
00186 assert(generic(tp->kids[0]->kids[0]->op) == INDIR);
00187 list(listnodes(tp->kids[0]->kids[0], 0, 0));
00188 p = listnodes(tp->kids[0], 0, 0);
00189 listnodes(tp->kids[1], 0, 0);
00190 }
00191 } else if (tp->kids[1]) {
00192 listnodes(tp->kids[0], 0, 0);
00193 p = listnodes(tp->kids[1], tlab, flab);
00194 } else
00195 p = listnodes(tp->kids[0], tlab, flab); } break;
00196 case JUMP: { assert(tlab == 0 && flab == 0);
00197 assert(tp->u.sym == 0);
00198 assert(tp->kids[0]);
00199 l = listnodes(tp->kids[0], 0, 0);
00200 list(newnode(JUMP+V, l, NULL, NULL));
00201 reset(); } break;
00202 case CALL: { Tree save = firstarg;
00203 firstarg = NULL;
00204 assert(tlab == 0 && flab == 0);
00205 if (tp->op == CALL+B && !IR->wants_callb) {
00206 Tree arg0 = tree(ARG+P, tp->kids[1]->type,
00207 tp->kids[1], NULL);
00208 if (IR->left_to_right)
00209 firstarg = arg0;
00210 l = listnodes(tp->kids[0], 0, 0);
00211 if (!IR->left_to_right || firstarg) {
00212 firstarg = NULL;
00213 listnodes(arg0, 0, 0);
00214 }
00215 p = newnode(CALL+V, l, NULL, NULL);
00216 } else {
00217 l = listnodes(tp->kids[0], 0, 0);
00218 r = listnodes(tp->kids[1], 0, 0);
00219 p = newnode(tp->op == CALL+B ? tp->op : op, l, r, NULL);
00220 }
00221 NEW0(p->syms[0], FUNC);
00222 assert(isptr(tp->kids[0]->type));
00223 assert(isfunc(tp->kids[0]->type->type));
00224 p->syms[0]->type = tp->kids[0]->type->type;
00225 list(p);
00226 reset();
00227 cfunc->u.f.ncalls++;
00228 firstarg = save;
00229 } break;
00230 case ARG: { assert(tlab == 0 && flab == 0);
00231 if (IR->left_to_right)
00232 listnodes(tp->kids[1], 0, 0);
00233 if (firstarg) {
00234 Tree arg = firstarg;
00235 firstarg = NULL;
00236 listnodes(arg, 0, 0);
00237 }
00238 l = listnodes(tp->kids[0], 0, 0);
00239 list(newnode(tp->op == ARG+B ? tp->op : op, l, NULL, NULL));
00240 forest->syms[0] = intconst(tp->type->size);
00241 forest->syms[1] = intconst(tp->type->align);
00242 if (!IR->left_to_right)
00243 listnodes(tp->kids[1], 0, 0); } break;
00244 case EQ: case NE: case GT: case GE: case LE:
00245 case LT: { assert(tp->u.sym == 0);
00246 assert(errcnt || tlab || flab);
00247 l = listnodes(tp->kids[0], 0, 0);
00248 r = listnodes(tp->kids[1], 0, 0);
00249 assert(errcnt || opkind(l->op) == opkind(r->op));
00250 assert(errcnt || optype(op) == optype(l->op));
00251 if (tlab)
00252 assert(flab == 0),
00253 list(newnode(generic(tp->op) + opkind(l->op), l, r, findlabel(tlab)));
00254 else if (flab) {
00255 switch (generic(tp->op)) {
00256 case EQ: op = NE; break;
00257 case NE: op = EQ; break;
00258 case GT: op = LE; break;
00259 case LT: op = GE; break;
00260 case GE: op = LT; break;
00261 case LE: op = GT; break;
00262 default: assert(0);
00263 }
00264 list(newnode(op + opkind(l->op), l, r, findlabel(flab)));
00265 }
00266 if (forest && forest->syms[0])
00267 forest->syms[0]->ref++; } break;
00268 case ASGN: { assert(tlab == 0 && flab == 0);
00269 if (tp->kids[0]->op == FIELD) {
00270 Tree x = tp->kids[0]->kids[0];
00271 Field f = tp->kids[0]->u.field;
00272 assert(generic(x->op) == INDIR);
00273 reset();
00274 l = listnodes(lvalue(x), 0, 0);
00275 if (fieldsize(f) < 8*f->type->size) {
00276 unsigned int fmask = fieldmask(f);
00277 unsigned int mask = fmask<<fieldright(f);
00278 Tree q = tp->kids[1];
00279 if (q->op == CNST+I && q->u.v.i == 0
00280 || q->op == CNST+U && q->u.v.u == 0)
00281 q = bittree(BAND, x, cnsttree(unsignedtype, (unsigned long)~mask));
00282 else if (q->op == CNST+I && (q->u.v.i&fmask) == fmask
00283 || q->op == CNST+U && (q->u.v.u&fmask) == fmask)
00284 q = bittree(BOR, x, cnsttree(unsignedtype, (unsigned long)mask));
00285 else {
00286 listnodes(q, 0, 0);
00287 q = bittree(BOR,
00288 bittree(BAND, rvalue(lvalue(x)),
00289 cnsttree(unsignedtype, (unsigned long)~mask)),
00290 bittree(BAND, shtree(LSH, cast(q, unsignedtype),
00291 cnsttree(unsignedtype, (unsigned long)fieldright(f))),
00292 cnsttree(unsignedtype, (unsigned long)mask)));
00293 }
00294 r = listnodes(q, 0, 0);
00295 op = ASGN + ttob(q->type);
00296 } else {
00297 r = listnodes(tp->kids[1], 0, 0);
00298 op = ASGN + ttob(tp->kids[1]->type);
00299 }
00300 } else {
00301 l = listnodes(tp->kids[0], 0, 0);
00302 r = listnodes(tp->kids[1], 0, 0);
00303 }
00304 list(newnode(tp->op == ASGN+B ? tp->op : op, l, r, NULL));
00305 forest->syms[0] = intconst(tp->kids[1]->type->size);
00306 forest->syms[1] = intconst(tp->kids[1]->type->align);
00307 if (isaddrop(tp->kids[0]->op)
00308 && !tp->kids[0]->u.sym->computed)
00309 kill(tp->kids[0]->u.sym);
00310 else
00311 reset();
00312 p = listnodes(tp->kids[1], 0, 0); } break;
00313 case BOR: case BAND: case BXOR:
00314 case ADD: case SUB: case RSH:
00315 case LSH: { assert(tlab == 0 && flab == 0);
00316 l = listnodes(tp->kids[0], 0, 0);
00317 r = listnodes(tp->kids[1], 0, 0);
00318 p = node(op, l, r, NULL); } break;
00319 case DIV: case MUL:
00320 case MOD: { assert(tlab == 0 && flab == 0);
00321 l = listnodes(tp->kids[0], 0, 0);
00322 r = listnodes(tp->kids[1], 0, 0);
00323 p = node(op, l, r, NULL);
00324 if (IR->mulops_calls && isint(tp->type)) {
00325 list(p);
00326 cfunc->u.f.ncalls++;
00327 } } break;
00328 case RET: { assert(tlab == 0 && flab == 0);
00329 l = listnodes(tp->kids[0], 0, 0);
00330 list(newnode(op, l, NULL, NULL)); } break;
00331 case CVF: case CVI: case CVP:
00332 case CVU: { assert(tlab == 0 && flab == 0);
00333 assert(optype(tp->kids[0]->op) != optype(tp->op) || tp->kids[0]->type->size != tp->type->size);
00334 l = listnodes(tp->kids[0], 0, 0);
00335 p = node(op, l, NULL, intconst(tp->kids[0]->type->size));
00336 } break;
00337 case BCOM:
00338 case NEG: { assert(tlab == 0 && flab == 0);
00339 l = listnodes(tp->kids[0], 0, 0);
00340 p = node(op, l, NULL, NULL); } break;
00341 case INDIR: { Type ty = tp->kids[0]->type;
00342 assert(tlab == 0 && flab == 0);
00343 l = listnodes(tp->kids[0], 0, 0);
00344 if (isptr(ty))
00345 ty = unqual(ty)->type;
00346 if (isvolatile(ty)
00347 || (isstruct(ty) && unqual(ty)->u.sym->u.s.vfields))
00348 p = newnode(tp->op == INDIR+B ? tp->op : op, l, NULL, NULL);
00349 else
00350 p = node(tp->op == INDIR+B ? tp->op : op, l, NULL, NULL); } break;
00351 case FIELD: { Tree q = tp->kids[0];
00352 if (tp->type == inttype) {
00353 long n = fieldleft(tp->u.field);
00354 q = shtree(RSH,
00355 shtree(LSH, q, cnsttree(inttype, n)),
00356 cnsttree(inttype, n + fieldright(tp->u.field)));
00357 } else if (fieldsize(tp->u.field) < 8*tp->u.field->type->size)
00358 q = bittree(BAND,
00359 shtree(RSH, q, cnsttree(inttype, (long)fieldright(tp->u.field))),
00360 cnsttree(unsignedtype, (unsigned long)fieldmask(tp->u.field)));
00361 assert(tlab == 0 && flab == 0);
00362 p = listnodes(q, 0, 0); } break;
00363 case ADDRG:
00364 case ADDRF: { assert(tlab == 0 && flab == 0);
00365 p = node(tp->op + sizeop(voidptype->size), NULL, NULL, tp->u.sym);
00366 } break;
00367 case ADDRL: { assert(tlab == 0 && flab == 0);
00368 if (tp->u.sym->temporary)
00369 addlocal(tp->u.sym);
00370 p = node(tp->op + sizeop(voidptype->size), NULL, NULL, tp->u.sym); } break;
00371 default:assert(0);
00372 }
00373 tp->node = p;
00374 return p;
00375 }
00376 static void list(Node p) {
00377 if (p && p->link == NULL) {
00378 if (forest) {
00379 p->link = forest->link;
00380 forest->link = p;
00381 } else
00382 p->link = p;
00383 forest = p;
00384 }
00385 }
00386 static void labelnode(int lab) {
00387 assert(lab);
00388 if (forest && forest->op == LABEL+V)
00389 equatelab(findlabel(lab), forest->syms[0]);
00390 else
00391 list(newnode(LABEL+V, NULL, NULL, findlabel(lab)));
00392 reset();
00393 }
00394 static void unlist(void) {
00395 Node p;
00396
00397 assert(forest);
00398 assert(forest != forest->link);
00399 p = forest->link;
00400 while (p->link != forest)
00401 p = p->link;
00402 p->link = forest->link;
00403 forest = p;
00404 }
00405 Tree cvtconst(Tree p) {
00406 Symbol q = constant(p->type, p->u.v);
00407 Tree e;
00408
00409 if (q->u.c.loc == NULL)
00410 q->u.c.loc = genident(STATIC, p->type, GLOBAL);
00411 if (isarray(p->type)) {
00412 e = simplify(ADDRG, atop(p->type), NULL, NULL);
00413 e->u.sym = q->u.c.loc;
00414 } else
00415 e = idtree(q->u.c.loc);
00416 return e;
00417 }
00418 void gencode(Symbol caller[], Symbol callee[]) {
00419 Code cp;
00420 Coordinate save;
00421
00422 if (prunetemps == -1)
00423 prunetemps = !IR->wants_dag;
00424 save = src;
00425 if (assignargs) {
00426 int i;
00427 Symbol p, q;
00428 cp = codehead.next->next;
00429 codelist = codehead.next;
00430 for (i = 0; (p = callee[i]) != NULL
00431 && (q = caller[i]) != NULL; i++)
00432 if (p->sclass != q->sclass || p->type != q->type)
00433 walk(asgn(p, idtree(q)), 0, 0);
00434 codelist->next = cp;
00435 cp->prev = codelist;
00436 }
00437 if (glevel && IR->stabsym) {
00438 int i;
00439 Symbol p, q;
00440 for (i = 0; (p = callee[i]) != NULL
00441 && (q = caller[i]) != NULL; i++) {
00442 (*IR->stabsym)(p);
00443 if (p->sclass != q->sclass || p->type != q->type)
00444 (*IR->stabsym)(q);
00445 }
00446 swtoseg(CODE);
00447 }
00448 cp = codehead.next;
00449 for ( ; errcnt <= 0 && cp; cp = cp->next)
00450 switch (cp->kind) {
00451 case Address: (*IR->address)(cp->u.addr.sym, cp->u.addr.base,
00452 cp->u.addr.offset); break;
00453 case Blockbeg: {
00454 Symbol *p = cp->u.block.locals;
00455 (*IR->blockbeg)(&cp->u.block.x);
00456 for ( ; *p; p++)
00457 if ((*p)->ref != 0.0)
00458 (*IR->local)(*p);
00459 else if (glevel) (*IR->local)(*p);
00460 }
00461 break;
00462 case Blockend: (*IR->blockend)(&cp->u.begin->u.block.x); break;
00463 case Defpoint: src = cp->u.point.src; break;
00464 case Gen: case Jump:
00465 case Label: if (prunetemps)
00466 cp->u.forest = prune(cp->u.forest);
00467 fixup(cp->u.forest);
00468 cp->u.forest = (*IR->gen)(cp->u.forest); break;
00469 case Local: (*IR->local)(cp->u.var); break;
00470 case Switch: break;
00471 default: assert(0);
00472 }
00473 src = save;
00474 }
00475 static void fixup(Node p) {
00476 for ( ; p; p = p->link)
00477 switch (generic(p->op)) {
00478 case JUMP:
00479 if (specific(p->kids[0]->op) == ADDRG+P)
00480 p->kids[0]->syms[0] =
00481 equated(p->kids[0]->syms[0]);
00482 break;
00483 case LABEL: assert(p->syms[0] == equated(p->syms[0])); break;
00484 case EQ: case GE: case GT: case LE: case LT: case NE:
00485 assert(p->syms[0]);
00486 p->syms[0] = equated(p->syms[0]);
00487 }
00488 }
00489 static Symbol equated(Symbol p) {
00490 { Symbol q; for (q = p->u.l.equatedto; q; q = q->u.l.equatedto) assert(p != q); }
00491 while (p->u.l.equatedto)
00492 p = p->u.l.equatedto;
00493 return p;
00494 }
00495 void emitcode(void) {
00496 Code cp;
00497 Coordinate save;
00498
00499 save = src;
00500 cp = codehead.next;
00501 for ( ; errcnt <= 0 && cp; cp = cp->next)
00502 switch (cp->kind) {
00503 case Address: break;
00504 case Blockbeg: if (glevel && IR->stabblock) {
00505 (*IR->stabblock)('{', cp->u.block.level - LOCAL, cp->u.block.locals);
00506 swtoseg(CODE);
00507 }
00508 break;
00509 case Blockend: if (glevel && IR->stabblock) {
00510 Code bp = cp->u.begin;
00511 foreach(bp->u.block.identifiers, bp->u.block.level, typestab, NULL);
00512 foreach(bp->u.block.types, bp->u.block.level, typestab, NULL);
00513 (*IR->stabblock)('}', bp->u.block.level - LOCAL, bp->u.block.locals);
00514 swtoseg(CODE);
00515 }
00516 break;
00517 case Defpoint: src = cp->u.point.src;
00518 if (glevel > 0 && IR->stabline) {
00519 (*IR->stabline)(&cp->u.point.src); swtoseg(CODE); } break;
00520 case Gen: case Jump:
00521 case Label: if (cp->u.forest)
00522 (*IR->emit)(cp->u.forest); break;
00523 case Local: if (glevel && IR->stabsym) {
00524 (*IR->stabsym)(cp->u.var);
00525 swtoseg(CODE);
00526 } break;
00527 case Switch: { int i;
00528 defglobal(cp->u.swtch.table, LIT);
00529 (*IR->defaddress)(equated(cp->u.swtch.labels[0]));
00530 for (i = 1; i < cp->u.swtch.size; i++) {
00531 long k = cp->u.swtch.values[i-1];
00532 while (++k < cp->u.swtch.values[i])
00533 assert(k < LONG_MAX),
00534 (*IR->defaddress)(equated(cp->u.swtch.deflab));
00535 (*IR->defaddress)(equated(cp->u.swtch.labels[i]));
00536 }
00537 swtoseg(CODE);
00538 } break;
00539 default: assert(0);
00540 }
00541 src = save;
00542 }
00543
00544 static Node undag(Node forest) {
00545 Node p;
00546
00547 tail = &forest;
00548 for (p = forest; p; p = p->link)
00549 if (generic(p->op) == INDIR) {
00550 assert(p->count >= 1);
00551 visit(p, 1);
00552 if (p->syms[2]) {
00553 assert(p->syms[2]->u.t.cse);
00554 p->syms[2]->u.t.cse = NULL;
00555 addlocal(p->syms[2]);
00556 }
00557 } else if (iscall(p->op) && p->count >= 1)
00558 visit(p, 1);
00559 else {
00560 assert(p->count == 0),
00561 visit(p, 1);
00562 *tail = p;
00563 tail = &p->link;
00564 }
00565 *tail = NULL;
00566 return forest;
00567 }
00568 static Node replace(Node p) {
00569 if (p && ( generic(p->op) == INDIR
00570 && generic(p->kids[0]->op) == ADDRL
00571 && p->kids[0]->syms[0]->temporary
00572 && p->kids[0]->syms[0]->u.t.replace)) {
00573 p = p->kids[0]->syms[0]->u.t.cse;
00574 if (generic(p->op) == INDIR && isaddrop(p->kids[0]->op))
00575 p = newnode(p->op, newnode(p->kids[0]->op, NULL, NULL,
00576 p->kids[0]->syms[0]), NULL, NULL);
00577 else if (generic(p->op) == ADDRG)
00578 p = newnode(p->op, NULL, NULL, p->syms[0]);
00579 else
00580 assert(0);
00581 p->count = 1;
00582 } else if (p) {
00583 p->kids[0] = replace(p->kids[0]);
00584 p->kids[1] = replace(p->kids[1]);
00585 }
00586 return p;
00587 }
00588 static Node prune(Node forest) {
00589 Node p, *tail = &forest;
00590 int count = 0;
00591
00592 for (p = forest; p; p = p->link) {
00593 if (count > 0) {
00594 p->kids[0] = replace(p->kids[0]);
00595 p->kids[1] = replace(p->kids[1]);
00596 }
00597 if (( generic(p->op) == ASGN
00598 && generic(p->kids[0]->op) == ADDRL
00599 && p->kids[0]->syms[0]->temporary
00600 && p->kids[0]->syms[0]->u.t.cse == p->kids[1])) {
00601 Symbol tmp = p->kids[0]->syms[0];
00602 if (!tmp->defined)
00603 (*IR->local)(tmp);
00604 tmp->defined = 1;
00605 if (( generic(p->kids[1]->op) == INDIR
00606 && isaddrop(p->kids[1]->kids[0]->op)
00607 && p->kids[1]->kids[0]->syms[0]->sclass == REGISTER)
00608 || (( generic(p->kids[1]->op) == INDIR
00609 && isaddrop(p->kids[1]->kids[0]->op)) && tmp->sclass == AUTO)
00610 || (generic(p->kids[1]->op) == ADDRG && tmp->sclass == AUTO)) {
00611 tmp->u.t.replace = 1;
00612 count++;
00613 continue;
00614 }
00615 }
00616
00617 *tail = p;
00618 tail = &(*tail)->link;
00619 }
00620 assert(*tail == NULL);
00621 return forest;
00622 }
00623 static Node visit(Node p, int listed) {
00624 if (p)
00625 if (p->syms[2])
00626 p = tmpnode(p);
00627 else if (p->count <= 1 && !iscall(p->op)
00628 || p->count == 0 && iscall(p->op)) {
00629 p->kids[0] = visit(p->kids[0], 0);
00630 p->kids[1] = visit(p->kids[1], 0);
00631 }
00632
00633 else if (specific(p->op) == ADDRL+P || specific(p->op) == ADDRF+P) {
00634 assert(!listed);
00635 p = newnode(p->op, NULL, NULL, p->syms[0]);
00636 p->count = 1;
00637 }
00638 else if (p->op == INDIR+B) {
00639 p = newnode(p->op, p->kids[0], NULL, NULL);
00640 p->count = 1;
00641 p->kids[0] = visit(p->kids[0], 0);
00642 p->kids[1] = visit(p->kids[1], 0);
00643 }
00644 else {
00645 p->kids[0] = visit(p->kids[0], 0);
00646 p->kids[1] = visit(p->kids[1], 0);
00647 p->syms[2] = temporary(REGISTER, btot(p->op, opsize(p->op)));
00648 assert(!p->syms[2]->defined);
00649 p->syms[2]->ref = 1;
00650 p->syms[2]->u.t.cse = p;
00651
00652 *tail = asgnnode(p->syms[2], p);
00653 tail = &(*tail)->link;
00654 if (!listed)
00655 p = tmpnode(p);
00656 };
00657 return p;
00658 }
00659 static Node tmpnode(Node p) {
00660 Symbol tmp = p->syms[2];
00661
00662 assert(tmp);
00663 if (--p->count == 0)
00664 p->syms[2] = NULL;
00665 p = newnode(INDIR + ttob(tmp->type),
00666 newnode(ADDRL + ttob(voidptype), NULL, NULL, tmp), NULL, NULL);
00667 p->count = 1;
00668 return p;
00669 }
00670 static Node asgnnode(Symbol tmp, Node p) {
00671 p = newnode(ASGN + ttob(tmp->type),
00672 newnode(ADDRL + ttob(voidptype), NULL, NULL, tmp), p, NULL);
00673 p->syms[0] = intconst(tmp->type->size);
00674 p->syms[1] = intconst(tmp->type->align);
00675 return p;
00676 }
00677