scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | README | LICENSE

commit ff7d31971e81ad9a878548ec864a5b972d9a943f
parent 22e4887dcf0da5a1325087e01067dcb3fc57128e
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Fri, 15 Dec 2017 21:59:18 +0100

[as] Rework section layer

There were several problems with the section layer
and this patch unifies sections and symbols, making
easier to handle them.

Diffstat:
Mas/as.h | 11+++++++----
Mas/expr.c | 8++++----
Mas/ins.c | 10++++++----
Mas/main.c | 3++-
Mas/myro.c | 12++----------
Mas/symbol.c | 135++++++++++++++++++++++++++++++++++++++++++++++---------------------------------
Mas/target/i386/proc.c | 3++-
Mas/target/z80/proc.c | 3++-
8 files changed, 103 insertions(+), 82 deletions(-)

diff --git a/as/as.h b/as/as.h @@ -9,6 +9,8 @@ enum symflags { FUNDEF = 1 << 3, FDEDUP = 1 << 4, FRELOC = 1 << 5, + FSECT = 1 << 6, + FNTYPE = 1 << 7, }; enum secflags { @@ -99,7 +101,7 @@ struct op { }; struct section { - String name; + Symbol *sym; char *mem; unsigned char flags; unsigned char fill; @@ -132,9 +134,10 @@ struct node { }; /* symbol.c */ -extern void isections(void); +extern void cleansecs(void); +extern void isecs(void); extern void emit(char *bytes, int nbytes); -extern Section *setsection(char *name); +extern Section *setsec(char *name, char *attr); extern Symbol *tmpsym(TUINT val); extern void killtmp(void); extern int toobig(Node *np, int type); @@ -142,7 +145,7 @@ extern void dumpstab(char *msg); extern String newstring(char *s); /* main.c */ -extern Symbol *lookup(char *name, int type); +extern Symbol *lookup(char *name); extern Symbol *deflabel(char *name); /* parser.c */ diff --git a/as/expr.c b/as/expr.c @@ -200,7 +200,7 @@ iden(void) } tok2str(); - yylval.sym = lookup(yytext, FUNDEF); + yylval.sym = lookup(yytext); return IDEN; } @@ -267,9 +267,9 @@ reg(void) while (isalnum(c = *endp)) ++endp; tok2str(); - yylval.sym = lookup(yytext, FREG); - if (!yylval.sym->argtype) - error("incorrect register name"); + yylval.sym = lookup(yytext); + if ((yylval.sym->flags & FREG) == 0) + error("incorrect register name '%s'", yytext); return REG; } diff --git a/as/ins.c b/as/ins.c @@ -3,6 +3,8 @@ static char sccsid[] = "@(#) ./as/ins.c"; #include "../inc/scc.h" #include "as.h" +extern Section *sabs, *sbss, *sdata, *stext; + char * tobytes(TUINT v, int nbytes, int inc) { @@ -79,23 +81,23 @@ section(Op *op, Node **args) { Symbol *sym = args[0]->sym; - setsection(sym->name.buf); + setsec(sym->name.buf, NULL); } void text(Op *op, Node **args) { - setsection("text"); + cursec = stext; } void data(Op *op, Node **args) { - setsection("data"); + cursec = sdata; } void bss(Op *op, Node **args) { - setsection("bss"); + cursec = sbss; } diff --git a/as/main.c b/as/main.c @@ -75,7 +75,7 @@ dopass(char *fname) if ((fp = fopen(fname, "r")) == NULL) die("as: error opening '%s'", fname); - isections(); + cleansecs(); setjmp(recover); while (nextline(fp, &line)) { @@ -128,6 +128,7 @@ main(int argc, char *argv[]) atexit(cleanup); iarch(); + isecs(); for (pass = 1; pass <= 2; pass++) { if (!dopass(infile)) return 1; diff --git a/as/myro.c b/as/myro.c @@ -35,14 +35,6 @@ writestrings(FILE *fp) off += len; } - for (sp = seclist; sp; sp = sp->next) { - str = &sp->name; - len = strlen(str->buf) + 1; - fwrite(str->buf, len, 1, fp); - str->offset = off; - off += len; - } - return off; } @@ -78,7 +70,7 @@ writesections(FILE *fp) if (id == MYROMAXSEC) die("too many sections for a myro file"); sp->id = id++; - sect.name = sp->name.offset; + sect.name = sp->sym->name.offset; sect.flags = getsecflags(sp); sect.fill = sp->fill; sect.aligment = sp->aligment; @@ -114,7 +106,7 @@ writesymbols(FILE *fp) struct myrosym symbol; for (sym = symlist; sym; sym = sym->next) { - if (sym->flags & FREG) + if (sym->flags & (FREG|FSECT)) continue; symbol.name = sym->name.offset; symbol.type = -1; diff --git a/as/symbol.c b/as/symbol.c @@ -11,37 +11,14 @@ static char sccsid[] = "@(#) ./as/symbol.c"; #define HASHSIZ 64 #define NALLOC 10 -static Section abss = { - .name = (String) {"abs"}, - .flags = SABS|SREAD|SWRITE|SFILE|SLOAD, -}; - -static Section bss = { - .name = (String) {"bss"}, - .flags = SREAD|SWRITE|SLOAD, - .next = &abss, -}; - -static Section data = { - .name = (String) {"data"}, - .flags = SREAD|SWRITE|SFILE|SLOAD, - .next = &bss, -}; - -static Section text = { - .name = (String) {"text"}, - .flags = SREAD|SEXEC|SLOAD|SFILE, - .next = &data, -}; - -Section *cursec = &text, *seclist = &text; - +Section *cursec, *seclist; +Section *sabs, *sbss, *sdata, *stext; +Symbol *linesym, *symlist; int pass; -static Symbol *hashtbl[HASHSIZ]; +static Symbol *hashtbl[HASHSIZ], *symlast; static Alloc *tmpalloc; -Symbol *linesym, *symlist, *symlast; #ifndef NDEBUG void @@ -65,7 +42,7 @@ dumpstab(char *msg) #endif Symbol * -lookup(char *name, int type) +lookup(char *name) { unsigned h; Symbol *sym, **list; @@ -81,17 +58,13 @@ lookup(char *name, int type) list = &hashtbl[h]; for (sym = *list; sym; sym = sym->hash) { t = sym->name.buf; - if (c != toupper(*t) || casecmp(t, name)) - continue; - symtype = sym->flags; - if (((symtype | type) & FUNDEF) == 0 && symtype != type) - continue; - return sym; + if (c == toupper(*t) && !casecmp(t, name)) + return sym; } sym = xmalloc(sizeof(*sym)); sym->name = newstring(name); - sym->flags = FRELOC | FUNDEF | type; + sym->flags = FRELOC | FUNDEF | FNTYPE; sym->value = 0; sym->section = cursec; sym->hash = *list; @@ -132,13 +105,14 @@ deflabel(char *name) name = label; } - sym = lookup(name, FUNDEF); + sym = lookup(name); if (pass == 1 && (sym->flags & FUNDEF) == 0) error("redefinition of label '%s'", name); if (cursec->flags & SABS) sym->flags &= ~FRELOC; sym->flags &= ~FUNDEF; sym->value = cursec->curpc; + sym->section = cursec; if (*name != '.') cursym = sym; @@ -177,50 +151,97 @@ incpc(int siz) } } - -static void -isect(Section *sec) +static int +secflags(char *attr) { - TUINT siz; + int c, flags; - sec->curpc = sec->pc = sec->base; - if (pass == 1 || !(sec->flags & SFILE)) - return; + if (!attr) + return 0; + + for (flags = 0; c = *attr++; ) { + switch (c) { + case 'w': + flags |= SWRITE; + break; + case 'r': + flags |= SREAD; + break; + case 'x': + flags |= SEXEC; + break; + case 'f': + flags |= SFILE; + break; + case 'l': + flags |= SLOAD; + break; + case 'a': + flags |= SABS; + break; + } + } - siz = sec->max - sec->base; - if (siz > SIZE_MAX) - die("out of memory"); - sec->mem = xmalloc(sec->max - sec->base); + return flags; } Section * -setsection(char *name) +setsec(char *name, char *attr) { Section *sec; + Symbol *sym; + int flags; - for (sec = seclist; sec; sec = sec->next) { - if (!strcmp(sec->name.buf, name)) - break; - } - if (!sec) { + cursec = NULL; + sym = lookup(name); + if ((sym->flags & (FNTYPE | FSECT)) == 0) + error("invalid section name '%s'", name); + + if ((sec = sym->section) == NULL) { sec = xmalloc(sizeof(*sec)); - sec->name = newstring(name); + sec->sym = sym; sec->base = sec->max = sec->pc = sec->curpc = 0; sec->next = seclist; sec->flags = 0; sec->fill = 0; sec->aligment = 0; + sec->next = seclist; + seclist = sec; + + sym->section = sec; + sym->flags = FSECT; } + sec->flags |= secflags(attr); + return cursec = sec; } void -isections(void) +isecs(void) +{ + sabs = setsec(".abs", "rwxafl"); + sbss = setsec(".bss", "rwl"); + sdata = setsec(".data", "rwfl"); + stext = setsec(".text", "rxfl"); +} + +void +cleansecs(void) { Section *sec; + TUINT siz; - for (sec = seclist; sec; sec = sec->next) - isect(sec); + for (sec = seclist; sec; sec = sec->next) { + sec->curpc = sec->pc = sec->base; + if (pass == 1 || !(sec->flags & SFILE)) + continue; + + siz = sec->max - sec->base; + if (siz > SIZE_MAX) + die("out of memory"); + sec->mem = xmalloc(sec->max - sec->base); + } + cursec = stext; } void diff --git a/as/target/i386/proc.c b/as/target/i386/proc.c @@ -92,7 +92,8 @@ iarch(void) }, *bp; for (bp = regs; bp->name; ++bp) { - Symbol *sym = lookup(bp->name, FREG); + Symbol *sym = lookup(bp->name); + sym->flags = FREG; sym->argtype = bp->type; } } diff --git a/as/target/z80/proc.c b/as/target/z80/proc.c @@ -45,7 +45,8 @@ iarch(void) }, *bp; for (bp = regs; bp->name; ++bp) { - Symbol *sym = lookup(bp->name, FREG); + Symbol *sym = lookup(bp->name); + sym->flags = FREG; sym->argtype = bp->type; } }