summary refs log tree commit diff
diff options
context:
space:
mode:
authorQuentin Carbonneaux <quentin@c9x.me>2022-11-24 11:08:33 +0100
committerQuentin Carbonneaux <quentin@c9x.me>2022-11-27 21:48:21 +0100
commit9126afa2da0e1635d78429075cc44ca576f68169 (patch)
tree0836f3da0fdfee9af24ca5dabb8244af61e5283e
parentb5da3f3d64c857baf808220e202dc37c5c039eb8 (diff)
downloadroux-9126afa2da0e1635d78429075cc44ca576f68169.tar.gz
new hlt block terminator
It is handy to express when
the end of a block cannot be
reached. If a hlt terminator
is executed, it traps the
program.

We don't go the llvm way and
specify execution semantics as
undefined behavior.
-rw-r--r--all.h2
-rw-r--r--amd64/emit.c3
-rw-r--r--amd64/isel.c4
-rw-r--r--arm64/emit.c3
-rw-r--r--arm64/isel.c13
-rw-r--r--fold.c2
-rw-r--r--parse.c11
-rw-r--r--rv64/emit.c3
-rw-r--r--tools/lexh.c2
9 files changed, 30 insertions, 13 deletions
diff --git a/all.h b/all.h
index d852609..3ddb944 100644
--- a/all.h
+++ b/all.h
@@ -154,7 +154,7 @@ enum J {
 	X(jfisle) X(jfislt) X(jfiuge) X(jfiugt) \
 	X(jfiule) X(jfiult) X(jffeq)  X(jffge)  \
 	X(jffgt)  X(jffle)  X(jfflt)  X(jffne)  \
-	X(jffo)   X(jffuo)
+	X(jffo)   X(jffuo)  X(hlt)
 #define X(j) J##j,
 	JMPS(X)
 #undef X
diff --git a/amd64/emit.c b/amd64/emit.c
index a034a66..9e5996b 100644
--- a/amd64/emit.c
+++ b/amd64/emit.c
@@ -582,6 +582,9 @@ amd64_emitfn(Fn *fn, FILE *f)
 			emitins(*i, fn, f);
 		lbl = 1;
 		switch (b->jmp.type) {
+		case Jhlt:
+			fprintf(f, "\tud2\n");
+			break;
 		case Jret0:
 			if (fn->dynalloc)
 				fprintf(f,
diff --git a/amd64/isel.c b/amd64/isel.c
index 63c304a..6d62275 100644
--- a/amd64/isel.c
+++ b/amd64/isel.c
@@ -465,7 +465,9 @@ seljmp(Blk *b, Fn *fn)
 	Ins *fi;
 	Tmp *t;
 
-	if (b->jmp.type == Jret0 || b->jmp.type == Jjmp)
+	if (b->jmp.type == Jret0
+	|| b->jmp.type == Jjmp
+	|| b->jmp.type == Jhlt)
 		return;
 	assert(b->jmp.type == Jjnz);
 	r = b->jmp.arg;
diff --git a/arm64/emit.c b/arm64/emit.c
index 38b7e1a..4a0316c 100644
--- a/arm64/emit.c
+++ b/arm64/emit.c
@@ -561,6 +561,9 @@ arm64_emitfn(Fn *fn, FILE *out)
 			emitins(i, e);
 		lbl = 1;
 		switch (b->jmp.type) {
+		case Jhlt:
+			fprintf(e->f, "\tbrk\t#1000\n");
+			break;
 		case Jret0:
 			s = (e->frame - e->padding) / 4;
 			for (r=arm64_rclob; *r>=0; r++)
diff --git a/arm64/isel.c b/arm64/isel.c
index 9b062d8..062beb3 100644
--- a/arm64/isel.c
+++ b/arm64/isel.c
@@ -239,16 +239,11 @@ seljmp(Blk *b, Fn *fn)
 	Ins *i, *ir;
 	int ck, cc, use;
 
-	switch (b->jmp.type) {
-	default:
-		assert(0 && "TODO 2");
-		break;
-	case Jret0:
-	case Jjmp:
+	if (b->jmp.type == Jret0
+	|| b->jmp.type == Jjmp
+	|| b->jmp.type == Jhlt)
 		return;
-	case Jjnz:
-		break;
-	}
+	assert(b->jmp.type == Jjnz);
 	r = b->jmp.arg;
 	use = -1;
 	b->jmp.arg = R;
diff --git a/fold.c b/fold.c
index 75554bf..4b4a811 100644
--- a/fold.c
+++ b/fold.c
@@ -147,6 +147,8 @@ visitjmp(Blk *b, int n, Fn *fn)
 		edge[n][0].work = flowrk;
 		flowrk = &edge[n][0];
 		break;
+	case Jhlt:
+		break;
 	default:
 		if (isret(b->jmp.type))
 			break;
diff --git a/parse.c b/parse.c
index 04ef8be..849c81d 100644
--- a/parse.c
+++ b/parse.c
@@ -44,6 +44,7 @@ enum {
 	Tjmp,
 	Tjnz,
 	Tret,
+	Thlt,
 	Texport,
 	Tthread,
 	Tfunc,
@@ -99,6 +100,7 @@ static char *kwmap[Ntok] = {
 	[Tjmp] = "jmp",
 	[Tjnz] = "jnz",
 	[Tret] = "ret",
+	[Thlt] = "hlt",
 	[Texport] = "export",
 	[Tthread] = "thread",
 	[Tfunc] = "function",
@@ -641,7 +643,10 @@ parseline(PState ps)
 			curb->s2 = findblk(tokval.str);
 		}
 		if (curb->s1 == curf->start || curb->s2 == curf->start)
-			err("invalid jump to the start node");
+			err("invalid jump to the start block");
+		goto Close;
+	case Thlt:
+		curb->jmp.type = Jhlt;
 	Close:
 		expect(Tnl);
 		closeblk();
@@ -1322,6 +1327,9 @@ printfn(Fn *fn, FILE *f)
 				fprintf(f, ", :%s", typ[fn->retty].name);
 			fprintf(f, "\n");
 			break;
+		case Jhlt:
+			fprintf(f, "\thlt\n");
+			break;
 		case Jjmp:
 			if (b->s1 != b->link)
 				fprintf(f, "\tjmp @%s\n", b->s1->name);
@@ -1332,6 +1340,7 @@ printfn(Fn *fn, FILE *f)
 				printref(b->jmp.arg, fn, f);
 				fprintf(f, ", ");
 			}
+			assert(b->s1 && b->s2);
 			fprintf(f, "@%s, @%s\n", b->s1->name, b->s2->name);
 			break;
 		}
diff --git a/rv64/emit.c b/rv64/emit.c
index 4ce6555..f9e58da 100644
--- a/rv64/emit.c
+++ b/rv64/emit.c
@@ -494,6 +494,9 @@ rv64_emitfn(Fn *fn, FILE *f)
 			emitins(i, fn, f);
 		lbl = 1;
 		switch (b->jmp.type) {
+		case Jhlt:
+			fprintf(f, "\tebreak\n");
+			break;
 		case Jret0:
 			if (fn->dynalloc) {
 				if (frame - 16 <= 2048)
diff --git a/tools/lexh.c b/tools/lexh.c
index 1aea3e0..a07514e 100644
--- a/tools/lexh.c
+++ b/tools/lexh.c
@@ -25,7 +25,7 @@ char *tok[] = {
 	"cgtd", "cged", "cned", "ceqd", "cod", "cuod",
 	"vaarg", "vastart", "...", "env",
 
-	"call", "phi", "jmp", "jnz", "ret", "export",
+	"call", "phi", "jmp", "jnz", "ret", "hlt", "export",
 	"function", "type", "data", "section", "align",
 	"l", "w", "sh", "uh", "h", "sb", "ub", "b",
 	"d", "s", "z", "loadw", "loadl", "loads", "loadd",