From 0151f3b76ad9dca6c73d44876c263d5e27d92ab3 Mon Sep 17 00:00:00 2001 From: Timon Kruiper Date: Sun, 3 Jan 2021 17:10:28 +0100 Subject: [PATCH] stage2: Add support for testing LLVM enabled builds in test-stage2 To make sure that we don't have to rebuild libc for every case, we now have a seperate cache directory for the global cache, which remains the same between test runs. Also make sure to destory the Compilation before executing a child process, otherwise the compiler deadlocks. (#7596) --- src/test.zig | 43 +++++++++++++++++++++++++++++++++++- test/stage2/llvm_backend.zig | 30 +++++++++++++++++++++++++ test/stage2/test.zig | 1 + 3 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 test/stage2/llvm_backend.zig diff --git a/src/test.zig b/src/test.zig index b74732d10d..67a30f1f32 100644 --- a/src/test.zig +++ b/src/test.zig @@ -135,6 +135,7 @@ pub const TestContext = struct { extension: Extension, object_format: ?std.builtin.ObjectFormat = null, emit_h: bool = false, + llvm_backend: bool = false, files: std.ArrayList(File), @@ -266,6 +267,21 @@ pub const TestContext = struct { return &ctx.cases.items[ctx.cases.items.len - 1]; } + /// Adds a test case that uses the LLVM backend to emit an executable. + /// Currently this implies linking libc, because only then we can generate a testable executable. + pub fn exeUsingLlvmBackend(ctx: *TestContext, name: []const u8, target: CrossTarget) *Case { + ctx.cases.append(Case{ + .name = name, + .target = target, + .updates = std.ArrayList(Update).init(ctx.cases.allocator), + .output_mode = .Exe, + .extension = .Zig, + .files = std.ArrayList(File).init(ctx.cases.allocator), + .llvm_backend = true, + }) catch unreachable; + return &ctx.cases.items[ctx.cases.items.len - 1]; + } + pub fn addObj( ctx: *TestContext, name: []const u8, @@ -518,10 +534,30 @@ pub const TestContext = struct { try thread_pool.init(std.testing.allocator); defer thread_pool.deinit(); + // Use the same global cache dir for all the tests, such that we for example don't have to + // rebuild musl libc for every case (when LLVM backend is enabled). + var global_tmp = std.testing.tmpDir(.{}); + defer global_tmp.cleanup(); + + var cache_dir = try global_tmp.dir.makeOpenPath("zig-cache", .{}); + defer cache_dir.close(); + const tmp_dir_path = try std.fs.path.join(std.testing.allocator, &[_][]const u8{ ".", "zig-cache", "tmp", &global_tmp.sub_path }); + defer std.testing.allocator.free(tmp_dir_path); + + const global_cache_directory: Compilation.Directory = .{ + .handle = cache_dir, + .path = try std.fs.path.join(std.testing.allocator, &[_][]const u8{ tmp_dir_path, "zig-cache" }), + }; + defer std.testing.allocator.free(global_cache_directory.path.?); + for (self.cases.items) |case| { if (build_options.skip_non_native and case.target.getCpuArch() != std.Target.current.cpu.arch) continue; + // Skip tests that require LLVM backend when it is not available + if (!build_options.have_llvm and case.llvm_backend) + continue; + var prg_node = root_node.start(case.name, case.updates.items.len); prg_node.activate(); defer prg_node.end(); @@ -537,6 +573,7 @@ pub const TestContext = struct { case, zig_lib_directory, &thread_pool, + global_cache_directory, ); } } @@ -548,6 +585,7 @@ pub const TestContext = struct { case: Case, zig_lib_directory: Compilation.Directory, thread_pool: *ThreadPool, + global_cache_directory: Compilation.Directory, ) !void { const target_info = try std.zig.system.NativeTargetInfo.detect(allocator, case.target); const target = target_info.target; @@ -601,7 +639,7 @@ pub const TestContext = struct { null; const comp = try Compilation.create(allocator, .{ .local_cache_directory = zig_cache_directory, - .global_cache_directory = zig_cache_directory, + .global_cache_directory = global_cache_directory, .zig_lib_directory = zig_lib_directory, .thread_pool = thread_pool, .root_name = "test_case", @@ -619,6 +657,9 @@ pub const TestContext = struct { .object_format = case.object_format, .is_native_os = case.target.isNativeOs(), .is_native_abi = case.target.isNativeAbi(), + .link_libc = case.llvm_backend, + .use_llvm = case.llvm_backend, + .self_exe_path = std.testing.zig_exe_path, }); defer comp.destroy(); diff --git a/test/stage2/llvm_backend.zig b/test/stage2/llvm_backend.zig new file mode 100644 index 0000000000..1b753621ea --- /dev/null +++ b/test/stage2/llvm_backend.zig @@ -0,0 +1,30 @@ +const std = @import("std"); +const TestContext = @import("../../src/test.zig").TestContext; +const build_options = @import("build_options"); + +// 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.zig.CrossTarget{ + .cpu_arch = .x86_64, + .os_tag = .linux, +}; + +pub fn addCases(ctx: *TestContext) !void { + { + var case = ctx.exeUsingLlvmBackend("simple addition and subtraction", linux_x64); + + case.addCompareOutput( + \\fn add(a: i32, b: i32) i32 { + \\ return a + b; + \\} + \\ + \\export fn main() c_int { + \\ var a: i32 = -5; + \\ const x = add(a, 7); + \\ var y = add(2, 0); + \\ y -= x; + \\ return y; + \\} + , ""); + } +} diff --git a/test/stage2/test.zig b/test/stage2/test.zig index 9a74e9ee09..6e25dc283b 100644 --- a/test/stage2/test.zig +++ b/test/stage2/test.zig @@ -31,6 +31,7 @@ pub fn addCases(ctx: *TestContext) !void { try @import("spu-ii.zig").addCases(ctx); try @import("arm.zig").addCases(ctx); try @import("aarch64.zig").addCases(ctx); + try @import("llvm_backend.zig").addCases(ctx); { var case = ctx.exe("hello world with updates", linux_x64);