commit 33282973c60e2f013997dfdcccf09d7c609e03c6
parent f41bc0887e953d67023c298aadcddab7c3aceb29
Author: Drew DeVault <sir@cmpwn.com>
Date: Thu, 4 Feb 2021 16:08:14 -0500
rt: add setjmp/longjmp, update test runner
Diffstat:
7 files changed, 66 insertions(+), 0 deletions(-)
diff --git a/rt/+test/abort.ha b/rt/+test/abort.ha
@@ -0,0 +1,13 @@
+export @noreturn @symbol("rt.abort") fn _abort(msg: str) void = {
+ reason = msg;
+ longjmp(&jmp, 1);
+};
+
+// See harec:include/gen.h
+const reasons: [_]str = [
+ "slice or array access out of bounds", // 0
+ "type assertion failed", // 1
+ "out of memory", // 2
+];
+
+export @noreturn fn abort_fixed(i: int) void = _abort(reasons[i]);
diff --git a/rt/+test/start.ha b/rt/+test/start.ha
@@ -20,6 +20,9 @@ fn dots(n: size) void = {
};
};
+let jmp: jmpbuf = jmpbuf { ... };
+let reason: str = "";
+
export fn start_ha() void = {
const ninit = (&init_end: uintptr - &init_start: uintptr): size
/ size(*fn() void);
@@ -43,7 +46,16 @@ export fn start_ha() void = {
print(test_start[i].name);
dots(maxname - len(test_start[i].name) + 3z);
print(" ");
+
+ if (setjmp(&jmp) != 0) {
+ nfail += 1z;
+ print("FAIL: ");
+ print(reason);
+ print("\n");
+ continue;
+ };
test_start[i].func();
+
npass += 1z;
print("OK\n");
};
diff --git a/rt/+x86_64/jmp.ha b/rt/+x86_64/jmp.ha
@@ -0,0 +1 @@
+type arch_jmpbuf = [8]u64;
diff --git a/rt/+x86_64/longjmp.s b/rt/+x86_64/longjmp.s
@@ -0,0 +1,15 @@
+/* Copyright 2011-2012 Nicholas J. Kain, licensed under standard MIT license */
+.global rt.longjmp
+.type rt.longjmp,@function
+rt.longjmp:
+ xor %eax,%eax
+ cmp $1,%esi /* CF = val ? 0 : 1 */
+ adc %esi,%eax /* eax = val + !val */
+ mov (%rdi),%rbx /* rdi is the jmp_buf, restore regs from it */
+ mov 8(%rdi),%rbp
+ mov 16(%rdi),%r12
+ mov 24(%rdi),%r13
+ mov 32(%rdi),%r14
+ mov 40(%rdi),%r15
+ mov 48(%rdi),%rsp
+ jmp *56(%rdi) /* goto saved address without altering rsp */
diff --git a/rt/+x86_64/setjmp.s b/rt/+x86_64/setjmp.s
@@ -0,0 +1,16 @@
+/* Copyright 2011-2012 Nicholas J. Kain, licensed under standard MIT license */
+.global rt.setjmp
+.type rt.setjmp,@function
+rt.setjmp:
+ mov %rbx,(%rdi) /* rdi is jmp_buf, move registers onto it */
+ mov %rbp,8(%rdi)
+ mov %r12,16(%rdi)
+ mov %r13,24(%rdi)
+ mov %r14,32(%rdi)
+ mov %r15,40(%rdi)
+ lea 8(%rsp),%rdx /* this is our rsp WITHOUT current ret addr */
+ mov %rdx,48(%rdi)
+ mov (%rsp),%rdx /* save return addr ptr for new rip */
+ mov %rdx,56(%rdi)
+ xor %eax,%eax /* always return 0 */
+ ret
diff --git a/rt/jmp.ha b/rt/jmp.ha
@@ -0,0 +1,9 @@
+type jmpbuf = struct {
+ __jb: arch_jmpbuf,
+ __fl: size,
+ __ss: [128z / size(size)]size,
+};
+
+fn setjmp(buf: *jmpbuf) int;
+
+@noreturn fn longjmp(buf: *jmpbuf, n: int) void;
diff --git a/rt/start-test.ha b/rt/start.ha