Annotation of researchv10no/cmd/lcc/c/init.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.