Skip to content

Commit ea48f06

Browse files
committed
stage2: address of threadlocal variable is not comptime known
Closes #13215
1 parent f96748e commit ea48f06

File tree

3 files changed

+61
-1
lines changed

3 files changed

+61
-1
lines changed

src/Sema.zig

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1917,6 +1917,7 @@ fn resolveMaybeUndefValAllowVariablesMaybeRuntime(
19171917
const ty_pl = sema.air_instructions.items(.data)[i].ty_pl;
19181918
const val = sema.air_values.items[ty_pl.payload];
19191919
if (val.tag() == .runtime_value) make_runtime.* = true;
1920+
if (val.isPtrToThreadLocal(sema.mod)) make_runtime.* = true;
19201921
return val;
19211922
},
19221923
.const_ty => {
@@ -32086,15 +32087,36 @@ fn elemPtrType(sema: *Sema, ptr_ty: Type, offset: ?usize) !Type {
3208632087
const ptr_info = ptr_ty.ptrInfo().data;
3208732088
const elem_ty = ptr_ty.elemType2();
3208832089
const allow_zero = ptr_info.@"allowzero" and (offset orelse 0) == 0;
32090+
const target = sema.mod.getTarget();
32091+
const parent_ty = ptr_ty.childType();
32092+
32093+
const vector_info: struct {
32094+
host_size: u16,
32095+
bit_offset: u16,
32096+
alignment: u32,
32097+
} = if (parent_ty.tag() == .vector) blk: {
32098+
const elem_bits = elem_ty.bitSize(target);
32099+
const is_packed = elem_bits != 0 and (elem_bits & (elem_bits - 1)) != 0;
32100+
// TODO: runtime-known index
32101+
assert(!is_packed or offset != null);
32102+
const is_packed_with_offset = is_packed and offset != null and offset.? != 0;
32103+
const target_offset = if (is_packed_with_offset) (if (target.cpu.arch.endian() == .Big) (parent_ty.vectorLen() - 1 - offset.?) else offset.?) else 0;
32104+
break :blk .{
32105+
.host_size = if (is_packed_with_offset) @intCast(u16, parent_ty.abiSize(target)) else 0,
32106+
.bit_offset = if (is_packed_with_offset) @intCast(u16, elem_bits * target_offset) else 0,
32107+
.alignment = if (is_packed_with_offset) @intCast(u16, parent_ty.abiAlignment(target)) else 0,
32108+
};
32109+
} else .{ .host_size = 0, .bit_offset = 0, .alignment = 0 };
32110+
3208932111
const alignment: u32 = a: {
3209032112
// Calculate the new pointer alignment.
3209132113
if (ptr_info.@"align" == 0) {
32114+
if (vector_info.alignment != 0) break :a vector_info.alignment;
3209232115
// ABI-aligned pointer. Any pointer arithmetic maintains the same ABI-alignedness.
3209332116
break :a 0;
3209432117
}
3209532118
// If the addend is not a comptime-known value we can still count on
3209632119
// it being a multiple of the type size.
32097-
const target = sema.mod.getTarget();
3209832120
const elem_size = elem_ty.abiSize(target);
3209932121
const addend = if (offset) |off| elem_size * off else elem_size;
3210032122

@@ -32111,5 +32133,7 @@ fn elemPtrType(sema: *Sema, ptr_ty: Type, offset: ?usize) !Type {
3211132133
.@"allowzero" = allow_zero,
3211232134
.@"volatile" = ptr_info.@"volatile",
3211332135
.@"align" = alignment,
32136+
.host_size = vector_info.host_size,
32137+
.bit_offset = vector_info.bit_offset,
3211432138
});
3211532139
}

src/value.zig

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2806,6 +2806,29 @@ pub const Value = extern union {
28062806
};
28072807
}
28082808

2809+
pub fn isPtrToThreadLocal(val: Value, mod: *Module) bool {
2810+
return switch (val.tag()) {
2811+
.variable => false,
2812+
else => val.isPtrToThreadLocalInner(mod),
2813+
};
2814+
}
2815+
2816+
fn isPtrToThreadLocalInner(val: Value, mod: *Module) bool {
2817+
return switch (val.tag()) {
2818+
.slice => val.castTag(.slice).?.data.ptr.isPtrToThreadLocalInner(mod),
2819+
.comptime_field_ptr => val.castTag(.comptime_field_ptr).?.data.field_val.isPtrToThreadLocalInner(mod),
2820+
.elem_ptr => val.castTag(.elem_ptr).?.data.array_ptr.isPtrToThreadLocalInner(mod),
2821+
.field_ptr => val.castTag(.field_ptr).?.data.container_ptr.isPtrToThreadLocalInner(mod),
2822+
.eu_payload_ptr => val.castTag(.eu_payload_ptr).?.data.container_ptr.isPtrToThreadLocalInner(mod),
2823+
.opt_payload_ptr => val.castTag(.opt_payload_ptr).?.data.container_ptr.isPtrToThreadLocalInner(mod),
2824+
.decl_ref => mod.declPtr(val.castTag(.decl_ref).?.data).val.isPtrToThreadLocalInner(mod),
2825+
.decl_ref_mut => mod.declPtr(val.castTag(.decl_ref_mut).?.data.decl_index).val.isPtrToThreadLocalInner(mod),
2826+
2827+
.variable => val.castTag(.variable).?.data.is_threadlocal,
2828+
else => false,
2829+
};
2830+
}
2831+
28092832
// Asserts that the provided start/end are in-bounds.
28102833
pub fn sliceArray(
28112834
val: Value,
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
threadlocal var global: u32 = 23;
2+
threadlocal var global_ptr: *u32 = &global;
3+
4+
pub export fn entry() void {
5+
if (global_ptr.* != 23) unreachable;
6+
}
7+
8+
// error
9+
// backend=stage2
10+
// target=native
11+
//
12+
// :2:36: error: unable to resolve comptime value
13+
// :2:36: note: container level variable initializers must be comptime-known

0 commit comments

Comments
 (0)