summary refs log tree commit diff
diff options
context:
space:
mode:
authorQuentin Carbonneaux <quentin.carbonneaux@yale.edu>2015-08-21 16:05:50 -0400
committerQuentin Carbonneaux <quentin.carbonneaux@yale.edu>2015-09-15 23:01:32 -0400
commit60b8b06aaba3cf63da32a2894b5a70a77596399f (patch)
tree88427f69a33bbfd32fce7005b33cb31afb5617d6
parent13e04cd1debf1ad715b8849d320ec058c4c919ae (diff)
downloadroux-60b8b06aaba3cf63da32a2894b5a70a77596399f.tar.gz
write more tests for dopm()
-rw-r--r--lisc/tools/pmov.c132
1 files changed, 107 insertions, 25 deletions
diff --git a/lisc/tools/pmov.c b/lisc/tools/pmov.c
index e3d2104..13714c3 100644
--- a/lisc/tools/pmov.c
+++ b/lisc/tools/pmov.c
@@ -1,24 +1,31 @@
-/*% cc -std=c99 -Wall -DTEST_PMOV -g -o # %
+/*% cc -O3 -std=c99 -Wall -DTEST_PMOV -o # %
+ *
+ * This is a test framwork for the dopm() function
+ * in rega.c, use it when you want to modify it or
+ * all the parallel move functions.
+ *
+ * You might need to decrease NReg to see it
+ * terminate, I used NReg == 7 at most.
  */
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
-static void assert_test(char *, int), fail(void);
+static void assert_test(char *, int), fail(void), iexec(int *);
 
 #include "../rega.c"
 
 static RMap mbeg;
 static Ins ins[NReg], *ip;
+static Blk dummyb = { .ins = ins };
 
 int
 main()
 {
-	Blk dummyb;
 	Ins *i1;
-	unsigned long long tm, rm;
+	unsigned long long tm, rm, cnt;
 	RMap mend;
-	int reg[NReg];
+	int reg[NReg], val[NReg+1];
 	int t, i, r, nr;
 
 	tmp = (Tmp[Tmp0+NReg]){{0}};
@@ -31,9 +38,7 @@ main()
 			sprintf(tmp[t].name, "tmp%d", t-Tmp0+1);
 		}
 
-	dummyb.ins = ins;
-	strcpy(dummyb.name, "dummy");
-
+	cnt = 0;
 	for (tm = 0; tm < 1ull << (2*NReg); tm++) {
 		mbeg.n = 0;
 		mbeg.b = (Bits){{0}};
@@ -63,7 +68,7 @@ main()
 			}
 
 		if (ip == ins)
-			/* cancel is the parallel move
+			/* cancel if the parallel move
 			 * is empty
 			 */
 			goto Nxt;
@@ -72,7 +77,6 @@ main()
 		 * in mbeg
 		 */
 		nr = ip - ins;
-		dummyb.nins = nr;
 		rm = (1ull << (nr+1)) - 1;
 		for (i=0; i<nr; i++)
 			reg[i] = i+1;
@@ -82,28 +86,51 @@ main()
 			 */
 			for (i=0, i1=ins; i1<ip; i1++, i++)
 				i1->arg[0] = TMP(reg[i]);
-#if 0
-			for (i=0; i<nr; i++)
-				printf("%d ", reg[i]);
-			printf("\n");
-#endif
 
 			/* compile the parallel move
 			 */
 			mend = mbeg;
 			dopm(&dummyb, ip-1, &mend);
+			cnt++;
 
-			// TODO
 			/* check that mend contain mappings for
 			 * source registers and does not map any
-			 * assigned temporary
+			 * assigned temporary, then check that
+			 * all temporaries in mend are mapped in
+			 * mbeg and not used in the copy
 			 */
+			for (i1=ins; i1<ip; i1++) {
+				r = i1->arg[0].val;
+				assert(rfree(&mend, r) == r);
+				t = i1->to.val;
+				assert(!BGET(mend.b, t));
+			}
+			for (i=0; i<mend.n; i++) {
+				t = mend.t[i];
+				assert(BGET(mbeg.b, t));
+				t -= Tmp0;
+				assert(((tm >> (2*t)) & 3) == 1);
+			}
 
-			// TODO
 			/* execute the code generated and check
 			 * that all assigned temporaries got their
-			 * value
+			 * value, and that all live variables's
+			 * content got preserved
 			 */
+			 for (i=1; i<=NReg; i++)
+			 	val[i] = i;
+			 iexec(val);
+			 for (i1=ins; i1<ip; i1++) {
+			 	t = i1->to.val;
+			 	r = rfind(&mbeg, t);
+			 	if (r != -1)
+			 		assert(val[r] == i1->arg[0].val);
+			 }
+			 for (i=0; i<mend.n; i++) {
+			 	t = mend.t[i];
+			 	r = mend.r[i];
+			 	assert(val[t-Tmp0+1] == r);
+			 }
 
 			/* find the next register assignment */
 			i = nr - 1;
@@ -133,11 +160,59 @@ main()
 		}
 	Nxt:	;
 	}
+	printf("%llu tests successful!\n", cnt);
 	exit(0);
 }
 
 
+/* execute what pmgen() wrote (swap, copy) */
+
+#define validr(r)           \
+	rtype(r) == RTmp && \
+	r.val > 0 &&        \
+	r.val <= NReg
+
+static void
+iexec(int val[])
+{
+	Ins *i;
+	int t;
+
+	for (i=insb; i<curi; i++)
+		switch (i->op) {
+		default:
+			assert(!"iexec: missing case\n");
+			exit(1);
+		case OSwap:
+			assert(validr(i->arg[0]));
+			assert(validr(i->arg[1]));
+			t = val[i->arg[0].val];
+			val[i->arg[0].val] = val[i->arg[1].val];
+			val[i->arg[1].val] = t;
+			break;
+		case OCopy:
+			assert(validr(i->to));
+			assert(validr(i->arg[0]));
+			val[i->to.val] = val[i->arg[0].val];
+			break;
+		}
+}
+
+
 /* failure diagnostics */
+
+static int re;
+
+static void
+replay()
+{
+	RMap mend;
+
+	re = 1;
+	mend = mbeg;
+	dopm(&dummyb, ip-1, &mend);
+}
+
 static void
 fail()
 {
@@ -155,6 +230,7 @@ fail()
 		printf("\t %s <- r%d\n",
 			tmp[i1->to.val].name,
 			i1->arg[0].val);
+	replay();
 	exit(1);
 }
 
@@ -163,20 +239,26 @@ assert_test(char *s, int x)
 {
 	if (x)
 		return;
+	if (re)
+		exit(1);
 	printf("!assertion failure: %s\n", s);
 	fail();
 }
 
+void diag(char *s)
+{
+	if (re)
+		exit(1);
+	printf("!diag failure: %s\n", s);
+	fail();
+}
+
 
 /* symbols required by the linker */
 char debug['Z'+1];
 Ins insb[NIns], *curi;
 
-void diag(char *s)
-{ printf("!diag failure: %s\n", s); fail(); }
-
 void *alloc(size_t n)
-{ return malloc(n); }
-
+{ return calloc(n, 1); }
 Blk *blocka()
-{ printf("!blocka called\n"); exit(1); }
+{ printf("!blocka\n"); exit(1); }