|
|
1.1 ! root 1: /* C compiler: dag processing */ ! 2: ! 3: #include "c.h" ! 4: #define NBUCKETS 020 ! 5: ! 6: struct code codehead = { Start }; ! 7: Code codelist = &codehead; /* list of code nodes for current function */ ! 8: int nodecount; /* # of available nodes in hash table */ ! 9: ! 10: static struct dag { /* dags: */ ! 11: struct node node; /* the node itself */ ! 12: struct dag *hlink; /* next dag on hash chain */ ! 13: } *buckets[NBUCKETS]; /* hash table */ ! 14: static Node nodelist; /* node list */ ! 15: dclproto(static struct dag *dagnode,(int, Node, Node, Symbol)); ! 16: dclproto(static void fixup,(Node)); ! 17: dclproto(static int haskid,(Node, Node)); ! 18: dclproto(static Node labelnode,(int)); ! 19: dclproto(static Node list,(Node)); ! 20: dclproto(static void reset,(void)); ! 21: dclproto(static void remove,(Node)); ! 22: dclproto(static void trash,(Node)); ! 23: dclproto(static void typestab,(Symbol, Generic)); ! 24: dclproto(static Node undag,(Node)); ! 25: dclproto(static Node undag1,(Node, Node)); ! 26: ! 27: /* addlocal - add local p to list of locals for the current block */ ! 28: void addlocal(p) Symbol p; { ! 29: if (!p->defined) { ! 30: code(Local)->u.var = p; ! 31: p->defined = 1; ! 32: p->scope = level; ! 33: } ! 34: } ! 35: ! 36: /* btot - map operator op or suffix op into a representative type */ ! 37: Type btot(op) int op; { ! 38: switch (optype(op)) { ! 39: case F: return floattype; ! 40: case D: return doubletype; ! 41: case C: return chartype; ! 42: case S: return shorttype; ! 43: case I: return inttype; ! 44: case U: return unsignedtype; ! 45: case P: return voidptype; ! 46: default: assert(0); ! 47: } ! 48: return 0; ! 49: } ! 50: ! 51: /* code - allocate a code node of kind and append to the code list */ ! 52: Code code(kind) { ! 53: Code cp; ! 54: ! 55: if (kind > Label) { ! 56: for (cp = codelist; cp->kind < Label; ) ! 57: cp = cp->prev; ! 58: if (cp->kind == Jump) ! 59: warning("unreachable code\n"); ! 60: } ! 61: cp = (Code)talloc(sizeof *cp); ! 62: cp->kind = kind; ! 63: cp->prev = codelist; ! 64: cp->next = 0; ! 65: codelist->next = cp; ! 66: return codelist = cp; ! 67: } ! 68: ! 69: /* dagnode - allocate a dag with the given fields */ ! 70: static struct dag *dagnode(op, l, r, sym) Node l, r; Symbol sym; { ! 71: register struct dag *p = (struct dag *) talloc(sizeof *p); ! 72: ! 73: BZERO(p, struct dag); ! 74: p->node.op = op; ! 75: if (p->node.kids[0] = l) ! 76: ++l->count; ! 77: if (p->node.kids[1] = r) ! 78: ++r->count; ! 79: p->node.syms[0] = sym; ! 80: return p; ! 81: } ! 82: ! 83: /* emitcode - emit code for the current function */ ! 84: void emitcode() { ! 85: Code bp, cp; ! 86: Coordinate save; ! 87: ! 88: save = src; ! 89: for (bp = 0, cp = &codehead; errcnt <= 0 && cp; cp = cp->next) ! 90: switch (cp->kind) { ! 91: case Blockbeg: ! 92: cp->u.block.prev = bp; ! 93: bp = cp; ! 94: if (glevel && IR->stabblock) { ! 95: (*IR->stabblock)('{', bp->u.block.level - LOCAL, bp->u.block.locals); ! 96: swtoseg(CODE); ! 97: } ! 98: break; ! 99: case Blockend: ! 100: if (glevel && IR->stabblock) { ! 101: foreach(bp->u.block.identifiers, bp->u.block.level, typestab, (Generic)0); ! 102: foreach(bp->u.block.types, bp->u.block.level, typestab, (Generic)0); ! 103: (*IR->stabblock)('}', bp->u.block.level - LOCAL, bp->u.block.locals); ! 104: swtoseg(CODE); ! 105: } ! 106: bp = bp->u.block.prev; ! 107: break; ! 108: case Local: ! 109: if (glevel && IR->stabsym) { ! 110: (*IR->stabsym)(cp->u.var); ! 111: swtoseg(CODE); ! 112: } ! 113: break; ! 114: case Defpoint: ! 115: src = cp->u.point.src; ! 116: if (glevel && IR->stabline) { ! 117: (*IR->stabline)(&cp->u.point.src); ! 118: swtoseg(CODE); ! 119: } ! 120: break; ! 121: case Jump: ! 122: if (cp->u.node == 0) ! 123: break; ! 124: /* else fall thru */ ! 125: case Gen: case Label: ! 126: (*IR->emit)(cp->u.node); ! 127: break; ! 128: case Switch: { ! 129: int i, k = cp->u.swtch.values[0]; ! 130: for (i = 0; i < cp->u.swtch.size; i++) { ! 131: while (k++ < cp->u.swtch.values[i]) ! 132: (*IR->defaddress)(cp->u.swtch.deflab->u.l.equatedto); ! 133: (*IR->defaddress)(cp->u.swtch.labels[i]->u.l.equatedto); ! 134: } ! 135: break; ! 136: } ! 137: } ! 138: src = save; ! 139: } ! 140: ! 141: /* fixup - re-aim equated labels to the true label */ ! 142: static void fixup(p) Node p; { ! 143: for ( ; p; p = p->link) ! 144: switch (generic(p->op)) { ! 145: case JUMP: ! 146: if (p->kids[0]->op == ADDRG+P) ! 147: p->kids[0]->syms[0] = p->kids[0]->syms[0]->u.l.equatedto; ! 148: break; ! 149: case LABEL: ! 150: case EQ: case GE: case GT: case LE: case LT: case NE: ! 151: assert(p->syms[0]); ! 152: p->syms[0] = p->syms[0]->u.l.equatedto; ! 153: } ! 154: } ! 155: ! 156: /* gencode - generate code for the current function */ ! 157: void gencode(caller, callee) Symbol caller[], callee[]; { ! 158: int i; ! 159: Code bp, cp; ! 160: Symbol p, q; ! 161: Coordinate save; ! 162: ! 163: save = src; ! 164: cp = codehead.next->next; ! 165: codelist = codehead.next; ! 166: for (i = 0; (p = callee[i]) && (q = caller[i]); i++) ! 167: if (p->sclass != q->sclass || p->type != q->type) { ! 168: walk(asgn(p, idnode(q)), 0, 0); ! 169: if (glevel && IR->stabsym) { ! 170: (*IR->stabsym)(p); ! 171: (*IR->stabsym)(q); ! 172: swtoseg(CODE); ! 173: } ! 174: } else if (glevel && IR->stabsym) { ! 175: (*IR->stabsym)(p); ! 176: swtoseg(CODE); ! 177: } ! 178: codelist->next = cp; ! 179: cp->prev = codelist; ! 180: for (bp = 0, cp = &codehead; errcnt <= 0 && cp; cp = cp->next) ! 181: switch (cp->kind) { ! 182: case Start: case Switch: ! 183: break; ! 184: case Defpoint: ! 185: src = cp->u.point.src; ! 186: break; ! 187: case Blockbeg: { ! 188: Symbol *p = cp->u.block.locals; ! 189: cp->u.block.prev = bp; ! 190: bp = cp; ! 191: (*IR->blockbeg)(&bp->u.block.x); ! 192: for ( ; *p; p++) ! 193: if ((*p)->ref || glevel) ! 194: (*IR->local)(*p); ! 195: break; ! 196: } ! 197: case Blockend: ! 198: (*IR->blockend)(&bp->u.block.x); ! 199: bp = bp->u.block.prev; ! 200: break; ! 201: case Local: ! 202: assert(cp->u.var->scope == bp->u.block.level); ! 203: (*IR->local)(cp->u.var); ! 204: break; ! 205: case Address: ! 206: (*IR->address)(cp->u.addr.sym, cp->u.addr.base, cp->u.addr.offset); ! 207: break; ! 208: case Jump: ! 209: if (cp->u.node == 0) ! 210: break; ! 211: /* else fall thru */ ! 212: case Gen: case Label: ! 213: fixup(cp->u.node); ! 214: if (IR->no_dag) ! 215: cp->u.node = undag(cp->u.node); ! 216: cp->u.node = (*IR->gen)(cp->u.node); ! 217: break; ! 218: default:assert(0); ! 219: } ! 220: src = save; ! 221: } ! 222: ! 223: /* haskid - does p appear as an operand in t? */ ! 224: static int haskid(p, t) Node p, t; { ! 225: if (t == 0) ! 226: return 0; ! 227: else if (p == t) ! 228: return 1; ! 229: else ! 230: return haskid(p, t->kids[0]) || haskid(p, t->kids[1]); ! 231: } ! 232: ! 233: /* labelnode - list and return a LABEL node for label lab */ ! 234: static Node labelnode(lab) { ! 235: assert(lab); ! 236: if (islabel(nodelist)) { ! 237: equatelab(findlabel(lab), nodelist->syms[0]); ! 238: return nodelist; ! 239: } ! 240: return list(newnode(LABEL+V, 0, 0, findlabel(lab))); ! 241: } ! 242: ! 243: /* list - list node p unless it's already listed; return p */ ! 244: static Node list(p) Node p; { ! 245: if (p && p->link == 0) { ! 246: if (nodelist) { ! 247: p->link = nodelist->link; ! 248: nodelist->link = p; ! 249: } else ! 250: p->link = p; ! 251: nodelist = p; ! 252: #ifdef DAGCHECK ! 253: { extern void type_checker(Node); type_checker(p); } ! 254: #endif ! 255: } ! 256: return p; ! 257: } ! 258: ! 259: /* listnodes - walk tree tp, building and listing dag nodes in execution order */ ! 260: Node listnodes(tp, tlab, flab) Tree tp; { ! 261: Opcode op; ! 262: Node p, l, r; ! 263: ! 264: if (tp == 0) ! 265: return 0; ! 266: if (tp->node) ! 267: return tp->node; ! 268: op = generic(tp->op); ! 269: switch (op) { ! 270: case AND: ! 271: if (flab) { ! 272: listnodes(tp->kids[0], 0, flab); ! 273: r = listnodes(tp->kids[1], 0, flab); ! 274: } else { ! 275: listnodes(tp->kids[0], 0, flab = genlabel(1)); ! 276: listnodes(tp->kids[1], tlab, 0); ! 277: r = labelnode(flab); ! 278: } ! 279: trash(0); ! 280: return r; ! 281: case NOT: ! 282: return listnodes(tp->kids[0], flab, tlab); ! 283: case OR: ! 284: if (tlab) { ! 285: listnodes(tp->kids[0], tlab, 0); ! 286: r = listnodes(tp->kids[1], tlab, 0); ! 287: } else { ! 288: listnodes(tp->kids[0], tlab = genlabel(1), 0); ! 289: listnodes(tp->kids[1], 0, flab); ! 290: r = labelnode(tlab); ! 291: } ! 292: trash(0); ! 293: return r; ! 294: case COND: { ! 295: Tree q; ! 296: assert(tlab == 0 && flab == 0); ! 297: if (tp->u.sym) ! 298: addlocal(tp->u.sym); ! 299: trash(0); ! 300: listnodes(tp->kids[0], 0, flab = genlabel(2)); ! 301: trash(0); ! 302: if (q = tp->kids[1]) { ! 303: assert(q->op == RIGHT); ! 304: listnodes(q->kids[0], 0, 0); ! 305: if (islabel(nodelist)) { ! 306: equatelab(nodelist->syms[0], findlabel(flab + 1)); ! 307: remove(nodelist); ! 308: } ! 309: trash(0); ! 310: } ! 311: if (q && q->kids[1]) { ! 312: list(jump(flab + 1)); ! 313: labelnode(flab); ! 314: listnodes(q->kids[1], 0, 0); ! 315: if (islabel(nodelist)) { ! 316: equatelab(nodelist->syms[0], findlabel(flab + 1)); ! 317: remove(nodelist); ! 318: } ! 319: } else ! 320: labelnode(flab); ! 321: p = labelnode(flab + 1); ! 322: trash(0); ! 323: if (tp->u.sym) { ! 324: Tree t = idnode(tp->u.sym); ! 325: tp->u.sym->ref = 0; /* undo idnode's setting ref */ ! 326: p = listnodes(t, 0, 0); ! 327: } ! 328: break; ! 329: } ! 330: case CNST: { ! 331: Type ty = unqual(tp->type); ! 332: assert(op == CNST+S || ty->u.sym); ! 333: if (op == CNST+S || ty->u.sym->addressed) ! 334: p = listnodes(cvtconst(tp), tlab, flab); ! 335: else if (tlab == 0 && flab == 0) ! 336: p = node(tp->op, 0, 0, constant(ty, tp->u.v)); ! 337: else { ! 338: assert(ty == inttype); ! 339: if (tlab && tp->u.v.i != 0) ! 340: p = list(jump(tlab)); ! 341: else if (flab && tp->u.v.i == 0) ! 342: p = list(jump(flab)); ! 343: else ! 344: p = 0; ! 345: } ! 346: break; ! 347: } ! 348: case RIGHT: ! 349: if (tp->kids[0] && generic(tp->kids[0]->op) == INDIR ! 350: && tp->kids[1] && generic(tp->kids[1]->op) == ASGN ! 351: && tp->kids[0]->kids[0] == tp->kids[1]->kids[0]) { /* e++ */ ! 352: p = listnodes(tp->kids[0], 0, 0); ! 353: if (nodelist) { ! 354: Node t; ! 355: for (t = nodelist; ; t = t->link) ! 356: if (haskid(p, t->link)) { ! 357: p->link = t->link; ! 358: t->link = p; ! 359: break; ! 360: } else if (t->link == nodelist) { ! 361: list(p); ! 362: break; ! 363: } ! 364: } else ! 365: list(p); ! 366: listnodes(tp->kids[1], 0, 0); ! 367: } else if (tp->kids[1]) { ! 368: if (tp->kids[0] && generic(tp->kids[0]->op) == CNST) ! 369: tp->kids[0] = 0; ! 370: listnodes(tp->kids[0], 0, 0); ! 371: p = listnodes(tp->kids[1], tlab, flab); ! 372: } else ! 373: p = listnodes(tp->kids[0], tlab, flab); ! 374: break; ! 375: case JUMP: ! 376: assert(tlab == 0 && flab == 0); ! 377: assert(tp->u.sym == 0); ! 378: assert(tp->kids[0]); ! 379: l = listnodes(tp->kids[0], 0, 0); ! 380: p = newnode(JUMP+V, l, 0, 0); ! 381: trash(0); ! 382: list(p); ! 383: break; ! 384: case CALL: ! 385: assert(tlab == 0 && flab == 0); ! 386: l = listnodes(tp->kids[0], 0, 0); /* arguments, function name */ ! 387: r = listnodes(tp->kids[1], 0, 0); ! 388: p = newnode(tp->op, l, r, 0); ! 389: p->syms[0] = (Symbol)talloc(sizeof *p->syms[0]); ! 390: BZERO(p->syms[0], struct symbol); ! 391: if (isptr(tp->kids[0]->type) && isfunc(tp->kids[0]->type->type)) ! 392: p->syms[0]->type = tp->kids[0]->type->type; ! 393: else ! 394: p->syms[0]->type = func(voidtype, 0, 1); ! 395: trash(0); ! 396: list(p); ! 397: cfunc->u.f.ncalls++; ! 398: break; ! 399: case ARG: ! 400: assert(tlab == 0 && flab == 0); ! 401: if (IR->left_to_right) ! 402: listnodes(tp->kids[1], 0, 0); ! 403: l = listnodes(tp->kids[0], 0, 0); ! 404: p = newnode(tp->op, l, 0, 0); ! 405: p->syms[0] = intconst(tp->type->size); ! 406: p->syms[1] = intconst(tp->type->align); ! 407: list(p); ! 408: if (!IR->left_to_right) ! 409: listnodes(tp->kids[1], 0, 0); ! 410: return 0; ! 411: case EQ: case NE: case GT: case GE: case LE: case LT: { ! 412: int lab; ! 413: assert(tp->u.sym == 0); ! 414: assert(errcnt || tlab || flab); ! 415: if (lab = flab) { ! 416: assert(tlab == 0); ! 417: switch (op) { ! 418: case EQ: op = NE + optype(tp->op); break; ! 419: case NE: op = EQ + optype(tp->op); break; ! 420: case GT: op = LE + optype(tp->op); break; ! 421: case LT: op = GE + optype(tp->op); break; ! 422: case GE: op = LT + optype(tp->op); break; ! 423: case LE: op = GT + optype(tp->op); break; ! 424: } ! 425: } else if (lab = tlab) ! 426: op = tp->op; ! 427: l = listnodes(tp->kids[0], 0, 0); ! 428: r = listnodes(tp->kids[1], 0, 0); ! 429: p = newnode(op, l, r, findlabel(lab)); ! 430: p->syms[0]->ref++; ! 431: list(p); ! 432: break; ! 433: } ! 434: case ASGN: ! 435: assert(tlab == 0 && flab == 0); ! 436: if (tp->kids[0]->op == FIELD) { ! 437: Tree x = tp->kids[0]->kids[0]; ! 438: Field p = tp->kids[0]->u.field; ! 439: assert(generic(x->op) == INDIR); ! 440: trash(0); ! 441: l = listnodes(lvalue(x), 0, 0); ! 442: if (fieldsize(p) < 8*p->type->size) { ! 443: unsigned int fmask = fieldmask(p); ! 444: unsigned int mask = fmask<<fieldright(p); ! 445: Tree q = tp->kids[1]; ! 446: if (q->op == CNST+I && q->u.v.i == 0 ! 447: || q->op == CNST+U && q->u.v.u == 0) ! 448: q = bitnode(BAND, x, constnode(~mask, unsignedtype)); ! 449: else if (q->op == CNST+I && (q->u.v.i&fmask) == fmask ! 450: || q->op == CNST+U && (q->u.v.u&fmask) == fmask) ! 451: q = bitnode(BOR, x, constnode(mask, unsignedtype)); ! 452: else ! 453: q = bitnode(BOR, ! 454: bitnode(BAND, x, constnode(~mask, unsignedtype)), ! 455: bitnode(BAND, shnode(LSH, cast(q, unsignedtype), ! 456: constnode(fieldright(p), inttype)), ! 457: constnode(mask, unsignedtype))); ! 458: r = listnodes(q, 0, 0); ! 459: } else ! 460: r = listnodes(tp->kids[1], 0, 0); ! 461: } else { ! 462: l = listnodes(tp->kids[0], 0, 0); ! 463: r = listnodes(tp->kids[1], 0, 0); ! 464: } ! 465: trash(isaddrop(tp->kids[0]->op) && !tp->kids[0]->u.sym->computed ? l : 0); ! 466: p = newnode(tp->op, l, r, 0); ! 467: p->syms[0] = intconst(tp->kids[1]->type->size); ! 468: p->syms[1] = intconst(tp->kids[1]->type->align); ! 469: list(p); ! 470: p = listnodes(tp->kids[1], 0, 0); ! 471: break; ! 472: case BAND: ! 473: assert(tlab == 0 && flab == 0); ! 474: l = listnodes(tp->kids[0], 0, 0); ! 475: if (IR->compl_band) ! 476: r = listnodes(cast( ! 477: simplify(BCOM+U, unsignedtype, ! 478: cast(tp->kids[1], unsignedtype), 0), ! 479: tp->kids[1]->type), 0, 0); ! 480: else ! 481: r = listnodes(tp->kids[1], 0, 0); ! 482: p = node(tp->op, l, r, 0); ! 483: break; ! 484: case RSH: ! 485: assert(tlab == 0 && flab == 0); ! 486: l = listnodes(tp->kids[0], 0, 0); ! 487: if (IR->compl_band && tp->op == RSH+I) ! 488: r = listnodes(simplify(NEG+I, inttype, tp->kids[1], 0), 0, 0); ! 489: else ! 490: r = listnodes(tp->kids[1], 0, 0); ! 491: p = node(tp->op, l, r, 0); ! 492: break; ! 493: case ADD: case SUB: case DIV: case MUL: case MOD: ! 494: case BOR: case BXOR: case LSH: ! 495: assert(tlab == 0 && flab == 0); ! 496: l = listnodes(tp->kids[0], 0, 0); ! 497: r = listnodes(tp->kids[1], 0, 0); ! 498: p = node(tp->op, l, r, 0); ! 499: if (IR->mulops_are_calls && ! 500: (p->op == DIV+I || p->op == MOD+I || p->op == MUL+I ! 501: || p->op == DIV+U || p->op == MOD+U || p->op == MUL+U)) ! 502: list(p); ! 503: break; ! 504: case RET: ! 505: assert(tlab == 0 && flab == 0); ! 506: l = listnodes(tp->kids[0], 0, 0); ! 507: p = newnode(tp->op, l, 0, 0); ! 508: list(p); ! 509: break; ! 510: case CVC: case CVD: case CVF: case CVI: ! 511: case CVP: case CVS: case CVU: case NEG: case BCOM: ! 512: assert(tlab == 0 && flab == 0); ! 513: l = listnodes(tp->kids[0], 0, 0); ! 514: p = node(tp->op, l, 0, 0); ! 515: break; ! 516: case INDIR: { ! 517: Type ty = tp->kids[0]->type; ! 518: if (isptr(ty)) ! 519: ty = unqual(ty)->type; ! 520: assert(tlab == 0 && flab == 0); ! 521: l = listnodes(tp->kids[0], 0, 0); ! 522: if (isvolatile(ty) || (isstruct(ty) && unqual(ty)->u.sym->u.s.vfields)) ! 523: p = newnode(tp->op, l, 0, 0); ! 524: else ! 525: p = node(tp->op, l, 0, 0); ! 526: break; ! 527: } ! 528: case FIELD: { ! 529: Tree q; ! 530: assert(tlab == 0 && flab == 0); ! 531: q = shnode(RSH, ! 532: shnode(LSH, tp->kids[0], ! 533: constnode(fieldleft(tp->u.field), inttype)), ! 534: constnode(8*tp->type->size - fieldsize(tp->u.field), inttype)); ! 535: p = listnodes(q, 0, 0); ! 536: break; ! 537: } ! 538: case ADDRL: ! 539: assert(tlab == 0 && flab == 0); ! 540: if (tp->u.sym->temporary) { ! 541: addlocal(tp->u.sym); ! 542: release(tp->u.sym); ! 543: } ! 544: p = node(tp->op, 0, 0, tp->u.sym); ! 545: break; ! 546: case ADDRG: case ADDRF: ! 547: assert(tlab == 0 && flab == 0); ! 548: if (tp->u.sym->scope == LABELS) ! 549: tp->u.sym->ref++; ! 550: p = node(tp->op, 0, 0, tp->u.sym); ! 551: break; ! 552: default:assert(0); ! 553: } ! 554: return tp->node = p; ! 555: } ! 556: ! 557: /* jump - return tree for a jump to lab */ ! 558: Node jump(lab) { ! 559: Symbol p = findlabel(lab); ! 560: ! 561: p->ref++; ! 562: return newnode(JUMP+V, node(ADDRG+P, 0, 0, p), 0, 0); ! 563: } ! 564: ! 565: /* newnode - allocate a node with the given fields */ ! 566: Node newnode(op, l, r, sym) Node l, r; Symbol sym; { ! 567: return &dagnode(op, l, r, sym)->node; ! 568: } ! 569: ! 570: /* node - search for a node with the given fields, or allocate it */ ! 571: Node node(op, l, r, sym) Node l, r; Symbol sym; { ! 572: int i = (opindex(op)^((unsigned)sym>>2))&(NBUCKETS-1); ! 573: register struct dag *p; ! 574: ! 575: for (p = buckets[i]; p; p = p->hlink) ! 576: if (p->node.op == op && p->node.syms[0] == sym ! 577: && p->node.kids[0] == l && p->node.kids[1] == r) ! 578: return &p->node; ! 579: p = dagnode(op, l, r, sym); ! 580: p->hlink = buckets[i]; ! 581: buckets[i] = p; ! 582: ++nodecount; ! 583: return &p->node; ! 584: } ! 585: ! 586: dclproto(static void printdag1,(Node, int, int)); ! 587: dclproto(static void printnode,(Node, int, int)); ! 588: ! 589: /* printdag - print dag p on fd, or the node list if p == 0 */ ! 590: void printdag(p, fd) Node p; { ! 591: printed(0); ! 592: if (p == 0) { ! 593: if (p = nodelist) ! 594: do { ! 595: p = p->link; ! 596: printdag1(p, fd, 0); ! 597: } while (p != nodelist); ! 598: } else if (*printed(nodeid((Tree)p))) ! 599: fprint(fd, "node'%d printed above\n", nodeid((Tree)p)); ! 600: else ! 601: printdag1(p, fd, 0); ! 602: } ! 603: ! 604: /* printdag1 - recursively print dag p */ ! 605: static void printdag1(p, fd, lev) Node p; { ! 606: int id, i; ! 607: ! 608: if (p == 0 || *printed(id = nodeid((Tree)p))) ! 609: return; ! 610: *printed(id) = 1; ! 611: for (i = 0; i < MAXKIDS; i++) ! 612: printdag1(p->kids[i], fd, lev + 1); ! 613: printnode(p, fd, lev); ! 614: } ! 615: ! 616: /* printnode - print fields of dag p */ ! 617: static void printnode(p, fd, lev) Node p; { ! 618: if (p) { ! 619: int i, id = nodeid((Tree)p); ! 620: fprint(fd, "%c%d%s", lev == 0 ? '\'' : '#', id, ! 621: &" "[id < 10 ? 0 : id < 100 ? 1 : 2]); ! 622: fprint(fd, "%s count=%d", opname(p->op), p->count); ! 623: for (i = 0; i < MAXKIDS && p->kids[i]; i++) ! 624: fprint(fd, " #%d", nodeid((Tree)p->kids[i])); ! 625: for (i = 0; i < MAXSYMS && p->syms[i]; i++) ! 626: fprint(fd, " %s", p->syms[i]->name); ! 627: fprint(fd, "\n"); ! 628: } ! 629: } ! 630: ! 631: /* remove - remove node p from the node list */ ! 632: static void remove(p) Node p; { ! 633: if (nodelist) { ! 634: Node q = nodelist; ! 635: for ( ; q->link != p && q->link != nodelist; q = q->link) ! 636: ; ! 637: assert(q->link == p); ! 638: q->link = p->link; ! 639: if (p == nodelist) ! 640: nodelist = q; ! 641: } ! 642: } ! 643: ! 644: /* reset - clear the dag */ ! 645: static void reset() { ! 646: BZERO(buckets, struct dag *[NBUCKETS]); ! 647: nodecount = 0; ! 648: } ! 649: ! 650: /* trash - preclude future links to rvalue of p or all values */ ! 651: static void trash(p) Node p; { ! 652: if (p) { ! 653: register int i; ! 654: register struct dag *q, **r; ! 655: for (i = 0; i < NBUCKETS; i++) ! 656: for (r = &buckets[i]; q = *r; ) ! 657: if (generic(q->node.op) == INDIR && (!isaddrop(q->node.kids[0]->op) ! 658: || q->node.kids[0]->syms[0] == p->syms[0])) { ! 659: *r = q->hlink; ! 660: --nodecount; ! 661: } else ! 662: r = &q->hlink; ! 663: } else if (nodecount > 0) ! 664: reset(); ! 665: } ! 666: ! 667: /* typestab - emit stab entries for p */ ! 668: static void typestab(p, cl) Symbol p; Generic cl; { ! 669: if (!isfunc(p->type) && (p->sclass == EXTERN || p->sclass == STATIC) && IR->stabsym) ! 670: (*IR->stabsym)(p); ! 671: else if ((p->sclass == TYPEDEF || p->sclass == 0) && IR->stabtype) ! 672: (*IR->stabtype)(p); ! 673: } ! 674: ! 675: #define iscall(p) (generic((p)->op) == CALL || IR->mulops_are_calls \ ! 676: && ((p)->op == DIV+I || (p)->op == MOD+I || (p)->op == MUL+I \ ! 677: || (p)->op == DIV+U || (p)->op == MOD+U || (p)->op == MUL+U)) ! 678: ! 679: /* undag - replace multiply-referenced nodes in nodelist by temporaries, return new nodelist */ ! 680: static Node undag(nodelist) Node nodelist; { ! 681: Node p, pred; ! 682: struct node head; ! 683: ! 684: head.link = nodelist; ! 685: for (pred = &head; p = pred->link; ) { ! 686: /* ! 687: * succ is p's successor, ! 688: * pred is p's predecessor, and ! 689: * p->link == pred; ! 690: * undag1(x, p) adds predecessors and maintains p->link == p->link->link. ! 691: */ ! 692: Node succ = p->link; ! 693: p->link = pred; ! 694: if (generic(p->op) == INDIR) { ! 695: assert(p->count >= 1); ! 696: undag1(p, p); ! 697: /* ! 698: * remove p from the node list, ! 699: * setting pred to the last node inserted (if any). ! 700: */ ! 701: pred = p->link; ! 702: pred->link = succ; ! 703: p->link = 0; ! 704: } else if (iscall(p) && p->count >= 1) { ! 705: Node q; ! 706: undag1(p, p); ! 707: /* ! 708: * p->link is p's predecessor, ! 709: * which is the ASGN of p to a temporary. ! 710: */ ! 711: assert(p->link && generic(p->link->op) == ASGN && p->link->kids[1] == p); ! 712: /* ! 713: * remove p from the node list, ! 714: * setting pred to the ASGN node. ! 715: */ ! 716: pred = p->link; ! 717: pred->link = succ; ! 718: /* ! 719: * re-insert p into the node list ! 720: * immediately before its predecessor; ! 721: * this places the CALL node before the ASGN node. ! 722: * / ! 723: for (q = &head; q && q->link != pred; q = q->link) ! 724: ; ! 725: assert(q); ! 726: q->link = p; ! 727: p->link = pred; */ ! 728: p->link = 0; ! 729: } else { ! 730: assert(p->count == 0); ! 731: undag1(p, p); ! 732: /* ! 733: * reestablish p's successor, and ! 734: * advance pred so that pred->link == succ ! 735: */ ! 736: p->link = succ; ! 737: pred = p; ! 738: } ! 739: } ! 740: rmtemps(0, LOCAL); ! 741: return head.link; ! 742: } ! 743: ! 744: /* undag1 - return a reference to the temporary holding value of p, or p */ ! 745: static Node undag1(p, root) Node p, root; { ! 746: Node e; ! 747: ! 748: if (p == 0) ! 749: ; ! 750: else if (p->syms[2]) { ! 751: e = newnode(INDIR + (isunsigned(p->syms[2]->type) ? I : ttob(p->syms[2]->type)), ! 752: newnode(ADDRL+P, 0, 0, p->syms[2]), 0, 0); ! 753: e->count = 1; ! 754: if (--p->count == 1) { ! 755: /* fprint(2, "releasing %s from ", p->syms[2]->name); printnode(p, 2, 1); ! 756: release(p->syms[2]); */ ! 757: p->syms[2] = 0; ! 758: } ! 759: p = e; ! 760: } else if (p->count <= 1 && !iscall(p) ! 761: || p->count == 0 && iscall(p)) { ! 762: p->kids[0] = undag1(p->kids[0], root); ! 763: p->kids[1] = undag1(p->kids[1], root); ! 764: } else if (p->op == ADDRL+P || p->op == ADDRF+P) { ! 765: assert(p != root); ! 766: p = newnode(p->op, 0, 0, p->syms[0]); ! 767: p->count = 1; ! 768: } else if (generic(p->op) == INDIR ! 769: && (p->kids[0]->op == ADDRL+P || p->kids[0]->op == ADDRF+P) ! 770: && p->kids[0]->syms[0]->sclass == REGISTER && p != root) { ! 771: p = newnode(p->op, ! 772: newnode(p->kids[0]->op, 0, 0, p->kids[0]->syms[0]), 0, 0); ! 773: p->count = 1; ! 774: } else if (p->op == INDIR+B) { ! 775: --p->count; ! 776: p = newnode(p->op, p->kids[0], 0, 0); ! 777: p->count = 1; ! 778: p->kids[0] = undag1(p->kids[0], root); ! 779: } else { ! 780: p->syms[2] = temporary(REGISTER, btot(p->op)); ! 781: /* fprint(2, "allocating %s to ", p->syms[2]->name); printnode(p, 2, 1); */ ! 782: if (!p->syms[2]->defined) { ! 783: p->syms[2]->scope = LOCAL; ! 784: p->syms[2]->ref = 1; ! 785: (*IR->local)(p->syms[2]); ! 786: p->syms[2]->defined = 1; ! 787: } ! 788: p->kids[0] = undag1(p->kids[0], root); ! 789: p->kids[1] = undag1(p->kids[1], root); ! 790: e = newnode(ASGN + (isunsigned(p->syms[2]->type) ? I : ttob(p->syms[2]->type)), ! 791: newnode(ADDRL+P, 0, 0, p->syms[2]), p, 0); ! 792: e->syms[0] = intconst(p->syms[2]->type->size); ! 793: e->syms[1] = intconst(p->syms[2]->type->align); ! 794: /* ! 795: * root->link is the root's predecessor; ! 796: * point the root's predecessor to the ASGN, ! 797: * make the ASGN the root's new predecessor, ! 798: * and make root the ASGN's successor. ! 799: */ ! 800: root->link = root->link->link = e; ! 801: e->link = root; ! 802: if (p != root) ! 803: p = undag1(p, root); /* returns reference to the temporary */ ! 804: } ! 805: return p; ! 806: } ! 807: ! 808: /* walk - list tree tp, generate code for current node list, reset node list */ ! 809: void walk(tp, tlab, flab) Tree tp; { ! 810: listnodes(tp, tlab, flab); ! 811: if (nodelist) { ! 812: trash(0); ! 813: code(Gen); ! 814: codelist->u.node = nodelist->link; ! 815: nodelist->link = 0; ! 816: nodelist = 0; ! 817: rmtemps(REGISTER, 0); ! 818: } ! 819: reset(); ! 820: ntree = 0; ! 821: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.