aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorVeikka Tuominen <git@vexu.eu>2022-11-04 23:12:34 +0200
committerVeikka Tuominen <git@vexu.eu>2022-11-05 13:22:21 +0200
commitea48f06fc2965ff2e9516c23e58a50a9db5da84b (patch)
treeeba6d1e1a58ca6c77c69c73ca23506092b64ed86 /src
parentf96748ebc19b0c083569e7677f65fe4454c32b57 (diff)
downloadzig-ea48f06fc2965ff2e9516c23e58a50a9db5da84b.tar.gz
zig-ea48f06fc2965ff2e9516c23e58a50a9db5da84b.zip
stage2: address of threadlocal variable is not comptime known
Closes #13215
Diffstat (limited to 'src')
-rw-r--r--src/Sema.zig26
-rw-r--r--src/value.zig23
2 files changed, 48 insertions, 1 deletions
diff --git a/src/Sema.zig b/src/Sema.zig
index 3259a0831b..e453d0d9e0 100644
--- a/src/Sema.zig
+++ b/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,
});
}
diff --git a/src/value.zig b/src/value.zig
index a727df5d22..792ec5068f 100644
--- a/src/value.zig
+++ b/src/value.zig
@@ -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,