From 1157dd95714e57a699f06066ccfc7ed511ebf43f Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Thu, 8 Oct 2026 01:55:13 -0400 Subject: [PATCH] test/llvm-ir: convert to new runner --- build.zig | 9 +- lib/std/posix.zig | 2 +- test/Runner.zig | 31 +++++-- test/llvm-ir/allowzero | 72 +++++++++++++++ test/llvm-ir/array_to_vector | 38 ++++++++ test/llvm-ir/dead_store | 43 +++++++++ test/llvm-ir/load_store_bool | 28 ++++++ test/llvm-ir/matrix.zon | 9 ++ test/llvm-ir/nonnull | 30 +++++++ test/llvm-ir/unused_load | 79 ++++++++++++++++ test/llvm_ir.zig | 170 ----------------------------------- test/src/LlvmIr.zig | 135 ---------------------------- test/tests.zig | 23 +---- 13 files changed, 331 insertions(+), 338 deletions(-) create mode 100644 test/llvm-ir/allowzero create mode 100644 test/llvm-ir/array_to_vector create mode 100644 test/llvm-ir/dead_store create mode 100644 test/llvm-ir/load_store_bool create mode 100644 test/llvm-ir/matrix.zon create mode 100644 test/llvm-ir/nonnull create mode 100644 test/llvm-ir/unused_load delete mode 100644 test/llvm_ir.zig delete mode 100644 test/src/LlvmIr.zig diff --git a/build.zig b/build.zig index f2b6c5c9b6d2a3a560b31c5605367bd776ec3f60..cca0bdb582e373599b54faef9414cc7a6eef393e 100644 --- a/build.zig +++ b/build.zig @@ -712,11 +712,6 @@ pub fn build(b: *std.Build) !void { .skip_libc = skip_libc, })); test_step.dependOn(tests.addCliTests(b)); - if (tests.addLlvmIrTests(b, .{ - .enable_llvm = enable_llvm, - .test_filters = test_filters, - .test_target_filters = test_target_filters, - })) |test_llvm_ir_step| test_step.dependOn(test_llvm_ir_step); try addWasiUpdateStep(b, version); @@ -822,6 +817,10 @@ pub fn build(b: *std.Build) !void { const test_incremental_step = b.step("test-incremental", "Run the incremental compilation tests"); try tests.addRunnerTests(b, runner, test_incremental_step, "test/incremental", @import("test/incremental/matrix.zon"), runner_opts); test_step.dependOn(test_incremental_step); + + const test_llvm_ir_step = b.step("test-llvm-ir", "Run the LLVM IR tests"); + try tests.addRunnerTests(b, runner, test_llvm_ir_step, "test/llvm-ir", @import("test/llvm-ir/matrix.zon"), runner_opts); + test_step.dependOn(test_llvm_ir_step); } fn addWasiUpdateStep(b: *std.Build, version: [:0]const u8) !void { diff --git a/lib/std/posix.zig b/lib/std/posix.zig index 146a521224cd1a041b9200eed79b1d1815918bfb..de41ed68cbe7619c947803c5705e6026525e3a3b 100644 --- a/lib/std/posix.zig +++ b/lib/std/posix.zig @@ -797,7 +797,7 @@ pub fn dl_iterate_phdr( const dl = @import("dynamic_library.zig"); switch (builtin.object_format) { - .elf, .c => {}, + .c, .elf, .llvmbc, .llvmir => {}, else => @compileError("dl_iterate_phdr is not available for this target"), } diff --git a/test/Runner.zig b/test/Runner.zig index d614036096d5de25984438bc00314d696d1409b0..5be751b87806c1b2bf6e16b3249722a134805d54 100644 --- a/test/Runner.zig +++ b/test/Runner.zig @@ -917,6 +917,7 @@ fn handleCommand( .arch_os_abi = triple, .object_format = switch (backend) { .sema, .selfhosted, .llvm => null, + .llvmir => "llvmir", .cbe => "c", }, }) catch |err| switch (err) { @@ -1075,7 +1076,7 @@ fn handleCommand( ), }; }, - .stdout, .exit, .gdb, .lldb => if (eb.errorMessageCount() > 0) { + .stdout, .exit, .llvm, .gdb, .lldb => if (eb.errorMessageCount() > 0) { eb.renderToStderr(runner.io, .{}, .auto) catch |err| switch (err) { error.Canceled => {}, else => {}, @@ -1146,6 +1147,7 @@ fn spawnCompiler( .sema => try argv.append(gpa, "-fno-emit-bin"), .selfhosted => try argv.append(gpa, "-fno-llvm"), .llvm => try argv.append(gpa, "-fllvm"), + .llvmir => try argv.append(gpa, "-ofmt=llvmir"), .cbe => try argv.append(gpa, "-ofmt=c"), } else try argv.appendSlice(gpa, &.{ "-I", path_buffer[0 .. (runner.args.lib_dir orelse return runner.fail("\"--lib=path/to/lib\" arg required with cbe", .{})) @@ -1287,6 +1289,8 @@ const Compiler = struct { /// Use the LLVM backend. /// Corresponds to `-fllvm -flld`. llvm, + /// Use the LLVM backend without libLLVM. + llvmir, /// Use the C backend. The output is compiled with `zig cc`. /// Corresponds to `-ofmt=c`. cbe, @@ -1325,7 +1329,7 @@ const Compiler = struct { return .{ .tag = header.tag, .body = body }; } - const Check = enum { errors, stdout, exit, gdb, lldb }; + const Check = enum { errors, stdout, exit, llvm, gdb, lldb }; fn checkSuccess( comp: *Compiler, update: *const Update, @@ -1361,7 +1365,7 @@ const Compiler = struct { var script_buffer: [512]u8 = undefined; const script_path, const script_file, var script_fw = script: switch (check) { .errors => return, - .stdout, .exit => .{ undefined, null, undefined }, + .stdout, .exit, .llvm => .{ undefined, null, undefined }, .gdb => { const script_path = tmp_dir_path ++ std.Io.Dir.path.sep_str ++ "gdb"; argv.appendSliceAssumeCapacity(&.{ "gdb", "--batch", "--command", script_path, "--args" }); @@ -1425,7 +1429,7 @@ const Compiler = struct { const out_path = try std.Io.Dir.path.join(arena, &.{ out_dir_path, comp.out_name }); const bin_path = switch (comp.target.backend.?) { .sema => return, - .selfhosted, .llvm => out_path, + .selfhosted, .llvm, .llvmir => out_path, .cbe => try comp.compileC(update.src_dir, out_path), }; @@ -1527,6 +1531,23 @@ const Compiler = struct { .exe = exe: switch (check) { .errors => unreachable, .stdout, .exit => if (use_executor) .search else .{ .file = bin_file }, + .llvm => { + var bin_fr = bin_file.reader(io, &.{}); + const actual = bin_fr.interface.readAllocAll(arena, @intCast( + bin_fr.getSize() catch |err| switch (err) { + error.Canceled => |e| return e, + else => |e| return runner.fail("unable to get size of {q}: {t}", .{ bin_path, e }), + }, + )) catch |err| switch (switch (err) { + error.OutOfMemory => |e| return e, + error.EndOfStream => |e| e, + error.ReadFailed => bin_fr.err.?, + }) { + error.Canceled => |e| return e, + else => |e| return runner.fail("unable to read {q}: {t}", .{ bin_path, e }), + }; + return update.checkMatches("LLVM IR", expected, actual); + }, .gdb, .lldb => { if (use_executor) { if (!runner.args.quiet) std.log.warn( @@ -1603,7 +1624,7 @@ const Compiler = struct { } switch (result.term) { .exited => |code| switch (check) { - .errors => unreachable, + .errors, .llvm => unreachable, .stdout => { if (code != 0) return update.fail( "generated executable {q} failed with code {d}", diff --git a/test/llvm-ir/allowzero b/test/llvm-ir/allowzero new file mode 100644 index 0000000000000000000000000000000000000000..e83cf1faf438b237f1d012a691d31998b4d437e3 --- /dev/null +++ b/test/llvm-ir/allowzero @@ -0,0 +1,72 @@ +#obj { +--name test +-Mroot=test.zig +#} + +#write test.zig { +export fn entry(ptr: *allowzero i16) i16 { + return ptr.*; +} +#} +#update "load" +#check llvm { +define #...@test.entry(ptr #...%0) #...#0 #...{ +#...load i16, ptr %0#... +} + +#... +attributes #0 = {#... null_pointer_is_valid #...} +#} + +#write test.zig { +export fn entry(ptr: *allowzero i16) void { + ptr.* = 42; +} +#} +#update "store" +#check llvm { +define #...@test.entry(ptr #...%0) #...#0 #...{ +#...store i16 42, ptr %0#... +} + +#... +attributes #0 = {#... null_pointer_is_valid #...} +#} + +#write test.zig { +export fn entry(ptr: *allowzero i16) i16 { + return entry2(ptr[0..1]); +} +fn entry2(slice: []allowzero i16) i16 { + @setRuntimeSafety(false); + return slice[0]; +} +#} +#update "slice load" +#check llvm { +define #...@test.entry2(#..., ptr #...%1, #...) #...#2 #...{ +#...load i16, ptr %#... +} + +#... +attributes #2 = {#... null_pointer_is_valid #...} +#} + +#write test.zig { +export fn entry(ptr: *allowzero i16) void { + entry2(ptr[0..1]); +} +fn entry2(slice: []allowzero i16) void { + @setRuntimeSafety(false); + slice[0] = 42; +} +#} +#update "slice store" +#check llvm { +define #...@test.entry2(#..., ptr #...%1, #...) #...#2 #...{ +#...store i16 42, ptr %#... +} + +#... +attributes #2 = {#... null_pointer_is_valid #...} +#} diff --git a/test/llvm-ir/array_to_vector b/test/llvm-ir/array_to_vector new file mode 100644 index 0000000000000000000000000000000000000000..ab182e1284306a69018581765d41d99d4e45e893 --- /dev/null +++ b/test/llvm-ir/array_to_vector @@ -0,0 +1,38 @@ +#obj { +--name test +-Mroot=test.zig +#} + +#write test.zig { +export fn entry(arr: *const [16]u8) @Vector(16, u8) { + return arr.*; +} +#} +#update "one vector load" +#check llvm { +define #...<16 x i8> @test.entry(#...) #...{ +#... + %1 = alloca [16 x i8], align 1#... + %3 = load <16 x i8>, ptr %1, align 1#... + ret <16 x i8> %3#... +#} + +#write test.zig { +export fn entry(a: *@Vector(8, u8), b: *@Vector(8, u8), src: [*]const u8) void { + const q: @Vector(16, u8) = src[0..16].*; + a.* = @shuffle(u8, q, undefined, @Vector(8, i32){ 0, 1, 2, 3, 4, 5, 6, 7 }); + b.* = @shuffle(u8, q, undefined, @Vector(8, i32){ 7, 8, 9, 10, 11, 12, 13, 14 }); +} +#} +#update "feeding overlapping shuffles" +#check llvm { +define #...void @test.entry(ptr #...%0, ptr #...%1, #...) #...{ +#... + %11 = load <16 x i8>, ptr %#... + %12 = shufflevector <16 x i8> %11, #... + store <8 x i8> %12, ptr %0, align 8#... + %13 = shufflevector <16 x i8> %11, #... + store <8 x i8> %13, ptr %1, align 8#... + ret void#... +} +#} diff --git a/test/llvm-ir/dead_store b/test/llvm-ir/dead_store new file mode 100644 index 0000000000000000000000000000000000000000..362b913db4c69597316b1d8bc3e0e82304ef6fc3 --- /dev/null +++ b/test/llvm-ir/dead_store @@ -0,0 +1,43 @@ +#obj { +--name test +-Mroot=test.zig +#} + +#write test.zig { +export fn entry(ptr: *volatile i16) void { + ptr.* = 123; + ptr.* = 321; +} +#} +#update "volatile" +#check llvm { +define #...@test.entry(ptr #...%0) #...{ +#...store volatile i16 123, ptr %0#... +#...store volatile i16 321, ptr %0#... +} + +#} + +#write test.zig { +export fn entry(ptr: *volatile i16) void { + entry2(ptr[0..1]); +} +fn entry2(slice: []volatile i16) void { + @setRuntimeSafety(false); + slice[0] = 123; + slice[0] = 321; +} +#} +#update "volatile slice" +#check llvm { +define #...@test.entry(#...) #...{ +#... +} + +#... +define #...@test.entry2(#...) #...{ +#...store volatile i16 123, ptr %#... +#...store volatile i16 321, ptr %#... +} + +#} diff --git a/test/llvm-ir/load_store_bool b/test/llvm-ir/load_store_bool new file mode 100644 index 0000000000000000000000000000000000000000..e38c45cfad468412e499a87dc42bbf9ae7844bc7 --- /dev/null +++ b/test/llvm-ir/load_store_bool @@ -0,0 +1,28 @@ +#obj { +--name test +-Mroot=test.zig +#} + +#write test.zig { +export fn foo(a: *bool, b: *align(2) bool) void { + const tmp = a.*; + a.* = b.*; + b.* = tmp; +} +#} +#update +#check llvm { +define #...void @test.foo(ptr #...%0, ptr #...%1) #...{ +#... + %5 = load i8, ptr %0, align 1#... + %6 = trunc nuw i8 %5 to i1#... + %8 = load i8, ptr %1, align 2#... + %9 = trunc nuw i8 %8 to i1#... + %10 = zext i1 %9 to i8#... + store i8 %10, ptr %0, align 1#... + %11 = zext i1 %6 to i8#... + store i8 %11, ptr %1, align 2#... + ret void#... +} + +#} diff --git a/test/llvm-ir/matrix.zon b/test/llvm-ir/matrix.zon new file mode 100644 index 0000000000000000000000000000000000000000..681e7f7c3a925f928804bb598be3b52a5fabad59 --- /dev/null +++ b/test/llvm-ir/matrix.zon @@ -0,0 +1,9 @@ +.{ + .{ + .target = .{}, + .cache_mode = .whole, + .backend = .llvmir, + .linker = .old, + .pic = .pic, + }, +} diff --git a/test/llvm-ir/nonnull b/test/llvm-ir/nonnull new file mode 100644 index 0000000000000000000000000000000000000000..d3cb0546bdc83b6e3256d17ff0caed5f0a5232bd --- /dev/null +++ b/test/llvm-ir/nonnull @@ -0,0 +1,30 @@ +#obj { +--name test +-Mroot=test.zig +#} + +#write test.zig { +export fn entry(ptr: *i16) i16 { + return ptr.*; +} +#} +#update "store" +#check llvm { +define #...@test.entry(ptr #...nonnull #...%0) #...{ +#...load i16, ptr %0#... +} + +#} + +#write test.zig { +export fn entry(ptr: *i16) void { + ptr.* = 42; +} +#} +#update "load" +#check llvm { +define #...@test.entry(ptr #...nonnull #...%0) #...{ +#...store i16 42, ptr %0#... +} + +#} diff --git a/test/llvm-ir/unused_load b/test/llvm-ir/unused_load new file mode 100644 index 0000000000000000000000000000000000000000..8f6f3a59cfa74bf420520802d2559b6f49bbe948 --- /dev/null +++ b/test/llvm-ir/unused_load @@ -0,0 +1,79 @@ +#obj { +--name test +-Mroot=test.zig +#} + +#write test.zig { +export fn entry(ptr: *i16) void { + _ = @atomicLoad(i16, ptr, .acquire); +} +#} +#update "atomic acquire" +#check llvm { +define #...@test.entry(ptr #...%0) #...{ +#...load atomic i16, ptr %0 acquire#... +} + +#} + +#write test.zig { +export fn entry(ptr: *volatile i16) void { + _ = @atomicLoad(i16, ptr, .unordered); +} +#} +#update "atomic volatile unordered" +#check llvm { +define #...@test.entry(ptr #...%0) #...{ +#...load atomic volatile i16, ptr %0 unordered#... +} + +#} + +#write test.zig { +export fn entry(ptr: *volatile i16) void { + _ = ptr.*; +} +#} +#update "volatile" +#check llvm { +define #...@test.entry(ptr #...%0) #...{ +#...load volatile i16, ptr %0#... +} + +#} + +#write test.zig { +export fn entry(ptr: *volatile i16) void { + entry2(ptr[0..1]); +} +fn entry2(slice: []volatile i16) void { + @setRuntimeSafety(false); + _ = slice[0]; +} +#} +#update "volatile slice" +#check llvm { +define #...@test.entry(#...) #...{ +#... +} + +#... +define #...@test.entry2(#...) #...{ +#...load volatile i16, ptr %#... +} + +#} + +#write test.zig { +const S = packed struct(u16) { a: u2, b: u8, c: u6 }; +export fn entry(ptr: *volatile S) void { + _ = ptr.b; +} +#} +#update "volatile packed" +#check llvm { +define #...@test.entry(ptr #...%0) #...{ +#...load volatile i16, ptr %#... +} + +#} diff --git a/test/llvm_ir.zig b/test/llvm_ir.zig deleted file mode 100644 index 9cb9dab42e85753e168fe7d9ca4f8c049754b19c..0000000000000000000000000000000000000000 --- a/test/llvm_ir.zig +++ /dev/null @@ -1,170 +0,0 @@ -pub fn addCases(cases: *tests.LlvmIrContext) void { - cases.addMatches("nonnull ptr load", - \\export fn entry(ptr: *i16) i16 { - \\ return ptr.*; - \\} - , &.{ - "ptr nonnull", - "load i16, ptr %0", - }, .{}); - - cases.addMatches("nonnull ptr store", - \\export fn entry(ptr: *i16) void { - \\ ptr.* = 42; - \\} - , &.{ - "ptr nonnull", - "store i16 42, ptr %0", - }, .{}); - - cases.addMatches("unused acquire atomic ptr load", - \\export fn entry(ptr: *i16) void { - \\ _ = @atomicLoad(i16, ptr, .acquire); - \\} - , &.{ - "load atomic i16, ptr %0 acquire", - }, .{}); - - cases.addMatches("unused unordered atomic volatile ptr load", - \\export fn entry(ptr: *volatile i16) void { - \\ _ = @atomicLoad(i16, ptr, .unordered); - \\} - , &.{ - "load atomic volatile i16, ptr %0 unordered", - }, .{}); - - cases.addMatches("unused volatile ptr load", - \\export fn entry(ptr: *volatile i16) void { - \\ _ = ptr.*; - \\} - , &.{ - "load volatile i16, ptr %0", - }, .{}); - - cases.addMatches("dead volatile ptr store", - \\export fn entry(ptr: *volatile i16) void { - \\ ptr.* = 123; - \\ ptr.* = 321; - \\} - , &.{ - "store volatile i16 123, ptr %0", - "store volatile i16 321, ptr %0", - }, .{}); - - cases.addMatches("unused volatile slice load", - \\export fn entry(ptr: *volatile i16) void { - \\ entry2(ptr[0..1]); - \\} - \\fn entry2(ptr: []volatile i16) void { - \\ _ = ptr[0]; - \\} - , &.{ - "load volatile i16, ptr", - }, .{}); - - cases.addMatches("dead volatile slice store", - \\export fn entry(ptr: *volatile i16) void { - \\ entry2(ptr[0..1]); - \\} - \\fn entry2(ptr: []volatile i16) void { - \\ ptr[0] = 123; - \\ ptr[0] = 321; - \\} - , &.{ - "store volatile i16 123, ptr", - "store volatile i16 321, ptr", - }, .{}); - - cases.addMatches("unused volatile packed pointer load", - \\const S = packed struct(u16) { a: u2, b: u8, c: u6 }; - \\export fn entry(ptr: *volatile S) void { - \\ _ = ptr.b; - \\} - , &.{ - "load volatile i16, ptr", - }, .{}); - - cases.addMatches("allowzero ptr load", - \\export fn entry(ptr: *allowzero i16) i16 { - \\ return ptr.*; - \\} - , &.{ - "null_pointer_is_valid", - "load i16, ptr %0", - }, .{}); - - cases.addMatches("allowzero ptr store", - \\export fn entry(ptr: *allowzero i16) void { - \\ ptr.* = 42; - \\} - , &.{ - "null_pointer_is_valid", - "store i16 42, ptr %0", - }, .{}); - - cases.addMatches("allowzero slice load", - \\export fn entry(ptr: *allowzero i16) i16 { - \\ return entry2(ptr[0..1]); - \\} - \\fn entry2(ptr: []allowzero i16) i16 { - \\ return ptr[0]; - \\} - , &.{ - "null_pointer_is_valid", - "load i16, ptr", - }, .{}); - - cases.addMatches("allowzero slice store", - \\export fn entry(ptr: *allowzero i16) void { - \\ entry2(ptr[0..1]); - \\} - \\fn entry2(ptr: []allowzero i16) void { - \\ ptr[0] = 42; - \\} - , &.{ - "null_pointer_is_valid", - "store i16 42, ptr", - }, .{}); - - cases.addMatches("load and store bool", - \\export fn foo(a: *bool, b: *align(2) bool) void { - \\ const tmp = a.*; - \\ a.* = b.*; - \\ b.* = tmp; - \\} - , &.{ - // TODO: this should all be one multiline string literal, but `-femit-llvm-ir` is currently - // emitting CRLF on Windows, which is a pain to handle here. In future that option will emit - // unoptimized LLVM IR emitted directly from Zig, so that bug will go away. - " %3 = load i8, ptr %0, align 1", - " %4 = trunc nuw i8 %3 to i1", - " %5 = load i8, ptr %1, align 2", - " %6 = trunc nuw i8 %5 to i1", - " %7 = zext i1 %6 to i8", - " store i8 %7, ptr %0, align 1", - " %8 = zext i1 %4 to i8", - " store i8 %8, ptr %1, align 2", - }, .{ .strip = true }); - - cases.addMatches("array to vector coercion is one vector load", - \\export fn entry(arr: *const [16]u8) @Vector(16, u8) { - \\ return arr.*; - \\} - , &.{ - "load <16 x i8>, ptr", - }, .{}); - - cases.addMatches("array to vector coercion feeding overlapping shuffles", - \\export fn entry(a: *@Vector(8, u8), b: *@Vector(8, u8), src: [*]const u8) void { - \\ const q: @Vector(16, u8) = src[0..16].*; - \\ a.* = @shuffle(u8, q, undefined, @Vector(8, i32){ 0, 1, 2, 3, 4, 5, 6, 7 }); - \\ b.* = @shuffle(u8, q, undefined, @Vector(8, i32){ 7, 8, 9, 10, 11, 12, 13, 14 }); - \\} - , &.{ - "load <16 x i8>, ptr", - "shufflevector <16 x i8>", - }, .{}); -} - -const std = @import("std"); -const tests = @import("tests.zig"); diff --git a/test/src/LlvmIr.zig b/test/src/LlvmIr.zig deleted file mode 100644 index 3dce66058b2c3eb21e9046f16091d348826d37a4..0000000000000000000000000000000000000000 --- a/test/src/LlvmIr.zig +++ /dev/null @@ -1,135 +0,0 @@ -b: *std.Build, -options: Options, -root_step: *std.Build.Step, - -pub const Options = struct { - enable_llvm: bool, - test_filters: []const []const u8, - test_target_filters: []const []const u8, -}; - -const TestCase = struct { - name: []const u8, - source: []const u8, - check: union(enum) { - matches: []const []const u8, - exact: []const u8, - }, - params: Params, - - pub const Params = struct { - code_model: std.builtin.CodeModel = .default, - dll_export_fns: ?bool = null, - dwarf_format: ?std.dwarf.Format = null, - error_tracing: ?bool = null, - no_builtin: ?bool = null, - omit_frame_pointer: ?bool = null, - // For most cases, we want to test the LLVM IR that we output; we don't want to be in the - // business of testing LLVM's optimization passes. `Debug` gets us the closest to that as it - // disables the vast majority of passes in LLVM. - optimize: std.builtin.Optimize = .debug, - pic: ?bool = null, - pie: ?bool = null, - red_zone: ?bool = null, - sanitize_thread: ?bool = null, - single_threaded: ?bool = null, - stack_check: ?bool = null, - stack_protector: ?bool = null, - strip: ?bool = null, - target: std.Target.Query = .{}, - unwind_tables: ?std.builtin.UnwindTables = null, - valgrind: ?bool = null, - }; -}; - -pub fn addMatches( - self: *LlvmIr, - name: []const u8, - source: []const u8, - matches: []const []const u8, - params: TestCase.Params, -) void { - self.addCase(.{ - .name = name, - .source = source, - .check = .{ .matches = matches }, - .params = params, - }); -} - -pub fn addExact( - self: *LlvmIr, - name: []const u8, - source: []const u8, - expected: []const []const u8, - params: TestCase.Params, -) void { - self.addCase(.{ - .name = name, - .source = source, - .check = .{ .exact = expected }, - .params = params, - }); -} - -pub fn addCase(self: *LlvmIr, case: TestCase) void { - const target = self.b.resolveTargetQuery(case.params.target); - if (self.options.test_target_filters.len > 0) { - const triple_txt = target.query.zigTriple(self.b.allocator) catch @panic("OOM"); - for (self.options.test_target_filters) |filter| { - if (std.mem.find(u8, triple_txt, filter) != null) break; - } else return; - } - - const name = std.fmt.allocPrint(self.b.allocator, "check llvm-ir {s}", .{case.name}) catch @panic("OOM"); - if (self.options.test_filters.len > 0) { - for (self.options.test_filters) |filter| { - if (std.mem.find(u8, name, filter) != null) break; - } else return; - } - - const obj = self.b.addObject(.{ - .name = "test", - .root_module = self.b.createModule(.{ - .root_source_file = self.b.addWriteFiles().add("test.zig", case.source), - - .code_model = case.params.code_model, - .error_tracing = case.params.error_tracing, - .omit_frame_pointer = case.params.omit_frame_pointer, - .optimize = case.params.optimize, - .pic = case.params.pic, - .sanitize_thread = case.params.sanitize_thread, - .single_threaded = case.params.single_threaded, - .strip = case.params.strip, - .target = target, - .unwind_tables = case.params.unwind_tables, - }), - .use_llvm = true, - }); - - obj.dll_export_fns = case.params.dll_export_fns; - obj.pie = case.params.pie; - - obj.root_module.dwarf_format = case.params.dwarf_format; - obj.root_module.no_builtin = case.params.no_builtin; - obj.root_module.red_zone = case.params.red_zone; - obj.root_module.stack_check = case.params.stack_check; - obj.root_module.stack_protector = case.params.stack_protector; - obj.root_module.valgrind = case.params.valgrind; - - // This is not very sophisticated at the moment. Eventually, we should move towards something - // like LLVM's `FileCheck` utility (https://llvm.org/docs/CommandGuide/FileCheck.html), though - // likely a more simplified version as we probably don't want a full-blown regex engine in the - // standard library... - const check = self.b.addCheckFile(obj.getEmittedLlvmIr(), switch (case.check) { - .matches => |m| .{ .expected_matches = m }, - .exact => |e| .{ .expected_exact = e }, - }); - check.setName(name); - check.max_bytes = 64 * 1024 * 1024; // allow fairly big LLVM IR files - - self.root_step.dependOn(&check.step); -} - -const LlvmIr = @This(); -const std = @import("std"); diff --git a/test/tests.zig b/test/tests.zig index c65cbcee859aee2911ac5bef1027a5db5485bddf..eca020095684e3ee05feaf4ba093c8d0e1fc6bdd 100644 --- a/test/tests.zig +++ b/test/tests.zig @@ -6,14 +6,12 @@ const OptimizeMode = std.builtin.Optimize; const Step = std.Build.Step; // Cases -const llvm_ir = @import("llvm_ir.zig"); const libc = @import("libc.zig"); const link = @import("link.zig"); // Implementations pub const ErrorTracesContext = @import("src/ErrorTrace.zig"); pub const StackTracesContext = @import("src/StackTrace.zig"); -pub const LlvmIrContext = @import("src/LlvmIr.zig"); pub const LibcContext = @import("src/Libc.zig"); pub const LinkContext = @import("src/Link.zig"); @@ -2196,7 +2194,7 @@ const link_targets = blk: { const RunnerTarget = struct { target: std.Target.Query, cache_mode: enum { whole, incremental }, - backend: enum { selfhosted, llvm, cbe }, + backend: enum { selfhosted, llvm, llvmir, cbe }, linker: enum { lld, old, new }, pic: enum { nopic, pic, pie }, }; @@ -3175,25 +3173,6 @@ fn isEditorFileName(name: []const u8) bool { std.mem.endsWith(u8, name, "~") or std.mem.endsWith(u8, name, ".swp"); } -pub fn addLlvmIrTests(b: *std.Build, options: LlvmIrContext.Options) ?*Step { - const step = b.step("test-llvm-ir", "Run the LLVM IR tests"); - - if (!options.enable_llvm) { - step.dependOn(&b.addFail("test-llvm-ir requires -Denable-llvm").step); - return null; - } - - var context: LlvmIrContext = .{ - .b = b, - .options = options, - .root_step = step, - }; - - llvm_ir.addCases(&context); - - return step; -} - const libc_test_nsz_targets: []const std.Target.Query = &.{ .{ .cpu_arch = .arm, -- 2.54.0