mirror of
https://github.com/ziglang/zig.git
synced 2026-02-14 13:30:45 +00:00
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.
This commit is contained in:
parent
90a945b38c
commit
13b917148e
@ -3213,11 +3213,18 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool {
|
||||
break :blk (try sema.resolveInstConst(&block_scope, src, linksection_ref)).val;
|
||||
};
|
||||
const address_space = blk: {
|
||||
const addrspace_ref = decl.zirAddrspaceRef();
|
||||
if (addrspace_ref == .none) break :blk .generic;
|
||||
const addrspace_tv = try sema.resolveInstConst(&block_scope, src, addrspace_ref);
|
||||
break :blk addrspace_tv.val.toEnum(std.builtin.AddressSpace);
|
||||
const addrspace_ctx: Sema.AddressSpaceContext = switch (decl_tv.val.tag()) {
|
||||
.function, .extern_fn => .function,
|
||||
.variable => .variable,
|
||||
else => .constant,
|
||||
};
|
||||
|
||||
break :blk switch (decl.zirAddrspaceRef()) {
|
||||
.none => .generic,
|
||||
else => |addrspace_ref| try sema.analyzeAddrspace(&block_scope, src, addrspace_ref, addrspace_ctx),
|
||||
};
|
||||
};
|
||||
|
||||
// Note this resolves the type of the Decl, not the value; if this Decl
|
||||
// is a struct, for example, this resolves `type` (which needs no resolution),
|
||||
// not the struct itself.
|
||||
|
||||
61
src/Sema.zig
61
src/Sema.zig
@ -6932,8 +6932,7 @@ fn zirPtrType(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) CompileErr
|
||||
const address_space = if (inst_data.flags.has_addrspace) blk: {
|
||||
const ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_i]);
|
||||
extra_i += 1;
|
||||
const addrspace_tv = try sema.resolveInstConst(block, .unneeded, ref);
|
||||
break :blk addrspace_tv.val.toEnum(std.builtin.AddressSpace);
|
||||
break :blk try sema.analyzeAddrspace(block, .unneeded, ref, .pointer);
|
||||
} else .generic;
|
||||
|
||||
const bit_start = if (inst_data.flags.has_bit_range) blk: {
|
||||
@ -8092,8 +8091,7 @@ fn zirFuncExtended(
|
||||
const address_space: std.builtin.AddressSpace = if (small.has_addrspace) blk: {
|
||||
const addrspace_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
|
||||
extra_index += 1;
|
||||
const addrspace_tv = try sema.resolveInstConst(block, addrspace_src, addrspace_ref);
|
||||
break :blk addrspace_tv.val.toEnum(std.builtin.AddressSpace);
|
||||
break :blk try sema.analyzeAddrspace(block, addrspace_src, addrspace_ref, .function);
|
||||
} else .generic;
|
||||
|
||||
const ret_ty_body = sema.code.extra[extra_index..][0..extra.data.ret_body_len];
|
||||
@ -10973,3 +10971,58 @@ fn analyzeComptimeAlloc(
|
||||
.decl = decl,
|
||||
}));
|
||||
}
|
||||
|
||||
/// The places where a user can specify an address space attribute
|
||||
pub const AddressSpaceContext = enum {
|
||||
/// A function is specificed to be placed in a certain address space.
|
||||
function,
|
||||
|
||||
/// A (global) variable is specified to be placed in a certain address space.
|
||||
/// In contrast to .constant, these values (and thus the address space they will be
|
||||
/// placed in) are required to be mutable.
|
||||
variable,
|
||||
|
||||
/// A (global) constant value is specified to be placed in a certain address space.
|
||||
/// In contrast to .variable, values placed in this address space are not required to be mutable.
|
||||
constant,
|
||||
|
||||
/// A pointer is ascripted to point into a certian address space.
|
||||
pointer,
|
||||
};
|
||||
|
||||
pub fn analyzeAddrspace(
|
||||
sema: *Sema,
|
||||
block: *Scope.Block,
|
||||
src: LazySrcLoc,
|
||||
zir_ref: Zir.Inst.Ref,
|
||||
ctx: AddressSpaceContext,
|
||||
) !std.builtin.AddressSpace {
|
||||
const addrspace_tv = try sema.resolveInstConst(block, src, zir_ref);
|
||||
const address_space = addrspace_tv.val.toEnum(std.builtin.AddressSpace);
|
||||
const target = sema.mod.getTarget();
|
||||
const arch = target.cpu.arch;
|
||||
|
||||
const supported = switch (address_space) {
|
||||
.generic => true,
|
||||
.gs, .fs, .ss => (arch == .i386 or arch == .x86_64) and ctx == .pointer,
|
||||
};
|
||||
|
||||
if (!supported) {
|
||||
// TODO error messages could be made more elaborate here
|
||||
const entity = switch (ctx) {
|
||||
.function => "functions",
|
||||
.variable => "mutable values",
|
||||
.constant => "constant values",
|
||||
.pointer => "pointers",
|
||||
};
|
||||
|
||||
return sema.mod.fail(
|
||||
&block.base,
|
||||
src,
|
||||
"{s} with address space '{s}' are not supported on {s}",
|
||||
.{ entity, @tagName(address_space), arch.genericName() },
|
||||
);
|
||||
}
|
||||
|
||||
return address_space;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user