mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
IRGen: make the autolink work better in COFF environments
This was obscured due to local workarounds. Because the reference is cross-module, and the symbol itself will be rebased, it cannot serve as a constant initializer (the value is not known until runtime). However, using a function pointer is permissible. The linker will materialize a thunk for the function itself and cause the module to be force linked. This also works on ELF and MachO as well. The overhead associated with this is pretty minimal as the function itself has an empty body, and flags will differentiate between a function and data symbol. The slight penalty in size (on the order of 2-4 bytes) allows for the same pattern to be used across all the targets.
This commit is contained in:
@@ -35,6 +35,7 @@
|
||||
#include "clang/Lex/HeaderSearch.h"
|
||||
#include "clang/Lex/HeaderSearchOptions.h"
|
||||
#include "clang/Frontend/CodeGenOptions.h"
|
||||
#include "llvm/IR/IRBuilder.h"
|
||||
#include "llvm/IR/Constants.h"
|
||||
#include "llvm/IR/DataLayout.h"
|
||||
#include "llvm/IR/DerivedTypes.h"
|
||||
@@ -851,19 +852,20 @@ void IRGenModule::addLinkLibrary(const LinkLibrary &linkLib) {
|
||||
if (linkLib.shouldForceLoad()) {
|
||||
llvm::SmallString<64> buf;
|
||||
encodeForceLoadSymbolName(buf, linkLib.getName());
|
||||
auto symbolAddr = Module.getOrInsertGlobal(buf.str(), Int1Ty);
|
||||
auto ForceImportThunk =
|
||||
Module.getOrInsertFunction(buf, llvm::FunctionType::get(VoidTy, false));
|
||||
if (useDllStorage())
|
||||
cast<llvm::GlobalVariable>(symbolAddr)
|
||||
cast<llvm::GlobalValue>(ForceImportThunk)
|
||||
->setDLLStorageClass(llvm::GlobalValue::DLLImportStorageClass);
|
||||
|
||||
buf += "_$";
|
||||
appendEncodedName(buf, IRGen.Opts.ModuleName);
|
||||
|
||||
if (!Module.getGlobalVariable(buf.str())) {
|
||||
auto ref = new llvm::GlobalVariable(Module, symbolAddr->getType(),
|
||||
auto ref = new llvm::GlobalVariable(Module, ForceImportThunk->getType(),
|
||||
/*isConstant=*/true,
|
||||
llvm::GlobalValue::WeakAnyLinkage,
|
||||
symbolAddr, buf.str());
|
||||
ForceImportThunk, buf.str());
|
||||
ref->setVisibility(llvm::GlobalValue::HiddenVisibility);
|
||||
auto casted = llvm::ConstantExpr::getBitCast(ref, Int8PtrTy);
|
||||
LLVMUsed.push_back(casted);
|
||||
@@ -953,13 +955,17 @@ void IRGenModule::emitAutolinkInfo() {
|
||||
if (!IRGen.Opts.ForceLoadSymbolName.empty()) {
|
||||
llvm::SmallString<64> buf;
|
||||
encodeForceLoadSymbolName(buf, IRGen.Opts.ForceLoadSymbolName);
|
||||
auto symbol =
|
||||
new llvm::GlobalVariable(Module, Int1Ty, /*isConstant=*/false,
|
||||
llvm::GlobalValue::CommonLinkage,
|
||||
llvm::Constant::getNullValue(Int1Ty),
|
||||
buf.str());
|
||||
auto ForceImportThunk =
|
||||
llvm::Function::Create(llvm::FunctionType::get(VoidTy, false),
|
||||
llvm::GlobalValue::WeakODRLinkage, buf,
|
||||
&Module);
|
||||
if (useDllStorage())
|
||||
symbol->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
|
||||
ForceImportThunk
|
||||
->setDLLStorageClass(llvm::GlobalValue::DLLExportStorageClass);
|
||||
|
||||
auto BB = llvm::BasicBlock::Create(getLLVMContext(), "", ForceImportThunk);
|
||||
llvm::IRBuilder<> IRB(BB);
|
||||
IRB.CreateRetVoid();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,23 @@
|
||||
// RUN: %empty-directory(%t)
|
||||
|
||||
// RUN: %swift -target i686--windows-msvc -parse-as-library -parse-stdlib -module-name autolink -module-link-name autolink -autolink-force-load -emit-ir -o - %s | %FileCheck %s
|
||||
// RUN: %swift -target i686--windows-itanium -parse-as-library -parse-stdlib -module-name autolink -module-link-name autolink -autolink-force-load -S -o - %s | %FileCheck %s -check-prefix CHECK-ASM-GNU
|
||||
// RUN: %swift -target i686--windows-msvc -parse-as-library -parse-stdlib -module-name autolink -module-link-name autolink -autolink-force-load -S -o - %s | %FileCheck %s -check-prefix CHECK-ASM-MSC
|
||||
// RUN: %swift -target i686--windows-msvc -parse-stdlib -autolink-force-load -module-name swiftMSVCRT -module-link-name swiftMSVCRT -emit-module -o %t/swiftMSVCRT.swiftmodule %S/../Inputs/empty.swift
|
||||
|
||||
// RUN: %swift -target i686--windows-msvc -parse-as-library -parse-stdlib -autolink-force-load -module-name autolink -module-link-name autolink -emit-ir -o - %s | %FileCheck %s
|
||||
// RUN: %swift -target i686--windows-msvc -parse-as-library -parse-stdlib -autolink-force-load -module-name autolink -module-link-name autolink -S -o - %s | %FileCheck %s -check-prefix CHECK-ASM-MSC
|
||||
|
||||
// RUN: %swift -target i686--windows-itanium -parse-stdlib -autolink-force-load -module-name swiftMSVCRT -module-link-name swiftMSVCRT -emit-module -o %t/swiftMSVCRT.swiftmodule %S/../Inputs/empty.swift
|
||||
|
||||
// RUN: %swift -target i686--windows-itanium -parse-as-library -parse-stdlib -autolink-force-load -module-name autolink -module-link-name autolink -emit-ir -o - %s | %FileCheck %s
|
||||
// RUN: %swift -target i686--windows-itanium -parse-as-library -parse-stdlib -autolink-force-load -module-name autolink -module-link-name autolink -S -o - %s | %FileCheck %s -check-prefix CHECK-ASM-GNU
|
||||
|
||||
// REQUIRES: OS=windows-msvc
|
||||
|
||||
import swiftMSVCRT
|
||||
|
||||
// CHECK: @"_swift_FORCE_LOAD_$_swiftMSVCRT_$_autolink" = weak hidden constant void ()* @"_swift_FORCE_LOAD_$_swiftMSVCRT"
|
||||
// CHECK: weak_odr dllexport void @"_swift_FORCE_LOAD_$_autolink"()
|
||||
|
||||
// CHECK-ASM-GNU: .ascii " -export:__swift_FORCE_LOAD_$_autolink"
|
||||
// CHECK-ASM-MSC: .ascii " /EXPORT:__swift_FORCE_LOAD_$_autolink"
|
||||
|
||||
// CHECK: @"_swift_FORCE_LOAD_$_autolink" = common dllexport global i1 false
|
||||
// CHECK-ASM-GNU: .ascii " -export:__swift_FORCE_LOAD_$_autolink,data"
|
||||
// CHECK-ASM-MSC: .ascii " /EXPORT:__swift_FORCE_LOAD_$_autolink,DATA"
|
||||
|
||||
|
||||
@@ -38,12 +38,16 @@ import someModule
|
||||
// FRAMEWORK-DAG: !{{[0-9]+}} = !{!"-framework", !"someModule"}
|
||||
|
||||
// NO-FORCE-LOAD-NOT: FORCE_LOAD
|
||||
// FORCE-LOAD: @"_swift_FORCE_LOAD_$_module" = common global i1 false
|
||||
// FORCE-LOAD-HEX: @"_swift_FORCE_LOAD_$306d6f64756c65" = common global i1 false
|
||||
|
||||
// FORCE-LOAD-CLIENT: @"_swift_FORCE_LOAD_$_module" = external global i1
|
||||
// FORCE-LOAD-CLIENT: @"_swift_FORCE_LOAD_$_module_$_autolinking" = weak hidden constant i1* @"_swift_FORCE_LOAD_$_module"
|
||||
// FORCE-LOAD: define weak_odr void @"_swift_FORCE_LOAD_$_module"() {
|
||||
// FORCE-LOAD: ret void
|
||||
// FORCE-LOAD: }
|
||||
// FORCE-LOAD-HEX: define weak_odr void @"_swift_FORCE_LOAD_$306d6f64756c65"() {
|
||||
// FORCE-LOAD-HEX: ret void
|
||||
// FORCE-LOAD-HEX: }
|
||||
|
||||
// FORCE-LOAD-CLIENT: @"_swift_FORCE_LOAD_$_module_$_autolinking" = weak hidden constant void ()* @"_swift_FORCE_LOAD_$_module"
|
||||
// FORCE-LOAD-CLIENT: @llvm.used = appending global [{{[0-9]+}} x i8*] [
|
||||
// FORCE-LOAD-CLIENT: i8* bitcast (i1** @"_swift_FORCE_LOAD_$_module_$_autolinking" to i8*)
|
||||
// FORCE-LOAD-CLIENT: i8* bitcast (void ()** @"_swift_FORCE_LOAD_$_module_$_autolinking" to i8*)
|
||||
// FORCE-LOAD-CLIENT: ], section "llvm.metadata"
|
||||
// FORCE-LOAD-CLIENT: declare void @"_swift_FORCE_LOAD_$_module"()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user