From a4690ecb1fc8a9ac5f7dfccfdf9f67c7a74e1569 Mon Sep 17 00:00:00 2001 From: kcbanner Date: Sun, 20 Oct 2024 16:30:12 -0400 Subject: [PATCH] Cause a compilation error to occur if using @extern with is_dll_import in a comptime scope. Add a note about thread local / dll import being the cause. --- src/Sema.zig | 12 +++++++++++- src/Value.zig | 4 ++-- src/codegen/llvm.zig | 9 +++++---- src/codegen/llvm/Builder.zig | 4 ++++ 4 files changed, 22 insertions(+), 7 deletions(-) diff --git a/src/Sema.zig b/src/Sema.zig index 95586e2161..17600cd1a2 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -876,6 +876,7 @@ const InferredAlloc = struct { const NeededComptimeReason = struct { needed_comptime_reason: []const u8, + value_comptime_reason: ?[]const u8 = null, block_comptime_reason: ?*const Block.ComptimeReason = null, }; @@ -2251,7 +2252,7 @@ fn resolveValueAllowVariables(sema: *Sema, inst: Air.Inst.Ref) CompileError!?Val } }; const val = Value.fromInterned(ip_index); - if (val.isPtrToThreadLocal(pt.zcu)) return null; + if (val.isPtrRuntimeValue(pt.zcu)) return null; return val; } @@ -2277,8 +2278,14 @@ pub fn resolveFinalDeclValue( const zcu = sema.pt.zcu; const val = try sema.resolveValueAllowVariables(air_ref) orelse { + const value_comptime_reason: ?[]const u8 = if (air_ref.toInterned()) |_| + "thread local and dll imported variables have runtime-known addresses" + else + null; + return sema.failWithNeededComptime(block, src, .{ .needed_comptime_reason = "global variable initializer must be comptime-known", + .value_comptime_reason = value_comptime_reason, }); }; if (val.isGenericPoison()) return error.GenericPoison; @@ -2296,6 +2303,9 @@ fn failWithNeededComptime(sema: *Sema, block: *Block, src: LazySrcLoc, reason: N const msg = try sema.errMsg(src, "unable to resolve comptime value", .{}); errdefer msg.destroy(sema.gpa); try sema.errNote(src, msg, "{s}", .{reason.needed_comptime_reason}); + if (reason.value_comptime_reason) |value_comptime_reason| { + try sema.errNote(src, msg, "{s}", .{value_comptime_reason}); + } if (reason.block_comptime_reason) |block_comptime_reason| { try block_comptime_reason.explain(sema, msg); diff --git a/src/Value.zig b/src/Value.zig index 157f47bc7e..464ee7f5e1 100644 --- a/src/Value.zig +++ b/src/Value.zig @@ -1340,11 +1340,11 @@ pub fn isLazySize(val: Value, zcu: *Zcu) bool { }; } -pub fn isPtrToThreadLocal(val: Value, zcu: *Zcu) bool { +pub fn isPtrRuntimeValue(val: Value, zcu: *Zcu) bool { const ip = &zcu.intern_pool; const nav = ip.getBackingNav(val.toIntern()).unwrap() orelse return false; return switch (ip.indexToKey(ip.getNav(nav).status.resolved.val)) { - .@"extern" => |e| e.is_threadlocal, + .@"extern" => |e| e.is_threadlocal or e.is_dll_import, .variable => |v| v.is_threadlocal, else => false, }; diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index a2c2f98a21..2657d2e799 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -3237,10 +3237,10 @@ pub const Object = struct { const ip = &zcu.intern_pool; const nav = ip.getNav(nav_index); const resolved = nav.status.resolved; - const is_extern, const is_threadlocal, const is_weak_linkage = switch (ip.indexToKey(resolved.val)) { - .variable => |variable| .{ false, variable.is_threadlocal, variable.is_weak_linkage }, - .@"extern" => |@"extern"| .{ true, @"extern".is_threadlocal, @"extern".is_weak_linkage }, - else => .{ false, false, false }, + const is_extern, const is_threadlocal, const is_weak_linkage, const is_dll_import = switch (ip.indexToKey(resolved.val)) { + .variable => |variable| .{ false, variable.is_threadlocal, variable.is_weak_linkage, false }, + .@"extern" => |@"extern"| .{ true, @"extern".is_threadlocal, @"extern".is_weak_linkage, @"extern".is_dll_import }, + else => .{ false, false, false, false }, }; const variable_index = try o.builder.addVariable( @@ -3257,6 +3257,7 @@ pub const Object = struct { if (is_threadlocal and !zcu.navFileScope(nav_index).mod.single_threaded) variable_index.setThreadLocal(.generaldynamic, &o.builder); if (is_weak_linkage) variable_index.setLinkage(.extern_weak, &o.builder); + if (is_dll_import) variable_index.setDllStorageClass(.dllimport, &o.builder); } else { variable_index.setLinkage(.internal, &o.builder); variable_index.setUnnamedAddr(.unnamed_addr, &o.builder); diff --git a/src/codegen/llvm/Builder.zig b/src/codegen/llvm/Builder.zig index d3aa6e34c4..2f38d4a019 100644 --- a/src/codegen/llvm/Builder.zig +++ b/src/codegen/llvm/Builder.zig @@ -2528,6 +2528,10 @@ pub const Variable = struct { return self.ptrConst(builder).global.setLinkage(linkage, builder); } + pub fn setDllStorageClass(self: Index, class: DllStorageClass, builder: *Builder) void { + return self.ptrConst(builder).global.setDllStorageClass(class, builder); + } + pub fn setUnnamedAddr(self: Index, unnamed_addr: UnnamedAddr, builder: *Builder) void { return self.ptrConst(builder).global.setUnnamedAddr(unnamed_addr, builder); }