scc

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

commit 38c240c4f09858a4ce71d70ee7fe16e7df7c9bff
parent ba98fe9738f78620b50c8351d46c95f923052dd7
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Sun, 17 Jan 2016 11:59:04 +0100

Move initializer code to a new file

This code is going to be too long, and it is not totally related
to expressions, so it is better to create a new file.

Diffstat:
cc1/Makefile | 2+-
cc1/cc1.h | 7++++---
cc1/decl.c | 2+-
cc1/expr.c | 199++++++-------------------------------------------------------------------------
cc1/init.c | 184+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 205 insertions(+), 189 deletions(-)

diff --git a/cc1/Makefile b/cc1/Makefile @@ -3,7 +3,7 @@ include ../config.mk OBJS = types.o decl.o lex.o error.o symbol.o main.o expr.o \ - code.o stmt.o cpp.o fold.o + code.o stmt.o cpp.o fold.o init.o all: cc1 diff --git a/cc1/cc1.h b/cc1/cc1.h @@ -374,13 +374,14 @@ extern Node *castcode(Node *np, Type *newtp); extern TUINT ones(int nbytes); /* expr.c */ -extern Node *expr(void), *negate(Node *np), *constexpr(void); +extern Node *decay(Node *), *negate(Node *np), *assign(Node *np);; extern Node *convert(Node *np, Type *tp1, char iscast); -extern Node *iconstexpr(void), *condexpr(void); +extern Node *iconstexpr(void), *condexpr(void), *expr(void); extern bool isnodecmp(int op); extern int negop(int op); extern bool cmpnode(Node *np, TUINT val); -extern Node *decay(Node *np); + +/* init.c */ extern void initializer(Symbol *sym, Type *tp, int nelem); /* cpp.c */ diff --git a/cc1/decl.c b/cc1/decl.c @@ -779,7 +779,7 @@ identifier(struct decl *dcl) if (sym->token == IDEN && sym->type->op != FTN) emit(ODECL, sym); - if (accept('=')) + if (yytoken == '=') 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 @@ -629,8 +629,6 @@ primary(void) return np; } -static Node *assign(void); - static Node * arguments(Node *np) { @@ -659,7 +657,7 @@ arguments(Node *np) toomany = 0; do { - arg = decay(assign()); + arg = decay(assign(NULL)); argtype = *targs; if (argtype == ellipsistype) { n = 0; @@ -1007,16 +1005,22 @@ ternary(void) return cond; } -static Node * -assign(void) +Node * +assign(Node *np) { - Node *np, *(*fun)(char , Node *, Node *); + Node *(*fun)(char , Node *, Node *); char op; - np = ternary(); + if (np) { + op = OINIT; + } else { + op = OASSIGN; + np = ternary(); + } + for (;;) { switch (yytoken) { - case '=': op = OASSIGN; fun = assignop; break; + case '=': /* op = op; */; 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; @@ -1031,7 +1035,7 @@ assign(void) } chklvalue(np); next(); - np = (fun)(op, np, assign()); + np = (fun)(op, np, assign(NULL)); } } @@ -1069,9 +1073,9 @@ expr(void) { Node *lp, *rp; - lp = assign(); + lp = assign(NULL); while (accept(',')) { - rp = assign(); + rp = assign(NULL); lp = node(OCOMMA, rp->type, lp, rp); } @@ -1088,176 +1092,3 @@ condexpr(void) warn("conditional expression is constant"); return np; } - -struct designator { - TINT pos; - struct designator *next; -}; - -static TINT -arydesig(Type *tp) -{ - TINT npos; - Node *np; - - if (tp->op != ARY) - errorp("array index in non-array initializer"); - next(); - np = iconstexpr(); - npos = np->sym->u.i; - freetree(np); - expect(']'); - return npos; -} - -static TINT -fielddesig(Type *tp) -{ - TINT npos; - int ons; - Symbol *sym, **p; - - if (!tp->aggreg) - errorp("field name not in record or union initializer"); - ons = namespace; - namespace = tp->ns; - next(); - namespace = ons; - if (yytoken != IDEN) - unexpected(); - sym = yylval.sym; - if ((sym->flags & ISDECLARED) == 0) { - errorp(" unknown field '%s' specified in initializer", - sym->name); - return 0; - } - for (p = tp->p.fields; *p != sym; ++p) - /* nothing */; - return p - tp->p.fields; -} - -static struct designator * -designation(Type *tp) -{ - struct designator *des = NULL, *d; - TINT (*fun)(Type *); - - for (;;) { - switch (yytoken) { - case '[': fun = arydesig; break; - case '.': fun = fielddesig; break; - default: - if (des) - expect('='); - return des; - } - d = xmalloc(sizeof(*d)); - d->next = NULL; - - if (!des) { - des = d; - } else { - des->next = d; - des = d; - } - des->pos = (*fun)(tp); - } -} - -static void -initlist(Symbol *sym, Type *tp) -{ - struct designator *des; - int toomany = 0; - TINT n; - Type *newtp; - - for (n = 0; ; ++n) { - if ((des = designation(tp)) == NULL) { - des = xmalloc(sizeof(*des)); - des->pos = n; - } else { - n = des->pos; - } - switch (tp->op) { - case ARY: - if (tp->defined && n >= tp->n.elem) { - if (!toomany) - warn("excess elements in array initializer"); - toomany = 1; - sym = NULL; - } - newtp = tp->type; - break; - case STRUCT: - if (n >= tp->n.elem) { - if (!toomany) - warn("excess elements in struct initializer"); - toomany = 1; - sym = NULL; - } else { - sym = tp->p.fields[n]; - newtp = sym->type; - } - break; - default: - newtp = tp; - warn("braces around scalar initializer"); - if (n > 0) { - if (!toomany) - warn("excess elements in scalar initializer"); - toomany = 1; - sym = NULL; - } - break; - } - initializer(sym, newtp, n); - if (!accept(',')) - break; - } - expect('}'); - - if (tp->op == ARY && !tp->defined) { - tp->n.elem = n + 1; - tp->defined = 1; - } -} - -void -initializer(Symbol *sym, Type *tp, int nelem) -{ - Node *np; - int flags = sym->flags; - - if (tp->op == FTN) - error("function '%s' is initialized like a variable", sym->name); - - if (accept('{')) { - initlist(sym, tp); - return; - } - np = assign(); - - /* if !sym it means there are too much initializers */ - if (!sym) - return; - if (nelem >= 0) - return; - - np = assignop(OINIT, varnode(sym), np); - - if (flags & ISDEFINED) { - errorp("redeclaration of '%s'", sym->name); - } else if ((flags & (ISGLOBAL|ISLOCAL|ISPRIVATE)) != 0) { - if (!np->right->constant) - errorp("initializer element is not constant"); - emit(OINIT, np); - sym->flags |= ISDEFINED; - } else if ((flags & (ISEXTERN|ISTYPEDEF)) != 0) { - errorp("'%s' has both '%s' and initializer", - sym->name, (flags&ISEXTERN) ? "extern" : "typedef"); - } else { - np->op = OASSIGN; - emit(OEXPR, np); - } -} diff --git a/cc1/init.c b/cc1/init.c @@ -0,0 +1,184 @@ + +#include <stdio.h> +#include <stdlib.h> + +#include "../inc/cc.h" +#include "../inc/sizes.h" +#include "cc1.h" + +struct designator { + TINT pos; + struct designator *next; +}; + +static TINT +arydesig(Type *tp) +{ + TINT npos; + Node *np; + + if (tp->op != ARY) + errorp("array index in non-array initializer"); + next(); + np = iconstexpr(); + npos = np->sym->u.i; + freetree(np); + expect(']'); + return npos; +} + +static TINT +fielddesig(Type *tp) +{ + TINT npos; + int ons; + Symbol *sym, **p; + + if (!tp->aggreg) + errorp("field name not in record or union initializer"); + ons = namespace; + namespace = tp->ns; + next(); + namespace = ons; + if (yytoken != IDEN) + unexpected(); + sym = yylval.sym; + if ((sym->flags & ISDECLARED) == 0) { + errorp(" unknown field '%s' specified in initializer", + sym->name); + return 0; + } + for (p = tp->p.fields; *p != sym; ++p) + /* nothing */; + return p - tp->p.fields; +} + +static struct designator * +designation(Type *tp) +{ + struct designator *des = NULL, *d; + TINT (*fun)(Type *); + + for (;;) { + switch (yytoken) { + case '[': fun = arydesig; break; + case '.': fun = fielddesig; break; + default: + if (des) + expect('='); + return des; + } + d = xmalloc(sizeof(*d)); + d->next = NULL; + + if (!des) { + des = d; + } else { + des->next = d; + des = d; + } + des->pos = (*fun)(tp); + } +} + +static void +initlist(Symbol *sym, Type *tp) +{ + struct designator *des; + int toomany = 0; + TINT n; + Type *newtp; + + for (n = 0; ; ++n) { + if ((des = designation(tp)) == NULL) { + des = xmalloc(sizeof(*des)); + des->pos = n; + } else { + n = des->pos; + } + switch (tp->op) { + case ARY: + if (tp->defined && n >= tp->n.elem) { + if (!toomany) + warn("excess elements in array initializer"); + toomany = 1; + sym = NULL; + } + newtp = tp->type; + break; + case STRUCT: + if (n >= tp->n.elem) { + if (!toomany) + warn("excess elements in struct initializer"); + toomany = 1; + sym = NULL; + } else { + sym = tp->p.fields[n]; + newtp = sym->type; + } + break; + default: + newtp = tp; + warn("braces around scalar initializer"); + if (n > 0) { + if (!toomany) + warn("excess elements in scalar initializer"); + toomany = 1; + sym = NULL; + } + break; + } + initializer(sym, newtp, n); + if (!accept(',')) + break; + } + expect('}'); + + if (tp->op == ARY && !tp->defined) { + tp->n.elem = n + 1; + tp->defined = 1; + } +} + +extern Node *assign(Node *np); + +void +initializer(Symbol *sym, Type *tp, int nelem) +{ + Node *np; + int flags = sym->flags; + + if (tp->op == FTN) + errorp("function '%s' is initialized like a variable", sym->name); + + switch (yytoken) { + case '{': + initlist(sym, tp); /* FIXME: This code is not complete */ + return; + case '=': + np = assign(varnode(sym)); + break; + } + + /* FIXME: old code used in the recursive call + * if (!sym) + * return; + * if (nelem >= 0) + * return; + */ + + if (flags & ISDEFINED) { + errorp("redeclaration of '%s'", sym->name); + } else if ((flags & (ISGLOBAL|ISLOCAL|ISPRIVATE)) != 0) { + if (!np->right->constant) + errorp("initializer element is not constant"); + emit(OINIT, np); + sym->flags |= ISDEFINED; + } else if ((flags & (ISEXTERN|ISTYPEDEF)) != 0) { + errorp("'%s' has both '%s' and initializer", + sym->name, (flags&ISEXTERN) ? "extern" : "typedef"); + } else { + np->op = OASSIGN; + emit(OEXPR, np); + } +}