hare

The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

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:
Art/+test/abort.ha | 13+++++++++++++
Mrt/+test/start.ha | 12++++++++++++
Art/+x86_64/jmp.ha | 1+
Art/+x86_64/longjmp.s | 15+++++++++++++++
Art/+x86_64/setjmp.s | 16++++++++++++++++
Art/jmp.ha | 9+++++++++
Rrt/start-test.ha -> rt/start.ha | 0
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