| author | |
| committer | |
| log | 00481668671a8719627922a05a1c143f9d0409ed |
| tree | c4433588297c002fe6424bacb48f2b6c15e10a48 |
| parent | aa4ac2f85fc145dafcd4de18065bdfa28f17cea0 |
| signature |
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 { |
| 1576 | 1576 | }; |
| 1577 | 1577 | } |
| 1578 | 1578 | |
| 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 { | |
| 1581 | 1588 | const is_nvptx = arch.isNvptx(); |
| 1582 | 1589 | const is_spirv = arch.isSpirV(); |
| 1583 | 1590 | const is_gpu = is_nvptx or is_spirv or arch == .amdgcn; |
| 1584 | 1591 | return switch (address_space) { |
| 1585 | 1592 | .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), | |
| 1588 | 1596 | .param => is_nvptx, |
| 1589 | 1597 | .input, .output, .uniform, .push_constant, .storage_buffer => is_spirv, |
| 1590 | 1598 | // 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)) { |
| 491 | 491 | /// This data structure is used by the Zig language code generation and |
| 492 | 492 | /// therefore must be kept in sync with the compiler implementation. |
| 493 | 493 | pub 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 | ||
| 494 | 509 | // CPU address spaces. |
| 495 | 510 | generic, |
| 496 | 511 | gs, |
src/Sema.zig+4-44| ... | ... | @@ -37220,30 +37220,12 @@ fn analyzeComptimeAlloc( |
| 37220 | 37220 | } }))); |
| 37221 | 37221 | } |
| 37222 | 37222 | |
| 37223 | /// The places where a user can specify an address space attribute | |
| 37224 | pub 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 | ||
| 37241 | 37223 | fn resolveAddressSpace( |
| 37242 | 37224 | sema: *Sema, |
| 37243 | 37225 | block: *Block, |
| 37244 | 37226 | src: LazySrcLoc, |
| 37245 | 37227 | zir_ref: Zir.Inst.Ref, |
| 37246 | ctx: AddressSpaceContext, | |
| 37228 | ctx: std.builtin.AddressSpace.Context, | |
| 37247 | 37229 | ) !std.builtin.AddressSpace { |
| 37248 | 37230 | const air_ref = try sema.resolveInst(zir_ref); |
| 37249 | 37231 | return sema.analyzeAsAddressSpace(block, src, air_ref, ctx); |
| ... | ... | @@ -37254,7 +37236,7 @@ pub fn analyzeAsAddressSpace( |
| 37254 | 37236 | block: *Block, |
| 37255 | 37237 | src: LazySrcLoc, |
| 37256 | 37238 | air_ref: Air.Inst.Ref, |
| 37257 | ctx: AddressSpaceContext, | |
| 37239 | ctx: std.builtin.AddressSpace.Context, | |
| 37258 | 37240 | ) !std.builtin.AddressSpace { |
| 37259 | 37241 | const pt = sema.pt; |
| 37260 | 37242 | const addrspace_ty = try sema.getBuiltinType(src, .AddressSpace); |
| ... | ... | @@ -37264,29 +37246,7 @@ pub fn analyzeAsAddressSpace( |
| 37264 | 37246 | const target = pt.zcu.getTarget(); |
| 37265 | 37247 | const arch = target.cpu.arch; |
| 37266 | 37248 | |
| 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)) { | |
| 37290 | 37250 | // TODO error messages could be made more elaborate here |
| 37291 | 37251 | const entity = switch (ctx) { |
| 37292 | 37252 | .function => "functions", |
| ... | ... | @@ -38728,7 +38688,7 @@ pub fn resolveNavPtrModifiers( |
| 38728 | 38688 | }; |
| 38729 | 38689 | |
| 38730 | 38690 | 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) { | |
| 38732 | 38692 | .@"var" => .variable, |
| 38733 | 38693 | else => switch (nav_ty.zigTypeTag(zcu)) { |
| 38734 | 38694 | .@"fn" => .function, |
src/target.zig+3-3| ... | ... | @@ -444,10 +444,10 @@ pub fn addrSpaceCastIsValid( |
| 444 | 444 | ) bool { |
| 445 | 445 | const arch = target.cpu.arch; |
| 446 | 446 | 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), | |
| 448 | 448 | .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; | |
| 451 | 451 | return to_generic or from_generic; |
| 452 | 452 | }, |
| 453 | 453 | else => return from == .generic and to == .generic, |