scc

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

commit a06b587d1805b93e880efea3773c084b6111d0c6
parent 481870312e7a7e2389e138a97698811977541970
Author: damia <alejandro.berna@sener.es>
Date:   Tue, 20 Dec 2016 17:33:01 +0100

[cc1] Add a new hash table for cpp symbols

The code of the symbol table is really complex because
we only have a hashtable, and it is creating some
situations that are complex. This is the first patch
of a serie and it does not change too much of the
structure of the code.

Diffstat:
Mcc1/cc1.h | 6+++++-
Mcc1/cpp.c | 18+++---------------
Mcc1/expr.c | 15++++++++-------
Mcc1/lex.c | 4++--
Mcc1/stmt.c | 2+-
Mcc1/symbol.c | 33+++++++++++++++++----------------
6 files changed, 36 insertions(+), 42 deletions(-)

diff --git a/cc1/cc1.h b/cc1/cc1.h @@ -9,6 +9,10 @@ /* * Definition of enumerations */ +enum { + NOALLOC, + ALLOC +}; enum typeprops { TDEFINED = 1 << 0, /* type defined */ @@ -364,7 +368,7 @@ extern void flushtypes(void); /* symbol.c */ extern void dumpstab(char *msg); -extern Symbol *lookup(int ns, char *name); +extern Symbol *lookup(int ns, char *name, int alloc); extern Symbol *nextsym(Symbol *sym, int ns); extern Symbol *install(int ns, Symbol *sym); extern Symbol *newsym(int ns); diff --git a/cc1/cpp.c b/cc1/cpp.c @@ -41,7 +41,7 @@ defdefine(char *macro, char *val, char *source) void undefmacro(char *s) { - killsym(lookup(NS_CPP, s)); + killsym(lookup(NS_CPP, s, NOALLOC)); } void @@ -84,8 +84,8 @@ icpp(void) defdefine("__LINE__", NULL, "built-in"); defdefine("__FILE__", NULL, "built-in"); - symline = lookup(NS_CPP, "__LINE__"); - symfile = lookup(NS_CPP, "__FILE__"); + symline = lookup(NS_CPP, "__LINE__", ALLOC); + symfile = lookup(NS_CPP, "__FILE__", ALLOC); for (bp = list; *bp; ++bp) defdefine(*bp, "1", "built-in"); @@ -248,18 +248,6 @@ expand(char *begin, Symbol *sym) char *arglist[NR_MACROARG], arguments[INPUTSIZ], buffer[BUFSIZE]; macroname = sym->name; - if ((sym->flags & SDECLARED) == 0) { - if (namespace == NS_CPP && !strcmp(sym->name, "defined")) - return 0; /* we found a 'defined in an #if */ - /* - * This case happens in #if were macro not defined must - * be expanded to 0 - */ - buffer[0] = '0'; - buffer[1] = '\0'; - elen = 1; - goto substitute; - } if (sym == symfile) { elen = sprintf(buffer, "\"%s\" ", input->fname); goto substitute; diff --git a/cc1/expr.c b/cc1/expr.c @@ -666,26 +666,27 @@ primary(void) emit(ODECL, sym); emit(OINIT, np); np = varnode(sym); - next(); break; case CONSTANT: np = constnode(sym); - next(); break; case IDEN: - if ((sym->flags & SDECLARED) == 0) + assert((sym->flags & SCONSTANT) == 0); + if ((sym->flags & SDECLARED) == 0) { + if (namespace == NS_CPP) { + np = constnode(zero); + break; + } sym = notdefined(sym); - if (sym->flags & SCONSTANT) { - np = constnode(sym); - break; } sym->flags |= SUSED; np = varnode(sym); - next(); break; default: unexpected(); } + next(); + return np; } diff --git a/cc1/lex.c b/cc1/lex.c @@ -496,8 +496,7 @@ iden(void) /* nothing */; input->p = p; tok2str(); - sym = lookup(namespace, yytext); - if (sym->ns == NS_CPP) { + if ((sym = lookup(NS_CPP, yytext, NOALLOC)) != NULL) { if (!disexpand && expand(begin, sym)) return next(); /* @@ -507,6 +506,7 @@ iden(void) if (lexmode != CPPMODE) sym = nextsym(sym, namespace); } + sym = lookup(namespace, yytext, ALLOC); yylval.sym = sym; if (sym->flags & SCONSTANT) return CONSTANT; diff --git a/cc1/stmt.c b/cc1/stmt.c @@ -20,7 +20,7 @@ label(void) switch (yytoken) { case IDEN: case TYPEIDEN: - sym = lookup(NS_LABEL, yytext); + sym = lookup(NS_LABEL, yytext, ALLOC); if (sym->flags & SDEFINED) error("label '%s' already defined", yytext); if ((sym->flags & SDECLARED) == 0) diff --git a/cc1/symbol.c b/cc1/symbol.c @@ -16,6 +16,7 @@ static unsigned short counterid; static Symbol *head, *labels; static Symbol *htab[NR_SYM_HASH]; +static Symbol *htabcpp[NR_SYM_HASH]; #ifndef NDEBUG void @@ -56,11 +57,12 @@ hash(const char *s) static void unlinkhash(Symbol *sym) { - Symbol **h, *p, *prev; + Symbol **tab, **h, *p, *prev; if ((sym->flags & SDECLARED) == 0) return; - h = &htab[hash(sym->name)]; + tab = (sym->ns == NS_CPP) ? htabcpp : htab; + h = &tab[hash(sym->name)]; for (prev = p = *h; p != sym; prev = p, p = p->hash) /* nothing */; if (prev == p) @@ -82,6 +84,8 @@ killsym(Symbol *sym) short f; char *name; + if (!sym) + return; f = sym->flags; if (f & SSTRING) free(sym->u.s); @@ -188,9 +192,10 @@ linksym(Symbol *sym) static Symbol * linkhash(Symbol *sym) { - Symbol **h, *p, *prev; + Symbol **tab, **h, *p, *prev; - h = &htab[hash(sym->name)]; + tab = (sym->ns == NS_CPP) ? htabcpp : htab; + h = &tab[hash(sym->name)]; for (prev = p = *h; p; prev = p, p = p->hash) { if (p->ctx <= sym->ctx) break; @@ -241,38 +246,34 @@ newlabel(void) } Symbol * -lookup(int ns, char *name) +lookup(int ns, char *name, int alloc) { - Symbol *sym; + Symbol *sym, **tab; int sns; char *t, c; c = *name; - for (sym = htab[hash(name)]; sym; sym = sym->hash) { + tab = (ns == NS_CPP) ? htabcpp : htab; + for (sym = tab[hash(name)]; sym; sym = sym->hash) { t = sym->name; if (*t != c || strcmp(t, name)) continue; sns = sym->ns; + if (sns == ns) + return sym; /* - * CPP namespace has a total priority over the another - * namespaces, because it is a previous pass, - * If we are looking in the CPP namespace, - * we don't want symbols related to keywords or types. * When a lookup is done in a namespace associated * to a struct we also want symbols of NS_IDEN which * are typedef, because in other case we cannot declare * fields of such types. + * TODO: Remove this trick */ - if (sns == NS_CPP && !disexpand || sns == ns) - return sym; - if (ns == NS_CPP) - continue; if (sns == NS_KEYWORD || (sym->flags & STYPEDEF) && ns >= NS_STRUCTS) { return sym; } } - return allocsym(ns, name); + return (alloc == ALLOC) ? allocsym(ns, name) : NULL; } Symbol *