Index: COFF/Driver.cpp =================================================================== --- COFF/Driver.cpp +++ COFF/Driver.cpp @@ -512,6 +512,24 @@ std::string Rsp = "/nologo\n"; std::vector Temps; + // Write out archive members that we used in symbol resolution and pass these + // to MSVC before any archives, so that MSVC uses the same objects to satisfy + // references. + std::vector EarlyObjects; + for (const auto *O : Symtab.ObjectFiles) { + if (O->ParentName.empty()) + continue; + SmallString<128> S; + int Fd; + if (auto EC = sys::fs::createTemporaryFile( + "lld-" + sys::path::filename(O->ParentName), ".obj", Fd, S)) + fatal(EC, "cannot create a temporary file"); + raw_fd_ostream OS(Fd, /*shouldClose*/ true); + OS << O->MB.getBuffer(); + EarlyObjects.push_back(S.str()); + Rsp += quote(S); + } + for (auto *Arg : Args) { switch (Arg->getOption().getID()) { case OPT_linkrepro: @@ -544,6 +562,9 @@ for (StringRef Path : Temps) sys::fs::remove(Path); + + for (StringRef Path : EarlyObjects) + sys::fs::remove(Path); } void LinkerDriver::enqueueTask(std::function Task) { Index: COFF/InputFiles.h =================================================================== --- COFF/InputFiles.h +++ COFF/InputFiles.h @@ -58,6 +58,8 @@ // Returns the CPU type this file was compiled to. virtual MachineTypes getMachineType() { return IMAGE_FILE_MACHINE_UNKNOWN; } + MemoryBufferRef MB; + // An archive file name if this file is created from an archive. StringRef ParentName; @@ -67,7 +69,6 @@ protected: InputFile(Kind K, MemoryBufferRef M) : MB(M), FileKind(K) {} - MemoryBufferRef MB; std::string Directives; private: Index: test/COFF/Inputs/msvclto-order-a.ll =================================================================== --- /dev/null +++ test/COFF/Inputs/msvclto-order-a.ll @@ -0,0 +1,7 @@ +target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-pc-windows-msvc" + +define void @foo() { + ret void +} + Index: test/COFF/Inputs/msvclto-order-b.ll =================================================================== --- /dev/null +++ test/COFF/Inputs/msvclto-order-b.ll @@ -0,0 +1,10 @@ +target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-pc-windows-msvc" + +declare void @doesntexist() + +define void @foo() { + call void @doesntexist() + ret void +} + Index: test/COFF/msvclto-order.ll =================================================================== --- /dev/null +++ test/COFF/msvclto-order.ll @@ -0,0 +1,23 @@ +; RUN: opt -thinlto-bc %s -o %t.obj +; RUN: llc -filetype=obj %S/Inputs/msvclto-order-a.ll -o %T/msvclto-order-a.obj +; RUN: llvm-ar crs %T/msvclto-order-a.lib %T/msvclto-order-a.obj +; RUN: llc -filetype=obj %S/Inputs/msvclto-order-b.ll -o %T/msvclto-order-b.obj +; RUN: llvm-ar crs %T/msvclto-order-b.lib %T/msvclto-order-b.obj +; RUN: lld-link /verbose /msvclto /out:%t.exe /entry:main %t.obj \ +; RUN: %T/msvclto-order-a.lib %T/msvclto-order-b.lib > %t.log || true +; RUN: FileCheck %s < %t.log + +; CHECK: : link.exe +; CHECK-NOT: .lib{{$}} +; CHECK: lld-msvclto-order-a{{.*}}.obj +; CHECK: .lib{{$}} + +target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-pc-windows-msvc" + +declare void @foo() + +define i32 @main() { + call void @foo() + ret i32 0 +}