Home
       init.c - scc - simple c99 compiler
  HTML git clone git://git.simple-cc.org/scc
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
   DIR README
   DIR LICENSE
       ---
       init.c (7136B)
       ---
            1 #include <stdint.h>
            2 #include <stdlib.h>
            3 #include <string.h>
            4 
            5 #include <scc/cstd.h>
            6 #include <scc/scc.h>
            7 #include "cc1.h"
            8 
            9 
           10 typedef struct init Init;
           11 
           12 struct designator {
           13         TINT pos;
           14         Node *expr;
           15         struct designator *next;
           16 };
           17 
           18 struct init {
           19         TUINT pos;
           20         TUINT max;
           21         struct designator *tail;
           22         struct designator *head;
           23 };
           24 
           25 static TINT
           26 arydesig(Type *tp, Init *ip)
           27 {
           28         TINT npos;
           29         Node *np;
           30 
           31         if (tp->op != ARY)
           32                 errorp("array index in non-array initializer");
           33         next();
           34         np = constexpr();
           35         npos = np->sym->u.i;
           36         if (npos < 0 || (tp->prop & TDEFINED) && npos >= tp->n.elem) {
           37                 errorp("array index in initializer exceeds array bounds");
           38                 npos = 0;
           39         }
           40         freetree(np);
           41         expect(']');
           42         return npos;
           43 }
           44 
           45 static TINT
           46 fielddesig(Type *tp, Init *ip)
           47 {
           48         int ons;
           49         Symbol *sym, **p;
           50 
           51         if (!(tp->prop & TAGGREG))
           52                 errorp("field name not in record or union initializer");
           53         ons = namespace;
           54         namespace = tp->ns;
           55         next();
           56         namespace = ons;
           57         if (yytoken != IDEN)
           58                 unexpected();
           59         sym = yylval.sym;
           60         next();
           61         if ((sym->flags & SDECLARED) == 0) {
           62                 errorp("unknown field '%s' specified in initializer",
           63                       sym->name);
           64                 return -1;
           65         }
           66         for (p = tp->p.fields; *p != sym; ++p)
           67                 ;
           68         return p - tp->p.fields;
           69 }
           70 
           71 static Init *
           72 init(Init *ip)
           73 {
           74         ip->tail = ip->head = NULL;
           75         ip->pos = ip->max = 0;
           76         return ip;
           77 }
           78 
           79 static Node *
           80 str2ary(Type *tp)
           81 {
           82         Node *np;
           83         Type *btp = tp->type;
           84         Symbol *sym;
           85         size_t len;
           86         char *s;
           87 
           88         np = assign();
           89         sym = np->left->sym;
           90         if (btp != chartype && btp != uchartype && btp != schartype) {
           91                 errorp("array of inappropriate type initialized from string constant");
           92                 return constnode(zero);
           93         }
           94 
           95         len = sym->type->n.elem-1;
           96         if (!(tp->prop & TDEFINED)) {
           97                 tp->n.elem = len+1;
           98                 deftype(tp);
           99         } else if (tp->n.elem < len) {
          100                 warn("initializer-string for array of chars is too long");
          101         }
          102 
          103         len = tp->n.elem;
          104         s = sym->u.s;
          105         sym = newstring(NULL, len);
          106         strncpy(sym->u.s, s, len);
          107         np->sym = sym;
          108         np->type = sym->type;
          109 
          110         return np;
          111 }
          112 
          113 static Node *
          114 initialize(Type *tp)
          115 {
          116         Node *np;
          117         Symbol *sym;
          118 
          119         if (tp->op == ARY && yytoken == STRING)
          120                 return str2ary(tp);
          121 
          122         if (yytoken == '{' || tp->op == STRUCT || tp->op == ARY)
          123                 return initlist(tp);
          124 
          125         np = assign();
          126         if (!eqtype(tp, np->type, EQUIV)) {
          127                 np = convert(decay(np), tp, 0);
          128                 if (!np) {
          129                         errorp("incorrect initializer");
          130                         return constnode(zero);
          131                 }
          132         }
          133 
          134         return simplify(np);
          135 }
          136 
          137 static Node *
          138 mkcompound(Init *ip, Type *tp)
          139 {
          140         Node **v, **p, *np;
          141         size_t n;
          142         struct designator *dp, *next;
          143         Symbol *sym;
          144         int isconst = 1;
          145 
          146         if (tp->op == UNION) {
          147                 np = NULL;
          148                 v = xmalloc(sizeof(*v));
          149                 for (dp = ip->head; dp; dp = next) {
          150                         freetree(np);
          151                         np = dp->expr;
          152                         next = dp->next;
          153                         free(dp);
          154                 }
          155                 if ((np->flags & NCONST) == 0)
          156                         isconst = 0;
          157                 *v = np;
          158         } else {
          159                 n = (tp->prop&TDEFINED) ? tp->n.elem : ip->max;
          160                 if (n == 0) {
          161                         v = NULL;
          162                 } else if (n > SIZE_MAX / sizeof(*v)) {
          163                         errorp("compound literal too big");
          164                         return constnode(zero);
          165                 } else {
          166                         n *= sizeof(*v);
          167                         v = memset(xmalloc(n), 0, n);
          168 
          169                         for (dp = ip->head; dp; dp = next) {
          170                                 p = &v[dp->pos];
          171                                 freetree(*p);
          172                                 np = dp->expr;
          173                                 *p = np;
          174                                 if ((np->flags & NCONST) == 0)
          175                                         isconst = 0;
          176                                 next = dp->next;
          177                                 free(dp);
          178                         }
          179                 }
          180         }
          181 
          182         sym = newsym(NS_IDEN, NULL);
          183         sym->u.init = v;
          184         sym->type = tp;
          185         sym->flags |= SINITLST;
          186 
          187         return (isconst ? constnode : varnode)(sym);
          188 }
          189 
          190 static void
          191 newdesig(Init *ip, Node *np)
          192 {
          193         struct designator *dp;
          194 
          195         dp = xmalloc(sizeof(*dp));
          196         dp->pos = ip->pos;
          197         dp->expr = np;
          198         dp->next = NULL;
          199 
          200         if (ip->head == NULL) {
          201                 ip->head = ip->tail = dp;
          202         } else {
          203                 ip->tail->next = dp;
          204                 ip->tail = dp;
          205         }
          206 
          207         if (ip->pos+1 > ip->max)
          208                 ip->max = ip->pos+1;
          209 }
          210 
          211 static Node *
          212 initlist_helper(Type *tp)
          213 {
          214         Init in;
          215         Node *np;
          216         Type *curtp;
          217         int braces, scalar, toomany, outbound;
          218         TINT nelem = tp->n.elem;
          219 
          220         init(&in);
          221         braces = scalar = toomany = 0;
          222 
          223         if (accept('{'))
          224                 braces = 1;
          225 
          226         for (;;) {
          227                 curtp = inttype;
          228                 switch (yytoken) {
          229                 case '[':
          230                         in.pos = arydesig(tp, &in);
          231                         curtp = tp->type;
          232                         goto desig_list;
          233                 case '.':
          234                         in.pos = fielddesig(tp, &in);
          235                         if (in.pos >= 0 && in.pos < nelem)
          236                                 curtp = tp->p.fields[in.pos]->type;
          237                 desig_list:
          238                         if (yytoken == '[' || yytoken == '.') {
          239                                 np = initlist(curtp);
          240                                 goto new_desig;
          241                         }
          242                         expect('=');
          243                 default:
          244                         outbound = 0;
          245 
          246                         switch (tp->op) {
          247                         case ARY:
          248                                 curtp = tp->type;
          249                                 if (!(tp->prop & TDEFINED) || in.pos < tp->n.elem)
          250                                         break;
          251                                 if (!toomany)
          252                                         warn("excess elements in array initializer");
          253                                 toomany = 1;
          254                                 outbound = 1;
          255                                 break;
          256                         case UNION:
          257                         case STRUCT:
          258                                 if (in.pos < nelem) {
          259                                         curtp = tp->p.fields[in.pos]->type;
          260                                         break;
          261                                 }
          262                                 if (!toomany)
          263                                         warn("excess elements in struct initializer");
          264                                 toomany = 1;
          265                                 outbound = 1;
          266                                 break;
          267                         default:
          268                                 curtp = tp;
          269                                 if (!scalar)
          270                                         warn("braces around scalar initializer");
          271                                 scalar = 1;
          272                                 if (in.pos == 0)
          273                                         break;
          274                                 if (!toomany)
          275                                         warn("excess elements in scalar initializer");
          276                                 toomany = 1;
          277                                 outbound = 1;
          278                                 break;
          279                         }
          280                         np = initialize(curtp);
          281                         if (outbound) {
          282                                 freetree(np);
          283                                 np = NULL;
          284                         }
          285                 }
          286 
          287 new_desig:
          288                 if (np)
          289                         newdesig(&in, np);
          290                 if (++in.pos == 0)
          291                         errorp("compound literal too big");
          292                 if (nelem == in.pos && !braces)
          293                         break;
          294                 if (!accept(','))
          295                         break;
          296                 if (yytoken == '}')
          297                         break;
          298         }
          299 
          300         if (braces)
          301                 expect('}');
          302 
          303 
          304         if (tp->op == ARY && !(tp->prop & TDEFINED)) {
          305                 tp->n.elem = in.max;
          306                 deftype(tp);
          307         }
          308         if (in.max == 0) {
          309                 errorp("empty braced initializer");
          310                 return constnode(zero);
          311         }
          312 
          313         return mkcompound(&in, tp);
          314 }
          315 
          316 Node *
          317 initlist(Type *tp)
          318 {
          319         Node *np;
          320         static int depth;
          321 
          322         if (depth == NR_SUBTYPE)
          323                 error("too many nested initializers");
          324 
          325         ++depth;
          326         np = initlist_helper(tp);
          327         --depth;
          328 
          329         return np;
          330 }
          331 
          332 static void
          333 autoinit(Symbol *sym, Node *np)
          334 {
          335         Symbol *hidden;
          336         Type *tp = sym->type;
          337 
          338 repeat:
          339         switch (tp->op) {
          340         case UNION:
          341                 np = np->sym->u.init[0];
          342                 tp = np->type;
          343                 goto repeat;
          344         case ARY:
          345         case STRUCT:
          346                 if (!(np->flags & NCONST))
          347                         abort(); /* TODO */
          348                 hidden = newsym(NS_IDEN, NULL);
          349                 hidden->id = newid();
          350                 hidden->type = sym->type;
          351                 hidden->flags |= SLOCAL | SHASINIT;
          352                 emit(ODECL, hidden);
          353                 emit(OINIT, np);
          354                 emit(ODECL, sym);
          355                 emit(OEXPR,
          356                      node(OASSIGN, tp, varnode(sym), varnode(hidden)));
          357                 break;
          358         default:
          359                 emit(ODECL, sym);
          360                 np = node(OASSIGN, tp, varnode(sym), np);
          361                 emit(OEXPR, np);
          362                 break;
          363         }
          364 }
          365 
          366 void
          367 initializer(Symbol *sym, Type *tp)
          368 {
          369         Node *np;
          370         int flags = sym->flags;
          371 
          372         if (tp->op == FTN) {
          373                 errorp("function '%s' initialized like a variable",
          374                        sym->name);
          375                 tp = inttype;
          376         }
          377         np = initialize(tp);
          378 
          379         if (flags & SDEFINED) {
          380                 errorp("redeclaration of '%s'", sym->name);
          381         } else if ((flags & (SGLOBAL|SLOCAL|SPRIVATE)) != 0) {
          382                 if ((np->flags & NCONST) == 0) {
          383                         errorp("initializer element is not constant");
          384                         return;
          385                 }
          386                 sym->flags |= SHASINIT;
          387                 sym->flags &= ~SEMITTED;
          388                 emit(ODECL, sym);
          389                 emit(OINIT, np);
          390                 sym->flags |= SDEFINED;
          391         } else if ((flags & (SEXTERN|STYPEDEF)) != 0) {
          392                 errorp("'%s' has both '%s' and initializer",
          393                        sym->name, (flags&SEXTERN) ? "extern" : "typedef");
          394         } else {
          395                 autoinit(sym, np);
          396         }
          397 }