From d267f0f968c97d77d8434ef9918c71fb4c11f45d Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 10 Aug 2022 14:08:09 -0700 Subject: [PATCH] LLVM: respect linksection for exported variables --- src/Sema.zig | 1 + src/codegen/llvm.zig | 11 +++++++++++ src/codegen/llvm/bindings.zig | 3 +++ 3 files changed, 15 insertions(+) diff --git a/src/Sema.zig b/src/Sema.zig index 9aaa761a03..f9b37f5b49 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -6351,6 +6351,7 @@ fn instantiateGenericCall( new_decl.is_exported = fn_owner_decl.is_exported; new_decl.has_align = fn_owner_decl.has_align; new_decl.has_linksection_or_addrspace = fn_owner_decl.has_linksection_or_addrspace; + new_decl.@"linksection" = fn_owner_decl.@"linksection"; new_decl.@"addrspace" = fn_owner_decl.@"addrspace"; new_decl.zir_decl_index = fn_owner_decl.zir_decl_index; new_decl.alive = true; // This Decl is called at runtime. diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 6d2922ea3f..aa846f4247 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -722,6 +722,10 @@ pub const Object = struct { dg.addFnAttrString(llvm_func, "no-stack-arg-probe", ""); } + if (decl.@"linksection") |section| { + llvm_func.setSection(section); + } + // Remove all the basic blocks of a function in order to start over, generating // LLVM IR from an empty function body. while (llvm_func.getFirstBasicBlock()) |bb| { @@ -1107,6 +1111,11 @@ pub const Object = struct { .hidden => llvm_global.setVisibility(.Hidden), .protected => llvm_global.setVisibility(.Protected), } + if (exports[0].options.section) |section| { + const section_z = try module.gpa.dupeZ(u8, section); + defer module.gpa.free(section_z); + llvm_global.setSection(section_z); + } if (decl.val.castTag(.variable)) |variable| { if (variable.data.is_threadlocal) { llvm_global.setThreadLocalMode(.GeneralDynamicTLSModel); @@ -2183,6 +2192,7 @@ pub const DeclGen = struct { const target = dg.module.getTarget(); var global = try dg.resolveGlobalDecl(decl_index); global.setAlignment(decl.getAlignment(target)); + if (decl.@"linksection") |section| global.setSection(section); assert(decl.has_tv); const init_val = if (decl.val.castTag(.variable)) |payload| init_val: { const variable = payload.data; @@ -2216,6 +2226,7 @@ pub const DeclGen = struct { new_global.setLinkage(global.getLinkage()); new_global.setUnnamedAddr(global.getUnnamedAddress()); new_global.setAlignment(global.getAlignment()); + if (decl.@"linksection") |section| new_global.setSection(section); new_global.setInitializer(llvm_init); // replaceAllUsesWith requires the type to be unchanged. So we bitcast // the new global to the old type and use that as the thing to replace diff --git a/src/codegen/llvm/bindings.zig b/src/codegen/llvm/bindings.zig index e4357b8060..baf67b15aa 100644 --- a/src/codegen/llvm/bindings.zig +++ b/src/codegen/llvm/bindings.zig @@ -126,6 +126,9 @@ pub const Value = opaque { pub const setThreadLocalMode = LLVMSetThreadLocalMode; extern fn LLVMSetThreadLocalMode(Global: *const Value, Mode: ThreadLocalMode) void; + pub const setSection = LLVMSetSection; + extern fn LLVMSetSection(Global: *const Value, Section: [*:0]const u8) void; + pub const deleteGlobal = LLVMDeleteGlobal; extern fn LLVMDeleteGlobal(GlobalVar: *const Value) void;