scc

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

commit d0763d72e63709ffc8af883c5dd2db4be98f6b77
parent e41e68626c04ea501561eb6eb4bf93e6dda9c6e8
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Wed,  6 Aug 2014 12:38:17 +0200

Split identifiers between local and global

This separation allows to use only the needed memory for a function
definition. If there is no difference between local and global,
we have to allocate memory for all the variables in the source,
because we don't know when they are not going to be used anymore.

Diffstat:
Mcc1/lex.c | 54------------------------------------------------------
Mcc1/symbol.c | 62+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
Mcc2/cc2.h | 5++++-
Mcc2/parser.c | 67+++++++++++++++++++++++++++++++++++++++++++++++++++++--------------
4 files changed, 116 insertions(+), 72 deletions(-)

diff --git a/cc1/lex.c b/cc1/lex.c @@ -186,60 +186,6 @@ end_string: return STRING; } -void -init_keywords(void) -{ - static struct { - char *str; - uint8_t token, value; - } *bp, buff[] = { - {"auto", SCLASS, AUTO}, - {"break", BREAK, BREAK}, - {"_Bool", TYPE, BOOL}, - {"case", CASE, CASE}, - {"char", TYPE, CHAR}, - {"const", TQUALIFIER, CONST}, - {"continue", CONTINUE, CONTINUE}, - {"default", DEFAULT, DEFAULT}, - {"do", DO, DO}, - {"double", TYPE, DOUBLE}, - {"else", ELSE, ELSE}, - {"enum", TYPE, ENUM}, - {"extern", SCLASS, EXTERN}, - {"float", TYPE, FLOAT}, - {"for", FOR, FOR}, - {"goto", GOTO, GOTO}, - {"if", IF, IF}, - {"int", TYPE, INT}, - {"long", TYPE, LONG}, - {"register", SCLASS, REGISTER}, - {"restrict", TQUALIFIER, RESTRICT}, - {"return", RETURN, RETURN}, - {"short", TYPE, SHORT}, - {"signed", TYPE, SIGNED}, - {"sizeof", SIZEOF, SIZEOF}, - {"static", SCLASS, STATIC}, - {"struct", TYPE, STRUCT}, - {"switch", SWITCH, SWITCH}, - {"typedef", SCLASS, TYPEDEF}, - {"union", TYPE, UNION}, - {"unsigned", TYPE, UNSIGNED}, - {"void", TYPE, VOID}, - {"volatile", TQUALIFIER, VOLATILE}, - {"while", WHILE, WHILE}, - {NULL, 0, 0}, - }; - register Symbol *sym; - extern short symid; - - for (bp = buff; bp->str; ++bp) { - sym = install(bp->str, NS_IDEN); - sym->token = bp->token; - sym->u.token = bp->value; - } - symid = 0; -} - static uint8_t iden(void) { diff --git a/cc1/symbol.c b/cc1/symbol.c @@ -10,7 +10,8 @@ #define NR_SYM_HASH 32 uint8_t curctx; -short symid; +short localcnt; +short globalcnt; static struct symtab { Symbol *head; @@ -66,8 +67,10 @@ context(Symbol *lbreak, Symbol *lcont, Caselist *lswitch) --curctx; freesyms(NS_IDEN); freesyms(NS_TAG); - if (curctx == 0) + if (curctx == 0) { + localcnt = 0; freesyms(NS_LABEL); + } } Symbol * @@ -95,7 +98,7 @@ install(char *s, uint8_t ns) sym->name = xstrdup(s); sym->ctx = curctx; sym->token = IDEN; - sym->id = symid++; + sym->id = (curctx) ? ++localcnt : ++globalcnt; sym->s.isdefined = 1; tbl = &symtab[ns]; sym->next = tbl->head; @@ -105,3 +108,56 @@ install(char *s, uint8_t ns) sym->hash = *t; return *t = sym; } + +void +init_keywords(void) +{ + static struct { + char *str; + uint8_t token, value; + } *bp, buff[] = { + {"auto", SCLASS, AUTO}, + {"break", BREAK, BREAK}, + {"_Bool", TYPE, BOOL}, + {"case", CASE, CASE}, + {"char", TYPE, CHAR}, + {"const", TQUALIFIER, CONST}, + {"continue", CONTINUE, CONTINUE}, + {"default", DEFAULT, DEFAULT}, + {"do", DO, DO}, + {"double", TYPE, DOUBLE}, + {"else", ELSE, ELSE}, + {"enum", TYPE, ENUM}, + {"extern", SCLASS, EXTERN}, + {"float", TYPE, FLOAT}, + {"for", FOR, FOR}, + {"goto", GOTO, GOTO}, + {"if", IF, IF}, + {"int", TYPE, INT}, + {"long", TYPE, LONG}, + {"register", SCLASS, REGISTER}, + {"restrict", TQUALIFIER, RESTRICT}, + {"return", RETURN, RETURN}, + {"short", TYPE, SHORT}, + {"signed", TYPE, SIGNED}, + {"sizeof", SIZEOF, SIZEOF}, + {"static", SCLASS, STATIC}, + {"struct", TYPE, STRUCT}, + {"switch", SWITCH, SWITCH}, + {"typedef", SCLASS, TYPEDEF}, + {"union", TYPE, UNION}, + {"unsigned", TYPE, UNSIGNED}, + {"void", TYPE, VOID}, + {"volatile", TQUALIFIER, VOLATILE}, + {"while", WHILE, WHILE}, + {NULL, 0, 0}, + }; + register Symbol *sym; + + for (bp = buff; bp->str; ++bp) { + sym = install(bp->str, NS_IDEN); + sym->token = bp->token; + sym->u.token = bp->value; + } + globalcnt = 0; +} diff --git a/cc2/cc2.h b/cc2/cc2.h @@ -17,9 +17,12 @@ typedef struct node { int8_t sethi; int8_t addrtype; union { - short id; + Symbol *sym; int imm; } u; struct node *left, *right; } Node; +#define AUTO 'A' +#define REGISTER 'R' +#define STATIC 'S' diff --git a/cc2/parser.c b/cc2/parser.c @@ -21,17 +21,37 @@ static Node *listexp[NR_EXPRESSIONS], **listp = &listexp[0]; static Node nodepool[NR_NODEPOOL], *newp = nodepool; static Symbol symtbl[NR_SYMBOLS]; +static Symbol *localtbl; +static Symbol *globaltbl; + extern void esyntax(void); -static short -getid(void) +static Symbol * +local(void) +{ + unsigned i; + static unsigned nr; + + scanf("%u", &i); + if (i >= NR_INT_IDENT) + esyntax(); + if (i >= nr) + localtbl = xrealloc(localtbl, i+1); + return &localtbl[i]; +} + +static Symbol * +global(void) { - int i; + unsigned i; + static unsigned nr; - scanf("%d", &i); - if (i < 0 || i >= NR_SYMBOLS) + scanf("%u", &i); + if (i >= NR_EXT_IDENT) esyntax(); - return i; + if (i >= nr) + globaltbl = xrealloc(globaltbl, i+1); + return &globaltbl[i]; } static Node * @@ -82,12 +102,31 @@ gettype(void) static void variable(char op) { + Symbol *sym; Node *np = newnode(); - short id = getid(); + switch (op) { + case 'A': + sym = local(); + op = AUTO; + break; + case 'R': + sym = local(); + op = REGISTER; + break; + case 'T': + sym = local(); + op = STATIC; + break; + case 'G': + sym = global(); + op = STATIC; + break; + } + + np->u.sym = sym; np->op = op; - np->u.id = id; - np->type = symtbl[id].u.v.type; + np->type = sym->u.v.type; np->left = np->right = NULL; push(np); } @@ -168,9 +207,9 @@ expression(void) } static void -declaration(char sclass) +declaration(char sclass, char islocal) { - Symbol *sym = &symtbl[getid()]; + Symbol *sym = (islocal) ? local() : global(); getchar(); /* skip tab */ sym->u.v.storage = sclass; @@ -191,7 +230,7 @@ chop(void) static void deflabel(void) { - Symbol *sym = &symtbl[getid()]; + Symbol *sym = local(); sym->u.l.addr = listp - listexp; chop(); @@ -217,7 +256,7 @@ function(void) /* struct */ break; case 'T': case 'A': case 'R': - declaration(c); + declaration(c, 1); break; case '}': chop(); @@ -238,7 +277,7 @@ parse(void) for (;;) { switch (c = getchar()) { case 'G': - declaration(c); + declaration(c, 0); break; case 'X': function();