[IRGen] Be smarter about adding the FORCE_LINK symbols for overlays (#15647)

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 1025eed64 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.
diff --git a/lib/IRGen/IRGenModule.cpp b/lib/IRGen/IRGenModule.cpp
index 88d136c..21ed904 100644
--- a/lib/IRGen/IRGenModule.cpp
+++ b/lib/IRGen/IRGenModule.cpp
@@ -909,6 +909,23 @@
   llvm_unreachable("Could not replace old linker options entry?");
 }
 
+/// Returns true if the object file generated by \p IGM will be the "first"
+/// object file in the module. This lets us determine where to put a symbol
+/// that must be unique.
+static bool isFirstObjectFileInModule(IRGenModule &IGM) {
+  if (IGM.getSILModule().isWholeModule())
+    return IGM.IRGen.getPrimaryIGM() == &IGM;
+
+  const DeclContext *DC = IGM.getSILModule().getAssociatedContext();
+  if (!DC)
+    return false;
+
+  assert(!isa<ModuleDecl>(DC) && "that would be a whole module build");
+  assert(isa<FileUnit>(DC) && "compiling something smaller than a file?");
+  ModuleDecl *containingModule = cast<FileUnit>(DC)->getParentModule();
+  return containingModule->getFiles().front() == DC;
+}
+
 void IRGenModule::emitAutolinkInfo() {
   // Collect the linker options already in the module (from ClangCodeGen).
   // FIXME: This constant should be vended by LLVM somewhere.
@@ -963,12 +980,13 @@
     addUsedGlobal(var);
   }
 
-  if (!IRGen.Opts.ForceLoadSymbolName.empty()) {
+  if (!IRGen.Opts.ForceLoadSymbolName.empty() &&
+      isFirstObjectFileInModule(*this)) {
     llvm::SmallString<64> buf;
     encodeForceLoadSymbolName(buf, IRGen.Opts.ForceLoadSymbolName);
     auto ForceImportThunk =
         llvm::Function::Create(llvm::FunctionType::get(VoidTy, false),
-                               llvm::GlobalValue::WeakODRLinkage, buf,
+                               llvm::GlobalValue::ExternalLinkage, buf,
                                &Module);
     if (useDllStorage())
       ForceImportThunk
diff --git a/test/IRGen/autolink-force-link.swift b/test/IRGen/autolink-force-link.swift
new file mode 100644
index 0000000..bcf3546
--- /dev/null
+++ b/test/IRGen/autolink-force-link.swift
@@ -0,0 +1,29 @@
+// RUN: %empty-directory(%t)
+
+// 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
+
+// CHECK-WMO: source_filename = "-"
+// CHECK-WMO: define void @"_swift_FORCE_LOAD_$_TEST"()
+// CHECK-WMO-NOT: source_filename
+
+
+// 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
+
+// CHECK-WMO-THREADED: source_filename = "-"
+// CHECK-WMO-THREADED: define void @"_swift_FORCE_LOAD_$_TEST"()
+// CHECK-WMO-THREADED: source_filename = "-"
+// CHECK-WMO-THREADED-NOT: _swift_FORCE_LOAD_$_TEST
+// CHECK-WMO-THREADED-NOT: source_filename
+
+
+// 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
+// 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
+
+// CHECK-SINGLE-FILE-FIRST: source_filename = "-"
+// CHECK-SINGLE-FILE-FIRST: define void @"_swift_FORCE_LOAD_$_TEST"()
+// CHECK-SINGLE-FILE-FIRST-NOT: source_filename
+
+// CHECK-SINGLE-FILE-SECOND: source_filename = "-"
+// CHECK-SINGLE-FILE-SECOND-NOT: _swift_FORCE_LOAD_$_TEST
+// CHECK-SINGLE-FILE-SECOND-NOT: source_filename
+
diff --git a/test/Serialization/autolinking.swift b/test/Serialization/autolinking.swift
index 468a226..f8e9ab1 100644
--- a/test/Serialization/autolinking.swift
+++ b/test/Serialization/autolinking.swift
@@ -38,10 +38,10 @@
 // FRAMEWORK-DAG: !{{[0-9]+}} = !{!"-framework", !"someModule"}
 
 // NO-FORCE-LOAD-NOT: FORCE_LOAD
-// FORCE-LOAD: define weak_odr void @"_swift_FORCE_LOAD_$_module"() {
+// FORCE-LOAD: define 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: define void @"_swift_FORCE_LOAD_$306d6f64756c65"() {
 // FORCE-LOAD-HEX:   ret void
 // FORCE-LOAD-HEX: }