summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--lisc/isel.c36
-rw-r--r--lisc/lisc.h4
-rw-r--r--lisc/live.c10
-rw-r--r--lisc/parse.c2
-rw-r--r--lisc/rega.c11
-rw-r--r--lisc/spill.c10
6 files changed, 49 insertions, 24 deletions
diff --git a/lisc/isel.c b/lisc/isel.c
index 42388af..2235cff 100644
--- a/lisc/isel.c
+++ b/lisc/isel.c
@@ -434,23 +434,26 @@ blit(Ref rstk, uint soff, Ref rsrc, uint sz, Fn *fn)
 	}
 }
 
-static void
+static int
 retr(Ref reg[2], AClass *aret)
 {
 	static int retreg[2][2] = {{RAX, RDX}, {XMM0, XMM0+1}};
-	int n, k, nr[2];
+	int n, k, ca, nr[2];
 
 	nr[0] = nr[1] = 0;
+	ca = 0;
 	for (n=0; aret->cls[n]>=0 && n<2; n++) {
 		k = KBASE(aret->cls[n]);
 		reg[n] = TMP(retreg[k][nr[k]++]);
+		ca += 1 << (2 * k);
 	}
+	return ca;
 }
 
 static void
 selret(Blk *b, Fn *fn)
 {
-	int j, k;
+	int j, k, ca;
 	Ref r, r0, reg[2];
 	AClass aret;
 
@@ -460,7 +463,6 @@ selret(Blk *b, Fn *fn)
 		return;
 
 	r0 = b->jmp.arg;
-	b->jmp.arg = R;
 	b->jmp.type = JRet0;
 
 	if (j == JRetc) {
@@ -470,8 +472,9 @@ selret(Blk *b, Fn *fn)
 			emit(OCopy, Kl, TMP(RAX), fn->retr, R);
 			chuse(fn->retr, +1, fn);
 			blit(fn->retr, 0, r0, aret.size, fn);
+			ca = 1;
 		} else {
-			retr(reg, &aret);
+			ca = retr(reg, &aret);
 			if (aret.size > 8) {
 				r = newtmp("abi", Kl, fn);
 				emit(OLoad, Kl, reg[1], r, R);
@@ -482,11 +485,16 @@ selret(Blk *b, Fn *fn)
 		}
 	} else {
 		k = j - JRetw;
-		if (KBASE(k) == 0)
+		if (KBASE(k) == 0) {
 			emit(OCopy, k, TMP(RAX), r0, R);
-		else
+			ca = 1;
+		} else {
 			emit(OCopy, k, TMP(XMM0), r0, R);
+			ca = 1 << 2;
+		}
 	}
+
+	b->jmp.arg = CALL(ca);
 }
 
 static void
@@ -607,14 +615,15 @@ MAKESURE(rsave_has_correct_size, sizeof rsave == NRSave * sizeof(int));
 MAKESURE(rclob_has_correct_size, sizeof rclob == NRClob * sizeof(int));
 
 bits
-calldef(Ins i, int p[2])
+retregs(Ref r, int p[2])
 {
 	bits b;
 	int ni, nf;
 
+	assert(rtype(r) == RACall);
 	b = 0;
-	ni = i.arg[1].val & 3;
-	nf = (i.arg[1].val >> 2) & 3;
+	ni = r.val & 3;
+	nf = (r.val >> 2) & 3;
 	if (ni >= 1)
 		b |= BIT(RAX);
 	if (ni >= 2)
@@ -631,14 +640,15 @@ calldef(Ins i, int p[2])
 }
 
 bits
-calluse(Ins i, int p[2])
+argregs(Ref r, int p[2])
 {
 	bits b;
 	int j, ni, nf;
 
+	assert(rtype(r) == RACall);
 	b = 0;
-	ni = (i.arg[1].val >> 4) & 15;
-	nf = (i.arg[1].val >> 8) & 15;
+	ni = (r.val >> 4) & 15;
+	nf = (r.val >> 8) & 15;
 	for (j=0; j<ni; j++)
 		b |= BIT(rsave[j]);
 	for (j=0; j<nf; j++)
diff --git a/lisc/lisc.h b/lisc/lisc.h
index c6405ca..41be0ad 100644
--- a/lisc/lisc.h
+++ b/lisc/lisc.h
@@ -536,8 +536,8 @@ void filllive(Fn *);
 /* isel.c */
 extern int rsave[/* NRSave */];
 extern int rclob[/* NRClob */];
-bits calldef(Ins, int[2]);
-bits calluse(Ins, int[2]);
+bits retregs(Ref, int[2]);
+bits argregs(Ref, int[2]);
 void isel(Fn *);
 
 /* spill.c */
diff --git a/lisc/live.c b/lisc/live.c
index 7efcfbf..43ceed9 100644
--- a/lisc/live.c
+++ b/lisc/live.c
@@ -107,19 +107,23 @@ Again:
 				phifix(t, phi, f->tmp);
 				nlv[KBASE(f->tmp[t].cls)]++;
 			}
-		bset(b->jmp.arg, b, nlv, phi, f->tmp);
+		if (rtype(b->jmp.arg) == RACall) {
+			assert(bscount(b->in) == 0 && nlv[0] == 0 && nlv[1] == 0);
+			b->in->t[0] |= retregs(b->jmp.arg, nlv);
+		} else
+			bset(b->jmp.arg, b, nlv, phi, f->tmp);
 		for (k=0; k<2; k++)
 			b->nlive[k] = nlv[k];
 		for (i=&b->ins[b->nins]; i!=b->ins;) {
 			if ((--i)->op == OCall && rtype(i->arg[1]) == RACall) {
-				b->in->t[0] &= ~calldef(*i, m);
+				b->in->t[0] &= ~retregs(i->arg[1], m);
 				for (k=0; k<2; k++)
 					nlv[k] -= m[k];
 				if (nlv[0] + NISave > b->nlive[0])
 					b->nlive[0] = nlv[0] + NISave;
 				if (nlv[1] + NFSave > b->nlive[1])
 					b->nlive[1] = nlv[1] + NFSave;
-				b->in->t[0] |= calluse(*i, m);
+				b->in->t[0] |= argregs(i->arg[1], m);
 				for (k=0; k<2; k++)
 					nlv[k] += m[k];
 			}
diff --git a/lisc/parse.c b/lisc/parse.c
index aa7bc27..49595c4 100644
--- a/lisc/parse.c
+++ b/lisc/parse.c
@@ -1055,7 +1055,7 @@ printfn(Fn *fn, FILE *f)
 		case JRetd:
 		case JRetc:
 			fprintf(f, "\t%s", jtoa[b->jmp.type]);
-			if (b->jmp.type != JRet0) {
+			if (b->jmp.type != JRet0 || !req(b->jmp.arg, R)) {
 				fprintf(f, " ");
 				printref(b->jmp.arg, fn, f);
 			}
diff --git a/lisc/rega.c b/lisc/rega.c
index 6c01dbb..ead2806 100644
--- a/lisc/rega.c
+++ b/lisc/rega.c
@@ -294,7 +294,7 @@ dopm(Blk *b, Ins *i, RMap *m)
 	} while (i != b->ins && regcpy(i-1));
 	assert(m0.n <= m->n);
 	if (i != b->ins && (i-1)->op == OCall) {
-		def = calldef(*(i-1), 0);
+		def = retregs((i-1)->arg[1], 0);
 		for (r=0; r<NRSave; r++)
 			if (!(BIT(rsave[r]) & def))
 				move(rsave[r], R, m);
@@ -364,10 +364,17 @@ doblk(Blk *b, RMap *cur)
 
 	if (rtype(b->jmp.arg) == RTmp)
 		b->jmp.arg = ralloc(cur, b->jmp.arg.val);
+	else if (rtype(b->jmp.arg) == RACall) {
+		/* add return registers */
+		rs = retregs(b->jmp.arg, 0);
+		for (r=0; rs; rs/=2, r++)
+			if (rs & 1)
+				radd(cur, r, r);
+	}
 	for (i=&b->ins[b->nins]; i!=b->ins;) {
 		switch ((--i)->op) {
 		case OCall:
-			rs = calluse(*i, 0);
+			rs = argregs(i->arg[1], 0);
 			for (r=0; r<NRSave; r++)
 				if (!(BIT(rsave[r]) & rs))
 					rfree(cur, rsave[r]);
diff --git a/lisc/spill.c b/lisc/spill.c
index 2d509a0..33392a3 100644
--- a/lisc/spill.c
+++ b/lisc/spill.c
@@ -290,11 +290,11 @@ dopm(Blk *b, Ins *i, BSet *v)
 	} while (i != b->ins && regcpy(i-1));
 	bscopy(u, v);
 	if (i != b->ins && (i-1)->op == OCall) {
-		v->t[0] &= ~calldef(*(i-1), 0);
+		v->t[0] &= ~retregs((i-1)->arg[1], 0);
 		limit2(v, NISave, NFSave, 0);
 		for (r=0, n=0; n<NRSave; n++)
 			r |= BIT(rsave[n]);
-		v->t[0] |= calluse(*(i-1), 0);
+		v->t[0] |= argregs((i-1)->arg[1], 0);
 	} else {
 		limit2(v, 0, 0, 0);
 		r = v->t[0];
@@ -365,6 +365,7 @@ spill(Fn *fn)
 		if (s2 && s2->id <= n)
 		if (!hd || s2->id >= hd->id)
 			hd = s2;
+		r = 0;
 		bszero(v);
 		if (hd) {
 			/* back-edge */
@@ -393,12 +394,15 @@ spill(Fn *fn)
 				bsunion(v, u);
 			}
 			limit2(v, 0, 0, w);
+		} else if (rtype(b->jmp.arg) == RACall) {
+			/* return */
+			r = retregs(b->jmp.arg, 0);
+			v->t[0] |= r;
 		}
 		bscopy(b->out, v);
 
 		/* 2. process the block instructions */
 		curi = &insb[NIns];
-		r = 0;
 		for (i=&b->ins[b->nins]; i!=b->ins;) {
 			i--;
 			if (regcpy(i)) {