URI:
       init.c - scc - simple c99 compiler
  HTML git clone git://git.simple-cc.org/scc
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       init.c (10494B)
       ---
            1 #include <assert.h>
            2 #include <stdint.h>
            3 #include <stdlib.h>
            4 #include <string.h>
            5 
            6 #include <scc/cstd.h>
            7 #include <scc/scc.h>
            8 #include "cc1.h"
            9 
           10 #define NOLIST 0
           11 #define INLIST 1
           12 
           13 
           14 typedef struct init Init;
           15 
           16 struct designator {
           17         long long pos;
           18         Node *expr;
           19         struct designator *next;
           20 };
           21 
           22 struct init {
           23         unsigned long long pos;
           24         unsigned long long max;
           25         struct designator *tail;
           26         struct designator *head;
           27 };
           28 
           29 int disstring;
           30 
           31 static long long
           32 arydesig(Type *tp, Init *ip)
           33 {
           34 
           35         long long npos;
           36         Node *np;
           37 
           38         if (tp->op != ARY)
           39                 errorp("array index in non-array initializer");
           40 
           41         next();
           42         if ((np = iconstexpr()) == NULL) {
           43                 errorp("array index in initializer not of integer type");
           44                 npos = 0;
           45         } else {
           46                 npos = np->sym->u.i;
           47         }
           48 
           49         if (npos < 0 || (tp->prop & TDEFINED) && npos >= tp->n.elem) {
           50                 errorp("array index in initializer exceeds array bounds");
           51                 npos = 0;
           52         }
           53         freetree(np);
           54         expect(']');
           55         return npos;
           56 }
           57 
           58 static long long
           59 fielddesig(Type *tp, Init *ip)
           60 {
           61         int ons;
           62         Symbol *sym, **p;
           63 
           64         if (!(tp->prop & TAGGREG))
           65                 errorp("field name not in record or union initializer");
           66         ons = namespace;
           67         namespace = tp->ns;
           68         next();
           69         namespace = ons;
           70         if (yytoken != IDEN)
           71                 unexpected();
           72         sym = yylval.sym;
           73         next();
           74         if ((sym->flags & SDECLARED) == 0) {
           75                 errorp("unknown field '%s' specified in initializer",
           76                       sym->name);
           77                 return -1;
           78         }
           79         for (p = tp->p.fields; *p != sym; ++p)
           80                 ;
           81         return p - tp->p.fields;
           82 }
           83 
           84 static Init *
           85 init(Init *ip)
           86 {
           87         ip->tail = ip->head = NULL;
           88         ip->pos = ip->max = 0;
           89         return ip;
           90 }
           91 
           92 static Node *
           93 str2ary(Type *tp)
           94 {
           95         char *s;
           96         Rune *rs;
           97         Node *np;
           98         Type *btp = tp->type;
           99         Symbol *str, *sym;
          100         long long i, olen, len;
          101 
          102         disstring = 1;
          103         np = assign();
          104         disstring = 0;
          105         str = np->left->sym;
          106 
          107         len = tp->n.elem;
          108         olen = str->type->n.elem-1;
          109         if (!(tp->prop & TDEFINED)) {
          110                 len = tp->n.elem = olen+1;
          111                 deftype(tp);
          112         } else if (len < olen) {
          113                 warn("initializer-string for array of chars is too long");
          114         }
          115 
          116         if (str->flags & SSTRING) {
          117                 if (btp != chartype && btp != uchartype && btp != schartype)
          118                         goto wrong;
          119                 s = str->u.s;
          120                 sym = newstring(NULL, len);
          121         } else {
          122                 if (btp->size != wchartype->size)
          123                         goto wrong;
          124                 rs = str->u.rs;
          125                 sym = newrstring(NULL, len);
          126         }
          127 
          128         for (i = 0; i < len; i++) {
          129                 if (str->flags & SSTRING)
          130                         sym->u.s[i] = (i < olen) ? *s++ : '\0';
          131                 else
          132                         sym->u.rs[i] = (i < olen) ? *rs++ : L'\0';
          133         }
          134 
          135         assert(np->op == OADDR);
          136         np->left->sym = sym;
          137         np->left->type = sym->type;
          138         np->sym = sym;
          139         np->type = sym->type;
          140 
          141         return np;
          142 
          143 wrong:
          144         errorp("array of inappropriate type initialized from string constant");
          145         return constnode(zero);
          146 }
          147 
          148 static Node *initlist(Type *);
          149 
          150 static Node *
          151 initialize(Type *tp, int inlist)
          152 {
          153         Node *np;
          154         Symbol *sym;
          155 
          156         if (tp->op == ARY && yytoken == STRING)
          157                 return str2ary(tp);
          158 
          159         if (yytoken == '{' || inlist && (tp->op == STRUCT || tp->op == ARY))
          160                 return initlist(tp);
          161 
          162         np = assign();
          163         if (!eqtype(tp, np->type, EQUIV)) {
          164                 np = convert(decay(np), tp, 0);
          165                 if (!np) {
          166                         errorp("incorrect initializer");
          167                         return constnode(zero);
          168                 }
          169         }
          170 
          171         return simplify(np);
          172 }
          173 
          174 static Node *
          175 mkcompound(Init *ip, Type *tp)
          176 {
          177         Node **v, **p, *np;
          178         size_t n;
          179         struct designator *dp, *next;
          180         Symbol *sym;
          181         int isconst = 1;
          182 
          183         if (tp->op == UNION) {
          184                 np = NULL;
          185                 v = xmalloc(sizeof(*v));
          186                 for (dp = ip->head; dp; dp = next) {
          187                         freetree(np);
          188                         np = dp->expr;
          189                         next = dp->next;
          190                         free(dp);
          191                 }
          192                 if ((np->flags & NCONST) == 0)
          193                         isconst = 0;
          194                 *v = np;
          195         } else {
          196                 n = (tp->prop&TDEFINED) ? tp->n.elem : ip->max;
          197                 if (n == 0) {
          198                         v = NULL;
          199                 } else if (n > SIZE_MAX / sizeof(*v)) {
          200                         errorp("compound literal too big");
          201                         return constnode(zero);
          202                 } else {
          203                         n *= sizeof(*v);
          204                         v = memset(xmalloc(n), 0, n);
          205 
          206                         for (dp = ip->head; dp; dp = next) {
          207                                 p = &v[dp->pos];
          208                                 freetree(*p);
          209                                 np = dp->expr;
          210                                 *p = np;
          211                                 if ((np->flags & NCONST) == 0)
          212                                         isconst = 0;
          213                                 next = dp->next;
          214                                 free(dp);
          215                         }
          216                 }
          217         }
          218 
          219         sym = newsym(NS_IDEN, NULL);
          220         sym->u.init = v;
          221         sym->type = tp;
          222         sym->flags |= SINITLST;
          223 
          224         return (isconst ? constnode : varnode)(sym);
          225 }
          226 
          227 static void
          228 newdesig(Init *ip, Node *np)
          229 {
          230         struct designator *dp;
          231 
          232         dp = xmalloc(sizeof(*dp));
          233         dp->pos = ip->pos;
          234         dp->expr = np;
          235         dp->next = NULL;
          236 
          237         if (ip->head == NULL) {
          238                 ip->head = ip->tail = dp;
          239         } else {
          240                 ip->tail->next = dp;
          241                 ip->tail = dp;
          242         }
          243 
          244         if (ip->pos+1 > ip->max)
          245                 ip->max = ip->pos+1;
          246 }
          247 
          248 static Node *
          249 initlist_helper(Type *tp)
          250 {
          251         Init in;
          252         Node *np;
          253         Type *curtp, *btp;
          254         int braces, scalar, toomany, outbound;
          255         long long nelem = tp->n.elem;
          256 
          257         braces = scalar = toomany = 0;
          258 
          259         if (accept('{'))
          260                 braces = 1;
          261 
          262         if (yytoken == STRING && tp->op == ARY) {
          263                 btp = tp->type;
          264                 if (btp == chartype || btp == uchartype || btp == schartype) {
          265                         np = str2ary(tp);
          266                         if (braces)
          267                                 expect('}');
          268                         return np;
          269                 }
          270         }
          271 
          272         init(&in);
          273         for (;;) {
          274                 curtp = inttype;
          275                 switch (yytoken) {
          276                 case '[':
          277                         in.pos = arydesig(tp, &in);
          278                         curtp = tp->type;
          279                         goto desig_list;
          280                 case '.':
          281                         in.pos = fielddesig(tp, &in);
          282                         if (in.pos >= 0 && in.pos < nelem)
          283                                 curtp = tp->p.fields[in.pos]->type;
          284                 desig_list:
          285                         if (yytoken == '[' || yytoken == '.') {
          286                                 np = initlist(curtp);
          287                                 goto new_desig;
          288                         }
          289                         expect('=');
          290                 default:
          291                         outbound = 0;
          292 
          293                         switch (tp->op) {
          294                         case ARY:
          295                                 curtp = tp->type;
          296                                 if (!(tp->prop & TDEFINED) || in.pos < tp->n.elem)
          297                                         break;
          298                                 if (!toomany)
          299                                         warn("excess elements in array initializer");
          300                                 toomany = 1;
          301                                 outbound = 1;
          302                                 break;
          303                         case UNION:
          304                         case STRUCT:
          305                                 if (in.pos < nelem) {
          306                                         curtp = tp->p.fields[in.pos]->type;
          307                                         break;
          308                                 }
          309                                 if (!toomany)
          310                                         warn("excess elements in struct initializer");
          311                                 toomany = 1;
          312                                 outbound = 1;
          313                                 break;
          314                         default:
          315                                 curtp = tp;
          316                                 if (!scalar)
          317                                         warn("braces around scalar initializer");
          318                                 scalar = 1;
          319                                 if (in.pos == 0)
          320                                         break;
          321                                 if (!toomany)
          322                                         warn("excess elements in scalar initializer");
          323                                 toomany = 1;
          324                                 outbound = 1;
          325                                 break;
          326                         }
          327                         np = initialize(curtp, INLIST);
          328                         if (outbound) {
          329                                 freetree(np);
          330                                 np = NULL;
          331                         }
          332                 }
          333 
          334 new_desig:
          335                 if (np)
          336                         newdesig(&in, np);
          337                 if (++in.pos == 0)
          338                         errorp("compound literal too big");
          339                 if (nelem == in.pos && !braces)
          340                         break;
          341                 if (!accept(','))
          342                         break;
          343                 if (yytoken == '}')
          344                         break;
          345         }
          346 
          347         if (braces)
          348                 expect('}');
          349 
          350 
          351         if (tp->op == ARY && !(tp->prop & TDEFINED)) {
          352                 tp->n.elem = in.max;
          353                 deftype(tp);
          354         }
          355         if (in.max == 0) {
          356                 errorp("empty braced initializer");
          357                 return constnode(zero);
          358         }
          359 
          360         return mkcompound(&in, tp);
          361 }
          362 
          363 static Node *
          364 initlist(Type *tp)
          365 {
          366         Node *np;
          367         static int depth;
          368 
          369         if (depth == NR_SUBTYPE)
          370                 error("too many nested initializers");
          371 
          372         ++depth;
          373         np = initlist_helper(tp);
          374         --depth;
          375 
          376         return np;
          377 }
          378 
          379 static void
          380 autofield(Symbol *sym, Node *np, Type *tp, unsigned long long *addr)
          381 {
          382         int align;
          383         Node *aux;
          384         unsigned long long na;
          385 
          386         align = tp->align - 1;
          387         na = *addr;
          388         na = (na + align) & ~align;
          389         *addr = na;
          390 
          391         aux = node(OADDR, pvoidtype, varnode(sym), NULL);
          392         aux = node(OADD, pvoidtype, aux, addrnode(na));
          393         aux = node(OPTR, tp, aux, NULL);
          394         aux = node(OASSIGN, tp, aux, np);
          395 
          396         emit(OEXPR, aux);
          397         *addr += tp->size;
          398 }
          399 
          400 static void
          401 autocomp(Symbol *sym, Node *np, Type *tp, unsigned long long *addr)
          402 {
          403         Type *p;
          404         Node *aux;
          405         Symbol *init;
          406         unsigned long long n;
          407 
          408         if (!np) {
          409                 init = NULL;
          410         } else {
          411                 if (!np->sym)
          412                         goto expression;
          413                 init = np->sym;
          414                 if ((init->flags & SINITLST) == 0)
          415                         goto expression;
          416         }
          417 
          418         switch (tp->op) {
          419         case PTR:
          420         case INT:
          421         case ENUM:
          422                 aux = init ? *init->u.init : zeronode(tp);
          423                 autofield(sym, aux, aux->type, addr);
          424                 break;
          425         case UNION:
          426                 aux = (init) ? init->u.init[0] : NULL;
          427                 p = (aux) ? aux->type : tp->p.fields[0]->type;
          428                 autocomp(sym, aux, p, addr);
          429                 break;
          430         case STRUCT:
          431         case ARY:
          432                 if (np && (np->flags & NCONST) != 0) {
          433                         Symbol *hidden = newsym(NS_IDEN, NULL);
          434                         hidden->id = newid();
          435                         hidden->type = init->type;
          436                         hidden->flags |= SLOCAL | SHASINIT;
          437                         emit(ODECL, hidden);
          438                         emit(OINIT, np);
          439                         np = varnode(hidden);
          440                         goto expression;
          441                 }
          442                 for (n = 0; n < tp->n.elem; ++n) {
          443                         aux = (init) ? init->u.init[n] : NULL;
          444                         p = (tp->op == ARY) ? tp->type : tp->p.fields[n]->type;
          445                         autocomp(sym, aux, p, addr);
          446                 }
          447                 break;
          448         default:
          449                 abort();
          450         }
          451 
          452         if (init) {
          453                 free(init->u.init);
          454                 init->u.init = NULL;
          455         }
          456         freetree(np);
          457         return;
          458 
          459 expression:
          460         autofield(sym, np, tp, addr);
          461 }
          462 
          463 static void
          464 emitstrings(Node *np)
          465 {
          466         unsigned f;
          467         Symbol *sym;
          468         long long i, n;
          469 
          470         if (!np)
          471                 return;
          472 
          473         if (np->op == OSYM) {
          474                 sym = np->sym;
          475                 f = sym->flags & (SSTRING|SRSTRING|SEMITTED|SINITLST);
          476                 if (f == SSTRING || f == SRSTRING) {
          477                         sym->flags |= SHASINIT;
          478                         emit(ODECL, sym);
          479                         emit(OINIT, constnode(sym));
          480                 } else if (f == SINITLST)  {
          481                         n =  (np->type->op == UNION) ? 1 : np->type->n.elem;
          482                         for (i = 0; i < n; ++i)
          483                                 emitstrings(sym->u.init[i]);
          484                 }
          485         }
          486 
          487         emitstrings(np->left);
          488         emitstrings(np->right);
          489 }
          490 
          491 static void
          492 autoinit(Symbol *sym, Node *np)
          493 {
          494         unsigned long long a;
          495         Symbol *hidden;
          496         Type *tp = np->type;
          497 
          498 repeat:
          499         switch (tp->op) {
          500         case UNION:
          501                 np = np->sym->u.init[0];
          502                 tp = np->type;
          503                 goto repeat;
          504         case ARY:
          505                 if (np->op == OADDR && np->sym->flags & SSTRING)
          506                         goto hidden_data;
          507         case STRUCT:
          508                 if (np->op != OSYM || (np->sym->flags & SINITLST) == 0)
          509                         goto expr;
          510         hidden_data:
          511                 if (!(np->flags & NCONST)) {
          512                         a = 0;
          513                         emitstrings(np);
          514                         emit(ODECL, sym);
          515                         autocomp(sym, np, np->type, &a);
          516                         break;
          517                 }
          518                 hidden = newsym(NS_IDEN, NULL);
          519                 hidden->id = newid();
          520                 hidden->type = sym->type;
          521                 hidden->flags |= SLOCAL | SHASINIT;
          522                 emit(ODECL, hidden);
          523                 emit(OINIT, np);
          524                 np = varnode(hidden);
          525         default:
          526         expr:
          527                 emitstrings(np);
          528                 emit(ODECL, sym);
          529                 np = node(OASSIGN, tp, varnode(sym), np);
          530                 emit(OEXPR, np);
          531                 break;
          532         }
          533 }
          534 
          535 void
          536 initializer(Symbol *sym)
          537 {
          538         Node *np;
          539         Type *tp = sym->type;
          540         int flags = sym->flags;
          541 
          542         if (tp->op == FTN) {
          543                 errorp("function '%s' initialized like a variable",
          544                        sym->name);
          545                 tp = inttype;
          546         }
          547         np = initialize(tp, NOLIST);
          548 
          549         if (flags & SDEFINED) {
          550                 errorp("redeclaration of '%s'", sym->name);
          551         } else if ((flags & (SGLOBAL|SLOCAL|SPRIVATE)) != 0) {
          552                 if ((np->flags & NCONST) == 0) {
          553                         errorp("initializer element is not constant");
          554                         return;
          555                 }
          556                 sym->flags |= SHASINIT;
          557                 sym->flags &= ~SEMITTED;
          558                 emit(ODECL, sym);
          559                 emit(OINIT, np);
          560                 sym->flags |= SDEFINED;
          561         } else if ((flags & (SEXTERN|STYPEDEF)) != 0) {
          562                 errorp("'%s' has both '%s' and initializer",
          563                        sym->name, (flags&SEXTERN) ? "extern" : "typedef");
          564         } else {
          565                 autoinit(sym, np);
          566         }
          567 }