summary refs log tree commit diff
path: root/parse.c
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 /parse.c
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.
Diffstat (limited to 'parse.c')
-rw-r--r--parse.c11
1 files changed, 10 insertions, 1 deletions
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;
 		}