authorgravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2021-09-01 17:33:45+02:00
committergravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2021-09-20 02:29:04+02:00
log13b917148e97560760eb13cd0e4a0b7365739f64
tree6c738f53f4bbcd131ac0c1d00364ed476fe21703
parent90a945b38c44c673e230feb8a6b124f5c8f977a1

Address Spaces: basic system to check for validity.

Validity checks are also based on context; whether the entity being validated is a mutable/constant value, a pointer (that is ascripted with an addrspace attribute) or a function with an addrspace attribute. Error messages are relatively simple for now.

2 files changed, 68 insertions(+), 8 deletions(-)

src/Module.zig+11-4
......@@ -3213,11 +3213,18 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool {
32133213 break :blk (try sema.resolveInstConst(&block_scope, src, linksection_ref)).val;
32143214 };
32153215 const address_space = blk: {
3216 const addrspace_ref = decl.zirAddrspaceRef();
3217 if (addrspace_ref == .none) break :blk .generic;
3218 const addrspace_tv = try sema.resolveInstConst(&block_scope, src, addrspace_ref);
3219 break :blk addrspace_tv.val.toEnum(std.builtin.AddressSpace);
3216 const addrspace_ctx: Sema.AddressSpaceContext = switch (decl_tv.val.tag()) {
3217 .function, .extern_fn => .function,
3218 .variable => .variable,
3219 else => .constant,
3220 };
3221
3222 break :blk switch (decl.zirAddrspaceRef()) {
3223 .none => .generic,
3224 else => |addrspace_ref| try sema.analyzeAddrspace(&block_scope, src, addrspace_ref, addrspace_ctx),
3225 };
32203226 };
3227
32213228 // Note this resolves the type of the Decl, not the value; if this Decl
32223229 // is a struct, for example, this resolves `type` (which needs no resolution),
32233230 // not the struct itself.
src/Sema.zig+57-4
......@@ -6932,8 +6932,7 @@ fn zirPtrType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErr
69326932 const address_space = if (inst_data.flags.has_addrspace) blk: {
69336933 const ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_i]);
69346934 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);
69376936 } else .generic;
69386937
69396938 const bit_start = if (inst_data.flags.has_bit_range) blk: {
......@@ -8092,8 +8091,7 @@ fn zirFuncExtended(
80928091 const address_space: std.builtin.AddressSpace = if (small.has_addrspace) blk: {
80938092 const addrspace_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
80948093 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);
80978095 } else .generic;
80988096
80998097 const ret_ty_body = sema.code.extra[extra_index..][0..extra.data.ret_body_len];
......@@ -10973,3 +10971,58 @@ fn analyzeComptimeAlloc(
1097310971 .decl = decl,
1097410972 }));
1097510973}
10974
10975/// The places where a user can specify an address space attribute
10976pub 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
10993pub 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}