scc

simple C compiler
git clone git://git.2f30.org/scc
Log | Files | Refs | README | LICENSE

commit 45e74e1d82c733ea83a2af7b06c2c897ff1df3e9
parent 0289c983456b286aea8fcf95c4a2e9950964317f
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Sun, 16 Nov 2014 05:45:24 -0500

Rewrite struct data structures

Type had a special type for fields of structures, and we were looking
in a list of fields each time that a . ir -> were used. This list needed
special routines for everyting. This patch removes this list and use
the symbol hash to storing the fields of structs. It uses a unique hash
for all the fields of all the structs, so it is needed a field in the
symbols to store the namespace.

Diffstat:
Mcc1/cc1.h | 21++++++++-------------
Mcc1/code.c | 22++++++++++++++++++----
Mcc1/decl.c | 179+++++++++++++++++++++++++++++++++++++------------------------------------------
Mcc1/expr.c | 22+++++++++++-----------
Mcc1/lex.c | 3++-
Mcc1/symbol.c | 22++++++----------------
Mcc1/types.c | 25+++++++------------------
7 files changed, 136 insertions(+), 158 deletions(-)

diff --git a/cc1/cc1.h b/cc1/cc1.h @@ -26,31 +26,26 @@ enum { NS_IDEN = 0, NS_TAG, NS_LABEL, + NS_STRUCTS, NR_NAMESPACES }; typedef struct ctype Type; typedef struct symbol Symbol; -typedef struct field { - char *name; - Type *type; - int id; - struct field *next; -} Field; - struct ctype { uint8_t op; /* type builder operator */ + uint8_t ns; char letter; /* letter of the type */ bool defined : 1; /* type defined (is not a forward reference) */ bool sign : 1; /* sign type */ struct ctype *type; /* base type */ struct ctype *next; /* next element in the hash */ + Type **pars; /* type parameters */ union { unsigned char rank; /* convertion rank */ short elem; /* number of type parameters */ } n; - void *pars; /* type parameters */ }; @@ -61,6 +56,7 @@ struct symbol { Type *type; short id; uint8_t ctx; + uint8_t ns; uint8_t token; struct { bool isglobal : 1; @@ -68,11 +64,11 @@ struct symbol { bool isauto : 1; bool isregister : 1; bool isdefined : 1; + bool isfield : 1; } s; union { int i; char *s; - struct symbol *sym; uint8_t token; } u; struct symbol *next; @@ -90,7 +86,6 @@ extern Symbol typedef struct caselist Caselist; extern void compound(Symbol *lbreak, Symbol *lcont, Caselist *lswitch); -extern Type *aggregate(Type *(*fun)(void)); extern void context(Symbol *lbreak, Symbol *lcont, Caselist *lswitch); extern Type *typename(void); @@ -161,7 +156,6 @@ typedef struct node { Symbol *sym; Type *type; char op; - Field *field; } u; struct node *childs[]; } Node; @@ -191,7 +185,8 @@ extern void emitswitch(short, Node *), emitcase(Symbol *, Node *), emitret(Type *tp), emitfun(Symbol *sym), - emitdefault(Symbol *); + emitdefault(Symbol *), + emitstruct(Symbol *sym), emitestruct(void); extern Node *node(void (*code)(Node *), @@ -202,7 +197,7 @@ extern Node *sizeofcode(Type *tp), *ternarycode(Node *cond, Node *ifyes, Node *ifno), *symcode(Symbol *sym), - *fieldcode(Node *child, struct field *fp); + *fieldcode(Node *child, Symbol *field); extern void freetree(Node *np); diff --git a/cc1/code.c b/cc1/code.c @@ -92,6 +92,8 @@ emitsym2(Symbol *sym) c = 'G'; else if (sym->s.isregister) c = 'R'; + else if (sym->s.isfield) + c = 'M'; else c = 'A'; printf("%c%d", c, sym->id); @@ -113,6 +115,18 @@ emitconst(Node *np) } void +emitstruct(Symbol *sym) +{ + printf("S%d\t(\n", sym->id); +} + +void +emitestruct(void) +{ + puts(")"); +} + +void emitsym(Node *np) { putchar('\t'); @@ -280,14 +294,14 @@ emitfield(Node *np) child = np->childs[0]; (*child->code)(child); - - printf("\tM%d", np->u.field->id); + putchar('\t'); + emitsym2(np->u.sym); } Node * -fieldcode(Node *child, struct field *fp) +fieldcode(Node *child, Symbol *field) { - Node *np = node(emitfield, fp->type, FIELD(fp), 1); + Node *np = node(emitfield, field->type, SYM(field), 1); np->childs[0] = child; return np; } diff --git a/cc1/decl.c b/cc1/decl.c @@ -70,33 +70,33 @@ fundcl(struct dcldata *dp) } static Symbol * -newiden(void) +newiden(uint8_t ns) { Symbol *sym; extern uint8_t curctx; - if (yylval.sym && yylval.sym->ctx == curctx) + if (yylval.sym && yylval.sym->ctx == curctx && yylval.sym->ns == ns) error("redeclaration of '%s'", yytext); - sym = install(yytext, NS_IDEN); + sym = install(yytext, ns); next(); return sym; } -static struct dcldata *declarator0(struct dcldata *dp); +static struct dcldata *declarator0(struct dcldata *dp, uint8_t ns); static struct dcldata * -directdcl(struct dcldata *dp) +directdcl(struct dcldata *dp, uint8_t ns) { register Symbol *sym; if (accept('(')) { - dp = declarator0(dp); + dp = declarator0(dp, ns); expect(')'); } else { if (yytoken == IDEN || yytoken == TYPEIDEN) - sym = newiden(); + sym = newiden(ns); else - sym = install("", NS_IDEN); + sym = install("", ns); dp = queue(dp, IDEN, 0, sym); } @@ -110,7 +110,7 @@ directdcl(struct dcldata *dp) } static struct dcldata* -declarator0(struct dcldata *dp) +declarator0(struct dcldata *dp, uint8_t ns) { register uint8_t n; @@ -119,7 +119,7 @@ declarator0(struct dcldata *dp) /* nothing */; } - dp = directdcl(dp); + dp = directdcl(dp, ns); while (n--) dp = queue(dp, PTR, 0, NULL); @@ -128,7 +128,7 @@ declarator0(struct dcldata *dp) } static Symbol * -declarator(Type *tp, int8_t flags) +declarator(Type *tp, int8_t flags, uint8_t ns) { struct dcldata data[NR_DECLARATORS+2]; register struct dcldata *bp; @@ -136,7 +136,7 @@ declarator(Type *tp, int8_t flags) memset(data, 0, sizeof(data)); data[NR_DECLARATORS].op = 255; - for (bp = declarator0(data)-1; bp >= data; --bp) { + for (bp = declarator0(data, ns)-1; bp >= data; --bp) { if (bp->op != IDEN) { tp = mktype(tp, bp->op, bp->nelem, bp->data); } else { @@ -212,7 +212,7 @@ specifier(int8_t *sclass) if (dcl) { if (size || sign) goto invalid_type; - tp = aggregate(dcl); + tp = (*dcl)(); } else { next(); } @@ -248,70 +248,11 @@ initializer(Symbol *sym) return NULL; } -/* TODO: bitfields */ - -static void -newfield(Type *tp, Symbol *sym) -{ - register Field *p, *q; - register char *s, *t; - - s = sym->name; - for (q = p = tp->pars; p; q = p, p = p->next) { - t = p->name; - if (*s == *t && !strcmp(s, t)) - error("duplicated fields '%s' and '%s'", s, t); - if (sym->u.i == p->id) - error("duplicated enumeration fields '%s' and '%s'", - s, t); - } - - p = xmalloc(sizeof(*p)); - p->name = xstrdup(s); - p->next = NULL; - p->id = sym->id; - p->type = sym->type; - if (!q) - tp->pars= p; - else - q->next = p; - - return; -} - -static void -fielddcl(Type *base) -{ - Type *tp; - Symbol *sym; - - switch (yytoken) { - case SCLASS: - error("storage class '%s' in struct/union field", yytext); - case IDEN: case TYPE: case TYPEIDEN: case TQUALIFIER: - tp = specifier(NULL); - case ';': - break; - default: - unexpected(); - } - - if (yytoken != ';') { - do { - sym = declarator(tp, ID_EXPECTED); - newfield(base, sym); - } while (accept(',')); - } - - expect(';'); - return; -} - -static Type * +static Symbol * newtag(uint8_t tag) { register Symbol *sym; - register Type *tp; + static uint8_t ns = NS_STRUCTS; switch (yytoken) { case IDEN: case TYPEIDEN: @@ -323,32 +264,80 @@ newtag(uint8_t tag) sym = install("", NS_TAG); break; } - if (!sym->type) + if (!sym->type) { + if (ns == NS_STRUCTS + NR_MAXSTRUCTS) + error("too much tags declared"); sym->type = mktype(NULL, tag, 0, NULL); - tp = sym->type; - if (tp->op != tag) + sym->type->ns = ns++; + } + + if (sym->type->op != tag) error("'%s' defined as wrong kind of tag", yytext); - return tp; + return sym; } +/* TODO: bitfields */ + static Type * structdcl(void) { - Type *tp; - uint8_t tag; + Type *tagtype, *buff[NR_MAXSTRUCTS], **bp = &buff[0]; + Symbol *tagsym, *sym; + uint8_t tag, n; + size_t siz; tag = yylval.token; next(); - tp = newtag(tag); - if (accept('{')) { - if (tp->defined) - error("redefinition of struct/union '%s'", yytext); - tp->defined = 1; - while (!accept('}')) - fielddcl(tp); + tagsym = newtag(tag); + tagtype = tagsym->type; + if (!accept('{')) + return tagtype; + + if (tagtype->defined) + error("redefinition of struct/union '%s'", yytext); + tagtype->defined = 1; + emitstruct(tagsym); + + while (!accept('}')) { + Type *base, *tp; + + switch (yytoken) { + case SCLASS: + error("storage class '%s' in struct/union field", + yytext); + case IDEN: case TYPE: case TYPEIDEN: case TQUALIFIER: + base = specifier(NULL); + break; + case ';': + next(); + continue; + default: + unexpected(); + } + + if (accept(';')) + error("identifier expected"); + + do { + sym = declarator(base, ID_EXPECTED, tagtype->ns); + sym->s.isfield = 1; + tp = sym->type; + if (tp->op == FTN) + error("invalid type in struct/union"); + if (bp == &buff[NR_MAXSTRUCTS]) + error("too much fields in struct/union"); + *bp++ = sym->type; + emitdcl(sym); + } while (accept(',')); + expect(';'); } - return tp; + emitestruct(); + n = bp - buff - 1; + siz = sizeof(Type *) * n; + tagtype->n.elem = n; + tagtype->pars = memcpy(xmalloc(siz), buff, siz); + return tagtype; } static Type * @@ -359,7 +348,8 @@ enumdcl(void) int val = 0; next(); - tp = newtag(ENUM); + tp = newtag(ENUM)->type; + if (yytoken == ';') return tp; @@ -370,12 +360,11 @@ enumdcl(void) while (yytoken != '}') { if (yytoken != IDEN) unexpected(); - sym = newiden(); + sym = newiden(NS_IDEN); sym->type = inttype; if (accept('=')) initializer(sym); sym->u.i = val++; - newfield(tp, sym); if (!accept(',')) break; } @@ -393,7 +382,7 @@ parameter(void) if ((tp = specifier(&sclass)) == voidtype) return tp; - sym = declarator(tp, ID_ACCEPTED); + sym = declarator(tp, ID_ACCEPTED, NS_IDEN); sym->s.isdefined = 1; /* TODO: check type of the parameter */ switch (sclass) { @@ -421,7 +410,7 @@ decl(void) return; do { - sym = declarator(tp, ID_EXPECTED); + sym = declarator(tp, ID_EXPECTED, NS_IDEN); sym->s.isdefined = 1; isfun = sym->type->op == FTN; @@ -470,7 +459,7 @@ typename(void) tp = specifier(&sclass); if (sclass) error("class storage in type name"); - sym = declarator(tp, ID_FORBIDDEN); + sym = declarator(tp, ID_FORBIDDEN, NS_IDEN); return sym->type; } @@ -488,7 +477,7 @@ extdecl(void) if (accept(';')) return; do { - sym = declarator(base, ID_EXPECTED); + sym = declarator(base, ID_EXPECTED, NS_IDEN); tp = sym->type; sym->s.isstatic = 1; sym->s.isglobal= 1; diff --git a/cc1/expr.c b/cc1/expr.c @@ -292,19 +292,20 @@ logic(char op, Node *np1, Node *np2) static Node * field(Node *np) { - Field *fp; + extern uint8_t lex_ns; + Symbol *sym; - if (yytoken != IDEN) - unexpected(); switch (np->typeop) { case STRUCT: case UNION: - for (fp = np->type->pars; fp; fp = fp->next) { - if (!strcmp(fp->name, yytext)) { - next(); - return fieldcode(np, fp); - } - } - error("field '%s' not found", yytext); + lex_ns = np->type->ns; + next(); + if (yytoken != IDEN) + unexpected(); + if ((sym = yylval.sym) == NULL) + error("incorrect field in struct/union"); + lex_ns = NS_IDEN; + next(); + return fieldcode(np, sym); default: error("struct or union expected"); } @@ -482,7 +483,6 @@ postfix(void) case INDIR: np1 = content(OPTR, np1); case '.': - next(); np1 = field(np1); break; case '(': diff --git a/cc1/lex.c b/cc1/lex.c @@ -10,6 +10,7 @@ #include "cc1.h" static FILE *yyin; +uint8_t lex_ns = NS_IDEN; const char *filename; unsigned linenum; @@ -202,7 +203,7 @@ iden(void) *bp = '\0'; ungetc(c, yyin); - sym = yylval.sym = lookup(yytext, NS_IDEN); + sym = yylval.sym = lookup(yytext, lex_ns); if (!sym || sym->token == IDEN) return IDEN; yylval.token = sym->u.token; diff --git a/cc1/symbol.c b/cc1/symbol.c @@ -47,18 +47,6 @@ freesyms(uint8_t ns) } } -Type * -aggregate(Type * (*fun)(void)) -{ - Type *tp; - - ++curctx; - tp = (*fun)(); - --curctx; - freesyms(NS_IDEN); - return tp; -} - void context(Symbol *lbreak, Symbol *lcont, Caselist *lswitch) { @@ -67,6 +55,7 @@ context(Symbol *lbreak, Symbol *lcont, Caselist *lswitch) --curctx; freesyms(NS_IDEN); freesyms(NS_TAG); + freesyms(NS_STRUCTS); if (curctx == 0) { localcnt = 0; freesyms(NS_LABEL); @@ -79,9 +68,9 @@ lookup(register char *s, uint8_t ns) struct symtab *tbl; register Symbol *sym; - tbl = &symtab[ns]; + tbl = &symtab[(ns > NS_STRUCTS) ? NS_STRUCTS : ns]; for (sym = tbl->htab[hash(s)]; sym; sym = sym->hash) { - if (!strcmp(sym->name, s)) + if (!strcmp(sym->name, s) && sym->ns == ns) return sym; } @@ -99,8 +88,9 @@ install(char *s, uint8_t ns) sym->ctx = curctx; sym->token = IDEN; sym->id = (curctx) ? ++localcnt : ++globalcnt; - sym->s.isdefined = 1; - tbl = &symtab[ns]; + sym->s.isdefined = 0; + sym->ns = ns; + tbl = &symtab[(ns > NS_STRUCTS) ? NS_STRUCTS : ns]; sym->next = tbl->head; tbl->head = sym; diff --git a/cc1/types.c b/cc1/types.c @@ -206,6 +206,7 @@ mktype(Type *tp, uint8_t op, short nelem, void *data) type.letter = letters[op]; type.pars = data; type.n.elem = nelem; + type.ns = 0; if (op == ARY && nelem == 0 || op == STRUCT || op == UNION) type.defined = 0; @@ -236,9 +237,11 @@ eqtype(Type *tp1, Type *tp2) if (tp1->op != tp2->op || tp1->n.elem != tp2->n.elem) return 0; switch (tp1->op) { + case ARY: case PTR: return eqtype(tp1->type, tp2->type); - /* TODO: use the same struct for function parameters and fields */ + case UNION: + case STRUCT: case FTN: p1 = tp1->pars, p2 = tp2->pars; for (n = tp1->n.elem; n != 0; --n) { @@ -246,23 +249,9 @@ eqtype(Type *tp1, Type *tp2) return 0; } return 1; - case UNION: - case STRUCT: { - Field *fp1 = tp1->pars, *fp2 = tp2->pars; - - while (fp1 && fp2) { - if (!eqtype(fp1->type, fp2->type)) - break; - fp1 = fp1->next; - fp2 = fp2->next; - } - return fp1 == fp2; - } - case ARY: - if (!eqtype(tp1->type, tp2->type)) - return 0; - return 1; - case ENUM: case INT: case FLOAT: + case ENUM: + /* TODO: Check when two enum are the same type */ + case INT: case FLOAT: return tp1->letter == tp2->letter; default: fputs("internal type error, aborting\n", stderr);