|
|
1.1 root 1: /* C compiler: initialization parsing */
2:
3: #include "c.h"
4:
5: static int curseg; /* current segment */
6: static struct structexp { /* current structure expression: */
7: Symbol var; /* temporary variable */
8: int off; /* offset in var */
9: Tree tree; /* evolving tree */
10: struct structexp *link; /* outer structure expression */
11: } *current;
12: dclproto(static int genasgn,(Tree, struct structexp *));
13: dclproto(static void genchar,(Symbol, struct structexp *));
14: dclproto(static void genspace,(int, struct structexp *));
15: dclproto(static int initarray,(int, Type, int));
16: dclproto(static int initchar,(int, Type));
17: dclproto(static void initend,(int, char []));
18: dclproto(static int initfields,(Field, Field));
19: dclproto(static int initstruct,(int, Type, int));
20: dclproto(static Tree initvalue,(Type));
21:
22: /* defglobal - define a global or static variable in segment seg */
23: void defglobal(p, seg) Symbol p; {
24: swtoseg(p->u.seg = seg);
25: if (p->sclass != STATIC)
26: (*IR->export)(p);
27: if (level == GLOBAL && glevel && IR->stabsym) {
28: (*IR->stabsym)(p);
29: swtoseg(p->u.seg);
30: }
31: (*IR->global)(p);
32: }
33:
34: /* defpointer - initialize a pointer to p or to 0 if p==0 */
35: void defpointer(p) Symbol p; {
36: if (p)
37: (*IR->defaddress)(p);
38: else {
39: Value v;
40: (*IR->defconst)(P, (v.p = 0, v));
41: }
42: }
43:
44: /* doconst - generate a variable for an out-of-line constant */
45: void doconst(p, cl) Symbol p; Generic cl; {
46: if (p->u.c.loc) {
47: defglobal(p->u.c.loc, p->u.c.loc->u.seg ? p->u.c.loc->u.seg : LIT);
48: if (isarray(p->type))
49: (*IR->defstring)(p->type->size, p->u.c.v.p);
50: else
51: (*IR->defconst)(ttob(p->type), p->u.c.v);
52: p->u.c.loc->defined = 1;
53: p->u.c.loc = 0;
54: }
55: }
56:
57: /* genasgn - append tree for assignment of e to evolving structure expression in *sp */
58: static int genasgn(e, sp) Tree e; struct structexp *sp; {
59: Tree p;
60:
61: sp->off = roundup(sp->off, e->type->size);
62: p = simplify(ADD+P, ptr(e->type), lvalue(idnode(sp->var)), constnode(sp->off, inttype));
63: if (isarray(e->type)) {
64: p = tree(ASGN+B, e->type, p, e);
65: p->u.sym = intconst(e->type->size);
66: } else
67: p = asgnnode(ASGN, retype(rvalue(p), e->type), e);
68: sp->tree = tree(RIGHT, voidtype, sp->tree, p);
69: sp->off += e->type->size;
70: return e->type->size;
71: }
72:
73: /* genchar - generate assignment of string constant p to array in *sp */
74: static void genchar(p, sp) Symbol p; struct structexp *sp; {
75: char *s = p->u.c.v.p;
76: int n;
77:
78: for (n = p->type->size; n > 0 && sp->off%inttype->align; n--)
79: genasgn(constnode((*s++)&0377, chartype), sp);
80: if (n > 0) {
81: static Value v;
82: Type ty = array(chartype, p->type->size - (s - p->u.c.v.p), 0);
83: Tree e = tree(ADDRG+P, atop(ty), 0, 0);
84: v.p = stringn(s, ty->size);
85: p = constant(ty, v);
86: if (p->u.c.loc == 0)
87: p->u.c.loc = genident(STATIC, ty, GLOBAL);
88: e->u.sym = p->u.c.loc;
89: e = tree(INDIR+B, ty, e, 0);
90: e->u.sym = intconst(ty->size);
91: genasgn(e, sp);
92: }
93: }
94:
95: /* genconst - generate/check constant expression e; return size */
96: int genconst(e, def) Tree e; {
97: for (;;)
98: switch (generic(e->op)) {
99: case ADDRG:
100: if (def)
101: (*IR->defaddress)(e->u.sym);
102: return e->type->size;
103: case CNST:
104: if (e->op == CNST+P && isarray(e->type)) {
105: e = cvtconst(e);
106: continue;
107: }
108: if (def)
109: (*IR->defconst)(ttob(e->type), e->u.v);
110: return e->type->size;
111: case RIGHT:
112: assert(e->kids[0] || e->kids[1]);
113: if (e->kids[1] && e->kids[0])
114: error("initializer must be constant\n");
115: e = e->kids[1] ? e->kids[1] : e->kids[0];
116: continue;
117: case CVP:
118: if (isarith(e->type))
119: error("cast from `%t' to `%t' is illegal in constant expressions\n",
120: e->kids[0]->type, e->type);
121: /* fall thru */
122: case CVC: case CVI: case CVS: case CVU:
123: case CVD: case CVF:
124: e = e->kids[0];
125: continue;
126: default:
127: error("initializer must be constant\n");
128: if (def)
129: genconst(constnode(0, inttype), def);
130: return inttype->size;
131: }
132: }
133:
134: /* genspace - generate n bytes of space or 0's */
135: static void genspace(n, sp) struct structexp *sp; {
136: if (sp == 0)
137: (*IR->space)(n);
138: else if (n <= inttype->size)
139: for ( ; n > 0; n--)
140: genasgn(constnode(0, chartype), sp);
141: else {
142: Tree e;
143: static Symbol zeros;
144: if (zeros == 0) {
145: zeros = install(stringd(genlabel(1)), &globals, 1);
146: zeros->sclass = STATIC;
147: zeros->type = array(chartype, n, 0);
148: zeros->generated = 1;
149: (*IR->defsymbol)(zeros);
150: }
151: if (n > zeros->type->size)
152: zeros->type = array(chartype, n, 0);
153: e = tree(INDIR+B, zeros->type, idnode(zeros), 0);
154: e->u.sym = intconst(n);
155: genasgn(e, sp);
156: }
157: }
158:
159: /* initarray - initialize array of ty of <= len bytes; if len == 0, go to } */
160: static int initarray(len, ty, lev) Type ty; {
161: int n = 0;
162:
163: do {
164: initializer(ty, lev);
165: n += ty->size;
166: if (len > 0 && n >= len || t != ',')
167: break;
168: t = gettok();
169: } while (t != '}');
170: return n;
171: }
172:
173: /* initchar - initialize array of <= len ty characters; if len == 0, go to } */
174: static int initchar(len, ty) Type ty; {
175: int n = 0;
176: char buf[16], *s = buf;
177:
178: do {
179: if (current) {
180: Type aty;
181: Tree e = expr1(0);
182: if (aty = assign(ty, e))
183: genasgn(cast(e, aty), current);
184: else
185: error("invalid initialization type; found `%t' expected `%s'\n",
186: e->type, ty);
187: ++n;
188: } else {
189: *s++ = initvalue(ty)->u.v.sc;
190: if (++n%inttype->size == 0) {
191: (*IR->defstring)(inttype->size, buf);
192: s = buf;
193: }
194: }
195: if (len > 0 && n >= len || t != ',')
196: break;
197: t = gettok();
198: } while (t != '}');
199: if (s > buf)
200: (*IR->defstring)(s - buf, buf);
201: return n;
202: }
203:
204: /* initend - finish off an initialization at level lev; accepts trailing comma */
205: static void initend(lev, follow) char follow[]; {
206: if (lev == 0 && t == ',')
207: t = gettok();
208: test('}', follow);
209: }
210:
211: /* initfields - initialize <= an unsigned's worth of bit fields in fields p to q */
212: static int initfields(p, q) Field p, q; {
213: unsigned int bits = 0;
214: int i, n = 0;
215:
216: if (current) {
217: Tree e = constnode(0, unsignedtype);
218: do {
219: Tree x = expr1(0);
220: if (fieldsize(p) < 8*p->type->size)
221: x = (*opnode['&'])(BAND, x,
222: constnode(fieldmask(p), unsignedtype));
223: e = (*opnode['|'])(BOR, e,
224: (*opnode[LSHIFT])(LSH, x, constnode(fieldright(p), inttype)));
225: if (p->link == q)
226: break;
227: p = p->link;
228: } while (t == ',' && (t = gettok()));
229: if (q && (n = q->offset - p->offset) < unsignedtype->size)
230: if (IR->little_endian)
231: for (i = 0; i < n; i++) {
232: genasgn(retype(e, chartype), current);
233: e = (*opnode[RSHIFT])(RSH, e, constnode(8, inttype));
234: }
235: else /* a big endian */
236: for (i = n - 1; i >= 0; i--) {
237: Tree x = (*opnode[RSHIFT])(RSH, e,
238: constnode(8*(unsignedtype->size - n + i), inttype));
239: genasgn(retype(x, chartype), current);
240: }
241: else
242: n = genasgn(e, current);
243: return n;
244: }
245: do {
246: i = initvalue(inttype)->u.v.i;
247: if (fieldsize(p) < 8*p->type->size) {
248: if (p->type == inttype && i >= 0 && (i&~(fieldmask(p)>>1)) != 0
249: || p->type == inttype && i < 0 && (i| (fieldmask(p)>>1)) != ~0
250: || p->type == unsignedtype && (i& ~fieldmask(p)))
251: warning("initializer exceeds bit-field width\n");
252: i &= fieldmask(p);
253: }
254: bits |= i<<fieldright(p);
255: if (IR->little_endian) {
256: if (fieldsize(p) + fieldright(p) > n)
257: n = fieldsize(p) + fieldright(p);
258: } else {
259: if (fieldsize(p) + fieldleft(p) > n)
260: n = fieldsize(p) + fieldleft(p);
261: }
262: if (p->link == q)
263: break;
264: p = p->link;
265: } while (t == ',' && (t = gettok()));
266: n = (n + 7)/8;
267: for (i = 0; i < n; i++) {
268: Value v;
269: if (IR->little_endian) {
270: v.uc = bits;
271: bits >>= 8;
272: } else { /* a big endian */
273: v.uc = bits>>(8*(unsignedtype->size - 1));
274: bits <<= 8;
275: }
276: (*IR->defconst)(C, v);
277: }
278: return n;
279: }
280:
281: /* initglobal - a new global identifier p, possibly initialized */
282: void initglobal(p, flag) Symbol p; {
283: Type ty;
284:
285: if (t == '=' || flag) {
286: if (p->sclass == STATIC) {
287: for (ty = p->type; isarray(ty); ty = ty->type)
288: ;
289: defglobal(p, isconst(ty) ? LIT : DATA);
290: } else
291: defglobal(p, DATA);
292: if (t == '=')
293: t = gettok();
294: ty = initializer(p->type, 0);
295: if (isarray(p->type) && p->type->size == 0)
296: p->type = ty;
297: p->defined = 1;
298: if (p->sclass == EXTERN)
299: p->sclass = AUTO;
300: if (level <= GLOBAL)
301: tfree();
302: }
303: }
304:
305: /* initializer - constexpr | { constexpr ( , constexpr )* [ , ] } */
306: Type initializer(ty, lev) Type ty; {
307: int n = 0;
308: Tree e;
309: Type aty;
310: static char follow[] = { IF, CHAR, STATIC, 0 };
311:
312: ty = unqual(ty);
313: if (isscalar(ty)) {
314: if (!current)
315: needconst++;
316: if (t == '{') {
317: t = gettok();
318: e = expr1(0);
319: initend(lev, follow);
320: } else
321: e = expr1(0);
322: e = pointer(e);
323: if (aty = assign(ty, e))
324: e = cast(e, aty);
325: else
326: error("invalid initialization type; found `%t' expected `%t'\n",
327: e->type, ty);
328: if (current)
329: n = genasgn(e, current);
330: else {
331: n = genconst(e, 1);
332: ntree = 0;
333: needconst--;
334: }
335: }
336: if ((isunion(ty) || isstruct(ty)) && ty->size == 0) {
337: static char follow[] = { CHAR, STATIC, 0 };
338: error("cannot initialize undefined `%t'\n", ty);
339: skipto(';', follow);
340: return ty;
341: } else if (isunion(ty)) {
342: if (t == '{') {
343: t = gettok();
344: n = initstruct(ty->u.sym->u.s.flist->type->size, ty, lev + 1);
345: initend(lev, follow);
346: } else {
347: if (lev == 0)
348: error("missing { in initialization of `%t'\n", ty);
349: n = initstruct(ty->u.sym->u.s.flist->type->size, ty, lev + 1);
350: }
351: } else if (isstruct(ty)) {
352: if (t == '{') {
353: t = gettok();
354: n = initstruct(0, ty, lev + 1);
355: test('}', follow);
356: } else if (current) {
357: e = expr1(0);
358: if (assign(ty, e))
359: genasgn(e, current);
360: else
361: error("invalid initialization type; found `%t' expected `%t'\n",
362: e->type, ty);
363: n = ty->size;
364: } else if (lev > 0)
365: n = initstruct(ty->size, ty, lev + 1);
366: else {
367: error("missing { in initialization of `%t'\n", ty);
368: n = initstruct(ty->u.sym->u.s.flist->type->size, ty, lev + 1);
369: }
370: }
371: if (isarray(ty))
372: aty = unqual(ty->type);
373: if (isarray(ty) && ischar(aty)) {
374: if (t == SCON) {
375: if (ty->size > 0 && ty->size == tsym->type->size - 1)
376: tsym->type = array(chartype, ty->size, IR->structmetric.align);
377: n = tsym->type->size;
378: if (current)
379: genchar(tsym, current);
380: else
381: (*IR->defstring)(tsym->type->size, tsym->u.c.v.p);
382: t = gettok();
383: } else if (t == '{') {
384: t = gettok();
385: if (t == SCON) {
386: ty = initializer(ty, lev + 1);
387: initend(lev, follow);
388: return ty;
389: }
390: n = initchar(0, aty);
391: test('}', follow);
392: } else if (lev > 0 && ty->size > 0)
393: n = initchar(ty->size, aty);
394: else { /* eg, char c[] = 0; */
395: error("missing { in initialization of `%t'\n", ty);
396: n = initchar(1, aty);
397: }
398: } else if (isarray(ty)) {
399: if (t == '{') {
400: t = gettok();
401: n = initarray(0, aty, lev + 1);
402: test('}', follow);
403: } else if (lev > 0 && ty->size > 0)
404: n = initarray(ty->size, aty, lev + 1);
405: else {
406: error("missing { in initialization of `%t'\n", ty);
407: n = initarray(aty->size, aty, lev + 1);
408: }
409: }
410: if (ty->size) {
411: if (n > ty->size)
412: error("too many initializers\n");
413: else if (n < ty->size)
414: genspace(ty->size - n, current);
415: } else if (isarray(ty) && ty->type->size > 0)
416: ty = array(ty->type, n/ty->type->size, 0);
417: else
418: ty->size = n;
419: return ty;
420: }
421:
422: /* initstruct - initialize a struct ty of <= len bytes; if len == 0, go to } */
423: static int initstruct(len, ty, lev) Type ty; {
424: int a, n = 0;
425: Field p = ty->u.sym->u.s.flist;
426:
427: do {
428: if (p->offset > n) {
429: genspace(p->offset - n, current);
430: n += p->offset - n;
431: }
432: if (p->lsb) {
433: Field q = p;
434: while (q->link && q->link->offset == p->offset)
435: q = q->link;
436: n += initfields(p, q->link);
437: p = q;
438: } else {
439: initializer(p->type, lev);
440: n += p->type->size;
441: }
442: if (p->link) {
443: p = p->link;
444: a = p->type->align;
445: } else
446: a = ty->align;
447: if (a && n%a) {
448: genspace(a - n%a, current);
449: n = roundup(n, a);
450: }
451: if (len > 0 && n >= len || t != ',')
452: break;
453: t = gettok();
454: } while (t != '}');
455: return n;
456: }
457:
458: /* initvalue - evaluate a constant expression for a value of integer type ty */
459: static Tree initvalue(ty) Type ty; {
460: Type aty;
461: Tree e;
462:
463: needconst++;
464: e = expr1(0);
465: if (aty = assign(ty, e))
466: e = cast(e, aty);
467: else {
468: error("invalid initialization type; found `%t' expected `%s'\n",
469: e->type, ty);
470: e = constnode(0, ty);
471: }
472: needconst--;
473: if (generic(e->op) != CNST) {
474: error("initializer must be constant\n");
475: e = constnode(0, ty);
476: }
477: return e;
478: }
479:
480: /* structexp - in-line structure expression '{' expr ( , expr )* [ , ] '}' */
481: Tree structexp(ty, t1) Type ty; Symbol t1; {
482: struct structexp e;
483:
484: e.var = t1;
485: e.off = 0;
486: e.tree = 0;
487: e.link = current;
488: current = &e;
489: initializer(ty, 0);
490: current = e.link;
491: return e.tree;
492: }
493:
494: /* swtoseg - switch to segment seg, if necessary */
495: void swtoseg(seg) {
496: if (curseg != seg)
497: (*IR->segment)(seg);
498: curseg = seg;
499: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.