Skip to content

Commit ad454c7

Browse files
authored
[IRGen] Be smarter about adding the FORCE_LINK symbols for overlays (#15687)
We use dummy symbols to force overlays not to get dropped when autolinking, even if the user doesn't use anything from them explicitly. This behavior is triggered by the semi-hidden flag -autolink-force-load. (It's semi-hidden because it has few legitimate uses in real life. If you searched for "how to force autolinking to pick up a library" and found this commit, don't just do this and move on. Come talk to me on forums.swift.org.) Previously we added these dummy symbols to every object file using "common" linkage, a little-known feature added for C that ensures that only one definition will actually get used in the final object file. However, the way we were doing that wouldn't work so well for COFF, and so in 1025eed Saleem changed this to use "weak ODR" linkage. This has *nearly* the same effect, and avoids some other weirdness, but has the downside of making the symbol in the final dylib "weak" itself, meaning that some /other/ library could come along and override it. That impacts loading time, and an Apple-internal tool caught that as rdar://39019606. To avoid this whole mess, "just" emit the symbol into the object file that corresponds to the first file in the module, which allows us to mark it as a normal public symbol. P.S. None of this is actually important at the moment because all of the overlays are built with single-threaded WMO, which always produces one object file anyway. But I wanted to get it right once and for all. (cherry picked from commit 6af333f)
1 parent 7ea8405 commit ad454c7

File tree

3 files changed

+51
-4
lines changed

3 files changed

+51
-4
lines changed

lib/IRGen/IRGenModule.cpp

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -929,6 +929,23 @@ static bool replaceModuleFlagsEntry(llvm::LLVMContext &Ctx,
929929
llvm_unreachable("Could not replace old linker options entry?");
930930
}
931931

932+
/// Returns true if the object file generated by \p IGM will be the "first"
933+
/// object file in the module. This lets us determine where to put a symbol
934+
/// that must be unique.
935+
static bool isFirstObjectFileInModule(IRGenModule &IGM) {
936+
if (IGM.getSILModule().isWholeModule())
937+
return IGM.IRGen.getPrimaryIGM() == &IGM;
938+
939+
const DeclContext *DC = IGM.getSILModule().getAssociatedContext();
940+
if (!DC)
941+
return false;
942+
943+
assert(!isa<ModuleDecl>(DC) && "that would be a whole module build");
944+
assert(isa<FileUnit>(DC) && "compiling something smaller than a file?");
945+
ModuleDecl *containingModule = cast<FileUnit>(DC)->getParentModule();
946+
return containingModule->getFiles().front() == DC;
947+
}
948+
932949
void IRGenModule::emitAutolinkInfo() {
933950
// Collect the linker options already in the module (from ClangCodeGen).
934951
// FIXME: This constant should be vended by LLVM somewhere.
@@ -983,12 +1000,13 @@ void IRGenModule::emitAutolinkInfo() {
9831000
addUsedGlobal(var);
9841001
}
9851002

986-
if (!IRGen.Opts.ForceLoadSymbolName.empty()) {
1003+
if (!IRGen.Opts.ForceLoadSymbolName.empty() &&
1004+
isFirstObjectFileInModule(*this)) {
9871005
llvm::SmallString<64> buf;
9881006
encodeForceLoadSymbolName(buf, IRGen.Opts.ForceLoadSymbolName);
9891007
auto ForceImportThunk =
9901008
llvm::Function::Create(llvm::FunctionType::get(VoidTy, false),
991-
llvm::GlobalValue::WeakODRLinkage, buf,
1009+
llvm::GlobalValue::ExternalLinkage, buf,
9921010
&Module);
9931011
if (useDllStorage())
9941012
ForceImportThunk

test/IRGen/autolink-force-link.swift

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// RUN: %empty-directory(%t)
2+
3+
// RUN: %swift -target x86_64-apple-macosx10.9 -parse-stdlib -autolink-force-load -module-name TEST -module-link-name TEST -emit-ir %s %S/../Inputs/empty.swift | %FileCheck -check-prefix=CHECK-WMO %s
4+
5+
// CHECK-WMO: source_filename = "-"
6+
// CHECK-WMO: define void @"_swift_FORCE_LOAD_$_TEST"()
7+
// CHECK-WMO-NOT: source_filename
8+
9+
10+
// RUN: %swift -target x86_64-apple-macosx10.9 -parse-stdlib -autolink-force-load -module-name TEST -module-link-name TEST -emit-ir -num-threads 1 %s %S/../Inputs/empty.swift | %FileCheck -check-prefix=CHECK-WMO-THREADED %s
11+
12+
// CHECK-WMO-THREADED: source_filename = "-"
13+
// CHECK-WMO-THREADED: define void @"_swift_FORCE_LOAD_$_TEST"()
14+
// CHECK-WMO-THREADED: source_filename = "-"
15+
// CHECK-WMO-THREADED-NOT: _swift_FORCE_LOAD_$_TEST
16+
// CHECK-WMO-THREADED-NOT: source_filename
17+
18+
19+
// RUN: %swift -target x86_64-apple-macosx10.9 -parse-stdlib -autolink-force-load -module-name TEST -module-link-name TEST -emit-ir -primary-file %s %S/../Inputs/empty.swift | %FileCheck -check-prefix=CHECK-SINGLE-FILE-FIRST %s
20+
// RUN: %swift -target x86_64-apple-macosx10.9 -parse-stdlib -autolink-force-load -module-name TEST -module-link-name TEST -emit-ir %S/../Inputs/empty.swift -primary-file %s | %FileCheck -check-prefix=CHECK-SINGLE-FILE-SECOND %s
21+
22+
// CHECK-SINGLE-FILE-FIRST: source_filename = "-"
23+
// CHECK-SINGLE-FILE-FIRST: define void @"_swift_FORCE_LOAD_$_TEST"()
24+
// CHECK-SINGLE-FILE-FIRST-NOT: source_filename
25+
26+
// CHECK-SINGLE-FILE-SECOND: source_filename = "-"
27+
// CHECK-SINGLE-FILE-SECOND-NOT: _swift_FORCE_LOAD_$_TEST
28+
// CHECK-SINGLE-FILE-SECOND-NOT: source_filename
29+

test/Serialization/autolinking.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,10 @@ import someModule
3838
// FRAMEWORK-DAG: !{{[0-9]+}} = !{!"-framework", !"someModule"}
3939

4040
// NO-FORCE-LOAD-NOT: FORCE_LOAD
41-
// FORCE-LOAD: define weak_odr void @"_swift_FORCE_LOAD_$_module"() {
41+
// FORCE-LOAD: define void @"_swift_FORCE_LOAD_$_module"() {
4242
// FORCE-LOAD: ret void
4343
// FORCE-LOAD: }
44-
// FORCE-LOAD-HEX: define weak_odr void @"_swift_FORCE_LOAD_$306d6f64756c65"() {
44+
// FORCE-LOAD-HEX: define void @"_swift_FORCE_LOAD_$306d6f64756c65"() {
4545
// FORCE-LOAD-HEX: ret void
4646
// FORCE-LOAD-HEX: }
4747

0 commit comments

Comments
 (0)