scc

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

commit 217331e8371160ff041a36e348b9a50ce3b81043
parent 2f85abe8f705f3fe4b60a58f94b15c8bd0f314d3
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Mon,  9 May 2016 14:20:21 +0200

[cc2-qbe] Add OBRANCH generation

OBRANCH is similar to OJMP, but it has a condition expression
and two labels instead of only one. A new function label()
is created to convert labels into nodes, which are needed
for jumps. Before this commit the code was making tricks
to link labels and nodes. This is not the best solution,
but it is the simpler.

Diffstat:
Mcc2/arch/qbe/arch.h | 1+
Mcc2/arch/qbe/cgen.c | 24+++++++++++++++++++++---
Mcc2/arch/qbe/code.c | 17+++++++++++++++--
Mcc2/cc2.h | 1+
Mcc2/code.c | 15++++++++++++---
5 files changed, 50 insertions(+), 8 deletions(-)

diff --git a/cc2/arch/qbe/arch.h b/cc2/arch/qbe/arch.h @@ -131,5 +131,6 @@ enum asmop { ASTRUNCD, ASJMP, + ASBRANCH, ASRET, }; diff --git a/cc2/arch/qbe/cgen.c b/cc2/arch/qbe/cgen.c @@ -216,7 +216,7 @@ cast(Node *nd, Node *ns) Node * cgen(Node *np) { - Node *l, *r; + Node *l, *r, *ifyes, *ifno, *next; Symbol *sym; Type *tp; int op, off; @@ -335,9 +335,27 @@ cgen(Node *np) case OOR: abort(); case OBRANCH: - abort(); + if (l && (l->flags & (ISTMP|ISCONS)) == 0) + l = np->left = load(l); + next = np->next; + if (next->label) { + sym = getsym(TMPSYM); + sym->kind = SLABEL; + next->label = sym; + } + ifyes = label(np->u.sym); + ifno = label(next->label); + op = ASBRANCH; + np = np->left; + goto emit_jump; case OJMP: - code(ASJMP, np, NULL, NULL); + ifyes = label(np->u.sym); + op = ASJMP; + np = ifno = NULL; + emit_jump: + code(op, np, ifyes, ifno); + deltree(ifyes); + deltree(ifno); return NULL; case ORET: if (l && (l->flags & (ISTMP|ISCONS)) == 0) diff --git a/cc2/arch/qbe/code.c b/cc2/arch/qbe/code.c @@ -9,7 +9,8 @@ #define ADDR_LEN (IDENTSIZ+64) -static void binary(void), unary(void), store(void), jmp(void), ret(void); +static void binary(void), unary(void), store(void), jmp(void), ret(void), + branch(void); static struct opdata { void (*fun)(void); @@ -122,6 +123,7 @@ static struct opdata { [ASEXTS] = {.fun = unary, .txt = "exts", .letter = 'd'}, [ASSLTOS]= {.fun = unary, .txt = "truncd", .letter = 's'}, + [ASBRANCH] = {.fun = branch}, [ASJMP] = {.fun = jmp}, [ASRET] = {.fun = ret}, }; @@ -403,7 +405,18 @@ ret(void) static void jmp(void) { - printf("\t\tjmp\t%s\n", addr2txt(&pc->to)); + printf("\t\tjmp\t%s\n", addr2txt(&pc->from1)); +} + +static void +branch(void) +{ + char to[ADDR_LEN], from1[ADDR_LEN], from2[ADDR_LEN]; + + strcpy(to, addr2txt(&pc->to)); + strcpy(from1, addr2txt(&pc->from1)); + strcpy(from2, addr2txt(&pc->from2)); + printf("\t\tjnz\t%s,%s,%s\n", to, from1, from2); } void diff --git a/cc2/cc2.h b/cc2/cc2.h @@ -202,6 +202,7 @@ extern void writeout(void), endinit(void), newfun(void); extern void code(int op, Node *to, Node *from1, Node *from2); extern void defvar(Symbol *), defpar(Symbol *), defglobal(Symbol *); extern void setlabel(Symbol *sym); +extern Node *label(Symbol *sym); /* node.c */ #define SETCUR 1 diff --git a/cc2/code.c b/cc2/code.c @@ -38,7 +38,6 @@ addr(Node *np, Addr *addr) addr->kind = OCONST; addr->u.i = np->u.i; break; - case OJMP: case OLABEL: addr->kind = SLABEL; goto symbol; @@ -50,11 +49,21 @@ addr(Node *np, Addr *addr) symbol: addr->u.sym = np->u.sym; break; - default: - abort(); } } +Node * +label(Symbol *sym) +{ + Node *np; + + np = newnode(); + np->op = OLABEL; + np->u.sym = sym; + + return np; +} + void setlabel(Symbol *sym) {