mirror of
https://github.com/ziglang/zig.git
synced 2026-01-21 06:45:24 +00:00
stage2: address of threadlocal variable is not comptime known
Closes #13215
This commit is contained in:
parent
f96748ebc1
commit
ea48f06fc2
26
src/Sema.zig
26
src/Sema.zig
@ -1917,6 +1917,7 @@ fn resolveMaybeUndefValAllowVariablesMaybeRuntime(
|
||||
const ty_pl = sema.air_instructions.items(.data)[i].ty_pl;
|
||||
const val = sema.air_values.items[ty_pl.payload];
|
||||
if (val.tag() == .runtime_value) make_runtime.* = true;
|
||||
if (val.isPtrToThreadLocal(sema.mod)) make_runtime.* = true;
|
||||
return val;
|
||||
},
|
||||
.const_ty => {
|
||||
@ -32086,15 +32087,36 @@ fn elemPtrType(sema: *Sema, ptr_ty: Type, offset: ?usize) !Type {
|
||||
const ptr_info = ptr_ty.ptrInfo().data;
|
||||
const elem_ty = ptr_ty.elemType2();
|
||||
const allow_zero = ptr_info.@"allowzero" and (offset orelse 0) == 0;
|
||||
const target = sema.mod.getTarget();
|
||||
const parent_ty = ptr_ty.childType();
|
||||
|
||||
const vector_info: struct {
|
||||
host_size: u16,
|
||||
bit_offset: u16,
|
||||
alignment: u32,
|
||||
} = if (parent_ty.tag() == .vector) blk: {
|
||||
const elem_bits = elem_ty.bitSize(target);
|
||||
const is_packed = elem_bits != 0 and (elem_bits & (elem_bits - 1)) != 0;
|
||||
// TODO: runtime-known index
|
||||
assert(!is_packed or offset != null);
|
||||
const is_packed_with_offset = is_packed and offset != null and offset.? != 0;
|
||||
const target_offset = if (is_packed_with_offset) (if (target.cpu.arch.endian() == .Big) (parent_ty.vectorLen() - 1 - offset.?) else offset.?) else 0;
|
||||
break :blk .{
|
||||
.host_size = if (is_packed_with_offset) @intCast(u16, parent_ty.abiSize(target)) else 0,
|
||||
.bit_offset = if (is_packed_with_offset) @intCast(u16, elem_bits * target_offset) else 0,
|
||||
.alignment = if (is_packed_with_offset) @intCast(u16, parent_ty.abiAlignment(target)) else 0,
|
||||
};
|
||||
} else .{ .host_size = 0, .bit_offset = 0, .alignment = 0 };
|
||||
|
||||
const alignment: u32 = a: {
|
||||
// Calculate the new pointer alignment.
|
||||
if (ptr_info.@"align" == 0) {
|
||||
if (vector_info.alignment != 0) break :a vector_info.alignment;
|
||||
// ABI-aligned pointer. Any pointer arithmetic maintains the same ABI-alignedness.
|
||||
break :a 0;
|
||||
}
|
||||
// If the addend is not a comptime-known value we can still count on
|
||||
// it being a multiple of the type size.
|
||||
const target = sema.mod.getTarget();
|
||||
const elem_size = elem_ty.abiSize(target);
|
||||
const addend = if (offset) |off| elem_size * off else elem_size;
|
||||
|
||||
@ -32111,5 +32133,7 @@ fn elemPtrType(sema: *Sema, ptr_ty: Type, offset: ?usize) !Type {
|
||||
.@"allowzero" = allow_zero,
|
||||
.@"volatile" = ptr_info.@"volatile",
|
||||
.@"align" = alignment,
|
||||
.host_size = vector_info.host_size,
|
||||
.bit_offset = vector_info.bit_offset,
|
||||
});
|
||||
}
|
||||
|
||||
@ -2806,6 +2806,29 @@ pub const Value = extern union {
|
||||
};
|
||||
}
|
||||
|
||||
pub fn isPtrToThreadLocal(val: Value, mod: *Module) bool {
|
||||
return switch (val.tag()) {
|
||||
.variable => false,
|
||||
else => val.isPtrToThreadLocalInner(mod),
|
||||
};
|
||||
}
|
||||
|
||||
fn isPtrToThreadLocalInner(val: Value, mod: *Module) bool {
|
||||
return switch (val.tag()) {
|
||||
.slice => val.castTag(.slice).?.data.ptr.isPtrToThreadLocalInner(mod),
|
||||
.comptime_field_ptr => val.castTag(.comptime_field_ptr).?.data.field_val.isPtrToThreadLocalInner(mod),
|
||||
.elem_ptr => val.castTag(.elem_ptr).?.data.array_ptr.isPtrToThreadLocalInner(mod),
|
||||
.field_ptr => val.castTag(.field_ptr).?.data.container_ptr.isPtrToThreadLocalInner(mod),
|
||||
.eu_payload_ptr => val.castTag(.eu_payload_ptr).?.data.container_ptr.isPtrToThreadLocalInner(mod),
|
||||
.opt_payload_ptr => val.castTag(.opt_payload_ptr).?.data.container_ptr.isPtrToThreadLocalInner(mod),
|
||||
.decl_ref => mod.declPtr(val.castTag(.decl_ref).?.data).val.isPtrToThreadLocalInner(mod),
|
||||
.decl_ref_mut => mod.declPtr(val.castTag(.decl_ref_mut).?.data.decl_index).val.isPtrToThreadLocalInner(mod),
|
||||
|
||||
.variable => val.castTag(.variable).?.data.is_threadlocal,
|
||||
else => false,
|
||||
};
|
||||
}
|
||||
|
||||
// Asserts that the provided start/end are in-bounds.
|
||||
pub fn sliceArray(
|
||||
val: Value,
|
||||
|
||||
@ -0,0 +1,13 @@
|
||||
threadlocal var global: u32 = 23;
|
||||
threadlocal var global_ptr: *u32 = &global;
|
||||
|
||||
pub export fn entry() void {
|
||||
if (global_ptr.* != 23) unreachable;
|
||||
}
|
||||
|
||||
// error
|
||||
// backend=stage2
|
||||
// target=native
|
||||
//
|
||||
// :2:36: error: unable to resolve comptime value
|
||||
// :2:36: note: container level variable initializers must be comptime-known
|
||||
Loading…
x
Reference in New Issue
Block a user