[lld] r294234 - Add an option to use the MSVC linker to link LTO-generated object files.
Rui Ueyama via llvm-commits
llvm-commits at lists.llvm.org
Mon Feb 6 12:47:56 PST 2017
Author: ruiu
Date: Mon Feb 6 14:47:55 2017
New Revision: 294234
URL: http://llvm.org/viewvc/llvm-project?rev=294234&view=rev
Log:
Add an option to use the MSVC linker to link LTO-generated object files.
This patch defines a new command line option, /MSVCLTO, to LLD.
If that option is given, LLD invokes link.exe to link LTO-generated
object files. This is hacky but useful because link.exe can create
PDB files.
Differential Revision: https://reviews.llvm.org/D29526
Added:
lld/trunk/test/COFF/Inputs/msvclto.s
lld/trunk/test/COFF/msvclto.ll
Modified:
lld/trunk/COFF/Driver.cpp
lld/trunk/COFF/Driver.h
lld/trunk/COFF/DriverUtils.cpp
lld/trunk/COFF/LTO.cpp
lld/trunk/COFF/LTO.h
lld/trunk/COFF/Options.td
lld/trunk/COFF/SymbolTable.cpp
lld/trunk/COFF/SymbolTable.h
Modified: lld/trunk/COFF/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Driver.cpp?rev=294234&r1=294233&r2=294234&view=diff
==============================================================================
--- lld/trunk/COFF/Driver.cpp (original)
+++ lld/trunk/COFF/Driver.cpp Mon Feb 6 14:47:55 2017
@@ -814,6 +814,14 @@ void LinkerDriver::link(ArrayRef<const c
addUndefined(mangle("_load_config_used"));
} while (run());
+ // If /msvclto is given, we use the MSVC linker to link LTO output files.
+ // This is useful because MSVC link.exe can generate complete PDBs.
+ if (Args.hasArg(OPT_msvclto)) {
+ std::vector<StringRef> ObjectFiles = Symtab.compileBitcodeFiles();
+ runMSVCLinker(Args, ObjectFiles);
+ exit(0);
+ }
+
// Do LTO by compiling bitcode input files to a set of native COFF files then
// link those files.
Symtab.addCombinedLTOObjects();
Modified: lld/trunk/COFF/Driver.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Driver.h?rev=294234&r1=294233&r2=294234&view=diff
==============================================================================
--- lld/trunk/COFF/Driver.h (original)
+++ lld/trunk/COFF/Driver.h Mon Feb 6 14:47:55 2017
@@ -178,6 +178,8 @@ void checkFailIfMismatch(StringRef Arg);
std::unique_ptr<MemoryBuffer>
convertResToCOFF(const std::vector<MemoryBufferRef> &MBs);
+void runMSVCLinker(llvm::opt::InputArgList &Args, ArrayRef<StringRef> Objects);
+
// Create enum with OPT_xxx values for each option in Options.td
enum {
OPT_INVALID = 0,
Modified: lld/trunk/COFF/DriverUtils.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/DriverUtils.cpp?rev=294234&r1=294233&r2=294234&view=diff
==============================================================================
--- lld/trunk/COFF/DriverUtils.cpp (original)
+++ lld/trunk/COFF/DriverUtils.cpp Mon Feb 6 14:47:55 2017
@@ -50,10 +50,18 @@ public:
void add(const char *S) { Args.push_back(Saver.save(S).data()); }
void run() {
+ if (Config->Verbose) {
+ outs() << Prog;
+ for (const char *Arg : Args)
+ outs() << " " << Arg;
+ outs() << '\n';
+ }
+
ErrorOr<std::string> ExeOrErr = sys::findProgramByName(Prog);
if (auto EC = ExeOrErr.getError())
fatal(EC, "unable to find " + Prog + " in PATH: ");
const char *Exe = Saver.save(*ExeOrErr).data();
+
Args.insert(Args.begin(), Exe);
Args.push_back(nullptr);
if (sys::ExecuteAndWait(Args[0], Args.data()) != 0) {
@@ -282,11 +290,19 @@ static void quoteAndPrint(raw_ostream &O
namespace {
class TemporaryFile {
public:
- TemporaryFile(StringRef Prefix, StringRef Extn) {
+ TemporaryFile(StringRef Prefix, StringRef Extn, StringRef Contents = "") {
SmallString<128> S;
if (auto EC = sys::fs::createTemporaryFile("lld-" + Prefix, Extn, S))
fatal(EC, "cannot create a temporary file");
Path = S.str();
+
+ if (!Contents.empty()) {
+ std::error_code EC;
+ raw_fd_ostream OS(Path, EC, sys::fs::F_None);
+ if (EC)
+ fatal(EC, "failed to open " + Path);
+ OS << Contents;
+ }
}
TemporaryFile(TemporaryFile &&Obj) {
@@ -617,6 +633,60 @@ convertResToCOFF(const std::vector<Memor
return File.getMemoryBuffer();
}
+static bool isBitcodeFile(StringRef Path) {
+ std::unique_ptr<MemoryBuffer> MB = check(
+ MemoryBuffer::getFile(Path, -1, false, true), "could not open " + Path);
+ StringRef Buf = MB->getBuffer();
+ return sys::fs::identify_magic(Buf) == sys::fs::file_magic::bitcode;
+}
+
+// Run MSVC link.exe for given in-memory object files.
+// Command line options are copied from those given to LLD.
+// This is for the /msvclto option.
+void runMSVCLinker(opt::InputArgList &Args, ArrayRef<StringRef> Objects) {
+ // Write the in-memory object files to disk.
+ std::vector<TemporaryFile> Temps;
+ for (StringRef S : Objects)
+ Temps.emplace_back("lto", "obj", S);
+
+ // Create a response file.
+ std::string Rsp = "/nologo ";
+ for (TemporaryFile &T : Temps)
+ Rsp += quote(T.Path) + " ";
+
+ for (auto *Arg : Args) {
+ switch (Arg->getOption().getID()) {
+ case OPT_linkrepro:
+ case OPT_lldmap:
+ case OPT_lldmap_file:
+ case OPT_msvclto:
+ // LLD-specific options are stripped.
+ break;
+ case OPT_opt:
+ if (!StringRef(Arg->getValue()).startswith("lld"))
+ Rsp += toString(Arg) + " ";
+ break;
+ case OPT_INPUT:
+ // Bitcode files are stripped as they've been compiled to
+ // native object files.
+ if (!isBitcodeFile(Arg->getValue()))
+ Rsp += quote(Arg->getValue()) + " ";
+ break;
+ default:
+ Rsp += toString(Arg) + " ";
+ }
+ }
+
+ if (Config->Verbose)
+ outs() << "link.exe " << Rsp << "\n";
+
+ // Run MSVC link.exe.
+ Temps.emplace_back("lto", "rsp", Rsp);
+ Executor E("link.exe");
+ E.add(Twine("@" + Temps.back().Path));
+ E.run();
+}
+
// Create OptTable
// Create prefix string literals used in Options.td
Modified: lld/trunk/COFF/LTO.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/LTO.cpp?rev=294234&r1=294233&r2=294234&view=diff
==============================================================================
--- lld/trunk/COFF/LTO.cpp (original)
+++ lld/trunk/COFF/LTO.cpp Mon Feb 6 14:47:55 2017
@@ -105,9 +105,8 @@ void BitcodeCompiler::add(BitcodeFile &F
}
// Merge all the bitcode files we have seen, codegen the result
-// and return the resulting ObjectFile(s).
-std::vector<InputFile *> BitcodeCompiler::compile() {
- std::vector<InputFile *> Ret;
+// and return the resulting objects.
+std::vector<StringRef> BitcodeCompiler::compile() {
unsigned MaxTasks = LTOObj->getMaxTasks();
Buff.resize(MaxTasks);
@@ -116,10 +115,9 @@ std::vector<InputFile *> BitcodeCompiler
llvm::make_unique<raw_svector_ostream>(Buff[Task]));
}));
- for (unsigned I = 0; I != MaxTasks; ++I) {
- if (Buff[I].empty())
- continue;
- Ret.push_back(make<ObjectFile>(MemoryBufferRef(Buff[I], "lto.tmp")));
- }
+ std::vector<StringRef> Ret;
+ for (unsigned I = 0; I != MaxTasks; ++I)
+ if (!Buff[I].empty())
+ Ret.emplace_back(Buff[I].data(), Buff[I].size());
return Ret;
}
Modified: lld/trunk/COFF/LTO.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/LTO.h?rev=294234&r1=294233&r2=294234&view=diff
==============================================================================
--- lld/trunk/COFF/LTO.h (original)
+++ lld/trunk/COFF/LTO.h Mon Feb 6 14:47:55 2017
@@ -44,7 +44,7 @@ public:
~BitcodeCompiler();
void add(BitcodeFile &F);
- std::vector<InputFile *> compile();
+ std::vector<StringRef> compile();
private:
std::unique_ptr<llvm::lto::LTO> LTOObj;
Modified: lld/trunk/COFF/Options.td
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/Options.td?rev=294234&r1=294233&r2=294234&view=diff
==============================================================================
--- lld/trunk/COFF/Options.td (original)
+++ lld/trunk/COFF/Options.td Mon Feb 6 14:47:55 2017
@@ -92,6 +92,7 @@ def help_q : Flag<["/?", "-?"], "">, Ali
// LLD extensions
def nosymtab : F<"nosymtab">;
+def msvclto : F<"msvclto">;
// Flags for debugging
def debugpdb : F<"debugpdb">;
Modified: lld/trunk/COFF/SymbolTable.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/SymbolTable.cpp?rev=294234&r1=294233&r2=294234&view=diff
==============================================================================
--- lld/trunk/COFF/SymbolTable.cpp (original)
+++ lld/trunk/COFF/SymbolTable.cpp Mon Feb 6 14:47:55 2017
@@ -351,19 +351,22 @@ SymbolBody *SymbolTable::addUndefined(St
return addUndefined(Name, nullptr, false)->body();
}
-void SymbolTable::addCombinedLTOObjects() {
- if (BitcodeFiles.empty())
- return;
-
+std::vector<StringRef> SymbolTable::compileBitcodeFiles() {
LTO.reset(new BitcodeCompiler);
for (BitcodeFile *F : BitcodeFiles)
LTO->add(*F);
+ return LTO->compile();
+}
- for (auto *File : LTO->compile()) {
- auto *Obj = cast<ObjectFile>(File);
- ObjectFiles.push_back(Obj);
+void SymbolTable::addCombinedLTOObjects() {
+ if (BitcodeFiles.empty())
+ return;
+ for (StringRef Object : compileBitcodeFiles()) {
+ auto *Obj = make<ObjectFile>(MemoryBufferRef(Object, "lto.tmp"));
Obj->parse();
+ ObjectFiles.push_back(Obj);
}
}
+
} // namespace coff
} // namespace lld
Modified: lld/trunk/COFF/SymbolTable.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/COFF/SymbolTable.h?rev=294234&r1=294233&r2=294234&view=diff
==============================================================================
--- lld/trunk/COFF/SymbolTable.h (original)
+++ lld/trunk/COFF/SymbolTable.h Mon Feb 6 14:47:55 2017
@@ -74,6 +74,7 @@ public:
// BitcodeFiles and add them to the symbol table. Called after all files are
// added and before the writer writes results to a file.
void addCombinedLTOObjects();
+ std::vector<StringRef> compileBitcodeFiles();
// The writer needs to handle DLL import libraries specially in
// order to create the import descriptor table.
Added: lld/trunk/test/COFF/Inputs/msvclto.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/Inputs/msvclto.s?rev=294234&view=auto
==============================================================================
--- lld/trunk/test/COFF/Inputs/msvclto.s (added)
+++ lld/trunk/test/COFF/Inputs/msvclto.s Mon Feb 6 14:47:55 2017
@@ -0,0 +1,3 @@
+.globl foo
+foo:
+ret
Added: lld/trunk/test/COFF/msvclto.ll
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/COFF/msvclto.ll?rev=294234&view=auto
==============================================================================
--- lld/trunk/test/COFF/msvclto.ll (added)
+++ lld/trunk/test/COFF/msvclto.ll Mon Feb 6 14:47:55 2017
@@ -0,0 +1,17 @@
+; RUN: llvm-as -o %t1.obj %s
+; RUN: llvm-mc -triple=x86_64-pc-windows-msvc -filetype=obj -o %t2.obj %p/Inputs/msvclto.s
+; RUN: lld-link %t1.obj %t2.obj /msvclto /out:%t.exe /opt:lldlto=1 /opt:icf \
+; RUN: /entry:main /verbose /subsystem:console > %t.log 2>&1 || true
+; RUN: FileCheck %s < %t.log
+
+; CHECK: link.exe /nologo {{.*}} {{.*}}2.obj /out:{{.*}}.exe /opt:icf /entry:main /verbose /subsystem:console
+
+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
+}
More information about the llvm-commits
mailing list