commit e71c40a5ac4f6cde512124b7289c1bfe9e1e0cc1
parent ed0d394707763dd7f00c5921640338eb44ef685f
Author: Drew DeVault <sir@cmpwn.com>
Date: Fri, 1 Jan 2021 14:26:59 -0500
Add expected build failure testing
Diffstat:
5 files changed, 69 insertions(+), 2 deletions(-)
diff --git a/rt/+linux/syscalls.ha b/rt/+linux/syscalls.ha
@@ -9,13 +9,38 @@ fn syscall6(u64, u64, u64, u64, u64, u64, u64) u64;
export fn write(fd: int, buf: *void, count: size) size =
syscall3(SYS_write, fd: u64, buf: uintptr: u64, count: u64): size;
+export fn close(fd: int) int = syscall1(SYS_close, fd: u64): int;
+
+export fn dup2(old: int, new: int) int =
+ syscall2(SYS_dup2, old: u64, new: u64): int;
+
export fn getpid() int = syscall0(SYS_getpid): int;
export @noreturn fn exit(status: int) void = syscall1(SYS_exit, status: u64);
+export fn fork() int = syscall0(SYS_fork): int;
+
+export fn execve(
+ path: *const char,
+ argv: *[*]nullable *const char,
+ envp: *[*]nullable *const char,
+) int = syscall3(SYS_execve,
+ path: uintptr: u64,
+ argv: uintptr: u64,
+ envp: uintptr: u64): int;
+
+export fn wait4(pid: int, status: *int, options: int, rusage: *void) void =
+ syscall4(SYS_wait4, pid: u64, status: uintptr: u64,
+ options: u64, rusage: uintptr: u64);
+
+export fn wexitstatus(status: int) int = status & 0xff00 >> 8;
+
export fn kill(pid: int, signal: int) int =
syscall2(SYS_kill, pid: u64, signal: u64): int;
+export fn pipe2(pipefd: *[2]int, flags: int) int =
+ syscall2(SYS_pipe2, pipefd: uintptr: u64, flags: u64): int;
+
export def SIGHUP: int = 1;
export def SIGINT: int = 2;
export def SIGQUIT: int = 3;
diff --git a/rt/Makefile b/rt/Makefile
@@ -1,5 +1,6 @@
libhart_srcs+=\
rt/abort.ha \
+ rt/compile.ha \
rt/rtmain.ha
libhart.a: harec $(libhart_srcs) $(libhart_objs)
diff --git a/rt/compile.ha b/rt/compile.ha
@@ -0,0 +1,36 @@
+// Runs the Hare compiler and returns the exit status.
+export fn compile(src: str) int = {
+ let pipefd = [-1, -1];
+ pipe2(&pipefd, 0);
+
+ let status: int = 0;
+ const child = fork();
+ if (child == 0) {
+ close(pipefd[1]);
+ dup2(pipefd[0], 0);
+ close(1);
+ close(2);
+
+ // XXX: This could be simplified a lot with some compiler
+ // improvements
+ let path = "./harec";
+ let param = "-";
+ let argv = [
+ path: nullable *const char,
+ param: nullable *const char,
+ null: nullable *const char,
+ ];
+ let envp: [1]nullable *const char = [null: nullable *const char];
+ execve(path: *const char,
+ &argv: *[*]nullable *const char,
+ &envp: *[*]nullable *const char);
+ abort();
+ } else {
+ close(pipefd[0]);
+ write(pipefd[1], src: *const char: *void, len(src));
+ close(pipefd[1]);
+ wait4(child, &status, 0, null: *void);
+ };
+
+ return status;
+};
diff --git a/tests/03-pointers.ha b/tests/03-pointers.ha
@@ -1,3 +1,5 @@
+fn rt::compile(src: str) int;
+
fn basics() void = {
let x = 42;
let y: *int = &x;
@@ -12,7 +14,10 @@ fn _nullable() void = {
let y = 42;
x = &y;
assert(*(x: *int) == 42);
- // TODO: Expected failures with nullable pointers
+
+ assert(rt::compile(
+ "fn test() void = { let x: nullable *int = null; *x; };",
+ ) != 0);
};
export fn main() void = {
diff --git a/tests/configure b/tests/configure
@@ -10,7 +10,7 @@ tests() {
04-strings
do
cat <<EOF
-tests/$t: rt tests/$t.ha
+tests/$t: libhart.a tests/$t.ha
@printf 'HAREC %s\t$@\n' "tests/$t"
@./harec -o tests/$t.ssa tests/$t.ha
@qbe -o tests/$t.s tests/$t.ssa