scc

Simple C99 Compiler
Log | Files | Refs | README | LICENSE

commit 43a3b37a514e390199668bab42c3451901de5917
parent 8f5f61842eec2f1553ddbc90bf454600168f0718
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Mon, 18 Jan 2016 15:20:50 +0100

Emit compound initializers

At this point we are not emiting anything, but we have the full process
working. We have to create a function which could emit this kind of
constants.

Diffstat:
cc1/cc1.h | 2+-
cc1/code.c | 2++
cc1/decl.c | 2+-
cc1/expr.c | 26+++++++++-----------------
cc1/init.c | 47+++++++++++++++++++++++++++--------------------
5 files changed, 40 insertions(+), 39 deletions(-)

diff --git a/cc1/cc1.h b/cc1/cc1.h @@ -384,7 +384,7 @@ extern Node *castcode(Node *np, Type *newtp); extern TUINT ones(int nbytes); /* expr.c */ -extern Node *decay(Node *), *negate(Node *np), *assign(Node *np);; +extern Node *decay(Node *), *negate(Node *np), *assign(void);; extern Node *convert(Node *np, Type *tp1, char iscast); extern Node *iconstexpr(void), *condexpr(void), *expr(void); extern bool isnodecmp(int op); diff --git a/cc1/code.c b/cc1/code.c @@ -207,6 +207,8 @@ emitconst(Node *np) for (bp = sym->u.s; c = *bp; ++bp) printf("%02X", c & 0xFF); break; + case STRUCT: + return; default: /* TODO: Handle other kind of constants */ abort(); diff --git a/cc1/decl.c b/cc1/decl.c @@ -788,7 +788,7 @@ identifier(struct decl *dcl) if (sym->token == IDEN && sym->type->op != FTN) emit(ODECL, sym); - if (yytoken == '=') + if (accept('=')) initializer(sym, sym->type, -1); if (!(sym->flags & (ISGLOBAL|ISEXTERN)) && tp->op != FTN) sym->flags |= ISDEFINED; diff --git a/cc1/expr.c b/cc1/expr.c @@ -512,9 +512,7 @@ static Node * assignop(char op, Node *lp, Node *rp) { if ((rp = convert(decay(rp), lp->type, 0)) == NULL) { - errorp((op == OINIT) ? - "incorrect initiliazer" : - "incompatible types when assigning"); + errorp("incompatible types when assigning"); return lp; } @@ -657,7 +655,7 @@ arguments(Node *np) toomany = 0; do { - arg = decay(assign(NULL)); + arg = decay(assign()); argtype = *targs; if (argtype == ellipsistype) { n = 0; @@ -1006,21 +1004,15 @@ ternary(void) } Node * -assign(Node *np) +assign(void) { - Node *(*fun)(char , Node *, Node *); + Node *np, *(*fun)(char , Node *, Node *); char op; - if (np) { - op = OINIT; - } else { - op = OASSIGN; - np = ternary(); - } - + np = ternary(); for (;;) { switch (yytoken) { - case '=': /* op = op; */; fun = assignop; break; + case '=': op = OASSIGN; fun = assignop; break; case MUL_EQ: op = OA_MUL; fun = arithmetic; break; case DIV_EQ: op = OA_DIV; fun = arithmetic; break; case MOD_EQ: op = OA_MOD; fun = integerop; break; @@ -1035,7 +1027,7 @@ assign(Node *np) } chklvalue(np); next(); - np = (fun)(op, np, assign(NULL)); + np = (fun)(op, np, assign()); } } @@ -1073,9 +1065,9 @@ expr(void) { Node *lp, *rp; - lp = assign(NULL); + lp = assign(); while (accept(',')) { - rp = assign(NULL); + rp = assign(); lp = node(OCOMMA, rp->type, lp, rp); } diff --git a/cc1/init.c b/cc1/init.c @@ -78,11 +78,24 @@ designation(Init *ip) return ip; } +static Node *initlist(Type *tp); + static Node * -initlist(Symbol *sym, Type *tp) +initialize(Type *tp) +{ + Node *np; + + np = (accept('{')) ? initlist(tp) : assign(); + if ((np = convert(decay(np), tp, 0)) == NULL) + errorp("incorrect initializer"); + return np; +} + +static Node * +initlist(Type *tp) { Init *ip; - Symbol *nsym; + Symbol *sym; struct designator *dp; int toomany = 0; Type *newtp; @@ -99,19 +112,20 @@ initlist(Symbol *sym, Type *tp) designation(ip); switch (tp->op) { case ARY: - newtp = tp->type; - if (!tp->defined || ip->pos < tp->n.elem) + newtp = sym->type; + if (!tp->defined || ip->pos <= tp->n.elem) break; if (!toomany) warn("excess elements in array initializer"); toomany = 1; break; case STRUCT: - if (ip->pos < tp->n.elem) { - sym = tp->p.fields[ip->pos]; + if (ip->pos <= tp->n.elem) { + sym = tp->p.fields[ip->pos-1]; newtp = sym->type; break; } + newtp = inttype; if (!toomany) warn("excess elements in struct initializer"); toomany = 1; @@ -119,7 +133,7 @@ initlist(Symbol *sym, Type *tp) default: newtp = tp; warn("braces around scalar initializer"); - if (ip->pos <= 0) + if (ip->pos == 1) break; if (!toomany) warn("excess elements in scalar initializer"); @@ -128,8 +142,7 @@ initlist(Symbol *sym, Type *tp) } dp = ip->head; dp->pos = ip->pos; - /* TODO: pass the correct parameters to initlist */ - dp->expr = (accept('{')) ? initlist(sym, tp) : assign(NULL); + dp->expr = initialize(newtp); if (!accept(',')) break; @@ -141,9 +154,10 @@ end_of_initializer: tp->n.elem = ip->pos; tp->defined = 1; } - nsym = newsym(NS_IDEN); - nsym->u.init = ip; - return constnode(nsym); + sym = newsym(NS_IDEN); + sym->u.init = ip; + sym->type = tp; + return constnode(sym); } void @@ -155,14 +169,7 @@ initializer(Symbol *sym, Type *tp, int nelem) if (tp->op == FTN) errorp("function '%s' is initialized like a variable", sym->name); - switch (yytoken) { - case '{': - initlist(sym, tp); - return; - case '=': - np = assign(varnode(sym)); - break; - } + np = node(OINIT, tp, varnode(sym), initialize(tp)); if (flags & ISDEFINED) { errorp("redeclaration of '%s'", sym->name);