scc

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

commit 1cc0995ffaabe9f5abc298123ff591df5ca32ce0
parent 169482fbf00dd02608f6fa20c928bdf12a56363d
Author: Roberto E. Vargas Caballero <roberto.vargas@igrid-td.com>
Date:   Thu,  7 Apr 2016 08:45:10 +0200

[cc2] Add defpar() and defvar()

Every target is going to do different things when a parameter
or a variable is declared, so the best thing we can do is to
create new functions to signal them these parsing events.

Diffstat:
Mcc2/arch/amd64-sysv/code.c | 19+++++++++++++++++--
Mcc2/arch/i386-sysv/code.c | 19+++++++++++++++++--
Mcc2/arch/qbe/code.c | 14++++++++++++--
Mcc2/arch/z80/cgen.c | 66++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mcc2/arch/z80/code.c | 43+++++++++++++++++++++++++++++++++++++++++--
Mcc2/cc2.h | 19++++++++++++++-----
Mcc2/node.c | 4+++-
Mcc2/parser.c | 54++++++++++++++++++++++--------------------------------
8 files changed, 192 insertions(+), 46 deletions(-)

diff --git a/cc2/arch/amd64-sysv/code.c b/cc2/arch/amd64-sysv/code.c @@ -174,16 +174,31 @@ label(Symbol *sym) } void -defsym(Symbol *sym, int alloc) +defglobal(Symbol *sym) { label(sym); - if (!alloc || (sym->type.flags & INITF)) + if (sym->kind == EXTRN || (sym->type.flags & INITF)) return; size2asm(&sym->type); puts("0"); } void +defvar(Symbol *sym) +{ +} + +void +defpar(Symbol *sym) +{ +} + +void +newfun(void) +{ +} + +void writeout(void) { } diff --git a/cc2/arch/i386-sysv/code.c b/cc2/arch/i386-sysv/code.c @@ -173,16 +173,31 @@ label(Symbol *sym) } void -defsym(Symbol *sym, int alloc) +defglobal(Symbol *sym) { label(sym); - if (!alloc || (sym->type.flags & INITF)) + if (sym->kind == EXTRN || (sym->type.flags & INITF)) return; size2asm(&sym->type); puts("0"); } void +defpar(Symbol *sym) +{ +} + +void +defvar(Symbol *sym) +{ +} + +void +newfun(void) +{ +} + +void writeout(void) { } diff --git a/cc2/arch/qbe/code.c b/cc2/arch/qbe/code.c @@ -109,9 +109,9 @@ size2asm(Type *tp) } void -defsym(Symbol *sym, int alloc) +defglobal(Symbol *sym) { - if (!alloc) + if (sym->kind == EXTRN) return; if (sym->kind == GLOB) fputs("export ", stdout); @@ -122,6 +122,16 @@ defsym(Symbol *sym, int alloc) } void +defpar(Symbol *sym) +{ +} + +void +defvar(Symbol *sym) +{ +} + +void data(Node *np) { putchar('\t'); diff --git a/cc2/arch/z80/cgen.c b/cc2/arch/z80/cgen.c @@ -7,7 +7,73 @@ generate(void) { } +/* + * This is strongly influenced by + * http://plan9.bell-labs.com/sys/doc/compiler.ps (/sys/doc/compiler.ps) + * calculate addresability as follows + * AUTO => 11 value+fp + * REG => 13 reg + * STATIC => 12 (value) + * CONST => 20 $value + */ +static Node * +address(Node *np) +{ + Node *lp, *rp; + + if (!np) + return np; + + np->complex = 0; + np->address = 0; + lp = np->left; + rp = np->right; + switch (np->op) { + case AUTO: + np->address = 11; + break; + case REG: + np->address = 13; + break; + case MEM: + np->address = 12; + break; + case CONST: + np->address = 20; + break; + default: + if (lp) + address(lp); + if (rp) + address(rp); + break; + } + + if (np->address > 10) + return np; + if (lp) + np->complex = lp->complex; + if (rp) { + int d = np->complex - rp->complex; + + if (d == 0) + ++np->complex; + else if (d < 0) + np->complex = rp->complex; + } + if (np->complex == 0) + ++np->complex; + return np; +} + void addressability(void) { + Node *np; + + if (!curfun) + return; + + for (np = curfun->u.label; np; np = np->stmt) + address(np); } diff --git a/cc2/arch/z80/code.c b/cc2/arch/z80/code.c @@ -14,6 +14,7 @@ enum segment { }; static int curseg = NOSEG; +static TSIZE offpar, offvar; static void segment(int seg) @@ -162,10 +163,48 @@ size2asm(Type *tp) } void -defsym(Symbol *sym, int alloc) +newfun() +{ + offpar = offvar = 0; +} + +void +defpar(Symbol *sym) +{ + TSIZE align, size; + + if (sym->kind != REG && sym->kind != AUTO) + return; + align = sym->type.align; + size = sym->type.size; + + offpar -= align-1 & ~align; + sym->u.off = offpar; + offpar -= size; + sym->kind = AUTO; +} + +void +defvar(Symbol *sym) +{ + TSIZE align, size; + + if (sym->kind != REG && sym->kind != AUTO) + return; + align = sym->type.align; + size = sym->type.size; + + offvar += align-1 & ~align; + sym->u.off = offvar; + offvar += size; + sym->kind = AUTO; +} + +void +defglobal(Symbol *sym) { label(sym); - if (!alloc || (sym->type.flags & INITF)) + if (sym->kind == EXTRN || (sym->type.flags & INITF)) return; size2asm(&sym->type); puts("0"); diff --git a/cc2/cc2.h b/cc2/cc2.h @@ -35,14 +35,22 @@ enum op { MEM = 'M', AUTO = 'A', REG = 'R', + CONST = '#', + STRING = '"', + LABEL = 'L', /* storage class */ GLOB = 'G', EXTRN = 'X', PRIVAT = 'Y', LOCAL = 'T', MEMBER = 'M', - LABEL = 'L', /* operands */ + OMEM = 'M', + OAUTO = 'A', + OREG = 'R', + OCONST = '#', + OSTRING = '"', + OLABEL = 'L', OADD = '+', OSUB = '-', OMUL = '*', @@ -74,8 +82,6 @@ enum op { OPTR = '@', OSYM = 'i', OCAST = 'g', - OCONST = '#', - OSTRING = '"', OINC = 'i', ODEC = 'd', /*statements */ @@ -134,6 +140,8 @@ struct symbol { struct node { char op; Type type; + char complex; + char address; union { TUINT i; char *s; @@ -163,14 +171,15 @@ extern void peephole(void); /* code.c */ extern void data(Node *np); -extern void defsym(Symbol *sym, int alloc); -extern void writeout(void), endinit(void); +extern void writeout(void), endinit(void), newfun(void); +extern void defvar(Symbol *), defpar(Symbol *), defglobal(Symbol *); /* node.c */ extern void cleannodes(void); extern void delnode(Node *np); extern void deltree(Node *np); extern Node *newnode(void); +extern Symbol *curfun; /* symbol.c */ extern Symbol *getsym(int id); diff --git a/cc2/node.c b/cc2/node.c @@ -8,14 +8,16 @@ #define NSYMBOLS 32 -int inhome; +Symbol *curfun; struct arena { Node *mem; struct arena *next; }; + static struct arena *arena; static Node *freep; +static int inhome; Node * newnode(void) diff --git a/cc2/parser.c b/cc2/parser.c @@ -44,14 +44,14 @@ static struct decoc { void (*parse)(char *token, union tokenop); union tokenop u; } optbl[] = { /* eval parse args */ - [AUTO] = { vardecl, symbol, .u.op = AUTO}, - [REG] = { vardecl, symbol, .u.op = REG}, - [GLOB] = { vardecl, symbol, .u.op = MEM}, - [EXTRN] = { vardecl, symbol, .u.op = MEM}, - [PRIVAT] = { vardecl, symbol, .u.op = MEM}, - [LOCAL] = { vardecl, symbol, .u.op = MEM}, - [MEMBER] = { flddecl, symbol, 0}, - [LABEL] = { labeldcl, symbol, 0}, + [AUTO] = { vardecl, symbol, .u.op = OAUTO}, + [REG] = { vardecl, symbol, .u.op = OREG}, + [GLOB] = { vardecl, symbol, .u.op = OMEM}, + [EXTRN] = { vardecl, symbol, .u.op = OMEM}, + [PRIVAT] = { vardecl, symbol, .u.op = OMEM}, + [LOCAL] = { vardecl, symbol, .u.op = OMEM}, + [MEMBER] = { flddecl, symbol, .u.op = OMEM}, + [LABEL] = { labeldcl, symbol, .u.op = OLABEL}, [INT8] = { NULL, type, .u.arg = &int8type}, [INT16] = { NULL, type, .u.arg = &int16type}, @@ -130,11 +130,9 @@ static struct decoc { [OTABLE] = { NULL, casetbl, 0} }; -static Symbol *curfun; -static int funpars = -1, sclass, ininit, endf, lineno; +static int sclass, inpars, ininit, endf, lineno; static Node *stmtp; static void *stack[STACKSIZ], **sp = stack; -static Symbol *params[NR_FUNPARAM]; static void push(void *elem) @@ -447,9 +445,9 @@ einit(char *token, union tokenop u) static void endpars(void) { - if (!curfun || funpars == -1) + if (!curfun || !inpars) error(ESYNTAX); - funpars = -1; + inpars = 0; } static void @@ -499,35 +497,28 @@ array(void) static void decl(Symbol *sym) { - int alloc; Type *tp = &sym->type; if (tp->flags & FUNF) { curfun = sym; - return; } else { switch (sym->kind) { case EXTRN: - alloc = 0; - break; case GLOB: case PRIVAT: case LOCAL: - alloc = 1; + defglobal(sym); break; case AUTO: case REG: - if (funpars >= 0) { - if (funpars == NR_FUNPARAM) - error(EOUTPAR); - params[funpars++] = sym; - } - return; + if (!curfun) + error(ESYNTAX); + ((inpars) ? defpar : defvar)(sym); + break; default: abort(); } } - defsym(sym, alloc); } static void @@ -622,8 +613,7 @@ stmt(void) static void beginfun(void) { - memset(params, 0, sizeof(params)); - funpars = 0; + inpars = 0; pushctx(); } @@ -633,19 +623,19 @@ endfun(void) Node *np; np = newnode(); - np->op = ONOP; - addstmt(np); - /* TODO: process the function */ curfun = NULL; - funpars = -1; + inpars = 0; /* I know, it is a bit redundant */ endf = 1; - popctx(); } void parse(void) { + cleannodes(); /* remove code of previous function */ + popctx(); /* remove context of previous function */ + curfun = NULL; endf = 0; + while (!endf && nextline()) /* nothing */; if (ferror(stdin))