diff --git a/lib/std/builtin.zig b/lib/std/builtin.zig index 869756fe5c70ad9eb68610c706096c8919a302d4..1d28e69d61729715dd08ab861182085868fa7531 100644 --- a/lib/std/builtin.zig +++ b/lib/std/builtin.zig @@ -160,8 +160,7 @@ pub const CallingConvention = enum { AAPCSVFP, SysV, Win64, - PtxKernel, - AmdgpuKernel, + Kernel, }; /// This data structure is used by the Zig language code generation and diff --git a/src/Sema.zig b/src/Sema.zig index c3c93452051aec18b4cfeb1a0420aadd30164869..e538334fcdc8021b888237ab74e207ad56bb74c5 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -8883,7 +8883,7 @@ fn funcCommon( }; return sema.failWithOwnedErrorMsg(msg); } - if (!ret_poison and !Type.fnCallingConventionAllowsZigTypes(cc_resolved) and !try sema.validateExternType(return_type, .ret_ty)) { + if (!ret_poison and !Type.fnCallingConventionAllowsZigTypes(target, cc_resolved) and !try sema.validateExternType(return_type, .ret_ty)) { const msg = msg: { const msg = try sema.errMsg(block, ret_ty_src, "return type '{}' not allowed in function with calling convention '{s}'", .{ return_type.fmt(sema.mod), @tagName(cc_resolved), @@ -8961,13 +8961,9 @@ fn funcCommon( .x86_64 => null, else => @as([]const u8, "x86_64"), }, - .PtxKernel => switch (arch) { - .nvptx, .nvptx64 => null, - else => @as([]const u8, "nvptx and nvptx64"), - }, - .AmdgpuKernel => switch (arch) { - .amdgcn => null, - else => @as([]const u8, "amdgcn"), + .Kernel => switch (arch) { + .nvptx, .nvptx64, .amdgcn, .spirv32, .spirv64 => null, + else => @as([]const u8, "nvptx, amdgcn and SPIR-V"), }, }) |allowed_platform| { return sema.fail(block, cc_src, "callconv '{s}' is only available on {s}, not {s}", .{ @@ -9093,10 +9089,11 @@ fn analyzeParameter( comptime_params[i] = param.is_comptime or requires_comptime; const this_generic = param.ty.tag() == .generic_poison; is_generic.* = is_generic.* or this_generic; - if (param.is_comptime and !Type.fnCallingConventionAllowsZigTypes(cc)) { + const target = sema.mod.getTarget(); + if (param.is_comptime and !Type.fnCallingConventionAllowsZigTypes(target, cc)) { return sema.fail(block, param_src, "comptime parameters not allowed in function with calling convention '{s}'", .{@tagName(cc)}); } - if (this_generic and !sema.no_partial_func_ty and !Type.fnCallingConventionAllowsZigTypes(cc)) { + if (this_generic and !sema.no_partial_func_ty and !Type.fnCallingConventionAllowsZigTypes(target, cc)) { return sema.fail(block, param_src, "generic parameters not allowed in function with calling convention '{s}'", .{@tagName(cc)}); } if (!param.ty.isValidParamType()) { @@ -9112,7 +9109,7 @@ fn analyzeParameter( }; return sema.failWithOwnedErrorMsg(msg); } - if (!this_generic and !Type.fnCallingConventionAllowsZigTypes(cc) and !try sema.validateExternType(param.ty, .param_ty)) { + if (!this_generic and !Type.fnCallingConventionAllowsZigTypes(target, cc) and !try sema.validateExternType(param.ty, .param_ty)) { const msg = msg: { const msg = try sema.errMsg(block, param_src, "parameter of type '{}' not allowed in function with calling convention '{s}'", .{ param.ty.fmt(sema.mod), @tagName(cc), @@ -22786,12 +22783,13 @@ fn validateExternType( }, .Fn => { if (position != .other) return false; - return switch (ty.fnCallingConvention()) { - // For now we want to authorize PTX kernel to use zig objects, even if we end up exposing the ABI. - // The goal is to experiment with more integrated CPU/GPU code. - .PtxKernel => true, - else => !Type.fnCallingConventionAllowsZigTypes(ty.fnCallingConvention()), - }; + const target = sema.mod.getTarget(); + // For now we want to authorize PTX kernel to use zig objects, even if we end up exposing the ABI. + // The goal is to experiment with more integrated CPU/GPU code. + if (ty.fnCallingConvention() == .Kernel and (target.cpu.arch == .nvptx or target.cpu.arch == .nvptx64)) { + return true; + } + return !Type.fnCallingConventionAllowsZigTypes(target, ty.fnCallingConvention()); }, .Enum => { var buf: Type.Payload.Bits = undefined; diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 233ec21ac18d084082f9c5c72894b0707a78770a..80c9f0d024cffd7566bc8c42345218b914c899e0 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -10350,11 +10350,8 @@ fn toLlvmCallConv(cc: std.builtin.CallingConvention, target: std.Target) llvm.Ca .Signal => .AVR_SIGNAL, .SysV => .X86_64_SysV, .Win64 => .Win64, - .PtxKernel => return switch (target.cpu.arch) { + .Kernel => return switch (target.cpu.arch) { .nvptx, .nvptx64 => .PTX_Kernel, - else => unreachable, - }, - .AmdgpuKernel => return switch (target.cpu.arch) { .amdgcn => .AMDGPU_KERNEL, else => unreachable, }, diff --git a/src/link/NvPtx.zig b/src/link/NvPtx.zig index 4c6c6fd8bec695da074fab90ed9d193e9f69c258..c542241cd91597a15bf4fd8d52487acc9a500857 100644 --- a/src/link/NvPtx.zig +++ b/src/link/NvPtx.zig @@ -1,7 +1,7 @@ //! NVidia PTX (Paralle Thread Execution) //! https://docs.nvidia.com/cuda/parallel-thread-execution/index.html //! For this we rely on the nvptx backend of LLVM -//! Kernel functions need to be marked both as "export" and "callconv(.PtxKernel)" +//! Kernel functions need to be marked both as "export" and "callconv(.Kernel)" const NvPtx = @This(); diff --git a/src/type.zig b/src/type.zig index 15525f14ebe7dd97e0efdb8837874f4a447fb015..9f1905b1ad94201fccea71611c366e5343f6bb5a 100644 --- a/src/type.zig +++ b/src/type.zig @@ -4796,9 +4796,12 @@ pub const Type = extern union { } /// Asserts the type is a function. - pub fn fnCallingConventionAllowsZigTypes(cc: std.builtin.CallingConvention) bool { + pub fn fnCallingConventionAllowsZigTypes(target: Target, cc: std.builtin.CallingConvention) bool { return switch (cc) { - .Unspecified, .Async, .Inline, .PtxKernel => true, + .Unspecified, .Async, .Inline => true, + // For now we want to authorize PTX kernel to use zig objects, even if we end up exposing the ABI. + // The goal is to experiment with more integrated CPU/GPU code. + .Kernel => target.cpu.arch == .nvptx or target.cpu.arch == .nvptx64, else => false, }; } diff --git a/test/nvptx.zig b/test/nvptx.zig index 57853a657dc941a686209c7079d4bc493f8d29e7..0bdc9455f76ddb28bc08686fc85b48611eff1ac6 100644 --- a/test/nvptx.zig +++ b/test/nvptx.zig @@ -10,7 +10,7 @@ pub fn addCases(ctx: *Cases) !void { \\ return a + b; \\} \\ - \\pub export fn add_and_substract(a: i32, out: *i32) callconv(.PtxKernel) void { + \\pub export fn add_and_substract(a: i32, out: *i32) callconv(.Kernel) void { \\ const x = add(a, 7); \\ var y = add(2, 0); \\ y -= x; @@ -29,7 +29,7 @@ pub fn addCases(ctx: *Cases) !void { \\ ); \\} \\ - \\pub export fn special_reg(a: []const i32, out: []i32) callconv(.PtxKernel) void { + \\pub export fn special_reg(a: []const i32, out: []i32) callconv(.Kernel) void { \\ const i = threadIdX(); \\ out[i] = a[i] + 7; \\} @@ -42,7 +42,7 @@ pub fn addCases(ctx: *Cases) !void { case.addCompile( \\var x: i32 addrspace(.global) = 0; \\ - \\pub export fn increment(out: *i32) callconv(.PtxKernel) void { + \\pub export fn increment(out: *i32) callconv(.Kernel) void { \\ x += 1; \\ out.* = x; \\} @@ -59,7 +59,7 @@ pub fn addCases(ctx: *Cases) !void { \\} \\ \\ var _sdata: [1024]f32 addrspace(.shared) = undefined; - \\ pub export fn reduceSum(d_x: []const f32, out: *f32) callconv(.PtxKernel) void { + \\ pub export fn reduceSum(d_x: []const f32, out: *f32) callconv(.Kernel) void { \\ var sdata = @addrSpaceCast(.generic, &_sdata); \\ const tid: u32 = threadIdX(); \\ var sum = d_x[tid];