|
|
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.