~mpu/qbe

new hlt block terminator v1 PROPOSED

Quentin Carbonneaux: 1
 new hlt block terminator

 9 files changed, 28 insertions(+), 14 deletions(-)
Export patchset (mbox)
How do I use this?

Copy & paste the following snippet into your terminal to import this patchset into git:

curl -s https://lists.sr.ht/~mpu/qbe/patches/37083/mbox | git am -3
Learn more about email & git

[PATCH] new hlt block terminator Export this patch

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.

---

I'm sharing this on the ML to
gather some feedback. I still
need to test on osx before
merging it in master.

For Hare, I expect we will want
to generate 'hlt' terminators
on abort paths, and more generally
when calling a @noreturn func.

hlt may also prove handy when
optimization passes have to kill
a jump that should be dead (e.g.,
that depends on data loaded from
uninitialized memory).

 all.h        |  2 +-
 amd64/emit.c |  3 +++
 amd64/isel.c |  4 +++-
 arm64/emit.c |  3 +++
 arm64/isel.c | 13 ++++---------
 fold.c       |  5 ++++-
 parse.c      |  7 ++++++-
 rv64/emit.c  |  3 +++
 tools/lexh.c |  2 +-
 9 files changed, 28 insertions(+), 14 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..3873e40 100644
--- a/fold.c
+++ b/fold.c
@@ -147,9 +147,12 @@ visitjmp(Blk *b, int n, Fn *fn)
		edge[n][0].work = flowrk;
		flowrk = &edge[n][0];
		break;
	case Jhlt:
	case_Jret:
		break;
	default:
		if (isret(b->jmp.type))
			break;
			goto case_Jret;
		die("unreachable");
	}
}
diff --git a/parse.c b/parse.c
index 04ef8be..5b18d7c 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();
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",
-- 
2.38.1