~sircmpwn/hare

33282973c60e2f013997dfdcccf09d7c609e03c6 — Drew DeVault 11 months ago f41bc08
rt: add setjmp/longjmp, update test runner
7 files changed, 66 insertions(+), 0 deletions(-)

A rt/+test/abort.ha
M rt/+test/start.ha
A rt/+x86_64/jmp.ha
A rt/+x86_64/longjmp.s
A rt/+x86_64/setjmp.s
A rt/jmp.ha
R rt/{start-test.ha => start.ha}
A rt/+test/abort.ha => rt/+test/abort.ha +13 -0
@@ 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]);

M rt/+test/start.ha => rt/+test/start.ha +12 -0
@@ 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");
	};

A rt/+x86_64/jmp.ha => rt/+x86_64/jmp.ha +1 -0
@@ 0,0 1,1 @@
type arch_jmpbuf = [8]u64;

A rt/+x86_64/longjmp.s => rt/+x86_64/longjmp.s +15 -0
@@ 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 */

A rt/+x86_64/setjmp.s => rt/+x86_64/setjmp.s +16 -0
@@ 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

A rt/jmp.ha => rt/jmp.ha +9 -0
@@ 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;

R rt/start-test.ha => rt/start.ha +0 -0