| author | |
| committer | |
| log | f000f8a59a8bf1121ecbe9b60ae50cc0218d3ba3 |
| tree | f4578be5065b377c3c158562206311ed4d28f99d |
| parent | 5ff7b04a6ad72eb86b6d467dfdc25bea1a9ecf63 |
allow test cases to chose wether to link libc or not.
default behavior is to not link libc, except for `exeUsingLLVMBackend`4 files changed, 52 insertions(+), 42 deletions(-)
src/link/NvPtx.zig+16-17| ... | ... | @@ -25,8 +25,21 @@ base: link.File, |
| 25 | 25 | llvm_object: *LlvmObject, |
| 26 | 26 | |
| 27 | 27 | pub fn createEmpty(gpa: Allocator, options: link.Options) !*NvPtx { |
| 28 | if (!build_options.have_llvm) return error.TODOArchNotSupported; | |
| 28 | if (!build_options.have_llvm) return error.PtxArchNotSupported; | |
| 29 | if (!options.use_llvm) return error.PtxArchNotSupported; | |
| 29 | 30 | |
| 31 | switch (options.target.cpu.arch) { | |
| 32 | .nvptx, .nvptx64 => {}, | |
| 33 | else => return error.PtxArchNotSupported, | |
| 34 | } | |
| 35 | ||
| 36 | switch (options.target.os.tag) { | |
| 37 | // TODO: does it also work with nvcl ? | |
| 38 | .cuda => {}, | |
| 39 | else => return error.PtxArchNotSupported, | |
| 40 | } | |
| 41 | ||
| 42 | const llvm_object = try LlvmObject.create(gpa, options); | |
| 30 | 43 | const nvptx = try gpa.create(NvPtx); |
| 31 | 44 | nvptx.* = .{ |
| 32 | 45 | .base = .{ |
| ... | ... | @@ -35,32 +48,19 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*NvPtx { |
| 35 | 48 | .file = null, |
| 36 | 49 | .allocator = gpa, |
| 37 | 50 | }, |
| 38 | .llvm_object = undefined, | |
| 51 | .llvm_object = llvm_object, | |
| 39 | 52 | }; |
| 40 | 53 | |
| 41 | switch (options.target.cpu.arch) { | |
| 42 | .nvptx, .nvptx64 => {}, | |
| 43 | else => return error.TODOArchNotSupported, | |
| 44 | } | |
| 45 | ||
| 46 | switch (options.target.os.tag) { | |
| 47 | // TODO: does it also work with nvcl ? | |
| 48 | .cuda => {}, | |
| 49 | else => return error.TODOOsNotSupported, | |
| 50 | } | |
| 51 | ||
| 52 | 54 | return nvptx; |
| 53 | 55 | } |
| 54 | 56 | |
| 55 | 57 | pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Options) !*NvPtx { |
| 56 | 58 | if (!build_options.have_llvm) @panic("nvptx target requires a zig compiler with llvm enabled."); |
| 57 | if (!options.use_llvm) return error.TODOArchNotSupported; | |
| 59 | if (!options.use_llvm) return error.PtxArchNotSupported; | |
| 58 | 60 | assert(options.object_format == .nvptx); |
| 59 | 61 | |
| 60 | 62 | const nvptx = try createEmpty(allocator, options); |
| 61 | errdefer nvptx.base.destroy(); | |
| 62 | 63 | log.info("Opening .ptx target file {s}", .{sub_path}); |
| 63 | nvptx.llvm_object = try LlvmObject.create(allocator, options); | |
| 64 | 64 | return nvptx; |
| 65 | 65 | } |
| 66 | 66 | |
| ... | ... | @@ -117,6 +117,5 @@ pub fn flushModule(self: *NvPtx, comp: *Compilation) !void { |
| 117 | 117 | }; |
| 118 | 118 | hack_comp.bin_file.options.emit = null; |
| 119 | 119 | } |
| 120 | ||
| 121 | 120 | return try self.llvm_object.flushModule(hack_comp); |
| 122 | 121 | } |
src/test.zig+6-10| ... | ... | @@ -175,6 +175,7 @@ pub const TestContext = struct { |
| 175 | 175 | is_test: bool = false, |
| 176 | 176 | expect_exact: bool = false, |
| 177 | 177 | backend: Backend = .stage2, |
| 178 | link_libc: bool = false, | |
| 178 | 179 | |
| 179 | 180 | files: std.ArrayList(File), |
| 180 | 181 | |
| ... | ... | @@ -331,6 +332,7 @@ pub const TestContext = struct { |
| 331 | 332 | .output_mode = .Exe, |
| 332 | 333 | .files = std.ArrayList(File).init(ctx.cases.allocator), |
| 333 | 334 | .backend = .llvm, |
| 335 | .link_libc = true, | |
| 334 | 336 | }) catch @panic("out of memory"); |
| 335 | 337 | return &ctx.cases.items[ctx.cases.items.len - 1]; |
| 336 | 338 | } |
| ... | ... | @@ -888,11 +890,6 @@ pub const TestContext = struct { |
| 888 | 890 | .llvm => true, |
| 889 | 891 | else => null, |
| 890 | 892 | }; |
| 891 | const use_stage1: ?bool = switch (case.backend) { | |
| 892 | .stage1 => true, | |
| 893 | else => null, | |
| 894 | }; | |
| 895 | const link_libc = case.backend == .llvm; | |
| 896 | 893 | const comp = try Compilation.create(allocator, .{ |
| 897 | 894 | .local_cache_directory = zig_cache_directory, |
| 898 | 895 | .global_cache_directory = global_cache_directory, |
| ... | ... | @@ -914,9 +911,9 @@ pub const TestContext = struct { |
| 914 | 911 | .is_native_os = case.target.isNativeOs(), |
| 915 | 912 | .is_native_abi = case.target.isNativeAbi(), |
| 916 | 913 | .dynamic_linker = target_info.dynamic_linker.get(), |
| 917 | .link_libc = link_libc, | |
| 914 | .link_libc = case.link_libc, | |
| 918 | 915 | .use_llvm = use_llvm, |
| 919 | .use_stage1 = use_stage1, | |
| 916 | .use_stage1 = null, // We already handled stage1 tests | |
| 920 | 917 | .self_exe_path = std.testing.zig_exe_path, |
| 921 | 918 | }); |
| 922 | 919 | defer comp.destroy(); |
| ... | ... | @@ -1145,7 +1142,7 @@ pub const TestContext = struct { |
| 1145 | 1142 | "-lc", |
| 1146 | 1143 | exe_path, |
| 1147 | 1144 | }); |
| 1148 | } else switch (host.getExternalExecutor(target_info, .{ .link_libc = link_libc })) { | |
| 1145 | } else switch (host.getExternalExecutor(target_info, .{ .link_libc = case.link_libc })) { | |
| 1149 | 1146 | .native => try argv.append(exe_path), |
| 1150 | 1147 | .bad_dl, .bad_os_or_cpu => return, // Pass test. |
| 1151 | 1148 | |
| ... | ... | @@ -1156,8 +1153,7 @@ pub const TestContext = struct { |
| 1156 | 1153 | }, |
| 1157 | 1154 | |
| 1158 | 1155 | .qemu => |qemu_bin_name| if (enable_qemu) { |
| 1159 | // TODO Ability for test cases to specify whether to link libc. | |
| 1160 | const need_cross_glibc = false; // target.isGnuLibC() and self.is_linking_libc; | |
| 1156 | const need_cross_glibc = target.isGnuLibC() and case.link_libc; | |
| 1161 | 1157 | const glibc_dir_arg = if (need_cross_glibc) |
| 1162 | 1158 | glibc_runtimes_dir orelse return // glibc dir not available; pass test |
| 1163 | 1159 | else |
test/cases.zig+1-2| ... | ... | @@ -16,6 +16,5 @@ pub fn addCases(ctx: *TestContext) !void { |
| 16 | 16 | try @import("stage2/riscv64.zig").addCases(ctx); |
| 17 | 17 | try @import("stage2/plan9.zig").addCases(ctx); |
| 18 | 18 | try @import("stage2/x86_64.zig").addCases(ctx); |
| 19 | // TODO https://github.com/ziglang/zig/issues/10968 | |
| 20 | //try @import("stage2/nvptx.zig").addCases(ctx); | |
| 19 | try @import("stage2/nvptx.zig").addCases(ctx); | |
| 21 | 20 | } |
test/stage2/nvptx.zig+29-13| ... | ... | @@ -1,21 +1,16 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | 2 | const TestContext = @import("../../src/test.zig").TestContext; |
| 3 | 3 | |
| 4 | const nvptx = std.zig.CrossTarget{ | |
| 5 | .cpu_arch = .nvptx64, | |
| 6 | .os_tag = .cuda, | |
| 7 | }; | |
| 8 | ||
| 9 | 4 | pub fn addCases(ctx: *TestContext) !void { |
| 10 | 5 | { |
| 11 | var case = ctx.exeUsingLlvmBackend("simple addition and subtraction", nvptx); | |
| 6 | var case = addPtx(ctx, "nvptx: simple addition and subtraction"); | |
| 12 | 7 | |
| 13 | 8 | case.compiles( |
| 14 | 9 | \\fn add(a: i32, b: i32) i32 { |
| 15 | 10 | \\ return a + b; |
| 16 | 11 | \\} |
| 17 | 12 | \\ |
| 18 | \\pub export fn main(a: i32, out: *i32) callconv(.PtxKernel) void { | |
| 13 | \\pub export fn add_and_substract(a: i32, out: *i32) callconv(.PtxKernel) void { | |
| 19 | 14 | \\ const x = add(a, 7); |
| 20 | 15 | \\ var y = add(2, 0); |
| 21 | 16 | \\ y -= x; |
| ... | ... | @@ -25,28 +20,28 @@ pub fn addCases(ctx: *TestContext) !void { |
| 25 | 20 | } |
| 26 | 21 | |
| 27 | 22 | { |
| 28 | var case = ctx.exeUsingLlvmBackend("read special registers", nvptx); | |
| 23 | var case = addPtx(ctx, "nvptx: read special registers"); | |
| 29 | 24 | |
| 30 | 25 | case.compiles( |
| 31 | \\fn tid() usize { | |
| 26 | \\fn threadIdX() usize { | |
| 32 | 27 | \\ var tid = asm volatile ("mov.u32 \t$0, %tid.x;" |
| 33 | 28 | \\ : [ret] "=r" (-> u32), |
| 34 | 29 | \\ ); |
| 35 | 30 | \\ return @as(usize, tid); |
| 36 | 31 | \\} |
| 37 | 32 | \\ |
| 38 | \\pub export fn main(a: []const i32, out: []i32) callconv(.PtxKernel) void { | |
| 39 | \\ const i = tid(); | |
| 33 | \\pub export fn special_reg(a: []const i32, out: []i32) callconv(.PtxKernel) void { | |
| 34 | \\ const i = threadIdX(); | |
| 40 | 35 | \\ out[i] = a[i] + 7; |
| 41 | 36 | \\} |
| 42 | 37 | ); |
| 43 | 38 | } |
| 44 | 39 | |
| 45 | 40 | { |
| 46 | var case = ctx.exeUsingLlvmBackend("address spaces", nvptx); | |
| 41 | var case = addPtx(ctx, "nvptx: address spaces"); | |
| 47 | 42 | |
| 48 | 43 | case.compiles( |
| 49 | \\var x: u32 addrspace(.global) = 0; | |
| 44 | \\var x: i32 addrspace(.global) = 0; | |
| 50 | 45 | \\ |
| 51 | 46 | \\pub export fn increment(out: *i32) callconv(.PtxKernel) void { |
| 52 | 47 | \\ x += 1; |
| ... | ... | @@ -55,3 +50,24 @@ pub fn addCases(ctx: *TestContext) !void { |
| 55 | 50 | ); |
| 56 | 51 | } |
| 57 | 52 | } |
| 53 | ||
| 54 | const nvptx_target = std.zig.CrossTarget{ | |
| 55 | .cpu_arch = .nvptx64, | |
| 56 | .os_tag = .cuda, | |
| 57 | }; | |
| 58 | ||
| 59 | pub fn addPtx( | |
| 60 | ctx: *TestContext, | |
| 61 | name: []const u8, | |
| 62 | ) *TestContext.Case { | |
| 63 | ctx.cases.append(TestContext.Case{ | |
| 64 | .name = name, | |
| 65 | .target = nvptx_target, | |
| 66 | .updates = std.ArrayList(TestContext.Update).init(ctx.cases.allocator), | |
| 67 | .output_mode = .Obj, | |
| 68 | .files = std.ArrayList(TestContext.File).init(ctx.cases.allocator), | |
| 69 | .link_libc = false, | |
| 70 | .backend = .llvm, | |
| 71 | }) catch @panic("out of memory"); | |
| 72 | return &ctx.cases.items[ctx.cases.items.len - 1]; | |
| 73 | } |