Commit ce8c61b0fc

Alex Rønne Petersen <alex@alexrp.com>
2025-01-24 02:04:51
std.Target: Move Cpu.Arch.supportsAddressSpace() up to Cpu.
This allows it to inspect CPU features which is needed for Propeller, and AVR in the future.
1 parent 0048166
Changed files (3)
lib/std/Target.zig
@@ -1576,34 +1576,6 @@ pub const Cpu = struct {
             };
         }
 
-        /// 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) 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
-                .flash, .flash1, .flash2, .flash3, .flash4, .flash5 => arch == .avr,
-
-                // Propeller address spaces:
-                .cog, .hub => arch == .propeller,
-                .lut => arch == .propeller, // TODO: This should check for the `p2` CPU feature.
-            };
-        }
-
         /// Returns a name that matches the lib/std/target/* source file name.
         pub fn genericName(arch: Arch) [:0]const u8 {
             return switch (arch) {
@@ -1999,6 +1971,35 @@ pub const Cpu = struct {
     pub fn baseline(arch: Arch, os: Os) Cpu {
         return Model.baseline(arch, os).toCpu(arch);
     }
+
+    /// 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(
+        cpu: Cpu,
+        address_space: std.builtin.AddressSpace,
+        context: ?std.builtin.AddressSpace.Context,
+    ) bool {
+        const arch = cpu.arch;
+
+        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) and (context == null or context == .pointer),
+            .flash, .flash1, .flash2, .flash3, .flash4, .flash5 => arch == .avr, // TODO this should also check how many flash banks the cpu has
+            .cog, .hub => arch == .propeller,
+            .lut => arch == .propeller and std.Target.propeller.featureSetHas(cpu.features, .p2),
+
+            .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,
+        };
+    }
 };
 
 pub fn zigTriple(target: Target, allocator: Allocator) Allocator.Error![]u8 {
src/Sema.zig
@@ -37244,9 +37244,8 @@ pub fn analyzeAsAddressSpace(
     const addrspace_val = try sema.resolveConstDefinedValue(block, src, coerced, .{ .simple = .@"addrspace" });
     const address_space = try sema.interpretBuiltinType(block, src, addrspace_val, std.builtin.AddressSpace);
     const target = pt.zcu.getTarget();
-    const arch = target.cpu.arch;
 
-    if (!arch.supportsAddressSpace(address_space, ctx)) {
+    if (!target.cpu.supportsAddressSpace(address_space, ctx)) {
         // TODO error messages could be made more elaborate here
         const entity = switch (ctx) {
             .function => "functions",
@@ -37258,7 +37257,7 @@ pub fn analyzeAsAddressSpace(
             block,
             src,
             "{s} with address space '{s}' are not supported on {s}",
-            .{ entity, @tagName(address_space), arch.genericName() },
+            .{ entity, @tagName(address_space), target.cpu.arch.genericName() },
         );
     }
 
src/target.zig
@@ -442,12 +442,11 @@ pub fn addrSpaceCastIsValid(
     from: AddressSpace,
     to: AddressSpace,
 ) bool {
-    const arch = target.cpu.arch;
-    switch (arch) {
-        .x86_64, .x86 => return arch.supportsAddressSpace(from, null) and arch.supportsAddressSpace(to, null),
+    switch (target.cpu.arch) {
+        .x86_64, .x86 => return target.cpu.supportsAddressSpace(from, null) and target.cpu.supportsAddressSpace(to, null),
         .nvptx64, .nvptx, .amdgcn => {
-            const to_generic = arch.supportsAddressSpace(from, null) and to == .generic;
-            const from_generic = arch.supportsAddressSpace(to, null) and from == .generic;
+            const to_generic = target.cpu.supportsAddressSpace(from, null) and to == .generic;
+            const from_generic = target.cpu.supportsAddressSpace(to, null) and from == .generic;
             return to_generic or from_generic;
         },
         else => return from == .generic and to == .generic,