scc

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

commit 79e21860ac133bb98f1dcf5a1ecf22759e6e0e26
parent 497fb0862cf20043e7f735c93b2e8f24934adf1f
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Fri,  8 Sep 2017 17:41:54 +0200

[as] Remove Bucket structure

A 2 pass assembler knows the size of the section, so we can
allocate the full buffer for it and avoid linked lists.

Diffstat:
as/as.h | 9++++-----
as/emit.c | 68+++++++++++++-------------------------------------------------------
as/main.c | 4+++-
3 files changed, 20 insertions(+), 61 deletions(-)

diff --git a/as/as.h b/as/as.h @@ -10,7 +10,7 @@ typedef struct ins Ins; typedef struct op Op; typedef struct arg Arg; typedef void Format(Op *, Arg *); -typedef struct sec Section; +typedef struct section Section; enum { BITS16, @@ -34,13 +34,12 @@ struct arg { TUINT val; }; -struct bucket; - -struct sec { +struct section { char *name; - struct bucket *mem; + char *mem; int flags; TUINT base; + TUINT max; TUINT curpc; TUINT pc; }; diff --git a/as/emit.c b/as/emit.c @@ -5,16 +5,6 @@ #include "../inc/scc.h" #include "as.h" -#define BUCKETSIZ 0x100 - -typedef struct bucket Bucket; - -struct bucket { - char mem[BUCKETSIZ]; - TUINT base; - struct bucket *next; -}; - Section text = (Section) {.name = "text", .flags = SRELOC|SEXEC|SFILE}; Section data = (Section) {.name = "data", .flags = SRELOC|SREAD|SWRITE|SFILE}; Section bss = (Section) {.name = "bss", .flags = SRELOC|SREAD|SWRITE}; @@ -22,42 +12,20 @@ Section *cursec = &text; int pass; -void -isections(void) -{ - text.curpc = text.pc = text.base; - data.curpc = data.pc = data.base; - bss.curpc = bss.pc = bss.base; -} - -static struct bucket * -alloc(TUINT addr) +static void +isec(Section *sec) { - struct bucket *bp; - - bp = memset(xmalloc(sizeof(*bp)), 0, sizeof(*bp)); - bp->base = addr+BUCKETSIZ & BUCKETSIZ-1; - return bp; + sec->curpc = sec->pc = sec->base; + if (sec->max > 0) + sec->mem = xmalloc(sec->max - sec->base); } -static void -emitbyte(Section *sec, char byte, TUINT addr) +void +isections(void) { - struct bucket *cur, *next; - TUINT base; - - for (cur = sec->mem; ; cur = cur->next) { - base = cur->base; - if (base <= addr && addr < base+BUCKETSIZ) - break; - - next = cur->next; - if (base < addr && next->base > addr) { - cur->next = alloc(addr); - cur->next->next = next; - } - } - cur->mem[addr - cur->base] = byte; + isec(&text); + isec(&data); + isec(&bss); } void @@ -68,29 +36,19 @@ emit(Section *sec, char *bytes, int nbytes) if (pass == 1 || !(sec->flags & SFILE)) return; - if (!sec->mem) { - sec->mem = alloc(sec->base); - sec->mem->next = sec->mem; - } - - for (addr = sec->pc; nbytes--; addr++) - emitbyte(sec, *bytes++, addr); + for (addr = sec->pc - sec->base; nbytes--; addr++) + sec->mem[addr] = *bytes++; } void writeout(char *name) { FILE *fp; - Bucket *bp; if ((fp = fopen(name, "wb")) == NULL) die("error opening output file '%s'\n", name); - for (bp = text.mem; ; bp = bp->next) { - fwrite(bp->mem, BUCKETSIZ, 1, fp); - if (bp->next == text.mem) - break; - } + fwrite(text.mem, text.max - text.base, 1, fp); if (fclose(fp)) die("error writing the output file"); diff --git a/as/main.c b/as/main.c @@ -69,8 +69,10 @@ as(char *text, char *xargs) return; } (*op->format)(op, args); - cursec->pc += op->size; cursec->curpc += op->size; + cursec->pc += op->size; + if (cursec->pc > cursec->max) + cursec->max = cursec->pc; } int