diff --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp --- a/lld/MachO/Driver.cpp +++ b/lld/MachO/Driver.cpp @@ -246,10 +246,20 @@ return CHECK(parseCachePruningPolicy(ltoPolicy), "invalid LTO cache policy"); } -static DenseMap loadedArchives; +static DenseMap loadedObjects; static InputFile *addFile(StringRef path, ForceLoad forceLoadArchive, bool isExplicit = true, bool isBundleLoader = false) { + // Avoid loading archives twice. If the archives are being force-loaded, + // loading them twice would create duplicate symbol errors. In the + // non-force-loading case, this is just a minor performance optimization. We + // don't take a reference to cachedFile here because the loadArchiveMember() + // call below may recursively call addFile() and invalidate this reference. + // For objects included multiple times in LC_LINKER_OPTIONs multiple loads + // can also lead to duplicate symbol errors. + if (InputFile *cachedFile = loadedObjects[path]) + return cachedFile; + Optional buffer = readFile(path); if (!buffer) return nullptr; @@ -259,15 +269,6 @@ file_magic magic = identify_magic(mbref.getBuffer()); switch (magic) { case file_magic::archive: { - // Avoid loading archives twice. If the archives are being force-loaded, - // loading them twice would create duplicate symbol errors. In the - // non-force-loading case, this is just a minor performance optimization. - // We don't take a reference to cachedFile here because the - // loadArchiveMember() call below may recursively call addFile() and - // invalidate this reference. - if (ArchiveFile *cachedFile = loadedArchives[path]) - return cachedFile; - std::unique_ptr archive = CHECK( object::Archive::create(mbref), path + ": failed to parse archive"); @@ -315,11 +316,11 @@ } file->addLazySymbols(); - newFile = loadedArchives[path] = file; + newFile = loadedObjects[path] = file; break; } case file_magic::macho_object: - newFile = make(mbref, getModTime(path), ""); + newFile = loadedObjects[path] = make(mbref, getModTime(path), ""); break; case file_magic::macho_dynamically_linked_shared_lib: case file_magic::macho_dynamically_linked_shared_lib_stub: @@ -331,7 +332,7 @@ } break; case file_magic::bitcode: - newFile = make(mbref, "", 0); + newFile = loadedObjects[path] = make(mbref, "", 0); break; case file_magic::macho_executable: case file_magic::macho_bundle: @@ -1097,7 +1098,7 @@ concatOutputSections.clear(); inputFiles.clear(); inputSections.clear(); - loadedArchives.clear(); + loadedObjects.clear(); syntheticSections.clear(); thunkMap.clear(); diff --git a/lld/test/MachO/framework-object.ll b/lld/test/MachO/framework-object.ll new file mode 100644 --- /dev/null +++ b/lld/test/MachO/framework-object.ll @@ -0,0 +1,30 @@ +; REQUIRES: x86 +; RUN: rm -rf %t; split-file %s %t + +; RUN: mkdir -p %t/Foo.framework +; RUN: llc --filetype=obj %t/framework.ll -o %t/Foo.framework/Foo +; RUN: llc --filetype=obj %t/load-framework-foo.ll -o %t/main +; RUN: %lld %t/main -F %t -framework Foo -framework Foo + +; RUN: llvm-as %t/framework.ll -o %t/Foo.framework/Foo +; RUN: llvm-as %t/load-framework-foo.ll -o %t/main +; RUN: %lld %t/main -F %t -framework Foo -framework Foo + +;--- framework.ll +target triple = "x86_64-apple-macosx10.15.0" +target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" + +define void @foo() { + ret void +} + +;--- load-framework-foo.ll +target triple = "x86_64-apple-macosx10.15.0" +target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" + +!0 = !{!"-framework", !"Foo"} +!llvm.linker.options = !{!0, !0} + +define void @main() { + ret void +}