commit f957dc886547ffab16c9f743889f51f23726f13a
parent 6a7fb9b9a0a08b584646222fdc7cd1ec03a7230c
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date: Thu, 19 Mar 2015 20:45:17 +0000
Add spill()
This function spill variable associated to a register into memory.
Diffstat:
3 files changed, 61 insertions(+), 32 deletions(-)
diff --git a/cc2/cc2.h b/cc2/cc2.h
@@ -53,8 +53,10 @@ typedef struct {
struct symbol {
unsigned short id;
char *name;
+ char kind;
bool public : 1;
bool extrn : 1;
+ bool dirty : 1;
union {
/* TODO: Admit inmediate of other type */
TINT imm;
diff --git a/cc2/cgen.c b/cc2/cgen.c
@@ -12,10 +12,10 @@ static uint8_t upper[] = {[DE] = D, [HL] = H, [BC] = B, [IY] = IYH};
static uint8_t lower[] = {[DE] = E, [HL] = L, [BC] = C, [IY] = IYL};
static uint8_t pair[] = {
[A] = A,
- [H] = HL, [L] = HL,
- [B] = BC, [C] = BC,
- [D] = DE, [E] = DE,
- [IYL] = IY, [IYH] = IY
+ [H] = HL, [L] = HL, [HL] = HL,
+ [B] = BC, [C] = BC, [BC] = BC,
+ [D] = DE, [E] = DE, [DE] = DE,
+ [IYL] = IY, [IYH] = IY, [IY] = IY
};
Node
@@ -117,6 +117,41 @@ allocreg(Node *np)
}
static void
+spill(uint8_t reg)
+{
+ Node *np, *r;
+ Symbol *sym;
+ uint8_t p, h, l;
+
+ if ((np = reguse[reg]) == NULL)
+ return;
+ if ((sym = np->sym) == NULL)
+ goto freereg;
+ if (!sym->dirty)
+ goto freereg;
+
+ r = regs[reg];
+ switch (np->type.size) {
+ case 1:
+ code(LDL, np, r);
+ break;
+ default:
+ abort();
+ }
+ sym->dirty = 0;
+
+freereg:
+ reguse[reg] = NULL;
+ p = pair[reg];
+ l = lower[p];
+ h = upper[p];
+ if (reg >= NREGS)
+ reguse[l] = reguse[h] = NULL;
+ else if (!reguse[l] && !reguse[h])
+ reguse[p] = NULL;
+}
+
+static void
moveto(Node *np, uint8_t reg)
{
Node *r = regs[reg], *u = reguse[reg];
@@ -127,7 +162,7 @@ moveto(Node *np, uint8_t reg)
if (op == u->op && sym && sym == u->sym)
return;
else
- ; /* TODO: Push the value? */
+ spill(reg);
}
switch (np->type.size) {
@@ -164,7 +199,7 @@ moveto(Node *np, uint8_t reg)
default:
abort();
}
- reguse[reg] = np;
+ reguse[pair[reg]] = reguse[reg] = np;
np->op = REG;
np->reg = reg;
}
@@ -176,31 +211,17 @@ move(Node *np)
}
static void
-push(uint8_t reg)
-{
- Node *np;
-
- if (reg < NREGS)
- reg = pair[reg];
- if ((np = reguse[lower[reg]]) != NULL)
- np->op = PUSHED;
- if ((np = reguse[upper[reg]]) != NULL)
- np->op = PUSHED;
- code(PUSH, NULL, regs[reg]);
-}
-
-static void
accum(Node *np)
{
+ Symbol *sym;
+
switch (np->type.size) {
case 1:
- if (reguse[A])
- push(A);
+ spill(A);
moveto(np, A);
break;
case 2:
- if (reguse[H] || reguse[L])
- push(HL);
+ spill(HL);
moveto(np, HL);
break;
case 4:
@@ -214,14 +235,13 @@ index(Node *np)
{
Node *u = reguse[HL];
- if (u) {
- Symbol *sym = np->sym;
-
- if (u->op == INDEX && sym && sym == u->sym) {
+ if (u && u->sym) {
+ if (u->op == INDEX && np->sym == u->sym) {
np->op = INDEX;
return;
- } else
- ; /* TODO: Push the value? */
+ } else {
+ spill(HL);
+ }
}
code(LDI, ®_HL, np);
np->op = INDEX;
@@ -295,7 +315,7 @@ add(Node *np)
break;
default:
abort();
- }
+ }
break;
default:
abort();
@@ -316,6 +336,7 @@ static void
assign(Node *np)
{
Node *lp = np->left, *rp = np->right;
+ Symbol *sym = lp->sym;
assert(rp->op == REG);
switch (np->type.size) {
@@ -340,6 +361,9 @@ assign(Node *np)
default:
abort();
}
+
+ if (sym)
+ sym->dirty = 0;
np->op = REG;
np->reg = rp->reg;
}
diff --git a/cc2/parser.c b/cc2/parser.c
@@ -287,12 +287,15 @@ gettype(char *type)
static Symbol *
symbol(uint8_t t, char *token)
{
+ Symbol *sym;
static Symbol *(*tbl[3])(char *)= {
[LOCAL] = local,
[GLOBAL] = global,
[PARAMETER] = parameter
};
- return (*tbl[t])(token+1);
+ sym = (*tbl[t])(token+1);
+ sym->kind = *token;
+ return sym;
}
static void