scc

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

commit 474ced6ed3e9334fb952e6503db2eb39f33bccef
parent dd9a761673306afd6ce10efffdbd224540b85f10
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Wed, 27 Sep 2017 16:28:18 +0100

[as] Add support for registers in expressions

Diffstat:
as/as.h | 4+++-
as/expr.c | 50++++++++++++++++++++++++++++++++++++++++----------
as/symbol.c | 16++++++++++------
as/target/i386/proc.c | 2+-
as/target/z80/proc.c | 2+-
5 files changed, 55 insertions(+), 19 deletions(-)

diff --git a/as/as.h b/as/as.h @@ -3,10 +3,12 @@ * type of segment */ enum symtype { + TUNDEF = 0, TABS = 1, TTEXT = 2, TBSS = 3, TDATA = 4, + TREG = 5, TMASK = 7, }; @@ -95,7 +97,7 @@ extern Symbol *tmpsym(TUINT val); extern void killtmp(void); /* main.c */ -extern Symbol *lookup(char *name); +extern Symbol *lookup(char *name, int type); extern Symbol *deflabel(char *name); /* parser.c */ diff --git a/as/expr.c b/as/expr.c @@ -181,7 +181,7 @@ iden(void) while (isalnum(c = *endp) || c == '_' || c == '.') ++endp; tok2str(); - yylval.sym = lookup(yytext); + yylval.sym = lookup(yytext, TUNDEF); return IDEN; } @@ -238,6 +238,21 @@ operator(void) } static int +reg(void) +{ + int c; + char *p; + + while (isalnum(c = *endp)) + ++endp; + tok2str(); + yylval.sym = lookup(yytext, TREG); + if (!yylval.sym->argtype) + error("incorrect register name"); + return REG; +} + +static int next(void) { int c; @@ -246,20 +261,34 @@ next(void) ++textp; endp = textp; - if ((c = *textp) == '\0') { + + switch (c = *textp) { + case '\0': strcpy(yytext, "EOS"); yylen = 3; c = EOS; - } else if (isalpha(c) || c == '_' || c == '.') { - c = iden(); - } else if (isdigit(c)) { - c = number(); - } else if (c == '\"') { + break; + case '"': c = string(); - } else if (c == '\'') { + break; + case '\'': c = character(); - } else { - c = operator(); + break; + case '%': + c = reg(); + break; + case '#': + case '$': + c = number(); + break; + default: + if (isdigit(c)) + c = number(); + else if (isalpha(c) || c == '_' || c == '.') + c = iden(); + else + c = operator(); + break; } return yytoken = c; @@ -291,6 +320,7 @@ primary(void) Node *np; switch (yytoken) { + case REG: case NUMBER: case IDEN: case STRING: diff --git a/as/symbol.c b/as/symbol.c @@ -44,11 +44,11 @@ static Alloc *tmpalloc; Symbol *linesym; Symbol * -lookup(char *name) +lookup(char *name, int type) { unsigned h; Symbol *sym, **list; - int c; + int c, symtype; char *t, *s; h = 0; @@ -60,13 +60,17 @@ lookup(char *name) list = &hashtbl[h]; for (sym = *list; sym; sym = sym->next) { t = sym->name; - if (c == toupper(*t) && !casecmp(t, name)) - return sym; + if (c != toupper(*t) || casecmp(t, name)) + continue; + symtype = sym->flags & TMASK; + if (symtype != TUNDEF && symtype != type) + continue; + return sym; } sym = xmalloc(sizeof(*sym)); sym->name = xstrdup(name); - sym->flags = (cursec->flags & TMASK) | FLOCAL | FUNDEF; + sym->flags = (cursec->flags & TMASK) | FLOCAL | FUNDEF | type; sym->desc = 0; sym->value = 0; sym->next = *list; @@ -100,7 +104,7 @@ deflabel(char *name) name = label; } - sym = lookup(name); + sym = lookup(name, TUNDEF); if (pass == 1 && (sym->flags & FUNDEF) == 0) error("redefinition of label '%s'", name); sym->flags &= ~FUNDEF; diff --git a/as/target/i386/proc.c b/as/target/i386/proc.c @@ -92,7 +92,7 @@ iarch(void) }, *bp; for (bp = regs; bp->name; ++bp) { - Symbol *sym = lookup(bp->name); + Symbol *sym = lookup(bp->name, TREG); sym->argtype = bp->type; } } diff --git a/as/target/z80/proc.c b/as/target/z80/proc.c @@ -45,7 +45,7 @@ iarch(void) }, *bp; for (bp = regs; bp->name; ++bp) { - Symbol *sym = lookup(bp->name); + Symbol *sym = lookup(bp->name, TREG); sym->argtype = bp->type; } }