| ... | ... | @@ -6932,8 +6932,7 @@ fn zirPtrType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErr |
| 6932 | 6932 | const address_space = if (inst_data.flags.has_addrspace) blk: { |
| 6933 | 6933 | const ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_i]); |
| 6934 | 6934 | extra_i += 1; |
| 6935 | | const addrspace_tv = try sema.resolveInstConst(block, .unneeded, ref); |
| 6936 | | break :blk addrspace_tv.val.toEnum(std.builtin.AddressSpace); |
| 6935 | break :blk try sema.analyzeAddrspace(block, .unneeded, ref, .pointer); |
| 6937 | 6936 | } else .generic; |
| 6938 | 6937 | |
| 6939 | 6938 | const bit_start = if (inst_data.flags.has_bit_range) blk: { |
| ... | ... | @@ -8092,8 +8091,7 @@ fn zirFuncExtended( |
| 8092 | 8091 | const address_space: std.builtin.AddressSpace = if (small.has_addrspace) blk: { |
| 8093 | 8092 | const addrspace_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]); |
| 8094 | 8093 | extra_index += 1; |
| 8095 | | const addrspace_tv = try sema.resolveInstConst(block, addrspace_src, addrspace_ref); |
| 8096 | | break :blk addrspace_tv.val.toEnum(std.builtin.AddressSpace); |
| 8094 | break :blk try sema.analyzeAddrspace(block, addrspace_src, addrspace_ref, .function); |
| 8097 | 8095 | } else .generic; |
| 8098 | 8096 | |
| 8099 | 8097 | const ret_ty_body = sema.code.extra[extra_index..][0..extra.data.ret_body_len]; |
| ... | ... | @@ -10973,3 +10971,58 @@ fn analyzeComptimeAlloc( |
| 10973 | 10971 | .decl = decl, |
| 10974 | 10972 | })); |
| 10975 | 10973 | } |
| 10974 | |
| 10975 | /// The places where a user can specify an address space attribute |
| 10976 | pub const AddressSpaceContext = enum { |
| 10977 | /// A function is specificed to be placed in a certain address space. |
| 10978 | function, |
| 10979 | |
| 10980 | /// A (global) variable is specified to be placed in a certain address space. |
| 10981 | /// In contrast to .constant, these values (and thus the address space they will be |
| 10982 | /// placed in) are required to be mutable. |
| 10983 | variable, |
| 10984 | |
| 10985 | /// A (global) constant value is specified to be placed in a certain address space. |
| 10986 | /// In contrast to .variable, values placed in this address space are not required to be mutable. |
| 10987 | constant, |
| 10988 | |
| 10989 | /// A pointer is ascripted to point into a certian address space. |
| 10990 | pointer, |
| 10991 | }; |
| 10992 | |
| 10993 | pub fn analyzeAddrspace( |
| 10994 | sema: *Sema, |
| 10995 | block: *Scope.Block, |
| 10996 | src: LazySrcLoc, |
| 10997 | zir_ref: Zir.Inst.Ref, |
| 10998 | ctx: AddressSpaceContext, |
| 10999 | ) !std.builtin.AddressSpace { |
| 11000 | const addrspace_tv = try sema.resolveInstConst(block, src, zir_ref); |
| 11001 | const address_space = addrspace_tv.val.toEnum(std.builtin.AddressSpace); |
| 11002 | const target = sema.mod.getTarget(); |
| 11003 | const arch = target.cpu.arch; |
| 11004 | |
| 11005 | const supported = switch (address_space) { |
| 11006 | .generic => true, |
| 11007 | .gs, .fs, .ss => (arch == .i386 or arch == .x86_64) and ctx == .pointer, |
| 11008 | }; |
| 11009 | |
| 11010 | if (!supported) { |
| 11011 | // TODO error messages could be made more elaborate here |
| 11012 | const entity = switch (ctx) { |
| 11013 | .function => "functions", |
| 11014 | .variable => "mutable values", |
| 11015 | .constant => "constant values", |
| 11016 | .pointer => "pointers", |
| 11017 | }; |
| 11018 | |
| 11019 | return sema.mod.fail( |
| 11020 | &block.base, |
| 11021 | src, |
| 11022 | "{s} with address space '{s}' are not supported on {s}", |
| 11023 | .{ entity, @tagName(address_space), arch.genericName() }, |
| 11024 | ); |
| 11025 | } |
| 11026 | |
| 11027 | return address_space; |
| 11028 | } |