summary refs log tree commit diff
path: root/lisc
diff options
context:
space:
mode:
authorQuentin Carbonneaux <quentin.carbonneaux@yale.edu>2016-03-18 10:42:16 -0400
committerQuentin Carbonneaux <quentin.carbonneaux@yale.edu>2016-03-18 10:47:57 -0400
commit73371a0f906916f18e2b9a085f8b49bdbfbbda06 (patch)
tree4b55d04ed9121e47df2298a9c5cdc3d330ee4f6e /lisc
parent5e388fffbc87d05d53e10517d5ba1c6350e2c01a (diff)
downloadroux-73371a0f906916f18e2b9a085f8b49bdbfbbda06.tar.gz
small fixes in selcall()
  * Floating point return values are now handled
    correctly (I thought they were...).

  * Use counts of the "stack pointer" used for
    memory arguments are tracked correctly.

  * Use counts of struct argument pointers are
    tracked correctly.
Diffstat (limited to 'lisc')
-rw-r--r--lisc/isel.c30
1 files changed, 22 insertions, 8 deletions
diff --git a/lisc/isel.c b/lisc/isel.c
index 51a0aa0..53f98be 100644
--- a/lisc/isel.c
+++ b/lisc/isel.c
@@ -659,17 +659,26 @@ selcall(Fn *fn, Ins *i0, Ins *i1)
 				stk += stk & 15;
 		}
 	stk += stk & 15;
-
-	if (!req(i1->arg[1], R))
-		diag("struct-returning function not implemented");
 	if (stk) {
 		r = getcon(-(int64_t)stk, fn);
 		emit(OSAlloc, Kl, R, r, R);
 	}
-	emit(OCopy, i1->cls, i1->to, TMP(RAX), R);
-	emit(OCall, i1->cls, R, i1->arg[0], CALL(1 | ca));
 
-	for (i=i0, a=ac, ni=ns=0; i<i1; i++, a++) {
+	if (!req(i1->arg[1], R)) {
+		diag("struct-returning function not implemented");
+	} else {
+		if (KBASE(i1->cls) == 0) {
+			emit(OCopy, i1->cls, i1->to, TMP(RAX), R);
+			ca += 1;
+		} else {
+			emit(OCopy, i1->cls, i1->to, TMP(XMM0), R);
+			ca += 1 << 2;
+		}
+	}
+	emit(OCall, i1->cls, R, i1->arg[0], CALL(ca));
+
+	ni = ns = 0;
+	for (i=i0, a=ac; i<i1; i++, a++) {
 		if (a->inmem)
 			continue;
 		r1 = rarg(a->cls[0], &ni, &ns);
@@ -679,13 +688,18 @@ selcall(Fn *fn, Ins *i0, Ins *i1)
 				r = newtmp("abi", Kl, fn);
 				emit(OLoad, a->cls[1], r2, r, R);
 				emit(OAdd, Kl, r, i->arg[1], getcon(8, fn));
+				chuse(i->arg[1], +1, fn);
 			}
 			emit(OLoad, a->cls[0], r1, i->arg[1], R);
 		} else
 			emit(OCopy, i->cls, r1, i->arg[0], R);
 	}
 
+	if (!stk)
+		return;
+
 	r = newtmp("abi", Kl, fn);
+	chuse(r, -1, fn);
 	for (i=i0, a=ac, off=0; i<i1; i++, a++) {
 		if (!a->inmem)
 			continue;
@@ -697,11 +711,11 @@ selcall(Fn *fn, Ins *i0, Ins *i1)
 			r1 = newtmp("abi", Kl, fn);
 			emit(OStorel, 0, R, i->arg[0], r1);
 			emit(OAdd, Kl, r1, r, getcon(off, fn));
+			chuse(r, +1, fn);
 		}
 		off += a->size;
 	}
-	if (stk)
-		emit(OSAlloc, Kl, r, getcon(stk, fn), R);
+	emit(OSAlloc, Kl, r, getcon(stk, fn), R);
 }
 
 static void