diff --git a/test/cases.zig b/test/cases.zig index 9bbdde4777..2c51078abd 100644 --- a/test/cases.zig +++ b/test/cases.zig @@ -11,7 +11,6 @@ pub const BuildOptions = struct { pub fn addCases(cases: *Cases, build_options: BuildOptions, b: *std.Build) !void { try @import("compile_errors.zig").addCases(cases, b); - try @import("cbe.zig").addCases(cases, b); try @import("llvm_targets.zig").addCases(cases, build_options, b); try @import("nvptx.zig").addCases(cases, b); } diff --git a/test/cbe.zig b/test/cbe.zig deleted file mode 100644 index 35c2d8e8f9..0000000000 --- a/test/cbe.zig +++ /dev/null @@ -1,953 +0,0 @@ -const std = @import("std"); -const Cases = @import("src/Cases.zig"); -const nl = if (@import("builtin").os.tag == .windows) "\r\n" else "\n"; - -pub fn addCases(ctx: *Cases, b: *std.Build) !void { - // These tests should work with all platforms, but we're using linux_x64 for - // now for consistency. Will be expanded eventually. - const linux_x64: std.Target.Query = .{ - .cpu_arch = .x86_64, - .os_tag = .linux, - }; - - { - var case = ctx.exeFromCompiledC("hello world with updates", .{}, b); - - // Regular old hello world - case.addCompareOutput( - \\extern fn puts(s: [*:0]const u8) c_int; - \\pub export fn main() c_int { - \\ _ = puts("hello world!"); - \\ return 0; - \\} - , "hello world!" ++ nl); - - // Now change the message only - case.addCompareOutput( - \\extern fn puts(s: [*:0]const u8) c_int; - \\pub export fn main() c_int { - \\ _ = puts("yo"); - \\ return 0; - \\} - , "yo" ++ nl); - - // Add an unused Decl - case.addCompareOutput( - \\extern fn puts(s: [*:0]const u8) c_int; - \\pub export fn main() c_int { - \\ _ = puts("yo!"); - \\ return 0; - \\} - \\fn unused() void {} - , "yo!" ++ nl); - - // Comptime return type and calling convention expected. - case.addError( - \\var x: i32 = 1234; - \\pub export fn main() x { - \\ return 0; - \\} - \\export fn foo() callconv(y) c_int { - \\ return 0; - \\} - \\var y: @import("std").builtin.CallingConvention = .C; - , &.{ - ":2:22: error: expected type 'type', found 'i32'", - ":5:26: error: unable to resolve comptime value", - ":5:26: note: calling convention must be comptime-known", - }); - } - - { - var case = ctx.exeFromCompiledC("var args", .{}, b); - - case.addCompareOutput( - \\extern fn printf(format: [*:0]const u8, ...) c_int; - \\ - \\pub export fn main() c_int { - \\ _ = printf("Hello, %s!\n", "world"); - \\ return 0; - \\} - , "Hello, world!" ++ nl); - } - - { - var case = ctx.exeFromCompiledC("errorFromInt", .{}, b); - - case.addCompareOutput( - \\pub export fn main() c_int { - \\ // comptime checks - \\ const a = error.A; - \\ const b = error.B; - \\ const c = @errorFromInt(2); - \\ const d = @errorFromInt(1); - \\ if (!(c == b)) unreachable; - \\ if (!(a == d)) unreachable; - \\ // runtime checks - \\ var x = error.A; - \\ var y = error.B; - \\ var z = @errorFromInt(2); - \\ var f = @errorFromInt(1); - \\ if (!(y == z)) unreachable; - \\ if (!(x == f)) unreachable; - \\ return 0; - \\} - , ""); - case.addError( - \\pub export fn main() c_int { - \\ _ = @errorFromInt(0); - \\ return 0; - \\} - , &.{":2:21: error: integer value '0' represents no error"}); - case.addError( - \\pub export fn main() c_int { - \\ _ = @errorFromInt(3); - \\ return 0; - \\} - , &.{":2:21: error: integer value '3' represents no error"}); - } - - { - var case = ctx.exeFromCompiledC("x86_64-linux inline assembly", linux_x64, b); - - // Exit with 0 - case.addCompareOutput( - \\fn exitGood() noreturn { - \\ asm volatile ("syscall" - \\ : - \\ : [number] "{rax}" (231), - \\ [arg1] "{rdi}" (0) - \\ ); - \\ unreachable; - \\} - \\ - \\pub export fn main() c_int { - \\ exitGood(); - \\} - , ""); - - // Pass a usize parameter to exit - case.addCompareOutput( - \\pub export fn main() c_int { - \\ exit(0); - \\} - \\ - \\fn exit(code: usize) noreturn { - \\ asm volatile ("syscall" - \\ : - \\ : [number] "{rax}" (231), - \\ [arg1] "{rdi}" (code) - \\ ); - \\ unreachable; - \\} - , ""); - - // Change the parameter to u8 - case.addCompareOutput( - \\pub export fn main() c_int { - \\ exit(0); - \\} - \\ - \\fn exit(code: u8) noreturn { - \\ asm volatile ("syscall" - \\ : - \\ : [number] "{rax}" (231), - \\ [arg1] "{rdi}" (code) - \\ ); - \\ unreachable; - \\} - , ""); - - // Do some arithmetic at the exit callsite - case.addCompareOutput( - \\pub export fn main() c_int { - \\ exitMath(1); - \\} - \\ - \\fn exitMath(a: u8) noreturn { - \\ exit(0 + a - a); - \\} - \\ - \\fn exit(code: u8) noreturn { - \\ asm volatile ("syscall" - \\ : - \\ : [number] "{rax}" (231), - \\ [arg1] "{rdi}" (code) - \\ ); - \\ unreachable; - \\} - \\ - , ""); - - // Invert the arithmetic - case.addCompareOutput( - \\pub export fn main() c_int { - \\ exitMath(1); - \\} - \\ - \\fn exitMath(a: u8) noreturn { - \\ exit(a + 0 - a); - \\} - \\ - \\fn exit(code: u8) noreturn { - \\ asm volatile ("syscall" - \\ : - \\ : [number] "{rax}" (231), - \\ [arg1] "{rdi}" (code) - \\ ); - \\ unreachable; - \\} - \\ - , ""); - } - - { - var case = ctx.exeFromCompiledC("alloc and retptr", .{}, b); - - case.addCompareOutput( - \\fn add(a: i32, b: i32) i32 { - \\ return a + b; - \\} - \\ - \\fn addIndirect(a: i32, b: i32) i32 { - \\ return add(a, b); - \\} - \\ - \\pub export fn main() c_int { - \\ return addIndirect(1, 2) - 3; - \\} - , ""); - } - - { - var case = ctx.exeFromCompiledC("inferred local const and var", .{}, b); - - case.addCompareOutput( - \\fn add(a: i32, b: i32) i32 { - \\ return a + b; - \\} - \\ - \\pub export fn main() c_int { - \\ const x = add(1, 2); - \\ var y = add(3, 0); - \\ y -= x; - \\ return y; - \\} - , ""); - } - { - var case = ctx.exeFromCompiledC("control flow", .{}, b); - - // Simple while loop - case.addCompareOutput( - \\pub export fn main() c_int { - \\ var a: c_int = 0; - \\ while (a < 5) : (a+=1) {} - \\ return a - 5; - \\} - , ""); - case.addCompareOutput( - \\pub export fn main() c_int { - \\ var a = true; - \\ while (!a) {} - \\ return 0; - \\} - , ""); - - // If expression - case.addCompareOutput( - \\pub export fn main() c_int { - \\ var cond: c_int = 0; - \\ var a: c_int = @as(c_int, if (cond == 0) - \\ 2 - \\ else - \\ 3) + 9; - \\ return a - 11; - \\} - , ""); - - // If expression with breakpoint that does not get hit - case.addCompareOutput( - \\pub export fn main() c_int { - \\ var x: i32 = 1; - \\ if (x != 1) @breakpoint(); - \\ return 0; - \\} - , ""); - - // Switch expression - case.addCompareOutput( - \\pub export fn main() c_int { - \\ var cond: c_int = 0; - \\ var a: c_int = switch (cond) { - \\ 1 => 1, - \\ 2 => 2, - \\ 99...300, 12 => 3, - \\ 0 => 4, - \\ else => 5, - \\ }; - \\ return a - 4; - \\} - , ""); - - // Switch expression missing else case. - case.addError( - \\pub export fn main() c_int { - \\ var cond: c_int = 0; - \\ const a: c_int = switch (cond) { - \\ 1 => 1, - \\ 2 => 2, - \\ 3 => 3, - \\ 4 => 4, - \\ }; - \\ return a - 4; - \\} - , &.{":3:22: error: switch must handle all possibilities"}); - - // Switch expression, has an unreachable prong. - case.addCompareOutput( - \\pub export fn main() c_int { - \\ var cond: c_int = 0; - \\ const a: c_int = switch (cond) { - \\ 1 => 1, - \\ 2 => 2, - \\ 99...300, 12 => 3, - \\ 0 => 4, - \\ 13 => unreachable, - \\ else => 5, - \\ }; - \\ return a - 4; - \\} - , ""); - - // Switch expression, has an unreachable prong and prongs write - // to result locations. - case.addCompareOutput( - \\pub export fn main() c_int { - \\ var cond: c_int = 0; - \\ var a: c_int = switch (cond) { - \\ 1 => 1, - \\ 2 => 2, - \\ 99...300, 12 => 3, - \\ 0 => 4, - \\ 13 => unreachable, - \\ else => 5, - \\ }; - \\ return a - 4; - \\} - , ""); - - // Integer switch expression has duplicate case value. - case.addError( - \\pub export fn main() c_int { - \\ var cond: c_int = 0; - \\ const a: c_int = switch (cond) { - \\ 1 => 1, - \\ 2 => 2, - \\ 96, 11...13, 97 => 3, - \\ 0 => 4, - \\ 90, 12 => 100, - \\ else => 5, - \\ }; - \\ return a - 4; - \\} - , &.{ - ":8:13: error: duplicate switch value", - ":6:15: note: previous value here", - }); - - // Boolean switch expression has duplicate case value. - case.addError( - \\pub export fn main() c_int { - \\ var a: bool = false; - \\ const b: c_int = switch (a) { - \\ false => 1, - \\ true => 2, - \\ false => 3, - \\ }; - \\ _ = b; - \\} - , &.{ - ":6:9: error: duplicate switch value", - }); - - // Sparse (no range capable) switch expression has duplicate case value. - case.addError( - \\pub export fn main() c_int { - \\ const A: type = i32; - \\ const b: c_int = switch (A) { - \\ i32 => 1, - \\ bool => 2, - \\ f64, i32 => 3, - \\ else => 4, - \\ }; - \\ _ = b; - \\} - , &.{ - ":6:14: error: duplicate switch value", - ":4:9: note: previous value here", - }); - - // Ranges not allowed for some kinds of switches. - case.addError( - \\pub export fn main() c_int { - \\ const A: type = i32; - \\ const b: c_int = switch (A) { - \\ i32 => 1, - \\ bool => 2, - \\ f16...f64 => 3, - \\ else => 4, - \\ }; - \\ _ = b; - \\} - , &.{ - ":3:30: error: ranges not allowed when switching on type 'type'", - ":6:12: note: range here", - }); - - // Switch expression has unreachable else prong. - case.addError( - \\pub export fn main() c_int { - \\ var a: u2 = 0; - \\ const b: i32 = switch (a) { - \\ 0 => 10, - \\ 1 => 20, - \\ 2 => 30, - \\ 3 => 40, - \\ else => 50, - \\ }; - \\ _ = b; - \\} - , &.{ - ":8:14: error: unreachable else prong; all cases already handled", - }); - } - //{ - // var case = ctx.exeFromCompiledC("optionals", .{}, b); - - // // Simple while loop - // case.addCompareOutput( - // \\pub export fn main() c_int { - // \\ var count: c_int = 0; - // \\ var opt_ptr: ?*c_int = &count; - // \\ while (opt_ptr) |_| : (count += 1) { - // \\ if (count == 4) opt_ptr = null; - // \\ } - // \\ return count - 5; - // \\} - // , ""); - - // // Same with non pointer optionals - // case.addCompareOutput( - // \\pub export fn main() c_int { - // \\ var count: c_int = 0; - // \\ var opt_ptr: ?c_int = count; - // \\ while (opt_ptr) |_| : (count += 1) { - // \\ if (count == 4) opt_ptr = null; - // \\ } - // \\ return count - 5; - // \\} - // , ""); - //} - - { - var case = ctx.exeFromCompiledC("errors", .{}, b); - case.addCompareOutput( - \\pub export fn main() c_int { - \\ var e1 = error.Foo; - \\ var e2 = error.Bar; - \\ assert(e1 != e2); - \\ assert(e1 == error.Foo); - \\ assert(e2 == error.Bar); - \\ return 0; - \\} - \\fn assert(b: bool) void { - \\ if (!b) unreachable; - \\} - , ""); - case.addCompareOutput( - \\pub export fn main() c_int { - \\ var e: anyerror!c_int = 0; - \\ const i = e catch 69; - \\ return i; - \\} - , ""); - case.addCompareOutput( - \\pub export fn main() c_int { - \\ var e: anyerror!c_int = error.Foo; - \\ const i = e catch 69; - \\ return 69 - i; - \\} - , ""); - case.addCompareOutput( - \\const E = error{e}; - \\const S = struct { x: u32 }; - \\fn f() E!u32 { - \\ const x = (try @as(E!S, S{ .x = 1 })).x; - \\ return x; - \\} - \\pub export fn main() c_int { - \\ const x = f() catch @as(u32, 0); - \\ if (x != 1) unreachable; - \\ return 0; - \\} - , ""); - } - - { - var case = ctx.exeFromCompiledC("structs", .{}, b); - case.addError( - \\const Point = struct { x: i32, y: i32 }; - \\pub export fn main() c_int { - \\ var p: Point = .{ - \\ .y = 24, - \\ .x = 12, - \\ .y = 24, - \\ }; - \\ return p.y - p.x - p.x; - \\} - , &.{ - ":4:10: error: duplicate struct field name", - ":6:10: note: duplicate name here", - ":3:21: note: struct declared here", - }); - case.addError( - \\const Point = struct { x: i32, y: i32 }; - \\pub export fn main() c_int { - \\ var p: Point = .{ - \\ .y = 24, - \\ }; - \\ return p.y - p.x - p.x; - \\} - , &.{ - ":3:21: error: missing struct field: x", - ":1:15: note: struct 'tmp.Point' declared here", - }); - case.addError( - \\const Point = struct { x: i32, y: i32 }; - \\pub export fn main() c_int { - \\ var p: Point = .{ - \\ .x = 12, - \\ .y = 24, - \\ .z = 48, - \\ }; - \\ return p.y - p.x - p.x; - \\} - , &.{ - ":6:10: error: no field named 'z' in struct 'tmp.Point'", - ":1:15: note: struct declared here", - }); - case.addCompareOutput( - \\const Point = struct { x: i32, y: i32 }; - \\pub export fn main() c_int { - \\ var p: Point = .{ - \\ .x = 12, - \\ .y = 24, - \\ }; - \\ return p.y - p.x - p.x; - \\} - , ""); - case.addCompareOutput( - \\const Point = struct { x: i32, y: i32, z: i32, a: i32, b: i32 }; - \\pub export fn main() c_int { - \\ var p: Point = .{ - \\ .x = 18, - \\ .y = 24, - \\ .z = 1, - \\ .a = 2, - \\ .b = 3, - \\ }; - \\ return p.y - p.x - p.z - p.a - p.b; - \\} - , ""); - } - - { - var case = ctx.exeFromCompiledC("unions", .{}, b); - - case.addError( - \\const U = union { - \\ a: u32, - \\ b - \\}; - , &.{ - ":3:5: error: union field missing type", - }); - - case.addError( - \\const E = enum { a, b }; - \\const U = union(E) { - \\ a: u32 = 1, - \\ b: f32 = 2, - \\}; - , &.{ - ":2:11: error: explicitly valued tagged union requires inferred enum tag type", - ":3:14: note: tag value specified here", - }); - - case.addError( - \\const U = union(enum) { - \\ a: u32 = 1, - \\ b: f32 = 2, - \\}; - , &.{ - ":1:11: error: explicitly valued tagged union missing integer tag type", - ":2:14: note: tag value specified here", - }); - } - - { - var case = ctx.exeFromCompiledC("enums", .{}, b); - - case.addError( - \\const E1 = packed enum { a, b, c }; - \\const E2 = extern enum { a, b, c }; - \\export fn foo() void { - \\ _ = E1.a; - \\} - \\export fn bar() void { - \\ _ = E2.a; - \\} - , &.{ - ":1:12: error: enums do not support 'packed' or 'extern'; instead provide an explicit integer tag type", - ":2:12: error: enums do not support 'packed' or 'extern'; instead provide an explicit integer tag type", - }); - - // comptime and types are caught in AstGen. - case.addError( - \\const E1 = enum { - \\ a, - \\ comptime b, - \\ c, - \\}; - \\const E2 = enum { - \\ a, - \\ b: i32, - \\ c, - \\}; - \\export fn foo() void { - \\ _ = E1.a; - \\} - \\export fn bar() void { - \\ _ = E2.a; - \\} - , &.{ - ":3:5: error: enum fields cannot be marked comptime", - ":8:8: error: enum fields do not have types", - ":6:12: note: consider 'union(enum)' here to make it a tagged union", - }); - - // @intFromEnum, @enumFromInt, enum literal coercion, field access syntax, comparison, switch - case.addCompareOutput( - \\const Number = enum { One, Two, Three }; - \\ - \\pub export fn main() c_int { - \\ var number1 = Number.One; - \\ var number2: Number = .Two; - \\ const number3: Number = @enumFromInt(2); - \\ if (number1 == number2) return 1; - \\ if (number2 == number3) return 1; - \\ if (@intFromEnum(number1) != 0) return 1; - \\ if (@intFromEnum(number2) != 1) return 1; - \\ if (@intFromEnum(number3) != 2) return 1; - \\ var x: Number = .Two; - \\ if (number2 != x) return 1; - \\ switch (x) { - \\ .One => return 1, - \\ .Two => return 0, - \\ number3 => return 2, - \\ } - \\} - , ""); - - // Specifying alignment is a parse error. - // This also tests going from a successful build to a parse error. - case.addError( - \\const E1 = enum { - \\ a, - \\ b align(4), - \\ c, - \\}; - \\export fn foo() void { - \\ _ = E1.a; - \\} - , &.{ - ":3:13: error: enum fields cannot be aligned", - }); - - // Redundant non-exhaustive enum mark. - // This also tests going from a parse error to an AstGen error. - case.addError( - \\const E1 = enum { - \\ a, - \\ _, - \\ b, - \\ c, - \\ _, - \\}; - \\export fn foo() void { - \\ _ = E1.a; - \\} - , &.{ - ":6:5: error: redundant non-exhaustive enum mark", - ":3:5: note: other mark here", - }); - - case.addError( - \\const E1 = enum { - \\ a, - \\ b, - \\ c, - \\ _ = 10, - \\}; - \\export fn foo() void { - \\ _ = E1.a; - \\} - , &.{ - ":5:9: error: '_' is used to mark an enum as non-exhaustive and cannot be assigned a value", - }); - - case.addError( - \\const E1 = enum { a, b, _ }; - \\export fn foo() void { - \\ _ = E1.a; - \\} - , &.{ - ":1:12: error: non-exhaustive enum missing integer tag type", - ":1:25: note: marked non-exhaustive here", - }); - - case.addError( - \\const E1 = enum { a, b, c, b, d }; - \\pub export fn main() c_int { - \\ _ = E1.a; - \\} - , &.{ - ":1:22: error: duplicate enum field name", - ":1:28: note: duplicate field here", - ":1:12: note: enum declared here", - }); - - case.addError( - \\pub export fn main() c_int { - \\ const a = true; - \\ _ = @intFromEnum(a); - \\} - , &.{ - ":3:20: error: expected enum or tagged union, found 'bool'", - }); - - case.addError( - \\pub export fn main() c_int { - \\ const a = 1; - \\ _ = @as(bool, @enumFromInt(a)); - \\} - , &.{ - ":3:19: error: expected enum, found 'bool'", - }); - - case.addError( - \\const E = enum { a, b, c }; - \\pub export fn main() c_int { - \\ _ = @as(E, @enumFromInt(3)); - \\} - , &.{ - ":3:16: error: enum 'tmp.E' has no tag with value '3'", - ":1:11: note: enum declared here", - }); - - case.addError( - \\const E = enum { a, b, c }; - \\pub export fn main() c_int { - \\ var x: E = .a; - \\ switch (x) { - \\ .a => {}, - \\ .c => {}, - \\ } - \\} - , &.{ - ":4:5: error: switch must handle all possibilities", - ":1:21: note: unhandled enumeration value: 'b'", - ":1:11: note: enum 'tmp.E' declared here", - }); - - case.addError( - \\const E = enum { a, b, c }; - \\pub export fn main() c_int { - \\ var x: E = .a; - \\ switch (x) { - \\ .a => {}, - \\ .b => {}, - \\ .b => {}, - \\ .c => {}, - \\ } - \\} - , &.{ - ":7:10: error: duplicate switch value", - ":6:10: note: previous value here", - }); - - case.addError( - \\const E = enum { a, b, c }; - \\pub export fn main() c_int { - \\ var x: E = .a; - \\ switch (x) { - \\ .a => {}, - \\ .b => {}, - \\ .c => {}, - \\ else => {}, - \\ } - \\} - , &.{ - ":8:14: error: unreachable else prong; all cases already handled", - }); - - case.addError( - \\const E = enum { a, b, c }; - \\pub export fn main() c_int { - \\ var x: E = .a; - \\ switch (x) { - \\ .a => {}, - \\ .b => {}, - \\ _ => {}, - \\ } - \\} - , &.{ - ":4:5: error: '_' prong only allowed when switching on non-exhaustive enums", - ":7:11: note: '_' prong here", - }); - - case.addError( - \\const E = enum { a, b, c }; - \\pub export fn main() c_int { - \\ _ = E.d; - \\} - , &.{ - ":3:11: error: enum 'tmp.E' has no member named 'd'", - ":1:11: note: enum declared here", - }); - - case.addError( - \\const E = enum { a, b, c }; - \\pub export fn main() c_int { - \\ var x: E = .d; - \\ _ = x; - \\} - , &.{ - ":3:17: error: no field named 'd' in enum 'tmp.E'", - ":1:11: note: enum declared here", - }); - } - - { - var case = ctx.exeFromCompiledC("shift right and left", .{}, b); - case.addCompareOutput( - \\pub export fn main() c_int { - \\ var i: u32 = 16; - \\ assert(i >> 1, 8); - \\ return 0; - \\} - \\fn assert(a: u32, b: u32) void { - \\ if (a != b) unreachable; - \\} - , ""); - - case.addCompareOutput( - \\pub export fn main() c_int { - \\ var i: u32 = 16; - \\ assert(i << 1, 32); - \\ return 0; - \\} - \\fn assert(a: u32, b: u32) void { - \\ if (a != b) unreachable; - \\} - , ""); - } - - { - var case = ctx.exeFromCompiledC("inferred error sets", .{}, b); - - case.addCompareOutput( - \\pub export fn main() c_int { - \\ if (foo()) |_| { - \\ @panic("test fail"); - \\ } else |err| { - \\ if (err != error.ItBroke) { - \\ @panic("test fail"); - \\ } - \\ } - \\ return 0; - \\} - \\fn foo() !void { - \\ return error.ItBroke; - \\} - , ""); - } - - { - // TODO: add u64 tests, ran into issues with the literal generated for std.math.maxInt(u64) - var case = ctx.exeFromCompiledC("add and sub wrapping operations", .{}, b); - case.addCompareOutput( - \\pub export fn main() c_int { - \\ // Addition - \\ if (!add_u3(1, 1, 2)) return 1; - \\ if (!add_u3(7, 1, 0)) return 1; - \\ if (!add_i3(1, 1, 2)) return 1; - \\ if (!add_i3(3, 2, -3)) return 1; - \\ if (!add_i3(-3, -2, 3)) return 1; - \\ if (!add_c_int(1, 1, 2)) return 1; - \\ // TODO enable these when stage2 supports std.math.maxInt - \\ //if (!add_c_int(maxInt(c_int), 2, minInt(c_int) + 1)) return 1; - \\ //if (!add_c_int(maxInt(c_int) + 1, -2, maxInt(c_int))) return 1; - \\ - \\ // Subtraction - \\ if (!sub_u3(2, 1, 1)) return 1; - \\ if (!sub_u3(0, 1, 7)) return 1; - \\ if (!sub_i3(2, 1, 1)) return 1; - \\ if (!sub_i3(3, -2, -3)) return 1; - \\ if (!sub_i3(-3, 2, 3)) return 1; - \\ if (!sub_c_int(2, 1, 1)) return 1; - \\ // TODO enable these when stage2 supports std.math.maxInt - \\ //if (!sub_c_int(maxInt(c_int), -2, minInt(c_int) + 1)) return 1; - \\ //if (!sub_c_int(minInt(c_int) + 1, 2, maxInt(c_int))) return 1; - \\ - \\ return 0; - \\} - \\fn add_u3(lhs: u3, rhs: u3, expected: u3) bool { - \\ return expected == lhs +% rhs; - \\} - \\fn add_i3(lhs: i3, rhs: i3, expected: i3) bool { - \\ return expected == lhs +% rhs; - \\} - \\fn add_c_int(lhs: c_int, rhs: c_int, expected: c_int) bool { - \\ return expected == lhs +% rhs; - \\} - \\fn sub_u3(lhs: u3, rhs: u3, expected: u3) bool { - \\ return expected == lhs -% rhs; - \\} - \\fn sub_i3(lhs: i3, rhs: i3, expected: i3) bool { - \\ return expected == lhs -% rhs; - \\} - \\fn sub_c_int(lhs: c_int, rhs: c_int, expected: c_int) bool { - \\ return expected == lhs -% rhs; - \\} - , ""); - } - - { - var case = ctx.exeFromCompiledC("rem", linux_x64, b); - case.addCompareOutput( - \\fn assert(ok: bool) void { - \\ if (!ok) unreachable; - \\} - \\fn rem(lhs: i32, rhs: i32, expected: i32) bool { - \\ return @rem(lhs, rhs) == expected; - \\} - \\pub export fn main() c_int { - \\ assert(rem(-5, 3, -2)); - \\ assert(rem(5, 3, 2)); - \\ return 0; - \\} - , ""); - } -}