summary refs log tree commit diff
path: root/lisc/isel.c
diff options
context:
space:
mode:
authorQuentin Carbonneaux <quentin.carbonneaux@yale.edu>2015-08-12 15:25:53 -0400
committerQuentin Carbonneaux <quentin.carbonneaux@yale.edu>2015-09-15 23:01:31 -0400
commit78bf28f56e7dcdd89efba5c69bd90ed858658162 (patch)
tree071be80e60e3d6ef0f4109112ac9a3803db5a896 /lisc/isel.c
parent8be35bf2be509f32d2fccc182743ae409838c4e4 (diff)
downloadroux-78bf28f56e7dcdd89efba5c69bd90ed858658162.tar.gz
add basic support for stack allocation
Diffstat (limited to 'lisc/isel.c')
-rw-r--r--lisc/isel.c40
1 files changed, 40 insertions, 0 deletions
diff --git a/lisc/isel.c b/lisc/isel.c
index 7c634d8..5b83081 100644
--- a/lisc/isel.c
+++ b/lisc/isel.c
@@ -42,6 +42,22 @@ newtmp(int type, Fn *fn)
 	return TMP(t);
 }
 
+static Ref
+newcon(int64_t val, Fn *fn)
+{
+	int c;
+
+	for (c=0; c<fn->ncon; c++)
+		if (fn->con[c].type == CNum && fn->con[c].val == val)
+			return CON(c);
+	fn->ncon++;
+	fn->con = realloc(fn->con, fn->ncon * sizeof fn->con[0]);
+	if (!fn->con)
+		diag("isel: out of memory");
+	fn->con[c] = (Con){.type = CNum, .val = val};
+	return CON(c);
+}
+
 static int
 noimm(Ref r, Fn *fn)
 {
@@ -96,6 +112,7 @@ sel(Ins i, Fn *fn)
 {
 	Ref r0, r1, ra, rd;
 	int n, ty, c;
+	int64_t val;
 
 	switch (i.op) {
 	case ODiv:
@@ -166,6 +183,29 @@ Emit:
 			}
 		}
 		break;
+	case OAlloc:
+		/* we need to make sure
+		 * the stack remains aligned
+		 * (rsp + 8 = 0) mod 16
+		 * as a consequence, the alloc
+		 * alignment is 8, we can change
+		 * that in the future
+		 */
+		if (rtype(i.arg[0]) == RCon) {
+			val = fn->con[i.arg[0].val].val;
+			val = (val + 15)  & ~INT64_C(15);
+			if (val < 0 || val > INT32_MAX)
+				diag("isel: alloc too large");
+			emit(OAlloc, i.to, newcon(val, fn), R);
+		} else {
+			/* r0 = (i.arg[0] + 15) & -16 */
+			r0 = newtmp(TLong, fn);
+			r1 = newtmp(TLong, fn);
+			emit(OAlloc, i.to, r0, R);
+			emit(OAnd, r0, r1, newcon(-16, fn));
+			emit(OAdd, r1, i.arg[0], newcon(15, fn));
+		}
+		break;
 	default:
 		if (OCmp <= i.op && i.op <= OCmp1) {
 			c = i.op - OCmp;