| 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,8 +25,21 @@ base: link.File, |
| 25 | llvm_object: *LlvmObject, | 25 | llvm_object: *LlvmObject, |
| 26 | 26 | ||
| 27 | pub fn createEmpty(gpa: Allocator, options: link.Options) !*NvPtx { | 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 | const nvptx = try gpa.create(NvPtx); | 43 | const nvptx = try gpa.create(NvPtx); |
| 31 | nvptx.* = .{ | 44 | nvptx.* = .{ |
| 32 | .base = .{ | 45 | .base = .{ |
| ... | @@ -35,32 +48,19 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*NvPtx { | ... | @@ -35,32 +48,19 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*NvPtx { |
| 35 | .file = null, | 48 | .file = null, |
| 36 | .allocator = gpa, | 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 | return nvptx; | 54 | return nvptx; |
| 53 | } | 55 | } |
| 54 | 56 | ||
| 55 | pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Options) !*NvPtx { | 57 | pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Options) !*NvPtx { |
| 56 | if (!build_options.have_llvm) @panic("nvptx target requires a zig compiler with llvm enabled."); | 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 | assert(options.object_format == .nvptx); | 60 | assert(options.object_format == .nvptx); |
| 59 | 61 | ||
| 60 | const nvptx = try createEmpty(allocator, options); | 62 | const nvptx = try createEmpty(allocator, options); |
| 61 | errdefer nvptx.base.destroy(); | ||
| 62 | log.info("Opening .ptx target file {s}", .{sub_path}); | 63 | log.info("Opening .ptx target file {s}", .{sub_path}); |
| 63 | nvptx.llvm_object = try LlvmObject.create(allocator, options); | ||
| 64 | return nvptx; | 64 | return nvptx; |
| 65 | } | 65 | } |
| 66 | 66 | ||
| ... | @@ -117,6 +117,5 @@ pub fn flushModule(self: *NvPtx, comp: *Compilation) !void { | ... | @@ -117,6 +117,5 @@ pub fn flushModule(self: *NvPtx, comp: *Compilation) !void { |
| 117 | }; | 117 | }; |
| 118 | hack_comp.bin_file.options.emit = null; | 118 | hack_comp.bin_file.options.emit = null; |
| 119 | } | 119 | } |
| 120 | |||
| 121 | return try self.llvm_object.flushModule(hack_comp); | 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,6 +175,7 @@ pub const TestContext = struct { |
| 175 | is_test: bool = false, | 175 | is_test: bool = false, |
| 176 | expect_exact: bool = false, | 176 | expect_exact: bool = false, |
| 177 | backend: Backend = .stage2, | 177 | backend: Backend = .stage2, |
| 178 | link_libc: bool = false, | ||
| 178 | 179 | ||
| 179 | files: std.ArrayList(File), | 180 | files: std.ArrayList(File), |
| 180 | 181 | ||
| ... | @@ -331,6 +332,7 @@ pub const TestContext = struct { | ... | @@ -331,6 +332,7 @@ pub const TestContext = struct { |
| 331 | .output_mode = .Exe, | 332 | .output_mode = .Exe, |
| 332 | .files = std.ArrayList(File).init(ctx.cases.allocator), | 333 | .files = std.ArrayList(File).init(ctx.cases.allocator), |
| 333 | .backend = .llvm, | 334 | .backend = .llvm, |
| 335 | .link_libc = true, | ||
| 334 | }) catch @panic("out of memory"); | 336 | }) catch @panic("out of memory"); |
| 335 | return &ctx.cases.items[ctx.cases.items.len - 1]; | 337 | return &ctx.cases.items[ctx.cases.items.len - 1]; |
| 336 | } | 338 | } |
| ... | @@ -888,11 +890,6 @@ pub const TestContext = struct { | ... | @@ -888,11 +890,6 @@ pub const TestContext = struct { |
| 888 | .llvm => true, | 890 | .llvm => true, |
| 889 | else => null, | 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 | const comp = try Compilation.create(allocator, .{ | 893 | const comp = try Compilation.create(allocator, .{ |
| 897 | .local_cache_directory = zig_cache_directory, | 894 | .local_cache_directory = zig_cache_directory, |
| 898 | .global_cache_directory = global_cache_directory, | 895 | .global_cache_directory = global_cache_directory, |
| ... | @@ -914,9 +911,9 @@ pub const TestContext = struct { | ... | @@ -914,9 +911,9 @@ pub const TestContext = struct { |
| 914 | .is_native_os = case.target.isNativeOs(), | 911 | .is_native_os = case.target.isNativeOs(), |
| 915 | .is_native_abi = case.target.isNativeAbi(), | 912 | .is_native_abi = case.target.isNativeAbi(), |
| 916 | .dynamic_linker = target_info.dynamic_linker.get(), | 913 | .dynamic_linker = target_info.dynamic_linker.get(), |
| 917 | .link_libc = link_libc, | 914 | .link_libc = case.link_libc, |
| 918 | .use_llvm = use_llvm, | 915 | .use_llvm = use_llvm, |
| 919 | .use_stage1 = use_stage1, | 916 | .use_stage1 = null, // We already handled stage1 tests |
| 920 | .self_exe_path = std.testing.zig_exe_path, | 917 | .self_exe_path = std.testing.zig_exe_path, |
| 921 | }); | 918 | }); |
| 922 | defer comp.destroy(); | 919 | defer comp.destroy(); |
| ... | @@ -1145,7 +1142,7 @@ pub const TestContext = struct { | ... | @@ -1145,7 +1142,7 @@ pub const TestContext = struct { |
| 1145 | "-lc", | 1142 | "-lc", |
| 1146 | exe_path, | 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 | .native => try argv.append(exe_path), | 1146 | .native => try argv.append(exe_path), |
| 1150 | .bad_dl, .bad_os_or_cpu => return, // Pass test. | 1147 | .bad_dl, .bad_os_or_cpu => return, // Pass test. |
| 1151 | 1148 | ||
| ... | @@ -1156,8 +1153,7 @@ pub const TestContext = struct { | ... | @@ -1156,8 +1153,7 @@ pub const TestContext = struct { |
| 1156 | }, | 1153 | }, |
| 1157 | 1154 | ||
| 1158 | .qemu => |qemu_bin_name| if (enable_qemu) { | 1155 | .qemu => |qemu_bin_name| if (enable_qemu) { |
| 1159 | // TODO Ability for test cases to specify whether to link libc. | 1156 | const need_cross_glibc = target.isGnuLibC() and case.link_libc; |
| 1160 | const need_cross_glibc = false; // target.isGnuLibC() and self.is_linking_libc; | ||
| 1161 | const glibc_dir_arg = if (need_cross_glibc) | 1157 | const glibc_dir_arg = if (need_cross_glibc) |
| 1162 | glibc_runtimes_dir orelse return // glibc dir not available; pass test | 1158 | glibc_runtimes_dir orelse return // glibc dir not available; pass test |
| 1163 | else | 1159 | else |
test/cases.zig+1-2| ... | @@ -16,6 +16,5 @@ pub fn addCases(ctx: *TestContext) !void { | ... | @@ -16,6 +16,5 @@ pub fn addCases(ctx: *TestContext) !void { |
| 16 | try @import("stage2/riscv64.zig").addCases(ctx); | 16 | try @import("stage2/riscv64.zig").addCases(ctx); |
| 17 | try @import("stage2/plan9.zig").addCases(ctx); | 17 | try @import("stage2/plan9.zig").addCases(ctx); |
| 18 | try @import("stage2/x86_64.zig").addCases(ctx); | 18 | try @import("stage2/x86_64.zig").addCases(ctx); |
| 19 | // TODO https://github.com/ziglang/zig/issues/10968 | 19 | try @import("stage2/nvptx.zig").addCases(ctx); |
| 20 | //try @import("stage2/nvptx.zig").addCases(ctx); | ||
| 21 | } | 20 | } |
test/stage2/nvptx.zig+29-13| ... | @@ -1,21 +1,16 @@ | ... | @@ -1,21 +1,16 @@ |
| 1 | const std = @import("std"); | 1 | const std = @import("std"); |
| 2 | const TestContext = @import("../../src/test.zig").TestContext; | 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 | pub fn addCases(ctx: *TestContext) !void { | 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 | case.compiles( | 8 | case.compiles( |
| 14 | \\fn add(a: i32, b: i32) i32 { | 9 | \\fn add(a: i32, b: i32) i32 { |
| 15 | \\ return a + b; | 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 | \\ const x = add(a, 7); | 14 | \\ const x = add(a, 7); |
| 20 | \\ var y = add(2, 0); | 15 | \\ var y = add(2, 0); |
| 21 | \\ y -= x; | 16 | \\ y -= x; |
| ... | @@ -25,28 +20,28 @@ pub fn addCases(ctx: *TestContext) !void { | ... | @@ -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 | case.compiles( | 25 | case.compiles( |
| 31 | \\fn tid() usize { | 26 | \\fn threadIdX() usize { |
| 32 | \\ var tid = asm volatile ("mov.u32 \t$0, %tid.x;" | 27 | \\ var tid = asm volatile ("mov.u32 \t$0, %tid.x;" |
| 33 | \\ : [ret] "=r" (-> u32), | 28 | \\ : [ret] "=r" (-> u32), |
| 34 | \\ ); | 29 | \\ ); |
| 35 | \\ return @as(usize, tid); | 30 | \\ return @as(usize, tid); |
| 36 | \\} | 31 | \\} |
| 37 | \\ | 32 | \\ |
| 38 | \\pub export fn main(a: []const i32, out: []i32) callconv(.PtxKernel) void { | 33 | \\pub export fn special_reg(a: []const i32, out: []i32) callconv(.PtxKernel) void { |
| 39 | \\ const i = tid(); | 34 | \\ const i = threadIdX(); |
| 40 | \\ out[i] = a[i] + 7; | 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 | case.compiles( | 43 | case.compiles( |
| 49 | \\var x: u32 addrspace(.global) = 0; | 44 | \\var x: i32 addrspace(.global) = 0; |
| 50 | \\ | 45 | \\ |
| 51 | \\pub export fn increment(out: *i32) callconv(.PtxKernel) void { | 46 | \\pub export fn increment(out: *i32) callconv(.PtxKernel) void { |
| 52 | \\ x += 1; | 47 | \\ x += 1; |
| ... | @@ -55,3 +50,24 @@ pub fn addCases(ctx: *TestContext) !void { | ... | @@ -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 | } |