commit 5ef65b780276437e03c0028b418a6be0ef23eba6
parent f36a56a6613493f8e19bf0c8449ce1fd001e9002
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date: Fri, 17 Jun 2016 13:28:26 +0200
[cc2-qbe] Move preambule to code instructions
Until this moment the preambule was writing directly using
printfs calls, but it created some problems related to the
restrictions impossed by qbe about basic blocks. It was
really hard to detect the cases where we were forced
to emit labels to define the begin of a basic block.
With this new approach the preamble is a set of instructions
and we can define where we need labels using the function
introduced a few commits ago.
Diffstat:
5 files changed, 59 insertions(+), 31 deletions(-)
diff --git a/cc2/arch/qbe/arch.h b/cc2/arch/qbe/arch.h
@@ -141,4 +141,6 @@ enum asmop {
ASCALL,
ASPAR,
ASPARE,
+ ASALLOC,
+ ASFORM,
};
diff --git a/cc2/arch/qbe/cgen.c b/cc2/arch/qbe/cgen.c
@@ -351,6 +351,30 @@ ternary(Node *np)
return np;
}
+static Node *
+function(void)
+{
+ Symbol *p;
+
+ /* allocate stack space for parameters */
+ for (p = locals; p && (p->type.flags & PARF) != 0; p = p->next)
+ code(ASALLOC, label2node(p), NULL, NULL);
+
+ /* allocate stack space for local variables) */
+ for ( ; p && p->id != TMPSYM; p = p->next) {
+ if (p->kind != SAUTO)
+ continue;
+ code(ASALLOC, label2node(p), NULL, NULL);
+ }
+ /* store formal parameters in parameters */
+ for (p = locals; p; p = p->next) {
+ if ((p->type.flags & PARF) == 0)
+ break;
+ code(ASFORM, label2node(p), NULL, NULL);
+ }
+ return NULL;
+}
+
/* TODO: Fix "memory leaks" */
Node *
cgen(Node *np)
@@ -374,6 +398,10 @@ cgen(Node *np)
switch (np->op) {
case OSTRING:
abort();
+ case OBFUN:
+ return function();
+ case OEFUN:
+ return NULL;
case OCONST:
case OLABEL:
np->flags |= ISCONS;
diff --git a/cc2/arch/qbe/code.c b/cc2/arch/qbe/code.c
@@ -10,7 +10,8 @@
#define ADDR_LEN (INTIDENTSIZ+64)
static void binary(void), unary(void), store(void), jmp(void), ret(void),
- branch(void), call(void), ecall(void), param(void);
+ branch(void), call(void), ecall(void), param(void),
+ alloc(void), form2local(void);
static struct opdata {
void (*fun)(void);
@@ -135,6 +136,8 @@ static struct opdata {
[ASCALL] = {.fun = ecall},
[ASPAR] = {.fun = param, .txt = "%s %s, "},
[ASPARE] = {.fun = param, .txt = "%s %s"},
+ [ASALLOC] = {.fun = alloc},
+ [ASFORM] = {.fun = form2local},
};
static char buff[ADDR_LEN];
@@ -295,16 +298,6 @@ data(Node *np)
putchar('\n');
}
-static void
-alloc(Symbol *sym)
-{
- Type *tp = &sym->type;
- extern Type ptrtype;
-
- printf("\t%s =%s\talloc%lu\t%lu\n",
- symname(sym), size2asm(&ptrtype), tp->align+3 & ~3, tp->size );
-}
-
void
writeout(void)
{
@@ -324,24 +317,6 @@ writeout(void)
}
puts(")\n{\n@.start");
- /* allocate stack space for parameters */
- for (p = locals; p && (p->type.flags & PARF) != 0; p = p->next)
- alloc(p);
-
- /* allocate stack space for local variables) */
- for ( ; p && p->id != TMPSYM; p = p->next) {
- if (p->kind == SAUTO)
- alloc(p);
- }
- /* store formal parameters in parameters */
- for (p = locals; p; p = p->next) {
- tp = &p->type;
- 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)
@@ -349,8 +324,6 @@ writeout(void)
if (pc->op)
(*optbl[pc->op].fun)();
}
- if (!prog)
- puts("\t\tret");
puts("}");
}
@@ -461,6 +434,27 @@ branch(void)
printf("\t\tjnz\t%s,%s,%s\n", to, from1, from2);
}
+static void
+alloc(void)
+{
+ Symbol *sym = pc->to.u.sym;
+ Type *tp = &sym->type;
+ extern Type ptrtype;
+
+ printf("\t%s =%s\talloc%lu\t%lu\n",
+ symname(sym), size2asm(&ptrtype), tp->align+3 & ~3, tp->size);
+}
+
+static void
+form2local(void)
+{
+ Symbol *sym = pc->to.u.sym;
+ Type *tp = &sym->type;
+ char *name = symname(sym);
+
+ printf("\t\tstore%s\t%s.val,%s\n", size2asm(tp), name, name);
+}
+
void
endinit(void)
{
diff --git a/cc2/cc2.h b/cc2/cc2.h
@@ -106,6 +106,8 @@ enum op {
ODEFAULT = 'f',
OBSWITCH = 's',
OESWITCH = 't',
+ OBFUN = 'x',
+ OEFUN = 'k',
};
enum nerrors {
diff --git a/cc2/parser.c b/cc2/parser.c
@@ -630,12 +630,14 @@ beginfun(void)
{
inpars = 1;
pushctx();
+ addstmt(newnode(OBFUN), SETCUR);
}
static void
endfun(void)
{
endf = 1;
+ addstmt(newnode(OEFUN), SETCUR);
}
void