shithub: scc

Download patch

ref: f957dc886547ffab16c9f743889f51f23726f13a
parent: 6a7fb9b9a0a08b584646222fdc7cd1ec03a7230c
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Thu Mar 19 16:45:17 EDT 2015

Add spill()

This function spill variable associated to a register into memory.

--- a/cc2/cc2.h
+++ b/cc2/cc2.h
@@ -53,8 +53,10 @@
 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;
--- a/cc2/cgen.c
+++ b/cc2/cgen.c
@@ -12,10 +12,10 @@
 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 @@
 }
 
 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 @@
 		if (op == u->op && sym && sym == u->sym)
 			return;
 		else
-			; /* TODO: Push the value? */
+			spill(reg);
 	}
 
 	switch (np->type.size) {
@@ -164,7 +199,7 @@
 	default:
 		abort();
 	}
-	reguse[reg] = np;
+	reguse[pair[reg]] = reguse[reg] = np;
 	np->op = REG;
 	np->reg = reg;
 }
@@ -176,31 +211,17 @@
 }
 
 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 @@
 {
 	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, &reg_HL, np);
 	np->op = INDEX;
@@ -295,7 +315,7 @@
 				break;
 			default:
 				abort();
-			}		
+			}
 			break;			
 		default:
 			abort();
@@ -316,6 +336,7 @@
 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 @@
 	default:
 		abort();
 	}
+
+	if (sym)
+		sym->dirty = 0;
 	np->op = REG;
 	np->reg = rp->reg;
 }
--- a/cc2/parser.c
+++ b/cc2/parser.c
@@ -287,12 +287,15 @@
 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