From 00481668671a8719627922a05a1c143f9d0409ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20R=C3=B8nne=20Petersen?= Date: Fri, 24 Jan 2025 01:58:31 +0100 Subject: [PATCH] std.Target: Make Cpu.Arch.supportsAddressSpace() take an optional context. Allows deduplicating the code in Sema. --- lib/std/Target.zig | 16 +++++++++++---- lib/std/builtin.zig | 15 ++++++++++++++ src/Sema.zig | 48 ++++----------------------------------------- src/target.zig | 6 +++--- 4 files changed, 34 insertions(+), 51 deletions(-) diff --git a/lib/std/Target.zig b/lib/std/Target.zig index be147f1e29..7eb17b1297 100644 --- a/lib/std/Target.zig +++ b/lib/std/Target.zig @@ -1576,15 +1576,23 @@ pub const Cpu = struct { }; } - /// Returns whether this architecture supports the address space - pub fn supportsAddressSpace(arch: Arch, address_space: std.builtin.AddressSpace) bool { + /// Returns whether this architecture supports `address_space`. If `context` is `null`, this + /// function simply answers the general question of whether the architecture has any concept + /// of `address_space`; if non-`null`, the function additionally checks whether + /// `address_space` is valid in that context. + pub fn supportsAddressSpace( + arch: Arch, + address_space: std.builtin.AddressSpace, + context: ?std.builtin.AddressSpace.Context, + ) bool { const is_nvptx = arch.isNvptx(); const is_spirv = arch.isSpirV(); const is_gpu = is_nvptx or is_spirv or arch == .amdgcn; return switch (address_space) { .generic => true, - .fs, .gs, .ss => arch == .x86_64 or arch == .x86, - .global, .constant, .local, .shared => is_gpu, + .fs, .gs, .ss => (arch == .x86_64 or arch == .x86) and (context == null or context == .pointer), + .global, .local, .shared => is_gpu, + .constant => is_gpu and (context == null or context == .constant), .param => is_nvptx, .input, .output, .uniform, .push_constant, .storage_buffer => is_spirv, // TODO this should also check how many flash banks the cpu has diff --git a/lib/std/builtin.zig b/lib/std/builtin.zig index dfa8862456..19570c28b6 100644 --- a/lib/std/builtin.zig +++ b/lib/std/builtin.zig @@ -491,6 +491,21 @@ pub const CallingConvention = union(enum(u8)) { /// This data structure is used by the Zig language code generation and /// therefore must be kept in sync with the compiler implementation. pub const AddressSpace = enum(u5) { + /// The places where a user can specify an address space attribute + pub const Context = enum { + /// A function is specified to be placed in a certain address space. + function, + /// A (global) variable is specified to be placed in a certain address space. + /// In contrast to .constant, these values (and thus the address space they will be + /// placed in) are required to be mutable. + variable, + /// A (global) constant value is specified to be placed in a certain address space. + /// In contrast to .variable, values placed in this address space are not required to be mutable. + constant, + /// A pointer is ascripted to point into a certain address space. + pointer, + }; + // CPU address spaces. generic, gs, diff --git a/src/Sema.zig b/src/Sema.zig index f6793edb9e..1fbec0ecc4 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -37220,30 +37220,12 @@ fn analyzeComptimeAlloc( } }))); } -/// The places where a user can specify an address space attribute -pub const AddressSpaceContext = enum { - /// A function is specified to be placed in a certain address space. - function, - - /// A (global) variable is specified to be placed in a certain address space. - /// In contrast to .constant, these values (and thus the address space they will be - /// placed in) are required to be mutable. - variable, - - /// A (global) constant value is specified to be placed in a certain address space. - /// In contrast to .variable, values placed in this address space are not required to be mutable. - constant, - - /// A pointer is ascripted to point into a certain address space. - pointer, -}; - fn resolveAddressSpace( sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref, - ctx: AddressSpaceContext, + ctx: std.builtin.AddressSpace.Context, ) !std.builtin.AddressSpace { const air_ref = try sema.resolveInst(zir_ref); return sema.analyzeAsAddressSpace(block, src, air_ref, ctx); @@ -37254,7 +37236,7 @@ pub fn analyzeAsAddressSpace( block: *Block, src: LazySrcLoc, air_ref: Air.Inst.Ref, - ctx: AddressSpaceContext, + ctx: std.builtin.AddressSpace.Context, ) !std.builtin.AddressSpace { const pt = sema.pt; const addrspace_ty = try sema.getBuiltinType(src, .AddressSpace); @@ -37264,29 +37246,7 @@ pub fn analyzeAsAddressSpace( const target = pt.zcu.getTarget(); const arch = target.cpu.arch; - const is_nv = arch.isNvptx(); - const is_amd = arch == .amdgcn; - const is_spirv = arch.isSpirV(); - const is_gpu = is_nv or is_amd or is_spirv; - - // TODO: Deduplicate with `std.Target.Cpu.Arch.supportsAddressSpace`. - const supported = switch (address_space) { - // TODO: on spir-v only when os is opencl. - .generic => true, - .gs, .fs, .ss => (arch == .x86 or arch == .x86_64) and ctx == .pointer, - // TODO: check that .shared and .local are left uninitialized - .param => is_nv, - .input, .output, .uniform, .push_constant, .storage_buffer => is_spirv, - .global, .shared, .local => is_gpu, - .constant => is_gpu and (ctx == .constant), - // TODO this should also check how many flash banks the cpu has - .flash, .flash1, .flash2, .flash3, .flash4, .flash5 => arch == .avr, - - .cog, .hub => arch == .propeller, - .lut => arch == .propeller and std.Target.propeller.featureSetHas(target.cpu.features, .p2), - }; - - if (!supported) { + if (!arch.supportsAddressSpace(address_space, ctx)) { // TODO error messages could be made more elaborate here const entity = switch (ctx) { .function => "functions", @@ -38728,7 +38688,7 @@ pub fn resolveNavPtrModifiers( }; const @"addrspace": std.builtin.AddressSpace = as: { - const addrspace_ctx: Sema.AddressSpaceContext = switch (zir_decl.kind) { + const addrspace_ctx: std.builtin.AddressSpace.Context = switch (zir_decl.kind) { .@"var" => .variable, else => switch (nav_ty.zigTypeTag(zcu)) { .@"fn" => .function, diff --git a/src/target.zig b/src/target.zig index d978757bc9..ed28657e20 100644 --- a/src/target.zig +++ b/src/target.zig @@ -444,10 +444,10 @@ pub fn addrSpaceCastIsValid( ) bool { const arch = target.cpu.arch; switch (arch) { - .x86_64, .x86 => return arch.supportsAddressSpace(from) and arch.supportsAddressSpace(to), + .x86_64, .x86 => return arch.supportsAddressSpace(from, null) and arch.supportsAddressSpace(to, null), .nvptx64, .nvptx, .amdgcn => { - const to_generic = arch.supportsAddressSpace(from) and to == .generic; - const from_generic = arch.supportsAddressSpace(to) and from == .generic; + const to_generic = arch.supportsAddressSpace(from, null) and to == .generic; + const from_generic = arch.supportsAddressSpace(to, null) and from == .generic; return to_generic or from_generic; }, else => return from == .generic and to == .generic,