|
|
1.1 ! root 1: /* C compiler: tree management */ ! 2: ! 3: #include "c.h" ! 4: ! 5: static struct arena first[] = { ! 6: 0, 0, 0, &first[0], 0, ! 7: 0, 0, 0, &first[1], 0, ! 8: }; ! 9: Arena permanent = &first[0]; /* permanent storage */ ! 10: Arena transient = &first[1]; /* transient storage; released at function end */ ! 11: static Arena freearenas; /* list of free arenas */ ! 12: ! 13: /* allocate - allocate n bytes in arena **p, adding a new arena if necessary */ ! 14: char *allocate(n, p) Arena *p; { ! 15: Arena ap = *p; ! 16: ! 17: while (ap->avail + n > ap->limit) ! 18: if (ap->next) { /* move to next arena */ ! 19: ap = ap->next; ! 20: ap->avail = (char *)ap + roundup(sizeof *ap, sizeof (double)); ! 21: } else if (ap->next = freearenas) { ! 22: freearenas = freearenas->next; ! 23: ap = ap->next; ! 24: ap->avail = (char *)ap + roundup(sizeof *ap, sizeof (double)); ! 25: ap->first = (*p)->first; ! 26: ap->next = 0; ! 27: } else { /* allocate a new arena */ ! 28: int m = n + MEMINCR*1024 + roundup(sizeof *ap, sizeof (double)); ! 29: ap->next = (Arena) malloc(m); ! 30: assert(ap->next && (int)ap->next >= 0); ! 31: if ((char *)ap->next == ap->limit) /* extend previous arena? */ ! 32: ap->limit = (char *)ap->next + m; ! 33: else { /* link to a new arena */ ! 34: ap = ap->next; ! 35: ap->limit = (char *)ap + m; ! 36: ap->avail = (char *)ap + roundup(sizeof *ap, sizeof (double)); ! 37: } ! 38: ap->first = (*p)->first; ! 39: ap->next = 0; ! 40: } ! 41: *p = ap; ! 42: ap->avail += n; ! 43: return ap->avail - n; ! 44: } ! 45: ! 46: /* deallocate - release all space in arena *p, except the first arena; reset *p */ ! 47: void deallocate(p) Arena *p; { ! 48: Arena first = (*p)->first; ! 49: ! 50: (*p)->next = freearenas; ! 51: freearenas = first->next; ! 52: first->next = 0; ! 53: *p = first; ! 54: } ! 55: ! 56: ! 57: /* cvtconst - convert a constant tree into tree for a global variable */ ! 58: Tree cvtconst(p) Tree p; { ! 59: Symbol q = constant(p->type, p->u.v); ! 60: Tree e; ! 61: ! 62: if (q->u.c.loc == 0) ! 63: q->u.c.loc = genident(STATIC, p->type, GLOBAL); ! 64: if (isarray(p->type)) { ! 65: e = tree(ADDRG+P, atop(p->type), 0, 0); ! 66: e->u.sym = q->u.c.loc; ! 67: } else ! 68: e = idnode(q->u.c.loc); ! 69: return e; ! 70: } ! 71: ! 72: /* hascall - does tree p contain a CALL? */ ! 73: int hascall(p) Tree p; { ! 74: if (p == 0) ! 75: return 0; ! 76: if (generic(p->op) == CALL || (IR->mulops_are_calls && ! 77: (p->op == DIV+I || p->op == MOD+I || p->op == MUL+I ! 78: || p->op == DIV+U || p->op == MOD+U || p->op == MUL+U))) ! 79: return 1; ! 80: return hascall(p->kids[0]) || hascall(p->kids[1]); ! 81: } ! 82: ! 83: /* opname - return string for operator op */ ! 84: char *opname(op) { ! 85: static char *opnames[] = { ! 86: "", ! 87: #define NEEDNAMES ! 88: #include "ops.h" ! 89: }; ! 90: char *name; ! 91: ! 92: switch (op) { ! 93: case AND: return "AND"; ! 94: case NOT: return "NOT"; ! 95: case OR: return "OR"; ! 96: case COND: return "COND"; ! 97: case RIGHT:return "RIGHT"; ! 98: case FIELD:return "FIELD"; ! 99: } ! 100: if (opindex(op) > 0 && opindex(op) < sizeof opnames/sizeof opnames[0]) ! 101: name = opnames[opindex(op)]; ! 102: else ! 103: name = stringd(opindex(op)); ! 104: if (optype(op) > 0 && optype(op) < sizeof (TYPENAMES) - 1) ! 105: return stringf("%s%c", name, TYPENAMES[optype(op)]); ! 106: else ! 107: return stringf("%s+%d", name, optype(op)); ! 108: } ! 109: ! 110: /* tree - allocate and initialize a tree node */ ! 111: int ntree = 0; /* next free tree in trees */ ! 112: static struct tree trees[100]; /* default allocation area for trees */ ! 113: ! 114: Tree tree(op, type, left, right) Type type; Tree left, right; { ! 115: register Tree p; ! 116: ! 117: if (ntree < sizeof trees/sizeof trees[0]) ! 118: p = &trees[ntree++]; ! 119: else ! 120: p = (Tree)talloc(sizeof *p); ! 121: BZERO(p, struct tree); ! 122: p->op = op; ! 123: p->type = type; ! 124: p->kids[0] = left; ! 125: p->kids[1] = right; ! 126: return p; ! 127: } ! 128: ! 129: /* retype - return a copy of tree p with type field = ty */ ! 130: Tree retype(p, ty) Tree p; Type ty;{ ! 131: Tree q; ! 132: ! 133: if (p->type == ty) ! 134: return p; ! 135: q = tree(p->op, ty, p->kids[0], p->kids[1]); ! 136: q->u = p->u; ! 137: return q; ! 138: } ! 139: ! 140: /* root - tree p will be a root; remove unnecessary temporaries */ ! 141: Tree root(p) Tree p; { ! 142: if (p == 0) ! 143: return p; ! 144: switch (generic(p->op)) { ! 145: case COND: { ! 146: Tree q = p->kids[1]; ! 147: assert(q && q->op == RIGHT); ! 148: if (p->u.sym && q->kids[0] && generic(q->kids[0]->op) == ASGN) ! 149: q->kids[0] = root(q->kids[0]->kids[1]); ! 150: else ! 151: q->kids[0] = root(q->kids[0]); ! 152: if (p->u.sym && q->kids[1] && generic(q->kids[1]->op) == ASGN) ! 153: q->kids[1] = root(q->kids[1]->kids[1]); ! 154: else ! 155: q->kids[1] = root(q->kids[1]); ! 156: if (p->u.sym) ! 157: release(p->u.sym); ! 158: p->u.sym = 0; ! 159: if (q->kids[0] == 0 && q->kids[1] == 0) ! 160: p = root(p->kids[0]); ! 161: } ! 162: break; ! 163: case AND: case OR: ! 164: if ((p->kids[1] = root(p->kids[1])) == 0) ! 165: p = root(p->kids[0]); ! 166: break; ! 167: case NOT: ! 168: return root(p->kids[0]); ! 169: case RIGHT: ! 170: if (p->kids[1] == 0) ! 171: return root(p->kids[0]); ! 172: if (p->kids[0] && p->kids[0]->op == CALL+B ! 173: && p->kids[1] && p->kids[1]->op == INDIR+B) ! 174: /* avoid premature release of the CALL+B temporary */ ! 175: return p->kids[0]; ! 176: if (p->kids[0] && p->kids[0]->op == RIGHT ! 177: && p->kids[1] == p->kids[0]->kids[0]) ! 178: /* de-construct e++ construction */ ! 179: return p->kids[0]->kids[1]; ! 180: /* fall thru */ ! 181: case EQ: case NE: case GT: case GE: case LE: case LT: ! 182: case ADD: case SUB: case MUL: case DIV: case MOD: ! 183: case LSH: case RSH: case BAND: case BOR: case BXOR: ! 184: p = tree(RIGHT, p->type, root(p->kids[0]), root(p->kids[1])); ! 185: return p->kids[0] || p->kids[1] ? p : 0; ! 186: case INDIR: ! 187: if (p->type->size == 0 && unqual(p->type) != voidtype) ! 188: warning("reference to `%t' elided\n", p->type); ! 189: if (isptr(p->kids[0]->type) && isvolatile(p->kids[0]->type->type)) ! 190: warning("reference to `volatile %t' elided\n", p->type); ! 191: /* fall thru */ ! 192: case CVI: case CVF: case CVD: case CVU: case CVC: case CVS: case CVP: ! 193: case NEG: case BCOM: case FIELD: ! 194: return root(p->kids[0]); ! 195: case ADDRL: ! 196: if (p->u.sym->temporary) ! 197: release(p->u.sym); ! 198: /* fall thru */ ! 199: case ADDRG: case ADDRF: case CNST: ! 200: return 0; ! 201: case ARG: case ASGN: case CALL: case JUMP: case LABEL: ! 202: break; ! 203: default: assert(0); ! 204: } ! 205: return p; ! 206: } ! 207: ! 208: /* texpr - parse an expression via f(tok), allocating trees in transient area */ ! 209: Tree texpr(f, tok) dclproto(Tree (*f),(int)); { ! 210: int n = ntree; ! 211: Tree p; ! 212: ! 213: ntree = sizeof trees/sizeof trees[0]; ! 214: p = (*f)(tok); ! 215: ntree = n; ! 216: return p; ! 217: } ! 218: ! 219: /* tfree - release space in all transient arenas and default tree area */ ! 220: void tfree() { ! 221: if (glevel < 3 && !xref) ! 222: deallocate(&transient); ! 223: ntree = 0; ! 224: } ! 225: ! 226: static int nid = 1; /* identifies trees & nodes in debugging output */ ! 227: static struct nodeid { ! 228: int printed; ! 229: Tree node; ! 230: } ids[500]; /* if ids[i].node == p, then p's id is i */ ! 231: ! 232: dclproto(static void printtree1,(Tree, int, int)); ! 233: ! 234: /* nodeid - lookup id for tree or node p */ ! 235: int nodeid(p) Tree p; { ! 236: int i = 1; ! 237: ! 238: ids[nid].node = p; ! 239: while (ids[i].node != p) ! 240: i++; ! 241: if (i == nid) ! 242: ids[nid++].printed = 0; ! 243: return i; ! 244: } ! 245: ! 246: /* printed - return pointer to ids[id].printed */ ! 247: int *printed(id) { ! 248: if (id) ! 249: return &ids[id].printed; ! 250: nid = 1; ! 251: return 0; ! 252: } ! 253: ! 254: /* printtree - print tree p on fd */ ! 255: void printtree(p, fd) Tree p; { ! 256: (void)printed(0); ! 257: printtree1(p, fd, 1); ! 258: } ! 259: ! 260: /* printtree1 - recursively print tree p */ ! 261: static void printtree1(p, fd, lev) Tree p; { ! 262: int i; ! 263: static char blanks[] = " "; ! 264: ! 265: if (p == 0 || *printed(i = nodeid(p))) ! 266: return; ! 267: fprint(fd, "#%d%s%s", i, &" "[i < 10 ? 0 : i < 100 ? 1 : 2], ! 268: &blanks[sizeof blanks - lev]); ! 269: fprint(fd, "%s %t", opname(p->op), p->type); ! 270: *printed(i) = 1; ! 271: for (i = 0; i < sizeof p->kids/sizeof p->kids[0]; i++) ! 272: if (p->kids[i]) ! 273: fprint(fd, " #%d", nodeid(p->kids[i])); ! 274: if (generic(p->op) == FIELD && p->u.field) ! 275: fprint(fd, " %s %d..%d", p->u.field->name, ! 276: fieldsize(p->u.field) + fieldright(p->u.field), fieldright(p->u.field)); ! 277: else if (generic(p->op) == CNST) ! 278: fprint(fd, " %s", vtoa(p->type, p->u.v)); ! 279: else if (p->u.sym) ! 280: fprint(fd, " %s", p->u.sym->name); ! 281: if (p->node) ! 282: fprint(fd, " node=0x%x", p->node); ! 283: fprint(fd, "\n"); ! 284: for (i = 0; i < sizeof p->kids/sizeof p->kids[0]; i++) ! 285: printtree1(p->kids[i], fd, lev + 1); ! 286: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.