Commit 66f3efb63b

Andrew Kelley <andrew@ziglang.org>
2022-05-13 09:00:20
migrate runtime safety tests to the new test harness
* migrate runtime safety tests to the new test harness - this required adding compare output / execution support for stage1 to the test harness. * rename `zig build test-stage2` to `zig build test-cases` since it now does quite a bit of stage1 testing actually. I named it this way since the main directory in the source tree associated with these tests is "test/cases/". * add some documentation for the test manifest format.
1 parent f32928c
Changed files (76)
ci
src
test
cases
safety
ci/azure/macos_script
@@ -71,12 +71,11 @@ release/bin/zig build test-standalone       -Denable-macos-sdk
 release/bin/zig build test-stack-traces     -Denable-macos-sdk
 release/bin/zig build test-cli              -Denable-macos-sdk
 release/bin/zig build test-asm-link         -Denable-macos-sdk
-release/bin/zig build test-runtime-safety   -Denable-macos-sdk
 release/bin/zig build test-translate-c      -Denable-macos-sdk
 release/bin/zig build test-run-translated-c -Denable-macos-sdk
 release/bin/zig build docs                  -Denable-macos-sdk
 release/bin/zig build test-fmt              -Denable-macos-sdk
-release/bin/zig build test-stage2           -Denable-macos-sdk
+release/bin/zig build test-cases            -Denable-macos-sdk
 
 if [ "${BUILD_REASON}" != "PullRequest" ]; then
   mv ../LICENSE release/
ci/drone/linux_script_test
@@ -34,12 +34,11 @@ case "$1" in
     ./build/zig build $BUILD_FLAGS test-stack-traces
     ./build/zig build $BUILD_FLAGS test-cli
     ./build/zig build $BUILD_FLAGS test-asm-link
-    ./build/zig build $BUILD_FLAGS test-runtime-safety
     ./build/zig build $BUILD_FLAGS test-translate-c
     ;;
   7)
     ./build/zig build $BUILD_FLAGS # test building self-hosted without LLVM
-    ./build/zig build $BUILD_FLAGS test-stage2
+    ./build/zig build $BUILD_FLAGS test-cases
     ;;
   '')
     echo "error: expecting test group argument"
ci/zinc/linux_test.sh
@@ -69,12 +69,11 @@ $ZIG build test-standalone       -fqemu -fwasmtime
 $ZIG build test-stack-traces     -fqemu -fwasmtime
 $ZIG build test-cli              -fqemu -fwasmtime
 $ZIG build test-asm-link         -fqemu -fwasmtime
-$ZIG build test-runtime-safety   -fqemu -fwasmtime
 $ZIG build test-translate-c      -fqemu -fwasmtime
 $ZIG build test-run-translated-c -fqemu -fwasmtime
 $ZIG build docs                  -fqemu -fwasmtime
 $ZIG build test-fmt              -fqemu -fwasmtime
-$ZIG build test-stage2           -fqemu -fwasmtime
+$ZIG build test-cases            -fqemu -fwasmtime
 
 # Produce the experimental std lib documentation.
 mkdir -p "$RELEASE_STAGING/docs/std"
src/test.zig
@@ -1394,7 +1394,22 @@ pub const TestContext = struct {
                     }
                 },
                 .CompareObjectFile => @panic("TODO implement in the test harness"),
-                .Execution => @panic("TODO implement in the test harness"),
+                .Execution => |expected_stdout| {
+                    switch (result.term) {
+                        .Exited => |code| {
+                            if (code != 0) {
+                                dumpArgs(zig_args.items);
+                                return error.CompilationFailed;
+                            }
+                        },
+                        else => {
+                            dumpArgs(zig_args.items);
+                            return error.CompilationCrashed;
+                        },
+                    }
+                    try std.testing.expectEqualStrings("", result.stderr);
+                    try std.testing.expectEqualStrings(expected_stdout, result.stdout);
+                },
                 .Header => @panic("TODO implement in the test harness"),
             }
             return;
test/cases/safety/@alignCast misaligned.zig
@@ -0,0 +1,21 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = message;
+    _ = stack_trace;
+    std.process.exit(0);
+}
+
+pub fn main() !void {
+    var array align(4) = [_]u32{0x11111111, 0x11111111};
+    const bytes = std.mem.sliceAsBytes(array[0..]);
+    if (foo(bytes) != 0x11111111) return error.Wrong;
+    return error.TestFailed;
+}
+fn foo(bytes: []u8) u32 {
+    const slice4 = bytes[1..5];
+    const int_slice = std.mem.bytesAsSlice(u32, @alignCast(4, slice4));
+    return int_slice[0];
+}
+// run
+// backend=stage1
\ No newline at end of file
test/cases/safety/@asyncCall with too small a frame.zig
@@ -0,0 +1,19 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = message;
+    _ = stack_trace;
+    std.process.exit(0);
+}
+pub fn main() !void {
+    var bytes: [1]u8 align(16) = undefined;
+    var ptr = other;
+    var frame = @asyncCall(&bytes, {}, ptr, .{});
+    _ = frame;
+    return error.TestFailed;
+}
+fn other() callconv(.Async) void {
+    suspend {}
+}
+// run
+// backend=stage1
test/cases/safety/@errSetCast error not present in destination.zig
@@ -0,0 +1,18 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = message;
+    _ = stack_trace;
+    std.process.exit(0);
+}
+const Set1 = error{A, B};
+const Set2 = error{A, C};
+pub fn main() !void {
+    foo(Set1.B) catch {};
+    return error.TestFailed;
+}
+fn foo(set1: Set1) Set2 {
+    return @errSetCast(Set2, set1);
+}
+// run
+// backend=stage1
\ No newline at end of file
test/cases/safety/@floatToInt cannot fit - negative out of range.zig
@@ -0,0 +1,17 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = message;
+    _ = stack_trace;
+    std.process.exit(0);
+}
+pub fn main() !void {
+    baz(bar(-129.1));
+    return error.TestFailed;
+}
+fn bar(a: f32) i8 {
+    return @floatToInt(i8, a);
+}
+fn baz(_: i8) void { }
+// run
+// backend=stage1
\ No newline at end of file
test/cases/safety/@floatToInt cannot fit - negative to unsigned.zig
@@ -0,0 +1,17 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = message;
+    _ = stack_trace;
+    std.process.exit(0);
+}
+pub fn main() !void {
+    baz(bar(-1.1));
+    return error.TestFailed;
+}
+fn bar(a: f32) u8 {
+    return @floatToInt(u8, a);
+}
+fn baz(_: u8) void { }
+// run
+// backend=stage1
\ No newline at end of file
test/cases/safety/@floatToInt cannot fit - positive out of range.zig
@@ -0,0 +1,17 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = message;
+    _ = stack_trace;
+    std.process.exit(0);
+}
+pub fn main() !void {
+    baz(bar(256.2));
+    return error.TestFailed;
+}
+fn bar(a: f32) u8 {
+    return @floatToInt(u8, a);
+}
+fn baz(_: u8) void { }
+// run
+// backend=stage1
\ No newline at end of file
test/cases/safety/@intCast to u0.zig
@@ -0,0 +1,19 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = message;
+    _ = stack_trace;
+    std.process.exit(0);
+}
+
+pub fn main() !void {
+    bar(1, 1);
+    return error.TestFailed;
+}
+
+fn bar(one: u1, not_zero: i32) void {
+    var x = one << @intCast(u0, not_zero);
+    _ = x;
+}
+// run
+// backend=stage1
\ No newline at end of file
test/cases/safety/@intToEnum - no matching tag value.zig
@@ -0,0 +1,22 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = message;
+    _ = stack_trace;
+    std.process.exit(0);
+}
+const Foo = enum {
+    A,
+    B,
+    C,
+};
+pub fn main() !void {
+    baz(bar(3));
+    return error.TestFailed;
+}
+fn bar(a: u2) Foo {
+    return @intToEnum(Foo, a);
+}
+fn baz(_: Foo) void {}
+// run
+// backend=stage1
test/cases/safety/@intToPtr address zero to non-optional byte-aligned pointer.zig
@@ -0,0 +1,15 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = message;
+    _ = stack_trace;
+    std.process.exit(0);
+}
+pub fn main() !void {
+    var zero: usize = 0;
+    var b = @intToPtr(*u8, zero);
+    _ = b;
+    return error.TestFailed;
+}
+// run
+// backend=stage1
test/cases/safety/@intToPtr address zero to non-optional pointer.zig
@@ -0,0 +1,15 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = message;
+    _ = stack_trace;
+    std.process.exit(0);
+}
+pub fn main() !void {
+    var zero: usize = 0;
+    var b = @intToPtr(*i32, zero);
+    _ = b;
+    return error.TestFailed;
+}
+// run
+// backend=stage1
test/cases/safety/@tagName on corrupted enum value.zig
@@ -0,0 +1,24 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = stack_trace;
+    if (std.mem.eql(u8, message, "invalid enum value")) {
+        std.process.exit(0);
+    }
+    std.process.exit(1);
+}
+
+const E = enum(u32) {
+    X = 1,
+};
+
+pub fn main() !void {
+    var e: E = undefined;
+    @memset(@ptrCast([*]u8, &e), 0x55, @sizeOf(E));
+    var n = @tagName(e);
+    _ = n;
+    return error.TestFailed;
+}
+
+// run
+// backend=stage1
test/cases/safety/@tagName on corrupted union value.zig
@@ -0,0 +1,25 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = stack_trace;
+    if (std.mem.eql(u8, message, "invalid enum value")) {
+        std.process.exit(0);
+    }
+    std.process.exit(1);
+}
+
+const U = union(enum(u32)) {
+    X: u8,
+};
+
+pub fn main() !void {
+    var u: U = undefined;
+    @memset(@ptrCast([*]u8, &u), 0x55, @sizeOf(U));
+    var t: @typeInfo(U).Union.tag_type.? = u;
+    var n = @tagName(t);
+    _ = n;
+    return error.TestFailed;
+}
+
+// run
+// backend=stage1
test/cases/safety/array slice sentinel mismatch.zig
@@ -0,0 +1,18 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = stack_trace;
+    if (std.mem.eql(u8, message, "sentinel mismatch")) {
+        std.process.exit(0);
+    }
+    std.process.exit(1);
+}
+pub fn main() !void {
+    var buf: [4]u8 = undefined;
+    const slice = buf[0..3 :0];
+    _ = slice;
+    return error.TestFailed;
+}
+// run
+// backend=stage1
+
test/cases/safety/awaiting twice.zig
@@ -0,0 +1,28 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = message;
+    _ = stack_trace;
+    std.process.exit(0);
+}
+var frame: anyframe = undefined;
+
+pub fn main() !void {
+    _ = async amain();
+    resume frame;
+    return error.TestFailed;
+}
+
+fn amain() void {
+    var f = async func();
+    await f;
+    await f;
+}
+
+fn func() void {
+    suspend {
+        frame = @frame();
+    }
+}
+// run
+// backend=stage1
test/cases/safety/bad union field access.zig
@@ -0,0 +1,24 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = message;
+    _ = stack_trace;
+    std.process.exit(0);
+}
+
+const Foo = union {
+    float: f32,
+    int: u32,
+};
+
+pub fn main() !void {
+    var f = Foo { .int = 42 };
+    bar(&f);
+    return error.TestFailed;
+}
+
+fn bar(f: *Foo) void {
+    f.float = 12.34;
+}
+// run
+// backend=stage1
\ No newline at end of file
test/cases/safety/calling panic.zig
@@ -0,0 +1,15 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = stack_trace;
+    if (std.mem.eql(u8, message, "oh no")) {
+        std.process.exit(0);
+    }
+    std.process.exit(1);
+}
+pub fn main() !void {
+    if (true) @panic("oh no");
+    return error.TestFailed;
+}
+// run
+// backend=stage1
\ No newline at end of file
test/cases/safety/cast []u8 to bigger slice of wrong size.zig
@@ -0,0 +1,18 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = message;
+    _ = stack_trace;
+    std.process.exit(0);
+}
+
+pub fn main() !void {
+    const x = widenSlice(&[_]u8{1, 2, 3, 4, 5});
+    if (x.len == 0) return error.Whatever;
+    return error.TestFailed;
+}
+fn widenSlice(slice: []align(1) const u8) []align(1) const i32 {
+    return std.mem.bytesAsSlice(i32, slice);
+}
+// run
+// backend=stage1
\ No newline at end of file
test/cases/safety/cast integer to global error and no code matches.zig
@@ -0,0 +1,16 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = message;
+    _ = stack_trace;
+    std.process.exit(0);
+}
+pub fn main() !void {
+    bar(9999) catch {};
+    return error.TestFailed;
+}
+fn bar(x: u16) anyerror {
+    return @intToError(x);
+}
+// run
+// backend=stage1
\ No newline at end of file
test/cases/safety/empty slice with sentinel out of bounds.zig
@@ -0,0 +1,20 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = stack_trace;
+    if (std.mem.eql(u8, message, "index out of bounds")) {
+        std.process.exit(0);
+    }
+    std.process.exit(1);
+}
+
+pub fn main() !void {
+    var buf_zero = [0]u8{};
+    const input: []u8 = &buf_zero;
+    const slice = input[0..0 :0];
+    _ = slice;
+    return error.TestFailed;
+}
+
+// run
+// backend=stage1
test/cases/safety/error return trace across suspend points.zig
@@ -0,0 +1,38 @@
+const std = @import("std");
+
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = message;
+    _ = stack_trace;
+    std.process.exit(0);
+}
+
+var failing_frame: @Frame(failing) = undefined;
+
+pub fn main() !void {
+    const p = nonFailing();
+    resume p;
+    const p2 = async printTrace(p);
+    _ = p2;
+    return error.TestFailed;
+}
+
+fn nonFailing() anyframe->anyerror!void {
+    failing_frame = async failing();
+    return &failing_frame;
+}
+
+fn failing() anyerror!void {
+    suspend {}
+    return second();
+}
+
+fn second() callconv(.Async) anyerror!void {
+    return error.Fail;
+}
+
+fn printTrace(p: anyframe->anyerror!void) void {
+    (await p) catch unreachable;
+}
+// run
+// backend=stage1
\ No newline at end of file
test/cases/safety/exact division failure - vectors.zig
@@ -0,0 +1,20 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = message;
+    _ = stack_trace;
+    std.process.exit(0);
+}
+
+pub fn main() !void {
+    var a: @Vector(4, i32) = [4]i32{111, 222, 333, 444};
+    var b: @Vector(4, i32) = [4]i32{111, 222, 333, 441};
+    const x = divExact(a, b);
+    _ = x;
+    return error.TestFailed;
+}
+fn divExact(a: @Vector(4, i32), b: @Vector(4, i32)) @Vector(4, i32) {
+    return @divExact(a, b);
+}
+// run
+// backend=stage1
\ No newline at end of file
test/cases/safety/exact division failure.zig
@@ -0,0 +1,18 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = message;
+    _ = stack_trace;
+    std.process.exit(0);
+}
+
+pub fn main() !void {
+    const x = divExact(10, 3);
+    if (x == 0) return error.Whatever;
+    return error.TestFailed;
+}
+fn divExact(a: i32, b: i32) i32 {
+    return @divExact(a, b);
+}
+// run
+// backend=stage1
\ No newline at end of file
test/cases/safety/integer addition overflow.zig
@@ -0,0 +1,22 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = stack_trace;
+    if (std.mem.eql(u8, message, "integer overflow")) {
+        std.process.exit(0);
+    }
+    std.process.exit(1);
+}
+
+pub fn main() !void {
+    const x = add(65530, 10);
+    if (x == 0) return error.Whatever;
+    return error.TestFailed;
+}
+
+fn add(a: u16, b: u16) u16 {
+    return a + b;
+}
+
+// run
+// backend=stage1
test/cases/safety/integer division by zero - vectors.zig
@@ -0,0 +1,19 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = message;
+    _ = stack_trace;
+    std.process.exit(0);
+}
+pub fn main() !void {
+    var a: @Vector(4, i32) = [4]i32{111, 222, 333, 444};
+    var b: @Vector(4, i32) = [4]i32{111, 0, 333, 444};
+    const x = div0(a, b);
+    _ = x;
+    return error.TestFailed;
+}
+fn div0(a: @Vector(4, i32), b: @Vector(4, i32)) @Vector(4, i32) {
+    return @divTrunc(a, b);
+}
+// run
+// backend=stage1
\ No newline at end of file
test/cases/safety/integer division by zero.zig
@@ -0,0 +1,17 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = message;
+    _ = stack_trace;
+    std.process.exit(0);
+}
+pub fn main() !void {
+    const x = div0(999, 0);
+    _ = x;
+    return error.TestFailed;
+}
+fn div0(a: i32, b: i32) i32 {
+    return @divTrunc(a, b);
+}
+// run
+// backend=stage1
\ No newline at end of file
test/cases/safety/integer multiplication overflow.zig
@@ -0,0 +1,18 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = message;
+    _ = stack_trace;
+    std.process.exit(0);
+}
+
+pub fn main() !void {
+    const x = mul(300, 6000);
+    if (x == 0) return error.Whatever;
+    return error.TestFailed;
+}
+fn mul(a: u16, b: u16) u16 {
+    return a * b;
+}
+// run
+// backend=stage1
\ No newline at end of file
test/cases/safety/integer negation overflow.zig
@@ -0,0 +1,18 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = message;
+    _ = stack_trace;
+    std.process.exit(0);
+}
+
+pub fn main() !void {
+    const x = neg(-32768);
+    if (x == 32767) return error.Whatever;
+    return error.TestFailed;
+}
+fn neg(a: i16) i16 {
+    return -a;
+}
+// run
+// backend=stage1
\ No newline at end of file
test/cases/safety/integer subtraction overflow.zig
@@ -0,0 +1,18 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = message;
+    _ = stack_trace;
+    std.process.exit(0);
+}
+
+pub fn main() !void {
+    const x = sub(10, 20);
+    if (x == 0) return error.Whatever;
+    return error.TestFailed;
+}
+fn sub(a: u16, b: u16) u16 {
+    return a - b;
+}
+// run
+// backend=stage1
\ No newline at end of file
test/cases/safety/intToPtr with misaligned address.zig
@@ -0,0 +1,17 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = stack_trace;
+    if (std.mem.eql(u8, message, "incorrect alignment")) {
+        std.process.exit(0);
+    }
+    std.process.exit(1);
+}
+pub fn main() !void {
+    var x: usize = 5;
+    var y = @intToPtr([*]align(4) u8, x);
+    _ = y;
+    return error.TestFailed;
+}
+// run
+// backend=stage1
test/cases/safety/invalid resume of async function.zig
@@ -0,0 +1,18 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = message;
+    _ = stack_trace;
+    std.process.exit(0);
+}
+pub fn main() !void {
+    var p = async suspendOnce();
+    resume p; //ok
+    resume p; //bad
+    return error.TestFailed;
+}
+fn suspendOnce() void {
+    suspend {}
+}
+// run
+// backend=stage1
test/cases/safety/nosuspend function call, callee suspends.zig
@@ -0,0 +1,19 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = message;
+    _ = stack_trace;
+    std.process.exit(0);
+}
+pub fn main() !void {
+    _ = nosuspend add(101, 100);
+    return error.TestFailed;
+}
+fn add(a: i32, b: i32) i32 {
+    if (a > 100) {
+        suspend {}
+    }
+    return a + b;
+}
+// run
+// backend=stage1
test/cases/safety/optional unwrap operator on C pointer.zig
@@ -0,0 +1,15 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = message;
+    _ = stack_trace;
+    std.process.exit(0);
+}
+pub fn main() !void {
+    var ptr: [*c]i32 = null;
+    var b = ptr.?;
+    _ = b;
+    return error.TestFailed;
+}
+// run
+// backend=stage1
test/cases/safety/optional unwrap operator on null pointer.zig
@@ -0,0 +1,15 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = message;
+    _ = stack_trace;
+    std.process.exit(0);
+}
+pub fn main() !void {
+    var ptr: ?*i32 = null;
+    var b = ptr.?;
+    _ = b;
+    return error.TestFailed;
+}
+// run
+// backend=stage1
test/cases/safety/out of bounds slice access.zig
@@ -0,0 +1,18 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = message;
+    _ = stack_trace;
+    std.process.exit(0);
+}
+pub fn main() !void {
+    const a = [_]i32{1, 2, 3, 4};
+    baz(bar(&a));
+    return error.TestFailed;
+}
+fn bar(a: []const i32) i32 {
+    return a[4];
+}
+fn baz(_: i32) void { }
+// run
+// backend=stage1
\ No newline at end of file
test/cases/safety/pointer casting null to non-optional pointer.zig
@@ -0,0 +1,15 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = message;
+    _ = stack_trace;
+    std.process.exit(0);
+}
+pub fn main() !void {
+    var c_ptr: [*c]u8 = 0;
+    var zig_ptr: *u8 = c_ptr;
+    _ = zig_ptr;
+    return error.TestFailed;
+}
+// run
+// backend=stage1
test/cases/safety/pointer slice sentinel mismatch.zig
@@ -0,0 +1,20 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = stack_trace;
+    if (std.mem.eql(u8, message, "sentinel mismatch")) {
+        std.process.exit(0);
+    }
+    std.process.exit(1);
+}
+
+pub fn main() !void {
+    var buf: [4]u8 = undefined;
+    const ptr: [*]u8 = &buf;
+    const slice = ptr[0..3 :0];
+    _ = slice;
+    return error.TestFailed;
+}
+
+// run
+// backend=stage1
test/cases/safety/resuming a function which is awaiting a call.zig
@@ -0,0 +1,20 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = message;
+    _ = stack_trace;
+    std.process.exit(0);
+}
+pub fn main() !void {
+    var frame = async first();
+    resume frame;
+    return error.TestFailed;
+}
+fn first() void {
+    other();
+}
+fn other() void {
+    suspend {}
+}
+// run
+// backend=stage1
test/cases/safety/resuming a function which is awaiting a frame.zig
@@ -0,0 +1,21 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = message;
+    _ = stack_trace;
+    std.process.exit(0);
+}
+pub fn main() !void {
+    var frame = async first();
+    resume frame;
+    return error.TestFailed;
+}
+fn first() void {
+    var frame = async other();
+    await frame;
+}
+fn other() void {
+    suspend {}
+}
+// run
+// backend=stage1
test/cases/safety/resuming a non-suspended function which has been suspended and resumed.zig
@@ -0,0 +1,31 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = message;
+    _ = stack_trace;
+    std.process.exit(0);
+}
+fn foo() void {
+    suspend {
+        global_frame = @frame();
+    }
+    var f = async bar(@frame());
+    _ = f;
+    std.os.exit(1);
+}
+
+fn bar(frame: anyframe) void {
+    suspend {
+        resume frame;
+    }
+    std.os.exit(1);
+}
+
+var global_frame: anyframe = undefined;
+pub fn main() !void {
+    _ = async foo();
+    resume global_frame;
+    std.os.exit(1);
+}
+// run
+// backend=stage1
test/cases/safety/resuming a non-suspended function which never been suspended.zig
@@ -0,0 +1,26 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = message;
+    _ = stack_trace;
+    std.process.exit(0);
+}
+fn foo() void {
+    var f = async bar(@frame());
+    _ = f;
+    std.os.exit(1);
+}
+
+fn bar(frame: anyframe) void {
+    suspend {
+        resume frame;
+    }
+    std.os.exit(1);
+}
+
+pub fn main() !void {
+    _ = async foo();
+    return error.TestFailed;
+}
+// run
+// backend=stage1
test/cases/safety/shift left by huge amount.zig
@@ -0,0 +1,20 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = stack_trace;
+    if (std.mem.eql(u8, message, "shift amount is greater than the type size")) {
+        std.process.exit(0);
+    }
+    std.process.exit(1);
+}
+
+pub fn main() !void {
+    var x: u24 = 42;
+    var y: u5 = 24;
+    var z = x >> y;
+    _ = z;
+    return error.TestFailed;
+}
+
+// run
+// backend=stage1
test/cases/safety/shift right by huge amount.zig
@@ -0,0 +1,20 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = stack_trace;
+    if (std.mem.eql(u8, message, "shift amount is greater than the type size")) {
+        std.process.exit(0);
+    }
+    std.process.exit(1);
+}
+
+pub fn main() !void {
+    var x: u24 = 42;
+    var y: u5 = 24;
+    var z = x << y;
+    _ = z;
+    return error.TestFailed;
+}
+
+// run
+// backend=stage1
test/cases/safety/signed integer division overflow - vectors.zig
@@ -0,0 +1,20 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = message;
+    _ = stack_trace;
+    std.process.exit(0);
+}
+
+pub fn main() !void {
+    var a: @Vector(4, i16) = [_]i16{ 1, 2, -32768, 4 };
+    var b: @Vector(4, i16) = [_]i16{ 1, 2, -1, 4 };
+    const x = div(a, b);
+    if (x[2] == 32767) return error.Whatever;
+    return error.TestFailed;
+}
+fn div(a: @Vector(4, i16), b: @Vector(4, i16)) @Vector(4, i16) {
+    return @divTrunc(a, b);
+}
+// run
+// backend=stage1
\ No newline at end of file
test/cases/safety/signed integer division overflow.zig
@@ -0,0 +1,18 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = message;
+    _ = stack_trace;
+    std.process.exit(0);
+}
+
+pub fn main() !void {
+    const x = div(-32768, -1);
+    if (x == 32767) return error.Whatever;
+    return error.TestFailed;
+}
+fn div(a: i16, b: i16) i16 {
+    return @divTrunc(a, b);
+}
+// run
+// backend=stage1
\ No newline at end of file
test/cases/safety/signed integer not fitting in cast to unsigned integer - widening.zig
@@ -0,0 +1,15 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = message;
+    _ = stack_trace;
+    std.process.exit(0);
+}
+pub fn main() !void {
+    var value: c_short = -1;
+    var casted = @intCast(u32, value);
+    _ = casted;
+    return error.TestFailed;
+}
+// run
+// backend=stage1
\ No newline at end of file
test/cases/safety/signed integer not fitting in cast to unsigned integer.zig
@@ -0,0 +1,18 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = message;
+    _ = stack_trace;
+    std.process.exit(0);
+}
+
+pub fn main() !void {
+    const x = unsigned_cast(-10);
+    if (x == 0) return error.Whatever;
+    return error.TestFailed;
+}
+fn unsigned_cast(x: i32) u32 {
+    return @intCast(u32, x);
+}
+// run
+// backend=stage1
\ No newline at end of file
test/cases/safety/signed shift left overflow.zig
@@ -0,0 +1,18 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = message;
+    _ = stack_trace;
+    std.process.exit(0);
+}
+
+pub fn main() !void {
+    const x = shl(-16385, 1);
+    if (x == 0) return error.Whatever;
+    return error.TestFailed;
+}
+fn shl(a: i16, b: u4) i16 {
+    return @shlExact(a, b);
+}
+// run
+// backend=stage1
\ No newline at end of file
test/cases/safety/signed shift right overflow.zig
@@ -0,0 +1,18 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = message;
+    _ = stack_trace;
+    std.process.exit(0);
+}
+
+pub fn main() !void {
+    const x = shr(-16385, 1);
+    if (x == 0) return error.Whatever;
+    return error.TestFailed;
+}
+fn shr(a: i16, b: u4) i16 {
+    return @shrExact(a, b);
+}
+// run
+// backend=stage1
\ No newline at end of file
test/cases/safety/signed-unsigned vector cast.zig
@@ -0,0 +1,19 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = stack_trace;
+    if (std.mem.eql(u8, message, "attempt to cast negative value to unsigned integer")) {
+        std.process.exit(0);
+    }
+    std.process.exit(1);
+}
+
+pub fn main() !void {
+    var x = @splat(4, @as(i32, -2147483647));
+    var y = @intCast(@Vector(4, u32), x);
+    _ = y;
+    return error.TestFailed;
+}
+
+// run
+// backend=stage1
test/cases/safety/slice sentinel mismatch - floats.zig
@@ -0,0 +1,19 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = stack_trace;
+    if (std.mem.eql(u8, message, "sentinel mismatch")) {
+        std.process.exit(0);
+    }
+    std.process.exit(1);
+}
+
+pub fn main() !void {
+    var buf: [4]f32 = undefined;
+    const slice = buf[0..3 :1.2];
+    _ = slice;
+    return error.TestFailed;
+}
+
+// run
+// backend=stage1
test/cases/safety/slice sentinel mismatch - optional pointers.zig
@@ -0,0 +1,19 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = stack_trace;
+    if (std.mem.eql(u8, message, "sentinel mismatch")) {
+        std.process.exit(0);
+    }
+    std.process.exit(1);
+}
+
+pub fn main() !void {
+    var buf: [4]?*i32 = undefined;
+    const slice = buf[0..3 :null];
+    _ = slice;
+    return error.TestFailed;
+}
+
+// run
+// backend=stage1
test/cases/safety/slice slice sentinel mismatch.zig
@@ -0,0 +1,18 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = stack_trace;
+    if (std.mem.eql(u8, message, "sentinel mismatch")) {
+        std.process.exit(0);
+    }
+    std.process.exit(1);
+}
+pub fn main() !void {
+    var buf: [4]u8 = undefined;
+    const slice = buf[0..];
+    const slice2 = slice[0..3 :0];
+    _ = slice2;
+    return error.TestFailed;
+}
+// run
+// backend=stage1
test/cases/safety/slice with sentinel out of bounds.zig
@@ -0,0 +1,20 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = stack_trace;
+    if (std.mem.eql(u8, message, "index out of bounds")) {
+        std.process.exit(0);
+    }
+    std.process.exit(1);
+}
+
+pub fn main() !void {
+    var buf = [4]u8{ 'a', 'b', 'c', 0 };
+    const input: []u8 = &buf;
+    const slice = input[0..4 :0];
+    _ = slice;
+    return error.TestFailed;
+}
+
+// run
+// backend=stage1
test/cases/safety/slicing null C pointer.zig
@@ -0,0 +1,16 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = message;
+    _ = stack_trace;
+    std.process.exit(0);
+}
+
+pub fn main() !void {
+    var ptr: [*c]const u32 = null;
+    var slice = ptr[0..3];
+    _ = slice;
+    return error.TestFailed;
+}
+// run
+// backend=stage1
\ No newline at end of file
test/cases/safety/switch on corrupted enum value.zig
@@ -0,0 +1,25 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = stack_trace;
+    if (std.mem.eql(u8, message, "reached unreachable code")) {
+        std.process.exit(0);
+    }
+    std.process.exit(1);
+}
+
+const E = enum(u32) {
+    X = 1,
+};
+
+pub fn main() !void {
+    var e: E = undefined;
+    @memset(@ptrCast([*]u8, &e), 0x55, @sizeOf(E));
+    switch (e) {
+        .X => @breakpoint(),
+    }
+    return error.TestFailed;
+}
+
+// run
+// backend=stage1
test/cases/safety/switch on corrupted union value.zig
@@ -0,0 +1,25 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = stack_trace;
+    if (std.mem.eql(u8, message, "reached unreachable code")) {
+        std.process.exit(0);
+    }
+    std.process.exit(1);
+}
+
+const U = union(enum(u32)) {
+    X: u8,
+};
+
+pub fn main() !void {
+    var u: U = undefined;
+    @memset(@ptrCast([*]u8, &u), 0x55, @sizeOf(U));
+    switch (u) {
+        .X => @breakpoint(),
+    }
+    return error.TestFailed;
+}
+
+// run
+// backend=stage1
test/cases/safety/truncating vector cast.zig
@@ -0,0 +1,19 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = stack_trace;
+    if (std.mem.eql(u8, message, "integer cast truncated bits")) {
+        std.process.exit(0);
+    }
+    std.process.exit(1);
+}
+
+pub fn main() !void {
+    var x = @splat(4, @as(u32, 0xdeadbeef));
+    var y = @intCast(@Vector(4, u16), x);
+    _ = y;
+    return error.TestFailed;
+}
+
+// run
+// backend=stage1
test/cases/safety/unsigned integer not fitting in cast to signed integer - same bit count.zig
@@ -0,0 +1,15 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = message;
+    _ = stack_trace;
+    std.process.exit(0);
+}
+pub fn main() !void {
+    var value: u8 = 245;
+    var casted = @intCast(i8, value);
+    _ = casted;
+    return error.TestFailed;
+}
+// run
+// backend=stage1
\ No newline at end of file
test/cases/safety/unsigned shift left overflow.zig
@@ -0,0 +1,18 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = message;
+    _ = stack_trace;
+    std.process.exit(0);
+}
+
+pub fn main() !void {
+    const x = shl(0b0010111111111111, 3);
+    if (x == 0) return error.Whatever;
+    return error.TestFailed;
+}
+fn shl(a: u16, b: u4) u16 {
+    return @shlExact(a, b);
+}
+// run
+// backend=stage1
\ No newline at end of file
test/cases/safety/unsigned shift right overflow.zig
@@ -0,0 +1,18 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = message;
+    _ = stack_trace;
+    std.process.exit(0);
+}
+
+pub fn main() !void {
+    const x = shr(0b0010111111111111, 3);
+    if (x == 0) return error.Whatever;
+    return error.TestFailed;
+}
+fn shr(a: u16, b: u4) u16 {
+    return @shrExact(a, b);
+}
+// run
+// backend=stage1
\ No newline at end of file
test/cases/safety/unsigned-signed vector cast.zig
@@ -0,0 +1,19 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = stack_trace;
+    if (std.mem.eql(u8, message, "integer cast truncated bits")) {
+        std.process.exit(0);
+    }
+    std.process.exit(1);
+}
+
+pub fn main() !void {
+    var x = @splat(4, @as(u32, 0x80000000));
+    var y = @intCast(@Vector(4, i32), x);
+    _ = y;
+    return error.TestFailed;
+}
+
+// run
+// backend=stage1
test/cases/safety/unwrap error.zig
@@ -0,0 +1,18 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = stack_trace;
+    if (std.mem.eql(u8, message, "attempt to unwrap error: Whatever")) {
+        std.process.exit(0);
+    }
+    std.process.exit(1);
+}
+pub fn main() !void {
+    bar() catch unreachable;
+    return error.TestFailed;
+}
+fn bar() !void {
+    return error.Whatever;
+}
+// run
+// backend=stage1
\ No newline at end of file
test/cases/safety/value does not fit in shortening cast - u0.zig
@@ -0,0 +1,18 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = message;
+    _ = stack_trace;
+    std.process.exit(0);
+}
+
+pub fn main() !void {
+    const x = shorten_cast(1);
+    if (x == 0) return error.Whatever;
+    return error.TestFailed;
+}
+fn shorten_cast(x: u8) u0 {
+    return @intCast(u0, x);
+}
+// run
+// backend=stage1
\ No newline at end of file
test/cases/safety/value does not fit in shortening cast.zig
@@ -0,0 +1,18 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = message;
+    _ = stack_trace;
+    std.process.exit(0);
+}
+
+pub fn main() !void {
+    const x = shorten_cast(200);
+    if (x == 0) return error.Whatever;
+    return error.TestFailed;
+}
+fn shorten_cast(x: i32) i8 {
+    return @intCast(i8, x);
+}
+// run
+// backend=stage1
\ No newline at end of file
test/cases/safety/vector integer addition overflow.zig
@@ -0,0 +1,19 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = message;
+    _ = stack_trace;
+    std.process.exit(0);
+}
+pub fn main() !void {
+    var a: @Vector(4, i32) = [_]i32{ 1, 2, 2147483643, 4 };
+    var b: @Vector(4, i32) = [_]i32{ 5, 6, 7, 8 };
+    const x = add(a, b);
+    _ = x;
+    return error.TestFailed;
+}
+fn add(a: @Vector(4, i32), b: @Vector(4, i32)) @Vector(4, i32) {
+    return a + b;
+}
+// run
+// backend=stage1
\ No newline at end of file
test/cases/safety/vector integer multiplication overflow.zig
@@ -0,0 +1,19 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = message;
+    _ = stack_trace;
+    std.process.exit(0);
+}
+pub fn main() !void {
+    var a: @Vector(4, u8) = [_]u8{ 1, 2, 200, 4 };
+    var b: @Vector(4, u8) = [_]u8{ 5, 6, 2, 8 };
+    const x = mul(b, a);
+    _ = x;
+    return error.TestFailed;
+}
+fn mul(a: @Vector(4, u8), b: @Vector(4, u8)) @Vector(4, u8) {
+    return a * b;
+}
+// run
+// backend=stage1
\ No newline at end of file
test/cases/safety/vector integer negation overflow.zig
@@ -0,0 +1,18 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = message;
+    _ = stack_trace;
+    std.process.exit(0);
+}
+pub fn main() !void {
+    var a: @Vector(4, i16) = [_]i16{ 1, -32768, 200, 4 };
+    const x = neg(a);
+    _ = x;
+    return error.TestFailed;
+}
+fn neg(a: @Vector(4, i16)) @Vector(4, i16) {
+    return -a;
+}
+// run
+// backend=stage1
\ No newline at end of file
test/cases/safety/vector integer subtraction overflow.zig
@@ -0,0 +1,19 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
+    _ = message;
+    _ = stack_trace;
+    std.process.exit(0);
+}
+pub fn main() !void {
+    var a: @Vector(4, u32) = [_]u32{ 1, 2, 8, 4 };
+    var b: @Vector(4, u32) = [_]u32{ 5, 6, 7, 8 };
+    const x = sub(b, a);
+    _ = x;
+    return error.TestFailed;
+}
+fn sub(a: @Vector(4, u32), b: @Vector(4, u32)) @Vector(4, u32) {
+    return a - b;
+}
+// run
+// backend=stage1
\ No newline at end of file
test/cases/README.md
@@ -0,0 +1,61 @@
+# Test Case Quick Reference
+
+Use comments at the **end of the file** to indicate metadata about the test
+case. Here are examples of different kinds of tests:
+
+## Compile Error Test
+
+If you want it to be run with `zig test` and match expected error messages:
+
+```zig
+// error
+// is_test=1
+//
+// :4:13: error: 'try' outside function scope
+```
+
+## Execution
+
+This will do `zig run` on the code and expect exit code 0.
+
+```zig
+// run
+```
+
+## Incremental Compilation
+
+Make multiple files that have ".", and then an integer, before the ".zig"
+extension, like this:
+
+```
+hello.0.zig
+hello.1.zig
+hello.2.zig
+```
+
+Each file can be a different kind of test, such as expecting compile errors,
+or expecting to be run and exit(0). The test harness will use these to simulate
+incremental compilation.
+
+At the time of writing there is no way to specify multiple files being changed
+as part of an update.
+
+## Subdirectories
+
+Subdirectories do not have any semantic meaning but they can be used for
+organization since the test harness will recurse into them. The full directory
+path will be prepended as a prefix on the test case name.
+
+## Limiting which Backends and Targets are Tested
+
+```zig
+// run
+// backend=stage2,llvm
+// target=x86_64-linux,x86_64-macos
+```
+
+Possible backends are:
+
+ * `stage1`: equivalent to `-fstage1`.
+ * `stage2`: equivalent to passing `-fno-stage1 -fno-LLVM`.
+ * `llvm`: equivalent to `-fLLVM -fno-stage1`.
test/runtime_safety.zig
@@ -1,1206 +0,0 @@
-const tests = @import("tests.zig");
-
-pub fn addCases(cases: *tests.CompareOutputContext) void {
-    {
-        const check_panic_msg =
-            \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
-            \\    _ = stack_trace;
-            \\    if (std.mem.eql(u8, message, "reached unreachable code")) {
-            \\        std.process.exit(126); // good
-            \\    }
-            \\    std.process.exit(0); // test failed
-            \\}
-        ;
-
-        cases.addRuntimeSafety("switch on corrupted enum value",
-            \\const std = @import("std");
-        ++ check_panic_msg ++
-            \\const E = enum(u32) {
-            \\    X = 1,
-            \\};
-            \\pub fn main() void {
-            \\    var e: E = undefined;
-            \\    @memset(@ptrCast([*]u8, &e), 0x55, @sizeOf(E));
-            \\    switch (e) {
-            \\        .X => @breakpoint(),
-            \\    }
-            \\}
-        );
-
-        cases.addRuntimeSafety("switch on corrupted union value",
-            \\const std = @import("std");
-        ++ check_panic_msg ++
-            \\const U = union(enum(u32)) {
-            \\    X: u8,
-            \\};
-            \\pub fn main() void {
-            \\    var u: U = undefined;
-            \\    @memset(@ptrCast([*]u8, &u), 0x55, @sizeOf(U));
-            \\    switch (u) {
-            \\        .X => @breakpoint(),
-            \\    }
-            \\}
-        );
-    }
-
-    {
-        const check_panic_msg =
-            \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
-            \\    _ = stack_trace;
-            \\    if (std.mem.eql(u8, message, "invalid enum value")) {
-            \\        std.process.exit(126); // good
-            \\    }
-            \\    std.process.exit(0); // test failed
-            \\}
-        ;
-
-        cases.addRuntimeSafety("@tagName on corrupted enum value",
-            \\const std = @import("std");
-        ++ check_panic_msg ++
-            \\const E = enum(u32) {
-            \\    X = 1,
-            \\};
-            \\pub fn main() void {
-            \\    var e: E = undefined;
-            \\    @memset(@ptrCast([*]u8, &e), 0x55, @sizeOf(E));
-            \\    var n = @tagName(e);
-            \\    _ = n;
-            \\}
-        );
-
-        cases.addRuntimeSafety("@tagName on corrupted union value",
-            \\const std = @import("std");
-        ++ check_panic_msg ++
-            \\const U = union(enum(u32)) {
-            \\    X: u8,
-            \\};
-            \\pub fn main() void {
-            \\    var u: U = undefined;
-            \\    @memset(@ptrCast([*]u8, &u), 0x55, @sizeOf(U));
-            \\    var t: @typeInfo(U).Union.tag_type.? = u;
-            \\    var n = @tagName(t);
-            \\    _ = n;
-            \\}
-        );
-    }
-
-    {
-        const check_panic_msg =
-            \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
-            \\    _ = stack_trace;
-            \\    if (std.mem.eql(u8, message, "index out of bounds")) {
-            \\        std.process.exit(126); // good
-            \\    }
-            \\    std.process.exit(0); // test failed
-            \\}
-        ;
-
-        cases.addRuntimeSafety("slice with sentinel out of bounds",
-            \\const std = @import("std");
-        ++ check_panic_msg ++
-            \\pub fn main() void {
-            \\    var buf = [4]u8{'a','b','c',0};
-            \\    const input: []u8 = &buf;
-            \\    const slice = input[0..4 :0];
-            \\    _ = slice;
-            \\}
-        );
-        cases.addRuntimeSafety("empty slice with sentinel out of bounds",
-            \\const std = @import("std");
-        ++ check_panic_msg ++
-            \\pub fn main() void {
-            \\    var buf_zero = [0]u8{};
-            \\    const input: []u8 = &buf_zero;
-            \\    const slice = input[0..0 :0];
-            \\    _ = slice;
-            \\}
-        );
-    }
-
-    cases.addRuntimeSafety("truncating vector cast",
-        \\const std = @import("std");
-        \\const V = @import("std").meta.Vector;
-        \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
-        \\    _ = stack_trace;
-        \\    if (std.mem.eql(u8, message, "integer cast truncated bits")) {
-        \\        std.process.exit(126); // good
-        \\    }
-        \\    std.process.exit(0); // test failed
-        \\}
-        \\pub fn main() void {
-        \\    var x = @splat(4, @as(u32, 0xdeadbeef));
-        \\    var y = @intCast(V(4, u16), x);
-        \\    _ = y;
-        \\}
-    );
-
-    cases.addRuntimeSafety("unsigned-signed vector cast",
-        \\const std = @import("std");
-        \\const V = @import("std").meta.Vector;
-        \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
-        \\    _ = stack_trace;
-        \\    if (std.mem.eql(u8, message, "integer cast truncated bits")) {
-        \\        std.process.exit(126); // good
-        \\    }
-        \\    std.process.exit(0); // test failed
-        \\}
-        \\pub fn main() void {
-        \\    var x = @splat(4, @as(u32, 0x80000000));
-        \\    var y = @intCast(V(4, i32), x);
-        \\    _ = y;
-        \\}
-    );
-
-    cases.addRuntimeSafety("signed-unsigned vector cast",
-        \\const std = @import("std");
-        \\const V = @import("std").meta.Vector;
-        \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
-        \\    _ = stack_trace;
-        \\    if (std.mem.eql(u8, message, "attempt to cast negative value to unsigned integer")) {
-        \\        std.process.exit(126); // good
-        \\    }
-        \\    std.process.exit(0); // test failed
-        \\}
-        \\pub fn main() void {
-        \\    var x = @splat(4, @as(i32, -2147483647));
-        \\    var y = @intCast(V(4, u32), x);
-        \\    _ = y;
-        \\}
-    );
-
-    cases.addRuntimeSafety("shift left by huge amount",
-        \\const std = @import("std");
-        \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
-        \\    _ = stack_trace;
-        \\    if (std.mem.eql(u8, message, "shift amount is greater than the type size")) {
-        \\        std.process.exit(126); // good
-        \\    }
-        \\    std.process.exit(0); // test failed
-        \\}
-        \\pub fn main() void {
-        \\    var x: u24 = 42;
-        \\    var y: u5 = 24;
-        \\    var z = x >> y;
-        \\    _ = z;
-        \\}
-    );
-
-    cases.addRuntimeSafety("shift right by huge amount",
-        \\const std = @import("std");
-        \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
-        \\    _ = stack_trace;
-        \\    if (std.mem.eql(u8, message, "shift amount is greater than the type size")) {
-        \\        std.process.exit(126); // good
-        \\    }
-        \\    std.process.exit(0); // test failed
-        \\}
-        \\pub fn main() void {
-        \\    var x: u24 = 42;
-        \\    var y: u5 = 24;
-        \\    var z = x << y;
-        \\    _ = z;
-        \\}
-    );
-
-    cases.addRuntimeSafety("slice sentinel mismatch - optional pointers",
-        \\const std = @import("std");
-        \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
-        \\    _ = stack_trace;
-        \\    if (std.mem.eql(u8, message, "sentinel mismatch")) {
-        \\        std.process.exit(126); // good
-        \\    }
-        \\    std.process.exit(0); // test failed
-        \\}
-        \\pub fn main() void {
-        \\    var buf: [4]?*i32 = undefined;
-        \\    const slice = buf[0..3 :null];
-        \\    _ = slice;
-        \\}
-    );
-
-    cases.addRuntimeSafety("slice sentinel mismatch - floats",
-        \\const std = @import("std");
-        \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
-        \\    _ = stack_trace;
-        \\    if (std.mem.eql(u8, message, "sentinel mismatch")) {
-        \\        std.process.exit(126); // good
-        \\    }
-        \\    std.process.exit(0); // test failed
-        \\}
-        \\pub fn main() void {
-        \\    var buf: [4]f32 = undefined;
-        \\    const slice = buf[0..3 :1.2];
-        \\    _ = slice;
-        \\}
-    );
-
-    cases.addRuntimeSafety("pointer slice sentinel mismatch",
-        \\const std = @import("std");
-        \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
-        \\    _ = stack_trace;
-        \\    if (std.mem.eql(u8, message, "sentinel mismatch")) {
-        \\        std.process.exit(126); // good
-        \\    }
-        \\    std.process.exit(0); // test failed
-        \\}
-        \\pub fn main() void {
-        \\    var buf: [4]u8 = undefined;
-        \\    const ptr: [*]u8 = &buf;
-        \\    const slice = ptr[0..3 :0];
-        \\    _ = slice;
-        \\}
-    );
-
-    cases.addRuntimeSafety("slice slice sentinel mismatch",
-        \\const std = @import("std");
-        \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
-        \\    _ = stack_trace;
-        \\    if (std.mem.eql(u8, message, "sentinel mismatch")) {
-        \\        std.process.exit(126); // good
-        \\    }
-        \\    std.process.exit(0); // test failed
-        \\}
-        \\pub fn main() void {
-        \\    var buf: [4]u8 = undefined;
-        \\    const slice = buf[0..];
-        \\    const slice2 = slice[0..3 :0];
-        \\    _ = slice2;
-        \\}
-    );
-
-    cases.addRuntimeSafety("array slice sentinel mismatch",
-        \\const std = @import("std");
-        \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
-        \\    _ = stack_trace;
-        \\    if (std.mem.eql(u8, message, "sentinel mismatch")) {
-        \\        std.process.exit(126); // good
-        \\    }
-        \\    std.process.exit(0); // test failed
-        \\}
-        \\pub fn main() void {
-        \\    var buf: [4]u8 = undefined;
-        \\    const slice = buf[0..3 :0];
-        \\    _ = slice;
-        \\}
-    );
-
-    cases.addRuntimeSafety("intToPtr with misaligned address",
-        \\const std = @import("std");
-        \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
-        \\    _ = stack_trace;
-        \\    if (std.mem.eql(u8, message, "incorrect alignment")) {
-        \\        std.os.exit(126); // good
-        \\    }
-        \\    std.os.exit(0); // test failed
-        \\}
-        \\pub fn main() void {
-        \\    var x: usize = 5;
-        \\    var y = @intToPtr([*]align(4) u8, x);
-        \\    _ = y;
-        \\}
-    );
-
-    cases.addRuntimeSafety("resuming a non-suspended function which never been suspended",
-        \\const std = @import("std");
-        \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
-        \\    _ = message;
-        \\    _ = stack_trace;
-        \\    std.os.exit(126);
-        \\}
-        \\fn foo() void {
-        \\    var f = async bar(@frame());
-        \\    _ = f;
-        \\    std.os.exit(0);
-        \\}
-        \\
-        \\fn bar(frame: anyframe) void {
-        \\    suspend {
-        \\        resume frame;
-        \\    }
-        \\    std.os.exit(0);
-        \\}
-        \\
-        \\pub fn main() void {
-        \\    _ = async foo();
-        \\}
-    );
-
-    cases.addRuntimeSafety("resuming a non-suspended function which has been suspended and resumed",
-        \\const std = @import("std");
-        \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
-        \\    _ = message;
-        \\    _ = stack_trace;
-        \\    std.os.exit(126);
-        \\}
-        \\fn foo() void {
-        \\    suspend {
-        \\        global_frame = @frame();
-        \\    }
-        \\    var f = async bar(@frame());
-        \\    _ = f;
-        \\    std.os.exit(0);
-        \\}
-        \\
-        \\fn bar(frame: anyframe) void {
-        \\    suspend {
-        \\        resume frame;
-        \\    }
-        \\    std.os.exit(0);
-        \\}
-        \\
-        \\var global_frame: anyframe = undefined;
-        \\pub fn main() void {
-        \\    _ = async foo();
-        \\    resume global_frame;
-        \\    std.os.exit(0);
-        \\}
-    );
-
-    cases.addRuntimeSafety("nosuspend function call, callee suspends",
-        \\const std = @import("std");
-        \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
-        \\    _ = message;
-        \\    _ = stack_trace;
-        \\    std.os.exit(126);
-        \\}
-        \\pub fn main() void {
-        \\    _ = nosuspend add(101, 100);
-        \\}
-        \\fn add(a: i32, b: i32) i32 {
-        \\    if (a > 100) {
-        \\        suspend {}
-        \\    }
-        \\    return a + b;
-        \\}
-    );
-
-    cases.addRuntimeSafety("awaiting twice",
-        \\const std = @import("std");
-        \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
-        \\    _ = message;
-        \\    _ = stack_trace;
-        \\    std.os.exit(126);
-        \\}
-        \\var frame: anyframe = undefined;
-        \\
-        \\pub fn main() void {
-        \\    _ = async amain();
-        \\    resume frame;
-        \\}
-        \\
-        \\fn amain() void {
-        \\    var f = async func();
-        \\    await f;
-        \\    await f;
-        \\}
-        \\
-        \\fn func() void {
-        \\    suspend {
-        \\        frame = @frame();
-        \\    }
-        \\}
-    );
-
-    cases.addRuntimeSafety("@asyncCall with too small a frame",
-        \\const std = @import("std");
-        \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
-        \\    _ = message;
-        \\    _ = stack_trace;
-        \\    std.os.exit(126);
-        \\}
-        \\pub fn main() void {
-        \\    var bytes: [1]u8 align(16) = undefined;
-        \\    var ptr = other;
-        \\    var frame = @asyncCall(&bytes, {}, ptr, .{});
-        \\    _ = frame;
-        \\}
-        \\fn other() callconv(.Async) void {
-        \\    suspend {}
-        \\}
-    );
-
-    cases.addRuntimeSafety("resuming a function which is awaiting a frame",
-        \\const std = @import("std");
-        \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
-        \\    _ = message;
-        \\    _ = stack_trace;
-        \\    std.os.exit(126);
-        \\}
-        \\pub fn main() void {
-        \\    var frame = async first();
-        \\    resume frame;
-        \\}
-        \\fn first() void {
-        \\    var frame = async other();
-        \\    await frame;
-        \\}
-        \\fn other() void {
-        \\    suspend {}
-        \\}
-    );
-
-    cases.addRuntimeSafety("resuming a function which is awaiting a call",
-        \\const std = @import("std");
-        \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
-        \\    _ = message;
-        \\    _ = stack_trace;
-        \\    std.os.exit(126);
-        \\}
-        \\pub fn main() void {
-        \\    var frame = async first();
-        \\    resume frame;
-        \\}
-        \\fn first() void {
-        \\    other();
-        \\}
-        \\fn other() void {
-        \\    suspend {}
-        \\}
-    );
-
-    cases.addRuntimeSafety("invalid resume of async function",
-        \\const std = @import("std");
-        \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
-        \\    _ = message;
-        \\    _ = stack_trace;
-        \\    std.os.exit(126);
-        \\}
-        \\pub fn main() void {
-        \\    var p = async suspendOnce();
-        \\    resume p; //ok
-        \\    resume p; //bad
-        \\}
-        \\fn suspendOnce() void {
-        \\    suspend {}
-        \\}
-    );
-
-    cases.addRuntimeSafety(".? operator on null pointer",
-        \\const std = @import("std");
-        \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
-        \\    _ = message;
-        \\    _ = stack_trace;
-        \\    std.os.exit(126);
-        \\}
-        \\pub fn main() void {
-        \\    var ptr: ?*i32 = null;
-        \\    var b = ptr.?;
-        \\    _ = b;
-        \\}
-    );
-
-    cases.addRuntimeSafety(".? operator on C pointer",
-        \\const std = @import("std");
-        \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
-        \\    _ = message;
-        \\    _ = stack_trace;
-        \\    std.os.exit(126);
-        \\}
-        \\pub fn main() void {
-        \\    var ptr: [*c]i32 = null;
-        \\    var b = ptr.?;
-        \\    _ = b;
-        \\}
-    );
-
-    cases.addRuntimeSafety("@intToPtr address zero to non-optional pointer",
-        \\const std = @import("std");
-        \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
-        \\    _ = message;
-        \\    _ = stack_trace;
-        \\    std.os.exit(126);
-        \\}
-        \\pub fn main() void {
-        \\    var zero: usize = 0;
-        \\    var b = @intToPtr(*i32, zero);
-        \\    _ = b;
-        \\}
-    );
-
-    cases.addRuntimeSafety("@intToPtr address zero to non-optional byte-aligned pointer",
-        \\const std = @import("std");
-        \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
-        \\    _ = message;
-        \\    _ = stack_trace;
-        \\    std.os.exit(126);
-        \\}
-        \\pub fn main() void {
-        \\    var zero: usize = 0;
-        \\    var b = @intToPtr(*u8, zero);
-        \\    _ = b;
-        \\}
-    );
-
-    cases.addRuntimeSafety("pointer casting null to non-optional pointer",
-        \\const std = @import("std");
-        \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
-        \\    _ = message;
-        \\    _ = stack_trace;
-        \\    std.os.exit(126);
-        \\}
-        \\pub fn main() void {
-        \\    var c_ptr: [*c]u8 = 0;
-        \\    var zig_ptr: *u8 = c_ptr;
-        \\    _ = zig_ptr;
-        \\}
-    );
-
-    cases.addRuntimeSafety("@intToEnum - no matching tag value",
-        \\const std = @import("std");
-        \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
-        \\    _ = message;
-        \\    _ = stack_trace;
-        \\    std.os.exit(126);
-        \\}
-        \\const Foo = enum {
-        \\    A,
-        \\    B,
-        \\    C,
-        \\};
-        \\pub fn main() void {
-        \\    baz(bar(3));
-        \\}
-        \\fn bar(a: u2) Foo {
-        \\    return @intToEnum(Foo, a);
-        \\}
-        \\fn baz(_: Foo) void {}
-    );
-
-    cases.addRuntimeSafety("@floatToInt cannot fit - negative to unsigned",
-        \\const std = @import("std");
-        \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
-        \\    _ = message;
-        \\    _ = stack_trace;
-        \\    std.os.exit(126);
-        \\}
-        \\pub fn main() void {
-        \\    baz(bar(-1.1));
-        \\}
-        \\fn bar(a: f32) u8 {
-        \\    return @floatToInt(u8, a);
-        \\}
-        \\fn baz(_: u8) void { }
-    );
-
-    cases.addRuntimeSafety("@floatToInt cannot fit - negative out of range",
-        \\const std = @import("std");
-        \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
-        \\    _ = message;
-        \\    _ = stack_trace;
-        \\    std.os.exit(126);
-        \\}
-        \\pub fn main() void {
-        \\    baz(bar(-129.1));
-        \\}
-        \\fn bar(a: f32) i8 {
-        \\    return @floatToInt(i8, a);
-        \\}
-        \\fn baz(_: i8) void { }
-    );
-
-    cases.addRuntimeSafety("@floatToInt cannot fit - positive out of range",
-        \\const std = @import("std");
-        \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
-        \\    _ = message;
-        \\    _ = stack_trace;
-        \\    std.os.exit(126);
-        \\}
-        \\pub fn main() void {
-        \\    baz(bar(256.2));
-        \\}
-        \\fn bar(a: f32) u8 {
-        \\    return @floatToInt(u8, a);
-        \\}
-        \\fn baz(_: u8) void { }
-    );
-
-    cases.addRuntimeSafety("calling panic",
-        \\const std = @import("std");
-        \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
-        \\    _ = message;
-        \\    _ = stack_trace;
-        \\    std.os.exit(126);
-        \\}
-        \\pub fn main() void {
-        \\    @panic("oh no");
-        \\}
-    );
-
-    cases.addRuntimeSafety("out of bounds slice access",
-        \\const std = @import("std");
-        \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
-        \\    _ = message;
-        \\    _ = stack_trace;
-        \\    std.os.exit(126);
-        \\}
-        \\pub fn main() void {
-        \\    const a = [_]i32{1, 2, 3, 4};
-        \\    baz(bar(&a));
-        \\}
-        \\fn bar(a: []const i32) i32 {
-        \\    return a[4];
-        \\}
-        \\fn baz(_: i32) void { }
-    );
-
-    cases.addRuntimeSafety("integer addition overflow",
-        \\const std = @import("std");
-        \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
-        \\    _ = message;
-        \\    _ = stack_trace;
-        \\    std.os.exit(126);
-        \\}
-        \\pub fn main() !void {
-        \\    const x = add(65530, 10);
-        \\    if (x == 0) return error.Whatever;
-        \\}
-        \\fn add(a: u16, b: u16) u16 {
-        \\    return a + b;
-        \\}
-    );
-
-    cases.addRuntimeSafety("vector integer addition overflow",
-        \\const std = @import("std");
-        \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
-        \\    _ = message;
-        \\    _ = stack_trace;
-        \\    std.os.exit(126);
-        \\}
-        \\pub fn main() void {
-        \\    var a: @Vector(4, i32) = [_]i32{ 1, 2, 2147483643, 4 };
-        \\    var b: @Vector(4, i32) = [_]i32{ 5, 6, 7, 8 };
-        \\    const x = add(a, b);
-        \\    _ = x;
-        \\}
-        \\fn add(a: @Vector(4, i32), b: @Vector(4, i32)) @Vector(4, i32) {
-        \\    return a + b;
-        \\}
-    );
-
-    cases.addRuntimeSafety("vector integer subtraction overflow",
-        \\const std = @import("std");
-        \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
-        \\    _ = message;
-        \\    _ = stack_trace;
-        \\    std.os.exit(126);
-        \\}
-        \\pub fn main() void {
-        \\    var a: @Vector(4, u32) = [_]u32{ 1, 2, 8, 4 };
-        \\    var b: @Vector(4, u32) = [_]u32{ 5, 6, 7, 8 };
-        \\    const x = sub(b, a);
-        \\    _ = x;
-        \\}
-        \\fn sub(a: @Vector(4, u32), b: @Vector(4, u32)) @Vector(4, u32) {
-        \\    return a - b;
-        \\}
-    );
-
-    cases.addRuntimeSafety("vector integer multiplication overflow",
-        \\const std = @import("std");
-        \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
-        \\    _ = message;
-        \\    _ = stack_trace;
-        \\    std.os.exit(126);
-        \\}
-        \\pub fn main() void {
-        \\    var a: @Vector(4, u8) = [_]u8{ 1, 2, 200, 4 };
-        \\    var b: @Vector(4, u8) = [_]u8{ 5, 6, 2, 8 };
-        \\    const x = mul(b, a);
-        \\    _ = x;
-        \\}
-        \\fn mul(a: @Vector(4, u8), b: @Vector(4, u8)) @Vector(4, u8) {
-        \\    return a * b;
-        \\}
-    );
-
-    cases.addRuntimeSafety("vector integer negation overflow",
-        \\const std = @import("std");
-        \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
-        \\    _ = message;
-        \\    _ = stack_trace;
-        \\    std.os.exit(126);
-        \\}
-        \\pub fn main() void {
-        \\    var a: @Vector(4, i16) = [_]i16{ 1, -32768, 200, 4 };
-        \\    const x = neg(a);
-        \\    _ = x;
-        \\}
-        \\fn neg(a: @Vector(4, i16)) @Vector(4, i16) {
-        \\    return -a;
-        \\}
-    );
-
-    cases.addRuntimeSafety("integer subtraction overflow",
-        \\const std = @import("std");
-        \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
-        \\    _ = message;
-        \\    _ = stack_trace;
-        \\    std.os.exit(126);
-        \\}
-        \\pub fn main() !void {
-        \\    const x = sub(10, 20);
-        \\    if (x == 0) return error.Whatever;
-        \\}
-        \\fn sub(a: u16, b: u16) u16 {
-        \\    return a - b;
-        \\}
-    );
-
-    cases.addRuntimeSafety("integer multiplication overflow",
-        \\const std = @import("std");
-        \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
-        \\    _ = message;
-        \\    _ = stack_trace;
-        \\    std.os.exit(126);
-        \\}
-        \\pub fn main() !void {
-        \\    const x = mul(300, 6000);
-        \\    if (x == 0) return error.Whatever;
-        \\}
-        \\fn mul(a: u16, b: u16) u16 {
-        \\    return a * b;
-        \\}
-    );
-
-    cases.addRuntimeSafety("integer negation overflow",
-        \\const std = @import("std");
-        \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
-        \\    _ = message;
-        \\    _ = stack_trace;
-        \\    std.os.exit(126);
-        \\}
-        \\pub fn main() !void {
-        \\    const x = neg(-32768);
-        \\    if (x == 32767) return error.Whatever;
-        \\}
-        \\fn neg(a: i16) i16 {
-        \\    return -a;
-        \\}
-    );
-
-    cases.addRuntimeSafety("signed integer division overflow",
-        \\const std = @import("std");
-        \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
-        \\    _ = message;
-        \\    _ = stack_trace;
-        \\    std.os.exit(126);
-        \\}
-        \\pub fn main() !void {
-        \\    const x = div(-32768, -1);
-        \\    if (x == 32767) return error.Whatever;
-        \\}
-        \\fn div(a: i16, b: i16) i16 {
-        \\    return @divTrunc(a, b);
-        \\}
-    );
-
-    cases.addRuntimeSafety("signed integer division overflow - vectors",
-        \\const std = @import("std");
-        \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
-        \\    _ = message;
-        \\    _ = stack_trace;
-        \\    std.os.exit(126);
-        \\}
-        \\pub fn main() !void {
-        \\    var a: @Vector(4, i16) = [_]i16{ 1, 2, -32768, 4 };
-        \\    var b: @Vector(4, i16) = [_]i16{ 1, 2, -1, 4 };
-        \\    const x = div(a, b);
-        \\    if (x[2] == 32767) return error.Whatever;
-        \\}
-        \\fn div(a: @Vector(4, i16), b: @Vector(4, i16)) @Vector(4, i16) {
-        \\    return @divTrunc(a, b);
-        \\}
-    );
-
-    cases.addRuntimeSafety("signed shift left overflow",
-        \\const std = @import("std");
-        \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
-        \\    _ = message;
-        \\    _ = stack_trace;
-        \\    std.os.exit(126);
-        \\}
-        \\pub fn main() !void {
-        \\    const x = shl(-16385, 1);
-        \\    if (x == 0) return error.Whatever;
-        \\}
-        \\fn shl(a: i16, b: u4) i16 {
-        \\    return @shlExact(a, b);
-        \\}
-    );
-
-    cases.addRuntimeSafety("unsigned shift left overflow",
-        \\const std = @import("std");
-        \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
-        \\    _ = message;
-        \\    _ = stack_trace;
-        \\    std.os.exit(126);
-        \\}
-        \\pub fn main() !void {
-        \\    const x = shl(0b0010111111111111, 3);
-        \\    if (x == 0) return error.Whatever;
-        \\}
-        \\fn shl(a: u16, b: u4) u16 {
-        \\    return @shlExact(a, b);
-        \\}
-    );
-
-    cases.addRuntimeSafety("signed shift right overflow",
-        \\const std = @import("std");
-        \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
-        \\    _ = message;
-        \\    _ = stack_trace;
-        \\    std.os.exit(126);
-        \\}
-        \\pub fn main() !void {
-        \\    const x = shr(-16385, 1);
-        \\    if (x == 0) return error.Whatever;
-        \\}
-        \\fn shr(a: i16, b: u4) i16 {
-        \\    return @shrExact(a, b);
-        \\}
-    );
-
-    cases.addRuntimeSafety("unsigned shift right overflow",
-        \\const std = @import("std");
-        \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
-        \\    _ = message;
-        \\    _ = stack_trace;
-        \\    std.os.exit(126);
-        \\}
-        \\pub fn main() !void {
-        \\    const x = shr(0b0010111111111111, 3);
-        \\    if (x == 0) return error.Whatever;
-        \\}
-        \\fn shr(a: u16, b: u4) u16 {
-        \\    return @shrExact(a, b);
-        \\}
-    );
-
-    cases.addRuntimeSafety("integer division by zero",
-        \\const std = @import("std");
-        \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
-        \\    _ = message;
-        \\    _ = stack_trace;
-        \\    std.os.exit(126);
-        \\}
-        \\pub fn main() void {
-        \\    const x = div0(999, 0);
-        \\    _ = x;
-        \\}
-        \\fn div0(a: i32, b: i32) i32 {
-        \\    return @divTrunc(a, b);
-        \\}
-    );
-
-    cases.addRuntimeSafety("integer division by zero - vectors",
-        \\const std = @import("std");
-        \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
-        \\    _ = message;
-        \\    _ = stack_trace;
-        \\    std.os.exit(126);
-        \\}
-        \\pub fn main() void {
-        \\    var a: @Vector(4, i32) = [4]i32{111, 222, 333, 444};
-        \\    var b: @Vector(4, i32) = [4]i32{111, 0, 333, 444};
-        \\    const x = div0(a, b);
-        \\    _ = x;
-        \\}
-        \\fn div0(a: @Vector(4, i32), b: @Vector(4, i32)) @Vector(4, i32) {
-        \\    return @divTrunc(a, b);
-        \\}
-    );
-
-    cases.addRuntimeSafety("exact division failure",
-        \\const std = @import("std");
-        \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
-        \\    _ = message;
-        \\    _ = stack_trace;
-        \\    std.os.exit(126);
-        \\}
-        \\pub fn main() !void {
-        \\    const x = divExact(10, 3);
-        \\    if (x == 0) return error.Whatever;
-        \\}
-        \\fn divExact(a: i32, b: i32) i32 {
-        \\    return @divExact(a, b);
-        \\}
-    );
-
-    cases.addRuntimeSafety("exact division failure - vectors",
-        \\const std = @import("std");
-        \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
-        \\    _ = message;
-        \\    _ = stack_trace;
-        \\    std.os.exit(126);
-        \\}
-        \\pub fn main() !void {
-        \\    var a: @Vector(4, i32) = [4]i32{111, 222, 333, 444};
-        \\    var b: @Vector(4, i32) = [4]i32{111, 222, 333, 441};
-        \\    const x = divExact(a, b);
-        \\    _ = x;
-        \\}
-        \\fn divExact(a: @Vector(4, i32), b: @Vector(4, i32)) @Vector(4, i32) {
-        \\    return @divExact(a, b);
-        \\}
-    );
-
-    cases.addRuntimeSafety("cast []u8 to bigger slice of wrong size",
-        \\const std = @import("std");
-        \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
-        \\    _ = message;
-        \\    _ = stack_trace;
-        \\    std.os.exit(126);
-        \\}
-        \\pub fn main() !void {
-        \\    const x = widenSlice(&[_]u8{1, 2, 3, 4, 5});
-        \\    if (x.len == 0) return error.Whatever;
-        \\}
-        \\fn widenSlice(slice: []align(1) const u8) []align(1) const i32 {
-        \\    return std.mem.bytesAsSlice(i32, slice);
-        \\}
-    );
-
-    cases.addRuntimeSafety("value does not fit in shortening cast",
-        \\const std = @import("std");
-        \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
-        \\    _ = message;
-        \\    _ = stack_trace;
-        \\    std.os.exit(126);
-        \\}
-        \\pub fn main() !void {
-        \\    const x = shorten_cast(200);
-        \\    if (x == 0) return error.Whatever;
-        \\}
-        \\fn shorten_cast(x: i32) i8 {
-        \\    return @intCast(i8, x);
-        \\}
-    );
-
-    cases.addRuntimeSafety("value does not fit in shortening cast - u0",
-        \\const std = @import("std");
-        \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
-        \\    _ = message;
-        \\    _ = stack_trace;
-        \\    std.os.exit(126);
-        \\}
-        \\pub fn main() !void {
-        \\    const x = shorten_cast(1);
-        \\    if (x == 0) return error.Whatever;
-        \\}
-        \\fn shorten_cast(x: u8) u0 {
-        \\    return @intCast(u0, x);
-        \\}
-    );
-
-    cases.addRuntimeSafety("signed integer not fitting in cast to unsigned integer",
-        \\const std = @import("std");
-        \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
-        \\    _ = message;
-        \\    _ = stack_trace;
-        \\    std.os.exit(126);
-        \\}
-        \\pub fn main() !void {
-        \\    const x = unsigned_cast(-10);
-        \\    if (x == 0) return error.Whatever;
-        \\}
-        \\fn unsigned_cast(x: i32) u32 {
-        \\    return @intCast(u32, x);
-        \\}
-    );
-
-    cases.addRuntimeSafety("signed integer not fitting in cast to unsigned integer - widening",
-        \\const std = @import("std");
-        \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
-        \\    _ = message;
-        \\    _ = stack_trace;
-        \\    std.os.exit(126);
-        \\}
-        \\pub fn main() void {
-        \\    var value: c_short = -1;
-        \\    var casted = @intCast(u32, value);
-        \\    _ = casted;
-        \\}
-    );
-
-    cases.addRuntimeSafety("unsigned integer not fitting in cast to signed integer - same bit count",
-        \\const std = @import("std");
-        \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
-        \\    _ = message;
-        \\    _ = stack_trace;
-        \\    std.os.exit(126);
-        \\}
-        \\pub fn main() void {
-        \\    var value: u8 = 245;
-        \\    var casted = @intCast(i8, value);
-        \\    _ = casted;
-        \\}
-    );
-
-    cases.addRuntimeSafety("unwrap error",
-        \\const std = @import("std");
-        \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
-        \\    _ = stack_trace;
-        \\    if (std.mem.eql(u8, message, "attempt to unwrap error: Whatever")) {
-        \\        std.os.exit(126); // good
-        \\    }
-        \\    std.os.exit(0); // test failed
-        \\}
-        \\pub fn main() void {
-        \\    bar() catch unreachable;
-        \\}
-        \\fn bar() !void {
-        \\    return error.Whatever;
-        \\}
-    );
-
-    cases.addRuntimeSafety("cast integer to global error and no code matches",
-        \\const std = @import("std");
-        \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
-        \\    _ = message;
-        \\    _ = stack_trace;
-        \\    std.os.exit(126);
-        \\}
-        \\pub fn main() void {
-        \\    bar(9999) catch {};
-        \\}
-        \\fn bar(x: u16) anyerror {
-        \\    return @intToError(x);
-        \\}
-    );
-
-    cases.addRuntimeSafety("@errSetCast error not present in destination",
-        \\const std = @import("std");
-        \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
-        \\    _ = message;
-        \\    _ = stack_trace;
-        \\    std.os.exit(126);
-        \\}
-        \\const Set1 = error{A, B};
-        \\const Set2 = error{A, C};
-        \\pub fn main() void {
-        \\    foo(Set1.B) catch {};
-        \\}
-        \\fn foo(set1: Set1) Set2 {
-        \\    return @errSetCast(Set2, set1);
-        \\}
-    );
-
-    cases.addRuntimeSafety("@alignCast misaligned",
-        \\const std = @import("std");
-        \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
-        \\    _ = message;
-        \\    _ = stack_trace;
-        \\    std.os.exit(126);
-        \\}
-        \\pub fn main() !void {
-        \\    var array align(4) = [_]u32{0x11111111, 0x11111111};
-        \\    const bytes = std.mem.sliceAsBytes(array[0..]);
-        \\    if (foo(bytes) != 0x11111111) return error.Wrong;
-        \\}
-        \\fn foo(bytes: []u8) u32 {
-        \\    const slice4 = bytes[1..5];
-        \\    const int_slice = std.mem.bytesAsSlice(u32, @alignCast(4, slice4));
-        \\    return int_slice[0];
-        \\}
-    );
-
-    cases.addRuntimeSafety("bad union field access",
-        \\const std = @import("std");
-        \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
-        \\    _ = message;
-        \\    _ = stack_trace;
-        \\    std.os.exit(126);
-        \\}
-        \\
-        \\const Foo = union {
-        \\    float: f32,
-        \\    int: u32,
-        \\};
-        \\
-        \\pub fn main() void {
-        \\    var f = Foo { .int = 42 };
-        \\    bar(&f);
-        \\}
-        \\
-        \\fn bar(f: *Foo) void {
-        \\    f.float = 12.34;
-        \\}
-    );
-
-    // @intCast a runtime integer to u0 actually results in a comptime-known value,
-    // but we still emit a safety check to ensure the integer was 0 and thus
-    // did not truncate information.
-    cases.addRuntimeSafety("@intCast to u0",
-        \\const std = @import("std");
-        \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
-        \\    _ = message;
-        \\    _ = stack_trace;
-        \\    std.os.exit(126);
-        \\}
-        \\
-        \\pub fn main() void {
-        \\    bar(1, 1);
-        \\}
-        \\
-        \\fn bar(one: u1, not_zero: i32) void {
-        \\    var x = one << @intCast(u0, not_zero);
-        \\    _ = x;
-        \\}
-    );
-
-    // This case makes sure that the code compiles and runs. There is not actually a special
-    // runtime safety check having to do specifically with error return traces across suspend points.
-    cases.addRuntimeSafety("error return trace across suspend points",
-        \\const std = @import("std");
-        \\
-        \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
-        \\    _ = message;
-        \\    _ = stack_trace;
-        \\    std.os.exit(126);
-        \\}
-        \\
-        \\var failing_frame: @Frame(failing) = undefined;
-        \\
-        \\pub fn main() void {
-        \\    const p = nonFailing();
-        \\    resume p;
-        \\    const p2 = async printTrace(p);
-        \\    _ = p2;
-        \\}
-        \\
-        \\fn nonFailing() anyframe->anyerror!void {
-        \\    failing_frame = async failing();
-        \\    return &failing_frame;
-        \\}
-        \\
-        \\fn failing() anyerror!void {
-        \\    suspend {}
-        \\    return second();
-        \\}
-        \\
-        \\fn second() callconv(.Async) anyerror!void {
-        \\    return error.Fail;
-        \\}
-        \\
-        \\fn printTrace(p: anyframe->anyerror!void) void {
-        \\    (await p) catch unreachable;
-        \\}
-    );
-
-    // Slicing a C pointer returns a non-allowzero slice, thus we need to emit
-    // a safety check to ensure the pointer is not null.
-    cases.addRuntimeSafety("slicing null C pointer",
-        \\const std = @import("std");
-        \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn {
-        \\    _ = message;
-        \\    _ = stack_trace;
-        \\    std.os.exit(126);
-        \\}
-        \\
-        \\pub fn main() void {
-        \\    var ptr: [*c]const u32 = null;
-        \\    var slice = ptr[0..3];
-        \\    _ = slice;
-        \\}
-    );
-}
test/tests.zig
@@ -18,7 +18,6 @@ const compare_output = @import("compare_output.zig");
 const standalone = @import("standalone.zig");
 const stack_traces = @import("stack_traces.zig");
 const assemble_and_link = @import("assemble_and_link.zig");
-const runtime_safety = @import("runtime_safety.zig");
 const translate_c = @import("translate_c.zig");
 const run_translated_c = @import("run_translated_c.zig");
 const gen_h = @import("gen_h.zig");
@@ -455,21 +454,6 @@ pub fn addStackTraceTests(b: *build.Builder, test_filter: ?[]const u8, modes: []
     return cases.step;
 }
 
-pub fn addRuntimeSafetyTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step {
-    const cases = b.allocator.create(CompareOutputContext) catch unreachable;
-    cases.* = CompareOutputContext{
-        .b = b,
-        .step = b.step("test-runtime-safety", "Run the runtime safety tests"),
-        .test_index = 0,
-        .test_filter = test_filter,
-        .modes = modes,
-    };
-
-    runtime_safety.addCases(cases);
-
-    return cases.step;
-}
-
 pub fn addStandaloneTests(
     b: *build.Builder,
     test_filter: ?[]const u8,
build.zig
@@ -40,10 +40,10 @@ pub fn build(b: *Builder) !void {
 
     const toolchain_step = b.step("test-toolchain", "Run the tests for the toolchain");
 
-    var test_stage2 = b.addTest("src/test.zig");
-    test_stage2.setBuildMode(mode);
-    test_stage2.addPackagePath("test_cases", "test/cases.zig");
-    test_stage2.single_threaded = single_threaded;
+    var test_cases = b.addTest("src/test.zig");
+    test_cases.setBuildMode(mode);
+    test_cases.addPackagePath("test_cases", "test/cases.zig");
+    test_cases.single_threaded = single_threaded;
 
     const fmt_build_zig = b.addFmt(&[_][]const u8{"build.zig"});
 
@@ -158,7 +158,7 @@ pub fn build(b: *Builder) !void {
     if (target.isWindows() and target.getAbi() == .gnu) {
         // LTO is currently broken on mingw, this can be removed when it's fixed.
         exe.want_lto = false;
-        test_stage2.want_lto = false;
+        test_cases.want_lto = false;
     }
 
     const exe_options = b.addOptions();
@@ -175,7 +175,7 @@ pub fn build(b: *Builder) !void {
 
     if (link_libc) {
         exe.linkLibC();
-        test_stage2.linkLibC();
+        test_cases.linkLibC();
     }
 
     const is_debug = mode == .Debug;
@@ -258,7 +258,7 @@ pub fn build(b: *Builder) !void {
             zig0.defineCMacro("ZIG_VERSION_PATCH", b.fmt("{d}", .{zig_version.patch}));
             zig0.defineCMacro("ZIG_VERSION_STRING", b.fmt("\"{s}\"", .{version}));
 
-            for ([_]*std.build.LibExeObjStep{ zig0, exe, test_stage2 }) |artifact| {
+            for ([_]*std.build.LibExeObjStep{ zig0, exe, test_cases }) |artifact| {
                 artifact.addIncludePath("src");
                 artifact.addIncludePath("deps/SoftFloat-3e/source/include");
                 artifact.addIncludePath("deps/SoftFloat-3e-prebuilt");
@@ -335,11 +335,11 @@ pub fn build(b: *Builder) !void {
             }
 
             try addCmakeCfgOptionsToExe(b, cfg, exe, use_zig_libcxx);
-            try addCmakeCfgOptionsToExe(b, cfg, test_stage2, use_zig_libcxx);
+            try addCmakeCfgOptionsToExe(b, cfg, test_cases, use_zig_libcxx);
         } else {
             // Here we are -Denable-llvm but no cmake integration.
             try addStaticLlvmOptionsToExe(exe);
-            try addStaticLlvmOptionsToExe(test_stage2);
+            try addStaticLlvmOptionsToExe(test_cases);
         }
     }
 
@@ -381,7 +381,7 @@ pub fn build(b: *Builder) !void {
     const test_filter = b.option([]const u8, "test-filter", "Skip tests that do not match filter");
 
     const test_stage2_options = b.addOptions();
-    test_stage2.addOptions("build_options", test_stage2_options);
+    test_cases.addOptions("build_options", test_stage2_options);
 
     test_stage2_options.addOption(bool, "enable_logging", enable_logging);
     test_stage2_options.addOption(bool, "enable_link_snapshots", enable_link_snapshots);
@@ -404,10 +404,10 @@ pub fn build(b: *Builder) !void {
     test_stage2_options.addOption([:0]const u8, "version", try b.allocator.dupeZ(u8, version));
     test_stage2_options.addOption(std.SemanticVersion, "semver", semver);
 
-    const test_stage2_step = b.step("test-stage2", "Run the stage2 compiler tests");
-    test_stage2_step.dependOn(&test_stage2.step);
+    const test_cases_step = b.step("test-cases", "Run the main compiler test cases");
+    test_cases_step.dependOn(&test_cases.step);
     if (!skip_stage2_tests) {
-        toolchain_step.dependOn(test_stage2_step);
+        toolchain_step.dependOn(test_cases_step);
     }
 
     var chosen_modes: [4]builtin.Mode = undefined;
@@ -485,7 +485,6 @@ pub fn build(b: *Builder) !void {
     toolchain_step.dependOn(tests.addStackTraceTests(b, test_filter, modes));
     toolchain_step.dependOn(tests.addCliTests(b, test_filter, modes));
     toolchain_step.dependOn(tests.addAssembleAndLinkTests(b, test_filter, modes));
-    toolchain_step.dependOn(tests.addRuntimeSafetyTests(b, test_filter, modes));
     toolchain_step.dependOn(tests.addTranslateCTests(b, test_filter));
     if (!skip_run_translated_c) {
         toolchain_step.dependOn(tests.addRunTranslatedCTests(b, test_filter, target));