authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-11-04 23:12:34+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-11-05 13:22:21+02:00
logea48f06fc2965ff2e9516c23e58a50a9db5da84b
treeeba6d1e1a58ca6c77c69c73ca23506092b64ed86
parentf96748ebc19b0c083569e7677f65fe4454c32b57

stage2: address of threadlocal variable is not comptime known

Closes #13215

3 files changed, 61 insertions(+), 1 deletions(-)

src/Sema.zig+25-1
...@@ -1917,6 +1917,7 @@ fn resolveMaybeUndefValAllowVariablesMaybeRuntime(...@@ -1917,6 +1917,7 @@ fn resolveMaybeUndefValAllowVariablesMaybeRuntime(
1917 const ty_pl = sema.air_instructions.items(.data)[i].ty_pl;1917 const ty_pl = sema.air_instructions.items(.data)[i].ty_pl;
1918 const val = sema.air_values.items[ty_pl.payload];1918 const val = sema.air_values.items[ty_pl.payload];
1919 if (val.tag() == .runtime_value) make_runtime.* = true;1919 if (val.tag() == .runtime_value) make_runtime.* = true;
1920 if (val.isPtrToThreadLocal(sema.mod)) make_runtime.* = true;
1920 return val;1921 return val;
1921 },1922 },
1922 .const_ty => {1923 .const_ty => {
...@@ -32086,15 +32087,36 @@ fn elemPtrType(sema: *Sema, ptr_ty: Type, offset: ?usize) !Type {...@@ -32086,15 +32087,36 @@ fn elemPtrType(sema: *Sema, ptr_ty: Type, offset: ?usize) !Type {
32086 const ptr_info = ptr_ty.ptrInfo().data;32087 const ptr_info = ptr_ty.ptrInfo().data;
32087 const elem_ty = ptr_ty.elemType2();32088 const elem_ty = ptr_ty.elemType2();
32088 const allow_zero = ptr_info.@"allowzero" and (offset orelse 0) == 0;32089 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
32089 const alignment: u32 = a: {32111 const alignment: u32 = a: {
32090 // Calculate the new pointer alignment.32112 // Calculate the new pointer alignment.
32091 if (ptr_info.@"align" == 0) {32113 if (ptr_info.@"align" == 0) {
32114 if (vector_info.alignment != 0) break :a vector_info.alignment;
32092 // ABI-aligned pointer. Any pointer arithmetic maintains the same ABI-alignedness.32115 // ABI-aligned pointer. Any pointer arithmetic maintains the same ABI-alignedness.
32093 break :a 0;32116 break :a 0;
32094 }32117 }
32095 // If the addend is not a comptime-known value we can still count on32118 // If the addend is not a comptime-known value we can still count on
32096 // it being a multiple of the type size.32119 // it being a multiple of the type size.
32097 const target = sema.mod.getTarget();
32098 const elem_size = elem_ty.abiSize(target);32120 const elem_size = elem_ty.abiSize(target);
32099 const addend = if (offset) |off| elem_size * off else elem_size;32121 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 {...@@ -32111,5 +32133,7 @@ fn elemPtrType(sema: *Sema, ptr_ty: Type, offset: ?usize) !Type {
32111 .@"allowzero" = allow_zero,32133 .@"allowzero" = allow_zero,
32112 .@"volatile" = ptr_info.@"volatile",32134 .@"volatile" = ptr_info.@"volatile",
32113 .@"align" = alignment,32135 .@"align" = alignment,
32136 .host_size = vector_info.host_size,
32137 .bit_offset = vector_info.bit_offset,
32114 });32138 });
32115}32139}
src/value.zig+23
...@@ -2806,6 +2806,29 @@ pub const Value = extern union {...@@ -2806,6 +2806,29 @@ pub const Value = extern union {
2806 };2806 };
2807 }2807 }
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
2809 // Asserts that the provided start/end are in-bounds.2832 // Asserts that the provided start/end are in-bounds.
2810 pub fn sliceArray(2833 pub fn sliceArray(
2811 val: Value,2834 val: Value,
test/cases/compile_errors/address_of_threadlocal_not_comptime_known.zig created+13
...@@ -0,0 +1,13 @@
1threadlocal var global: u32 = 23;
2threadlocal var global_ptr: *u32 = &global;
3
4pub 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