summary refs log tree commit diff
diff options
context:
space:
mode:
authorQuentin Carbonneaux <quentin.carbonneaux@yale.edu>2015-07-28 22:40:50 -0400
committerQuentin Carbonneaux <quentin.carbonneaux@yale.edu>2015-09-15 23:01:29 -0400
commitfd964388f76443a46f6f091c2aa64cb4e62341e6 (patch)
treeca7a1d63b85d22d53dc62e60032f95885a0aab27
parent5f14d7fd7c514a9d6c34803407c579bc17438ef0 (diff)
downloadroux-fd964388f76443a46f6f091c2aa64cb4e62341e6.tar.gz
add a code emitter for at&t syntax
-rw-r--r--lisc/emit.c117
-rw-r--r--lisc/lisc.h6
-rw-r--r--lisc/main.c22
-rw-r--r--lisc/spill.c1
4 files changed, 145 insertions, 1 deletions
diff --git a/lisc/emit.c b/lisc/emit.c
new file mode 100644
index 0000000..9841c14
--- /dev/null
+++ b/lisc/emit.c
@@ -0,0 +1,117 @@
+#include "lisc.h"
+
+
+static void
+eref(Ref r, Fn *fn, FILE *f)
+{
+	switch (rtype(r)) {
+	case RSym:
+		assert(fn->sym[r.val].type == SReg);
+		fprintf(f, "%%%s", fn->sym[r.val].name);
+		break;
+	case RSlot:
+		fprintf(f, "-%d(%%rbp)", 8 * r.val);
+		break;
+	case RConst:
+		fprintf(f, "$%d", (int)r.val);
+		break;
+	default:
+		diag("emitref: invalid reference");
+	}
+}
+
+static void
+eop(char *op, Ref a, Ref b, Fn *fn, FILE *f)
+{
+	fprintf(f, "\t%s ", op);
+	eref(a, fn, f);
+	if (!req(b, R)) {
+		fprintf(f, ", ");
+		eref(b, fn, f);
+	}
+	fprintf(f, "\n");
+}
+
+static void
+eins(Ins i, Fn *fn, FILE *f)
+{
+	static char *opi[] = {
+		[OAdd] = "add",
+		[OSub] = "sub",
+	};
+
+	switch (i.op) {
+	case OAdd:
+	case OSub:
+		if (!req(i.to, i.arg[0]))
+			eop("mov", i.arg[0], i.to, fn, f);
+		eop(opi[i.op], i.arg[1], i.to, fn, f);
+		break;
+	case OStore:
+		i.to = i.arg[1];
+		/* fall through */
+	case OCopy:
+	case OLoad:
+		if (!req(i.arg[0], i.to))
+			eop("mov", i.arg[0], i.to, fn, f);
+		break;
+	case OSwap:
+		eop("xchg", i.arg[0], i.arg[1], fn, f);
+		break;
+	case ONop:
+		break;
+	default:
+		diag("emit: unhandled instruction");
+	}
+}
+
+void
+emitfn(Fn *fn, FILE *f)
+{
+	char *js;
+	Blk *b, *s;
+	Ins *i;
+
+	fprintf(f,
+		".text\n"
+		".globl liscf\n"
+		".type liscf, @function\n"
+		"liscf:\n"
+		"\tpush %%rbp\n"
+		"\tmov %%rsp, %%rbp\n"
+		"\tsub $%u, %%rsp\n",
+		fn->nspill * 8
+	);
+	for (b=fn->start; b; b=b->link) {
+		fprintf(f, ".L%s:\n", b->name);
+		for (i=b->ins; i-b->ins < b->nins; i++)
+			eins(*i, fn, f);
+		switch (b->jmp.type) {
+		case JRet:
+			fprintf(f,
+				"\tleave\n"
+				"\tret\n"
+			);
+			break;
+		case JJmp:
+			if (b->s1 != b->link)
+				fprintf(f, "\tjmp .L%s\n", b->s1->name);
+			break;
+		case JJez:
+			if (b->s1 == b->link) {
+				js = "jnz";
+				s = b->s2;
+			} else if (b->s2 == b->link) {
+				js = "jz";
+				s = b->s1;
+			} else
+				diag("emit: unhandled jump (1)");
+			eop("test", b->jmp.arg, b->jmp.arg, fn, f);
+			fprintf(f, "\t%s .L%s\n", js, s->name);
+			break;
+		default:
+			diag("emit: unhandled jump (2)");
+		}
+	}
+
+}
diff --git a/lisc/lisc.h b/lisc/lisc.h
index f3b9913..d1c25f0 100644
--- a/lisc/lisc.h
+++ b/lisc/lisc.h
@@ -19,9 +19,9 @@ enum {
 	RAX = 1,
 	RCX,
 	RDX,
-	RBX,
 	RSI,
 	RDI,
+	RBX,
 	R8,
 	R9,
 	R10,
@@ -164,6 +164,7 @@ struct Fn {
 	int ntmp;
 	int nblk;
 	Blk **rpo;
+	uint nspill;
 };
 
 
@@ -197,3 +198,6 @@ void spill(Fn *);
 
 /* rega.c */
 void rega(Fn *);
+
+/* emit.c */
+void emitfn(Fn *, FILE *);
diff --git a/lisc/main.c b/lisc/main.c
index d3688ad..81bbb72 100644
--- a/lisc/main.c
+++ b/lisc/main.c
@@ -113,6 +113,28 @@ main(int ac, char *av[])
 		goto RPODump;
 		break;
 	}
+	case 'e': {
+		int n;
+
+		fprintf(stderr, "[Testing Code Emission]\n");
+		fillrpo(fn);
+		fillpreds(fn);
+		filllive(fn);
+		fillcost(fn);
+		spill(fn);
+		rega(fn);
+		fillrpo(fn);
+		assert(fn->rpo[0] == fn->start);
+		for (n=0;; n++)
+			if (n == fn->nblk-1) {
+				fn->rpo[n]->link = 0;
+				break;
+			} else
+				fn->rpo[n]->link = fn->rpo[n+1];
+		emitfn(fn, stdout);
+		pr = 0;
+		break;
+	}
 	default:
 		break;
 	}
diff --git a/lisc/spill.c b/lisc/spill.c
index 76957fc..1181bc1 100644
--- a/lisc/spill.c
+++ b/lisc/spill.c
@@ -391,4 +391,5 @@ spill(Fn *fn)
 		memcpy(b->ins, curi, b->nins * sizeof(Ins));
 		b->in = v;
 	}
+	fn->nspill = ns;
 }