Annotation of researchv10no/cmd/lcc/c/init.c, revision 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.