authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2025-01-24 01:58:31+01:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2025-02-17 19:17:56+01:00
log00481668671a8719627922a05a1c143f9d0409ed
treec4433588297c002fe6424bacb48f2b6c15e10a48
parentaa4ac2f85fc145dafcd4de18065bdfa28f17cea0
signaturebadge-check Signed by SSH key SHA256:7B/LJ7bpR1eX8aCXSr4mtd5M45VMPKcx9zY8e95b5QM

std.Target: Make Cpu.Arch.supportsAddressSpace() take an optional context.

Allows deduplicating the code in Sema.

4 files changed, 34 insertions(+), 51 deletions(-)

lib/std/Target.zig+12-4
......@@ -1576,15 +1576,23 @@ pub const Cpu = struct {
15761576 };
15771577 }
15781578
1579 /// Returns whether this architecture supports the address space
1580 pub fn supportsAddressSpace(arch: Arch, address_space: std.builtin.AddressSpace) bool {
1579 /// Returns whether this architecture supports `address_space`. If `context` is `null`, this
1580 /// function simply answers the general question of whether the architecture has any concept
1581 /// of `address_space`; if non-`null`, the function additionally checks whether
1582 /// `address_space` is valid in that context.
1583 pub fn supportsAddressSpace(
1584 arch: Arch,
1585 address_space: std.builtin.AddressSpace,
1586 context: ?std.builtin.AddressSpace.Context,
1587 ) bool {
15811588 const is_nvptx = arch.isNvptx();
15821589 const is_spirv = arch.isSpirV();
15831590 const is_gpu = is_nvptx or is_spirv or arch == .amdgcn;
15841591 return switch (address_space) {
15851592 .generic => true,
1586 .fs, .gs, .ss => arch == .x86_64 or arch == .x86,
1587 .global, .constant, .local, .shared => is_gpu,
1593 .fs, .gs, .ss => (arch == .x86_64 or arch == .x86) and (context == null or context == .pointer),
1594 .global, .local, .shared => is_gpu,
1595 .constant => is_gpu and (context == null or context == .constant),
15881596 .param => is_nvptx,
15891597 .input, .output, .uniform, .push_constant, .storage_buffer => is_spirv,
15901598 // TODO this should also check how many flash banks the cpu has
lib/std/builtin.zig+15
......@@ -491,6 +491,21 @@ pub const CallingConvention = union(enum(u8)) {
491491/// This data structure is used by the Zig language code generation and
492492/// therefore must be kept in sync with the compiler implementation.
493493pub const AddressSpace = enum(u5) {
494 /// The places where a user can specify an address space attribute
495 pub const Context = enum {
496 /// A function is specified to be placed in a certain address space.
497 function,
498 /// A (global) variable is specified to be placed in a certain address space.
499 /// In contrast to .constant, these values (and thus the address space they will be
500 /// placed in) are required to be mutable.
501 variable,
502 /// A (global) constant value is specified to be placed in a certain address space.
503 /// In contrast to .variable, values placed in this address space are not required to be mutable.
504 constant,
505 /// A pointer is ascripted to point into a certain address space.
506 pointer,
507 };
508
494509 // CPU address spaces.
495510 generic,
496511 gs,
src/Sema.zig+4-44
......@@ -37220,30 +37220,12 @@ fn analyzeComptimeAlloc(
3722037220 } })));
3722137221}
3722237222
37223/// The places where a user can specify an address space attribute
37224pub const AddressSpaceContext = enum {
37225 /// A function is specified to be placed in a certain address space.
37226 function,
37227
37228 /// A (global) variable is specified to be placed in a certain address space.
37229 /// In contrast to .constant, these values (and thus the address space they will be
37230 /// placed in) are required to be mutable.
37231 variable,
37232
37233 /// A (global) constant value is specified to be placed in a certain address space.
37234 /// In contrast to .variable, values placed in this address space are not required to be mutable.
37235 constant,
37236
37237 /// A pointer is ascripted to point into a certain address space.
37238 pointer,
37239};
37240
3724137223fn resolveAddressSpace(
3724237224 sema: *Sema,
3724337225 block: *Block,
3724437226 src: LazySrcLoc,
3724537227 zir_ref: Zir.Inst.Ref,
37246 ctx: AddressSpaceContext,
37228 ctx: std.builtin.AddressSpace.Context,
3724737229) !std.builtin.AddressSpace {
3724837230 const air_ref = try sema.resolveInst(zir_ref);
3724937231 return sema.analyzeAsAddressSpace(block, src, air_ref, ctx);
......@@ -37254,7 +37236,7 @@ pub fn analyzeAsAddressSpace(
3725437236 block: *Block,
3725537237 src: LazySrcLoc,
3725637238 air_ref: Air.Inst.Ref,
37257 ctx: AddressSpaceContext,
37239 ctx: std.builtin.AddressSpace.Context,
3725837240) !std.builtin.AddressSpace {
3725937241 const pt = sema.pt;
3726037242 const addrspace_ty = try sema.getBuiltinType(src, .AddressSpace);
......@@ -37264,29 +37246,7 @@ pub fn analyzeAsAddressSpace(
3726437246 const target = pt.zcu.getTarget();
3726537247 const arch = target.cpu.arch;
3726637248
37267 const is_nv = arch.isNvptx();
37268 const is_amd = arch == .amdgcn;
37269 const is_spirv = arch.isSpirV();
37270 const is_gpu = is_nv or is_amd or is_spirv;
37271
37272 // TODO: Deduplicate with `std.Target.Cpu.Arch.supportsAddressSpace`.
37273 const supported = switch (address_space) {
37274 // TODO: on spir-v only when os is opencl.
37275 .generic => true,
37276 .gs, .fs, .ss => (arch == .x86 or arch == .x86_64) and ctx == .pointer,
37277 // TODO: check that .shared and .local are left uninitialized
37278 .param => is_nv,
37279 .input, .output, .uniform, .push_constant, .storage_buffer => is_spirv,
37280 .global, .shared, .local => is_gpu,
37281 .constant => is_gpu and (ctx == .constant),
37282 // TODO this should also check how many flash banks the cpu has
37283 .flash, .flash1, .flash2, .flash3, .flash4, .flash5 => arch == .avr,
37284
37285 .cog, .hub => arch == .propeller,
37286 .lut => arch == .propeller and std.Target.propeller.featureSetHas(target.cpu.features, .p2),
37287 };
37288
37289 if (!supported) {
37249 if (!arch.supportsAddressSpace(address_space, ctx)) {
3729037250 // TODO error messages could be made more elaborate here
3729137251 const entity = switch (ctx) {
3729237252 .function => "functions",
......@@ -38728,7 +38688,7 @@ pub fn resolveNavPtrModifiers(
3872838688 };
3872938689
3873038690 const @"addrspace": std.builtin.AddressSpace = as: {
38731 const addrspace_ctx: Sema.AddressSpaceContext = switch (zir_decl.kind) {
38691 const addrspace_ctx: std.builtin.AddressSpace.Context = switch (zir_decl.kind) {
3873238692 .@"var" => .variable,
3873338693 else => switch (nav_ty.zigTypeTag(zcu)) {
3873438694 .@"fn" => .function,
src/target.zig+3-3
......@@ -444,10 +444,10 @@ pub fn addrSpaceCastIsValid(
444444) bool {
445445 const arch = target.cpu.arch;
446446 switch (arch) {
447 .x86_64, .x86 => return arch.supportsAddressSpace(from) and arch.supportsAddressSpace(to),
447 .x86_64, .x86 => return arch.supportsAddressSpace(from, null) and arch.supportsAddressSpace(to, null),
448448 .nvptx64, .nvptx, .amdgcn => {
449 const to_generic = arch.supportsAddressSpace(from) and to == .generic;
450 const from_generic = arch.supportsAddressSpace(to) and from == .generic;
449 const to_generic = arch.supportsAddressSpace(from, null) and to == .generic;
450 const from_generic = arch.supportsAddressSpace(to, null) and from == .generic;
451451 return to_generic or from_generic;
452452 },
453453 else => return from == .generic and to == .generic,