summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--lisc/isel.c67
-rw-r--r--lisc/lisc.h4
-rw-r--r--lisc/parse.c4
-rw-r--r--lisc/ssa.c15
-rw-r--r--lisc/util.c76
5 files changed, 106 insertions, 60 deletions
diff --git a/lisc/isel.c b/lisc/isel.c
index 48f9dfc..49b8f28 100644
--- a/lisc/isel.c
+++ b/lisc/isel.c
@@ -13,37 +13,6 @@
  *   constant allocX in the first basic block)
  */
 
-static Ref
-newtmp(Fn *fn)
-{
-	static int n;
-	int t;
-
-	t = fn->ntmp++;
-	fn->tmp = realloc(fn->tmp, fn->ntmp * sizeof fn->tmp[0]);
-	if (!fn->tmp)
-		diag("isel: out of memory");
-	memset(&fn->tmp[t], 0, sizeof fn->tmp[t]);
-	fn->tmp[t].spill = -1;
-	sprintf(fn->tmp[t].name, "isel%d", ++n);
-	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)
@@ -81,7 +50,7 @@ selcmp(Ref arg[2], int w, Fn *fn)
 	emit(OXCmp, w, R, arg[1], arg[0]);
 	r = arg[1];
 	if (w && rtype(r) == RCon && noimm(r, fn)) {
-		curi->arg[0] = newtmp(fn);
+		curi->arg[0] = newtmp("isel", fn);
 		emit(OCopy, w, curi->arg[0], r, R);
 	}
 }
@@ -110,7 +79,7 @@ sel(Ins i, Fn *fn)
 		cpy[n].s = -1;
 		s = rslot(r0, fn);
 		if (s != -1) {
-			r0 = newtmp(fn);
+			r0 = newtmp("isel", fn);
 			i.arg[n] = r0;
 			cpy[n].r = r0;
 			cpy[n].s = s;
@@ -131,7 +100,7 @@ sel(Ins i, Fn *fn)
 			/* immediates not allowed for
 			 * divisions in x86
 			 */
-			r0 = newtmp(fn);
+			r0 = newtmp("isel", fn);
 		} else
 			r0 = i.arg[1];
 		emit(OXDiv, w, R, r0, R);
@@ -188,7 +157,7 @@ Emit:
 			 */
 			r0 = i.arg[n];
 			if (rtype(r0) == RCon && noimm(r0, fn)) {
-				curi->arg[n] = newtmp(fn);
+				curi->arg[n] = newtmp("isel", fn);
 				emit(OCopy, 1, curi->arg[n], r0, R);
 			}
 		}
@@ -205,14 +174,14 @@ Emit:
 			val = (val + 15)  & ~INT64_C(15);
 			if (val < 0 || val > INT32_MAX)
 				diag("isel: alloc too large");
-			emit(OAlloc, 0, i.to, newcon(val, fn), R);
+			emit(OAlloc, 0, i.to, getcon(val, fn), R);
 		} else {
 			/* r0 = (i.arg[0] + 15) & -16 */
-			r0 = newtmp(fn);
-			r1 = newtmp(fn);
+			r0 = newtmp("isel", fn);
+			r1 = newtmp("isel", fn);
 			emit(OSAlloc, 0, i.to, r0, R);
-			emit(OAnd, 1, r0, r1, newcon(-16, fn));
-			emit(OAdd, 1, r1, i.arg[0], newcon(15, fn));
+			emit(OAnd, 1, r0, r1, getcon(-16, fn));
+			emit(OAdd, 1, r1, i.arg[0], getcon(15, fn));
 		}
 		break;
 	default:
@@ -502,7 +471,7 @@ selcall(Fn *fn, Ins *i0, Ins *i1)
 	if (!req(i1->arg[1], R))
 		diag("struct-returning function not implemented");
 	if (stk) {
-		r = newcon(-(int64_t)stk, fn);
+		r = getcon(-(int64_t)stk, fn);
 		emit(OSAlloc, 0, R, r, R);
 	}
 	emit(OCopy, i1->wide, i1->to, TMP(RAX), R);
@@ -516,9 +485,9 @@ selcall(Fn *fn, Ins *i0, Ins *i1)
 				diag("isel: unsupported float struct");
 			if (a->size > 8) {
 				r = TMP(rsave[ni+1]);
-				r1 = newtmp(fn);
+				r1 = newtmp("isel", fn);
 				emit(OLoad, 1, r, r1, R);
-				r = newcon(8, fn);
+				r = getcon(8, fn);
 				emit(OAdd, 1, r1, i->arg[1], r);
 				r = TMP(rsave[ni]);
 				ni += 2;
@@ -580,12 +549,12 @@ selpar(Fn *fn, Ins *i0, Ins *i1)
 		if (i->op == OParc) {
 			if (a->rty[0] == RSse || a->rty[1] == RSse)
 				diag("isel: unsupported float struct");
-			r1 = newtmp(fn);
+			r1 = newtmp("isel", fn);
 			*curi++ = (Ins){OCopy, 1, r1, {r}};
 			a->rty[0] = r1.val;
 			if (a->size > 8) {
 				r = TMP(rsave[ni++]);
-				r1 = newtmp(fn);
+				r1 = newtmp("isel", fn);
 				*curi++ = (Ins){OCopy, 1, r1, {r}};
 				a->rty[1] = r1.val;
 			}
@@ -600,12 +569,12 @@ selpar(Fn *fn, Ins *i0, Ins *i1)
 			;
 		r1 = i->to;
 		r = TMP(a->rty[0]);
-		r2 = newcon(a->size, fn);
+		r2 = getcon(a->size, fn);
 		*curi++ = (Ins){OAlloc+al, 1, r1, {r2}};
 		*curi++ = (Ins){OStorel, 0, R, {r, r1}};
 		if (a->size > 8) {
-			r = newtmp(fn);
-			r2 = newcon(8, fn);
+			r = newtmp("isel", fn);
+			r2 = getcon(8, fn);
 			*curi++ = (Ins){OAdd, 1, r, {r1, r2}};
 			r1 = TMP(a->rty[1]);
 			*curi++ = (Ins){OStorel, 0, R, {r1, r}};
@@ -695,7 +664,7 @@ isel(Fn *fn)
 					assert(a+1 < p->narg);
 				s = rslot(p->arg[a], fn);
 				if (s != -1) {
-					p->arg[a] = newtmp(fn);
+					p->arg[a] = newtmp("isel", fn);
 					emit(OAddr, 1, p->arg[a], SLOT(s), R);
 				}
 			}
diff --git a/lisc/lisc.h b/lisc/lisc.h
index 511498d..453d2ca 100644
--- a/lisc/lisc.h
+++ b/lisc/lisc.h
@@ -279,6 +279,10 @@ void emiti(Ins);
 int bcnt(Bits *);
 void idup(Ins **, Ins *, ulong);
 Ins *icpy(Ins *, Ins *, ulong);
+void *valloc(ulong, size_t);
+void vgrow(void *, ulong);
+Ref newtmp(char *, Fn *);
+Ref getcon(int64_t, Fn *);
 
 /* parse.c */
 extern OpDesc opdesc[NOp];
diff --git a/lisc/parse.c b/lisc/parse.c
index fd135c1..05cb32c 100644
--- a/lisc/parse.c
+++ b/lisc/parse.c
@@ -611,9 +611,9 @@ parsefn()
 		err("empty file");
 	if (curb->jmp.type == JXXX)
 		err("last block misses jump");
-	fn->tmp = alloc(ntmp * sizeof tmp[0]);
+	fn->tmp = valloc(ntmp, sizeof tmp[0]);
 	memcpy(fn->tmp, tmp, ntmp * sizeof tmp[0]);
-	fn->con = alloc(ncon * sizeof con[0]);
+	fn->con = valloc(ncon, sizeof con[0]);
 	memcpy(fn->con, con, ncon * sizeof con[0]);
 	fn->ntmp = ntmp;
 	fn->ncon = ncon;
diff --git a/lisc/ssa.c b/lisc/ssa.c
index 97ba707..e60edc0 100644
--- a/lisc/ssa.c
+++ b/lisc/ssa.c
@@ -197,6 +197,7 @@ topdef(Blk *b, Fn *f, int w)
 void
 ssafix(Fn *f, int t)
 {
+	char s[NString];
 	uint n;
 	int t0, t1, w;
 	Ref rt;
@@ -214,7 +215,7 @@ ssafix(Fn *f, int t)
 		/* rename defs and some in-blocks uses */
 		for (p=b->phi; p; p=p->link)
 			if (req(p->to, rt)) {
-				t1 = f->ntmp++;
+				t1 = t0++;
 				p->to = TMP(t1);
 				w |= p->wide;
 			}
@@ -227,7 +228,7 @@ ssafix(Fn *f, int t)
 			}
 			if (req(i->to, rt)) {
 				w |= i->wide;
-				t1 = f->ntmp++;
+				t1 = t0++;
 				i->to = TMP(t1);
 			}
 		}
@@ -251,13 +252,9 @@ ssafix(Fn *f, int t)
 			b->jmp.arg = topdef(b, f, w);
 	}
 	/* add new temporaries */
-	f->tmp = realloc(f->tmp, f->ntmp * sizeof f->tmp[0]);
-	if (!f->tmp)
-		diag("ssafix: out of memory");
-	for (t1=t0; t0<f->ntmp; t0++) {
-		f->tmp[t0] = f->tmp[t];
-		snprintf(f->tmp[t0].name, NString, "%s%d",
-			f->tmp[t].name, t0-t1);
+	for (t1=f->ntmp; t1<t0; t1++) {
+		snprintf(s, NString, "%s%d", f->tmp[t].name, t0-t1);
+		newtmp(s, f);
 	}
 	free(top);
 	free(bot);
diff --git a/lisc/util.c b/lisc/util.c
index e62fd1a..399c144 100644
--- a/lisc/util.c
+++ b/lisc/util.c
@@ -1,5 +1,23 @@
 #include "lisc.h"
 
+typedef struct Vec Vec;
+
+struct Vec {
+	ulong mag;
+	size_t esz;
+	ulong cap;
+	union {
+		long long ll;
+		long double ld;
+		void *ptr;
+	} align[];
+};
+
+enum {
+	VMin = 2,
+	VMag = 0xcabba9e,
+};
+
 Typ typ[NTyp];
 Ins insb[NIns], *curi;
 
@@ -80,3 +98,61 @@ icpy(Ins *d, Ins *s, ulong n)
 	memcpy(d, s, n * sizeof(Ins));
 	return d + n;
 }
+
+void *
+valloc(ulong len, size_t esz)
+{
+	ulong cap;
+	Vec *v;
+
+	v = alloc(len * esz + sizeof(Vec));
+	v->mag = VMag;
+	for (cap=VMin; cap<len; cap*=2)
+		;
+	v->cap = cap;
+	v->esz = esz;
+	return v + 1;
+}
+
+void
+vgrow(void *vp, ulong len)
+{
+	Vec *v;
+	void *v1;
+
+	v = *(Vec **)vp - 1;
+	assert(v+1 && v->mag == VMag);
+	if (v->cap >= len)
+		return;
+	v1 = valloc(len, v->esz);
+	memcpy(v1, v+1, v->cap * v->esz);
+	free(v);
+	*(Vec **)vp = v1;
+}
+
+Ref
+newtmp(char *prfx, Fn *fn)
+{
+	static int n;
+	int t;
+
+	t = fn->ntmp++;
+	vgrow(&fn->tmp, fn->ntmp);
+	sprintf(fn->tmp[t].name, "%s%d", prfx, ++n);
+	fn->tmp[t].spill = -1;
+	return TMP(t);
+}
+
+Ref
+getcon(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++;
+	vgrow(&fn->con, fn->ncon);
+	fn->con[c] = (Con){.type = CNum, .val = val};
+	return CON(c);
+}