| author | |
| committer | |
| log | 628e9e6d040979bd0a2cba05e854014dee5a7d55 |
| tree | b2d86569b54d792808b608402cc9d1ea8ec7d161 |
| parent | d8da9a01fcfebf14a9f262cabf36f1c0767d2e2b |
| signature |
5 files changed, 78 insertions(+), 1 deletions(-)
lib/std/builtin.zig+6| ... | @@ -157,6 +157,12 @@ pub const AddressSpace = enum { | ... | @@ -157,6 +157,12 @@ pub const AddressSpace = enum { |
| 157 | gs, | 157 | gs, |
| 158 | fs, | 158 | fs, |
| 159 | ss, | 159 | ss, |
| 160 | // GPU address spaces | ||
| 161 | global, | ||
| 162 | constant, | ||
| 163 | param, | ||
| 164 | shared, | ||
| 165 | local, | ||
| 160 | }; | 166 | }; |
| 161 | 167 | ||
| 162 | /// This data structure is used by the Zig language code generation and | 168 | /// This data structure is used by the Zig language code generation and |
src/Sema.zig+4-1| ... | @@ -18006,10 +18006,14 @@ pub fn analyzeAddrspace( | ... | @@ -18006,10 +18006,14 @@ pub fn analyzeAddrspace( |
| 18006 | const address_space = addrspace_tv.val.toEnum(std.builtin.AddressSpace); | 18006 | const address_space = addrspace_tv.val.toEnum(std.builtin.AddressSpace); |
| 18007 | const target = sema.mod.getTarget(); | 18007 | const target = sema.mod.getTarget(); |
| 18008 | const arch = target.cpu.arch; | 18008 | const arch = target.cpu.arch; |
| 18009 | const is_gpu = arch == .nvptx or arch == .nvptx64; | ||
| 18009 | 18010 | ||
| 18010 | const supported = switch (address_space) { | 18011 | const supported = switch (address_space) { |
| 18011 | .generic => true, | 18012 | .generic => true, |
| 18012 | .gs, .fs, .ss => (arch == .i386 or arch == .x86_64) and ctx == .pointer, | 18013 | .gs, .fs, .ss => (arch == .i386 or arch == .x86_64) and ctx == .pointer, |
| 18014 | // TODO: check that .shared and .local are left uninitialized | ||
| 18015 | .global, .param, .shared, .local => is_gpu, | ||
| 18016 | .constant => is_gpu and (ctx == .constant), | ||
| 18013 | }; | 18017 | }; |
| 18014 | 18018 | ||
| 18015 | if (!supported) { | 18019 | if (!supported) { |
| ... | @@ -18020,7 +18024,6 @@ pub fn analyzeAddrspace( | ... | @@ -18020,7 +18024,6 @@ pub fn analyzeAddrspace( |
| 18020 | .constant => "constant values", | 18024 | .constant => "constant values", |
| 18021 | .pointer => "pointers", | 18025 | .pointer => "pointers", |
| 18022 | }; | 18026 | }; |
| 18023 | |||
| 18024 | return sema.fail( | 18027 | return sema.fail( |
| 18025 | block, | 18028 | block, |
| 18026 | src, | 18029 | src, |
src/codegen/llvm.zig+10| ... | @@ -801,6 +801,16 @@ pub const DeclGen = struct { | ... | @@ -801,6 +801,16 @@ pub const DeclGen = struct { |
| 801 | .gs => llvm.address_space.x86.gs, | 801 | .gs => llvm.address_space.x86.gs, |
| 802 | .fs => llvm.address_space.x86.fs, | 802 | .fs => llvm.address_space.x86.fs, |
| 803 | .ss => llvm.address_space.x86.ss, | 803 | .ss => llvm.address_space.x86.ss, |
| 804 | else => unreachable, | ||
| 805 | }, | ||
| 806 | .nvptx, .nvptx64 => switch (address_space) { | ||
| 807 | .generic => llvm.address_space.default, | ||
| 808 | .global => llvm.address_space.nvptx.global, | ||
| 809 | .constant => llvm.address_space.nvptx.constant, | ||
| 810 | .param => llvm.address_space.nvptx.param, | ||
| 811 | .shared => llvm.address_space.nvptx.shared, | ||
| 812 | .local => llvm.address_space.nvptx.local, | ||
| 813 | else => unreachable, | ||
| 804 | }, | 814 | }, |
| 805 | else => switch (address_space) { | 815 | else => switch (address_space) { |
| 806 | .generic => llvm.address_space.default, | 816 | .generic => llvm.address_space.default, |
test/cases.zig+1| ... | @@ -16,4 +16,5 @@ pub fn addCases(ctx: *TestContext) !void { | ... | @@ -16,4 +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 | try @import("stage2/nvptx.zig").addCases(ctx); | ||
| 19 | } | 20 | } |
test/stage2/nvptx.zig created+57| ... | @@ -0,0 +1,57 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const TestContext = @import("../../src/test.zig").TestContext; | ||
| 3 | |||
| 4 | const nvptx = std.zig.CrossTarget{ | ||
| 5 | .cpu_arch = .nvptx64, | ||
| 6 | .os_tag = .cuda, | ||
| 7 | }; | ||
| 8 | |||
| 9 | pub fn addCases(ctx: *TestContext) !void { | ||
| 10 | { | ||
| 11 | var case = ctx.exeUsingLlvmBackend("simple addition and subtraction", nvptx); | ||
| 12 | |||
| 13 | case.compiles( | ||
| 14 | \\fn add(a: i32, b: i32) i32 { | ||
| 15 | \\ return a + b; | ||
| 16 | \\} | ||
| 17 | \\ | ||
| 18 | \\pub export fn main(a: i32, out: *i32) callconv(.PtxKernel) void { | ||
| 19 | \\ const x = add(a, 7); | ||
| 20 | \\ var y = add(2, 0); | ||
| 21 | \\ y -= x; | ||
| 22 | \\ out.* = y; | ||
| 23 | \\} | ||
| 24 | ); | ||
| 25 | } | ||
| 26 | |||
| 27 | { | ||
| 28 | var case = ctx.exeUsingLlvmBackend("read special registers", nvptx); | ||
| 29 | |||
| 30 | case.compiles( | ||
| 31 | \\fn tid() usize { | ||
| 32 | \\ var tid = asm volatile ("mov.u32 \t$0, %tid.x;" | ||
| 33 | \\ : [ret] "=r" (-> u32), | ||
| 34 | \\ ); | ||
| 35 | \\ return @as(usize, tid); | ||
| 36 | \\} | ||
| 37 | \\ | ||
| 38 | \\pub export fn main(a: []const i32, out: []i32) callconv(.PtxKernel) void { | ||
| 39 | \\ const i = tid(); | ||
| 40 | \\ out[i] = a[i] + 7; | ||
| 41 | \\} | ||
| 42 | ); | ||
| 43 | } | ||
| 44 | |||
| 45 | { | ||
| 46 | var case = ctx.exeUsingLlvmBackend("address spaces", nvptx); | ||
| 47 | |||
| 48 | case.compiles( | ||
| 49 | \\var x: u32 addrspace(.global) = 0; | ||
| 50 | \\ | ||
| 51 | \\pub export fn increment(out: *i32) callconv(.PtxKernel) void { | ||
| 52 | \\ x += 1; | ||
| 53 | \\ out.* = x; | ||
| 54 | \\} | ||
| 55 | ); | ||
| 56 | } | ||
| 57 | } | ||