scc

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

commit f6ede3c51c169d6115b12de5cce5b1881d0b3247
parent 0b5080ef495991eb73e8d946285a14d1ca143409
Author: Roberto E. Vargas Caballero <Roberto E. Vargas Caballero>
Date:   Fri, 22 Apr 2016 00:03:16 +0200

Merge remote-tracking branch 'origin/master'

Diffstat:
Mcc2/arch/qbe/arch.h | 15+++++++++++++--
Mcc2/arch/qbe/cgen.c | 45+++++++++++++++++++++++++++++++++++++++------
Mcc2/arch/qbe/code.c | 72+++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------
Mcc2/cc2.h | 4++--
Mcc2/node.c | 1+
Mcc2/parser.c | 7+++++--
6 files changed, 115 insertions(+), 29 deletions(-)

diff --git a/cc2/arch/qbe/arch.h b/cc2/arch/qbe/arch.h @@ -5,8 +5,19 @@ #define TSIZE unsigned long enum asmop { - ASLOAD, - ASASSIG, + ASSTB, + ASSTH, + ASSTW, + ASSTL, + ASSTS, + ASSTD, + + ASLDB, + ASLDH, + ASLDW, + ASLDL, + ASLDS, + ASLDD, ASADDW, ASSUBW, diff --git a/cc2/arch/qbe/cgen.c b/cc2/arch/qbe/cgen.c @@ -107,11 +107,30 @@ static Node * load(Node *np) { Node *new; + int op; + Type *tp = &np->type; new = tmpnode(newnode()); new->left = np; - new->type = np->type; - code(ASLOAD, new, np, NULL); + new->type = *tp; + + switch (tp->size) { + case 1: + op = ASLDB; + break; + case 2: + op = ASLDH; + break; + case 4: + op = (tp->flags & INTF) ? ASLDW : ASLDS; + break; + case 8: + op = (tp->flags & INTF) ? ASLDL : ASLDD; + break; + default: + abort(); + } + code(op, new, np, NULL); return new; } @@ -133,7 +152,6 @@ cgen(Node *np) tp = &np->type; switch (np->op) { - case OREG: case OSTRING: abort(); case OCONST: @@ -182,8 +200,7 @@ cgen(Node *np) l = np->left = load(l); if ((r->flags & (ISTMP|ISCONS)) == 0) r = np->right = load(r); - tmpnode(np); - code(op, np, l, r); + code(op, tmpnode(np), l, r); return np; case ONOP: case OBLOOP: @@ -198,7 +215,23 @@ cgen(Node *np) case ODEC: abort(); case OASSIG: - code(ASASSIG, l, r, NULL); + switch (tp->size) { + case 1: + op = ASSTB; + break; + case 2: + op = ASSTH; + break; + case 4: + op = (tp->flags & INTF) ? ASSTW : ASSTS; + break; + case 8: + op = (tp->flags & INTF) ? ASSTL : ASSTD; + break; + default: + abort(); + } + code(op, l, r, NULL); return r; case OCALL: case OFIELD: diff --git a/cc2/arch/qbe/code.c b/cc2/arch/qbe/code.c @@ -16,8 +16,19 @@ static struct opdata { char *txt; char letter; } optbl [] = { - [ASLOAD] = {.fun = load, .txt = "load", .letter = 'w'}, - [ASASSIG] = {.fun = store, .txt = "store", .letter = 'w'}, + [ASLDB] = {.fun = load, .txt = "load", .letter = 'b'}, + [ASLDH] = {.fun = load, .txt = "load", .letter = 'h'}, + [ASLDW] = {.fun = load, .txt = "load", .letter = 'w'}, + [ASLDL] = {.fun = load, .txt = "load", .letter = 'l'}, + [ASLDS] = {.fun = load, .txt = "load", .letter = 's'}, + [ASLDD] = {.fun = load, .txt = "load", .letter = 'd'}, + + [ASSTB] = {.fun = store, .txt = "store", .letter = 'b'}, + [ASSTH] = {.fun = store, .txt = "store", .letter = 'h'}, + [ASSTW] = {.fun = store, .txt = "store", .letter = 'w'}, + [ASSTL] = {.fun = store, .txt = "store", .letter = 'l'}, + [ASSTS] = {.fun = store, .txt = "store", .letter = 's'}, + [ASSTD] = {.fun = store, .txt = "store", .letter = 'd'}, [ASADDW] = {.fun = binary, .txt = "add", .letter = 'w'}, [ASSUBW] = {.fun = binary, .txt = "sub", .letter = 'w'}, @@ -250,31 +261,53 @@ data(Node *np) putchar('\n'); } +static void +alloc(Symbol *sym) +{ + Type *tp = &sym->type; + + printf("\t%s %s=\talloc%lld\t%lld\n", + symname(sym), size2asm(tp), + (long long) tp->size, (long long) tp->align); +} + void writeout(void) { Symbol *p; Type *tp; - char *sep; + char *sep, *name; if (curfun->kind == SGLOB) fputs("export ", stdout); - printf("function %s %s(", size2asm(&curfun->rtype), symname(curfun)); + printf("function %s %s(", size2asm(&rtype), symname(curfun)); + /* declare formal parameters */ for (sep = "", p = locals; p; p = p->next, sep = ",") { if ((p->type.flags & PARF) == 0) break; - printf("%s%s %s", sep, size2asm(&p->type), symname(p)); + printf("%s%s %s.val", sep, size2asm(&p->type), symname(p)); } - puts(")"); + puts(")\n{"); + + /* allocate stack space for parameters */ + for (p = locals; p && (p->type.flags & PARF) == 0; p = p->next) + alloc(p); - for ( ; p && p->id != TMPSYM; p = p->next) { + /* allocate stack space for local variables) */ + for ( ; p && p->id != TMPSYM; p = p->next) + alloc(p); + + /* store formal parameters in parameters */ + for (p = locals; p; p = p->next) { tp = &p->type; - printf("\t%s %s=\talloc%lld\t%lld\n", - symname(p), size2asm(tp), - (long long) tp->size, (long long) tp->align); + if ((tp->flags & PARF) == 0) + break; + name = symname(p); + printf("\t\tstore%s\t%s.val,%s\n", size2asm(tp), name, name); } + /* emit assembler instructions */ for (pc = prog; pc; pc = pc->next) { if (pc->label) printf("%s:\n", symname(pc->label)); @@ -312,18 +345,23 @@ binary(void) static void store(void) { - printf("\t\t%s%c\t", optbl[pc->op].txt, 'w'), - fputs(addr2txt(&pc->from1), stdout); - putchar(','); - fputs(addr2txt(&pc->to), stdout); - putchar('\n'); + struct opdata *p = &optbl[pc->op]; + char to[ADDR_LEN], from[ADDR_LEN]; + + strcpy(to, addr2txt(&pc->to)); + strcpy(from, addr2txt(&pc->from1)); + printf("\t\t%s%c\t%s,%s\n", p->txt, p->letter, from, to); } static void load(void) { - printf("\t%s %c=\t", addr2txt(&pc->to), 'w'); - printf("%s\t%s\n", optbl[pc->op].txt, addr2txt(&pc->from1)); + struct opdata *p = &optbl[pc->op]; + char to[ADDR_LEN], from[ADDR_LEN]; + + strcpy(to, addr2txt(&pc->to)); + strcpy(from, addr2txt(&pc->from1)); + printf("\t%s %c=\t%s\t%s\n", to, p->letter, p->txt, from); } void diff --git a/cc2/cc2.h b/cc2/cc2.h @@ -132,7 +132,6 @@ struct type { struct symbol { Type type; - Type rtype; unsigned short id; unsigned short numid; char *name; @@ -208,7 +207,6 @@ extern void cleannodes(void); extern void delnode(Node *np); extern void deltree(Node *np); extern Node *newnode(void); -extern Symbol *curfun; /* symbol.c */ #define TMPSYM 0 @@ -218,5 +216,7 @@ extern void pushctx(void); extern void freesym(Symbol *sym); /* globals */ +extern Type rtype; +extern Symbol *curfun; extern Symbol *locals; extern Inst *pc, *prog; diff --git a/cc2/node.c b/cc2/node.c @@ -10,6 +10,7 @@ #define NNODES 32 Symbol *curfun; +Type rtype; struct arena { Node *mem; diff --git a/cc2/parser.c b/cc2/parser.c @@ -181,10 +181,13 @@ static void symbol(char *token, union tokenop u) { Node *np; + Symbol *sym; sclass = u.op >> 8; np = newnode(); - np->u.sym = getsym(atoi(token+1)); + sym = getsym(atoi(token+1)); + np->u.sym = sym; + np->type = sym->type; np->op = u.op & 0xFF; push(np); } @@ -534,7 +537,7 @@ vardecl(void) sym->name = name; sym->type = *tp; if (tp->flags & FUNF) - sym->rtype = *rp; + rtype = *rp; sym->kind = sclass; if (ininit)