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