ref: 2e0d56a3a143cd10b4d0c5163c0c8a37f54ae511
parent: a4e43c119fe7f2c9e6f2c80b0092ac379fa8e4c7
author: Roberto E. Vargas Caballero <[email protected]>
date: Mon May 9 10:20:21 EDT 2016
[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.
--- a/cc2/arch/qbe/arch.h
+++ b/cc2/arch/qbe/arch.h
@@ -131,5 +131,6 @@
ASTRUNCD,
ASJMP,
+ ASBRANCH,
ASRET,
};
--- a/cc2/arch/qbe/cgen.c
+++ b/cc2/arch/qbe/cgen.c
@@ -216,7 +216,7 @@
Node *
cgen(Node *np)
{
- Node *l, *r;
+ Node *l, *r, *ifyes, *ifno, *next;
Symbol *sym;
Type *tp;
int op, off;
@@ -335,9 +335,27 @@
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)
--- 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 @@
[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 @@
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
--- a/cc2/cc2.h
+++ b/cc2/cc2.h
@@ -202,6 +202,7 @@
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
--- a/cc2/code.c
+++ b/cc2/code.c
@@ -38,7 +38,6 @@
addr->kind = OCONST;
addr->u.i = np->u.i;
break;
- case OJMP:
case OLABEL:
addr->kind = SLABEL;
goto symbol;
@@ -50,9 +49,19 @@
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