diff --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp --- a/lld/MachO/Driver.cpp +++ b/lld/MachO/Driver.cpp @@ -274,8 +274,7 @@ if (config->allLoad || forceLoadArchive) { if (Optional buffer = readFile(path)) { for (const ArchiveMember &member : getArchiveMembers(*buffer)) { - inputFiles.push_back( - make(member.mbref, member.modTime, path)); + inputFiles.insert(make(member.mbref, member.modTime, path)); printArchiveMemberLoad( (forceLoadArchive ? "-force_load" : "-all_load"), inputFiles.back()); @@ -293,7 +292,7 @@ if (Optional buffer = readFile(path)) { for (const ArchiveMember &member : getArchiveMembers(*buffer)) { if (hasObjCSection(member.mbref)) { - inputFiles.push_back( + inputFiles.insert( make(member.mbref, member.modTime, path)); printArchiveMemberLoad("-ObjC", inputFiles.back()); } @@ -325,7 +324,7 @@ // print the .a name here. if (config->printEachFile && magic != file_magic::archive) lld::outs() << toString(newFile) << '\n'; - inputFiles.push_back(newFile); + inputFiles.insert(newFile); } return newFile; } @@ -521,7 +520,7 @@ lto->add(*bitcodeFile); for (ObjFile *file : lto->compile()) - inputFiles.push_back(file); + inputFiles.insert(file); } // Replaces common symbols with defined symbols residing in __common sections. @@ -873,7 +872,7 @@ StringRef fileName = arg->getValue(2); Optional buffer = readFile(fileName); if (buffer) - inputFiles.push_back(make(*buffer, segName, sectName)); + inputFiles.insert(make(*buffer, segName, sectName)); } // Initialize InputSections. diff --git a/lld/MachO/DriverUtils.cpp b/lld/MachO/DriverUtils.cpp --- a/lld/MachO/DriverUtils.cpp +++ b/lld/MachO/DriverUtils.cpp @@ -15,7 +15,7 @@ #include "lld/Common/Memory.h" #include "lld/Common/Reproduce.h" #include "llvm/ADT/CachedHashString.h" -#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/Option/Arg.h" #include "llvm/Option/ArgList.h" #include "llvm/Option/Option.h" @@ -168,33 +168,32 @@ return {}; } -static Optional makeDylibFromTapi(MemoryBufferRef mbref, - DylibFile *umbrella) { - Expected> result = TextAPIReader::get(mbref); - if (!result) { - error("could not load TAPI file at " + mbref.getBufferIdentifier() + ": " + - toString(result.takeError())); - return {}; - } - return make(**result, umbrella); -} - -static DenseSet loadedDylibs; +// It's not uncommon to have multiple attempts to load a single dylib, +// especially if it's a commonly re-exported core library. +static DenseMap loadedDylibs; Optional macho::loadDylib(MemoryBufferRef mbref, DylibFile *umbrella) { StringRef path = mbref.getBufferIdentifier(); - if (loadedDylibs.contains(CachedHashStringRef(path))) - return {}; - loadedDylibs.insert(CachedHashStringRef(path)); + DylibFile *&file = loadedDylibs[CachedHashStringRef(path)]; + if (file) + return file; file_magic magic = identify_magic(mbref.getBuffer()); - if (magic == file_magic::tapi_file) - return makeDylibFromTapi(mbref, umbrella); - - assert(magic == file_magic::macho_dynamically_linked_shared_lib || - magic == file_magic::macho_dynamically_linked_shared_lib_stub); - return make(mbref, umbrella); + if (magic == file_magic::tapi_file) { + Expected> result = TextAPIReader::get(mbref); + if (!result) { + error("could not load TAPI file at " + mbref.getBufferIdentifier() + + ": " + toString(result.takeError())); + return {}; + } + file = make(**result, umbrella); + } else { + assert(magic == file_magic::macho_dynamically_linked_shared_lib || + magic == file_magic::macho_dynamically_linked_shared_lib_stub); + file = make(mbref, umbrella); + } + return file; } uint32_t macho::getModTime(StringRef path) { diff --git a/lld/MachO/InputFiles.h b/lld/MachO/InputFiles.h --- a/lld/MachO/InputFiles.h +++ b/lld/MachO/InputFiles.h @@ -14,6 +14,7 @@ #include "lld/Common/LLVM.h" #include "lld/Common/Memory.h" #include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/SetVector.h" #include "llvm/BinaryFormat/MachO.h" #include "llvm/DebugInfo/DWARF/DWARFUnit.h" #include "llvm/Object/Archive.h" @@ -158,7 +159,7 @@ std::unique_ptr obj; }; -extern std::vector inputFiles; +extern llvm::SetVector inputFiles; llvm::Optional readFile(StringRef path); diff --git a/lld/MachO/InputFiles.cpp b/lld/MachO/InputFiles.cpp --- a/lld/MachO/InputFiles.cpp +++ b/lld/MachO/InputFiles.cpp @@ -85,7 +85,7 @@ .str(); } -std::vector macho::inputFiles; +SetVector macho::inputFiles; std::unique_ptr macho::tar; int InputFile::idCount = 0; @@ -516,7 +516,7 @@ void loadReexport(StringRef path, DylibFile *umbrella) { Optional reexport = loadReexportHelper(path, umbrella); if (reexport && isImplicitlyLinked(path)) - inputFiles.push_back(*reexport); + inputFiles.insert(*reexport); } DylibFile::DylibFile(MemoryBufferRef mb, DylibFile *umbrella) @@ -670,7 +670,7 @@ " has unhandled file type"); return; } - inputFiles.push_back(file); + inputFiles.insert(file); // ld64 doesn't demangle sym here even with -demangle. Match that, so // intentionally no call to toMachOString() here. diff --git a/lld/test/MachO/invalid/duplicate-symbol.s b/lld/test/MachO/invalid/duplicate-symbol.s --- a/lld/test/MachO/invalid/duplicate-symbol.s +++ b/lld/test/MachO/invalid/duplicate-symbol.s @@ -2,6 +2,7 @@ # RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %s -o %t.o # RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %s -o %t-dup.o # RUN: not %lld -o /dev/null %t-dup.o %t.o 2>&1 | FileCheck %s +# RUN: not %lld -o /dev/null %t.o %t.o 2>&1 | FileCheck %s # CHECK: error: duplicate symbol: _main diff --git a/lld/test/MachO/weak-import.s b/lld/test/MachO/weak-import.s --- a/lld/test/MachO/weak-import.s +++ b/lld/test/MachO/weak-import.s @@ -6,6 +6,10 @@ # RUN: %lld -weak-lSystem %t/test.o -weak_framework CoreFoundation -weak_library %t/libfoo.dylib -o %t/test # RUN: llvm-objdump --macho --all-headers %t/test | FileCheck %s -DDIR=%t +# RUN: %lld -weak-lSystem %t/test.o \ +# RUN: -framework CoreFoundation -weak_framework CoreFoundation -framework CoreFoundation \ +# RUN: %t/libfoo.dylib -weak_library %t/libfoo.dylib %t/libfoo.dylib -o %t/test +# RUN: llvm-objdump --macho --all-headers %t/test | FileCheck %s -DDIR=%t # CHECK: cmd LC_LOAD_WEAK_DYLIB # CHECK-NEXT: cmdsize