[COFF] added support for /lldsavetemps

Summary: This adds an option to save temporary files generated during link-time optimization. This can be useful for debugging.

Reviewers: ruiu, pcc

Reviewed By: ruiu, pcc

Subscribers: mehdi_amini

Differential Revision: https://reviews.llvm.org/D29518

llvm-svn: 294498
This commit is contained in:
Bob Haarman 2017-02-08 18:36:41 +00:00
parent d93d7754c4
commit 69b196dd91
5 changed files with 54 additions and 3 deletions

View File

@ -105,6 +105,8 @@ struct Configuration {
std::map<std::string, int> DLLOrder;
SymbolBody *DelayLoadHelper = nullptr;
bool SaveTemps = false;
// Used for SafeSEH.
Symbol *SEHTable = nullptr;
Symbol *SEHCount = nullptr;

View File

@ -622,6 +622,10 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
}
}
// Handle /lldsavetemps
if (Args.hasArg(OPT_lldsavetemps))
Config->SaveTemps = true;
// Handle /failifmismatch
for (auto *Arg : Args.filtered(OPT_failifmismatch))
checkFailIfMismatch(Arg->getValue());

View File

@ -54,6 +54,14 @@ static void checkError(Error E) {
});
}
static void saveBuffer(StringRef Buffer, const Twine &Path) {
std::error_code EC;
raw_fd_ostream OS(Path.str(), EC, sys::fs::OpenFlags::F_None);
if (EC)
error("cannot create " + Path + ": " + EC.message());
OS << Buffer;
}
static std::unique_ptr<lto::LTO> createLTO() {
lto::Config Conf;
Conf.Options = InitTargetOptionsFromCodeGenFlags();
@ -61,6 +69,9 @@ static std::unique_ptr<lto::LTO> createLTO() {
Conf.DisableVerify = true;
Conf.DiagHandler = diagnosticHandler;
Conf.OptLevel = Config->LTOOptLevel;
if (Config->SaveTemps)
checkError(Conf.addSaveTemps(std::string(Config->OutputFile) + ".",
/*UseInputModulePath*/ true));
lto::ThinBackend Backend;
if (Config->LTOJobs != -1u)
Backend = lto::createInProcessThinBackend(Config->LTOJobs);
@ -116,8 +127,16 @@ std::vector<StringRef> BitcodeCompiler::compile() {
}));
std::vector<StringRef> Ret;
for (unsigned I = 0; I != MaxTasks; ++I)
if (!Buff[I].empty())
Ret.emplace_back(Buff[I].data(), Buff[I].size());
for (unsigned I = 0; I != MaxTasks; ++I) {
if (Buff[I].empty())
continue;
if (Config->SaveTemps) {
if (I == 0)
saveBuffer(Buff[I], Config->OutputFile + ".lto.obj");
else
saveBuffer(Buff[I], Config->OutputFile + Twine(I) + ".lto.obj");
}
Ret.emplace_back(Buff[I].data(), Buff[I].size());
}
return Ret;
}

View File

@ -28,6 +28,8 @@ def heap : P<"heap", "Size of the heap">;
def implib : P<"implib", "Import library name">;
def libpath : P<"libpath", "Additional library search path">;
def linkrepro : P<"linkrepro", "Dump linker invocation and input files for debugging">;
def lldsavetemps : F<"lldsavetemps">,
HelpText<"Save temporary files instead of deleting them">;
def machine : P<"machine", "Specify target platform">;
def merge : P<"merge", "Combine sections">;
def mllvm : P<"mllvm", "Options to pass to LLVM">;

View File

@ -0,0 +1,24 @@
; RUN: rm -f %T/savetemps.*
; RUN: llvm-as -o %T/savetemps.obj %s
; RUN: lld-link /out:%T/savetemps.exe /entry:main /subsystem:console %T/savetemps.obj
; RUN: not llvm-dis -o - %T/savetemps.exe.0.0.preopt.bc
; RUN: not llvm-dis -o - %T/savetemps.exe.0.2.internalize.bc
; RUN: not llvm-dis -o - %T/savetemps.exe.0.4.opt.bc
; RUN: not llvm-dis -o - %T/savetemps.exe.0.5.precodegen.bc
; RUN: not llvm-objdump -s %T/savetemps.exe.lto.obj
; RUN: lld-link /lldsavetemps /out:%T/savetemps.exe /entry:main /subsystem:console %T/savetemps.obj
; RUN: llvm-dis -o - %T/savetemps.exe.0.0.preopt.bc | FileCheck %s
; RUN: llvm-dis -o - %T/savetemps.exe.0.2.internalize.bc | FileCheck %s
; RUN: llvm-dis -o - %T/savetemps.exe.0.4.opt.bc | FileCheck %s
; RUN: llvm-dis -o - %T/savetemps.exe.0.5.precodegen.bc | FileCheck %s
; RUN: llvm-objdump -s %T/savetemps.exe.lto.obj | FileCheck --check-prefix=CHECK-OBJDUMP %s
; CHECK: define i32 @main()
; CHECK-OBJDUMP: file format COFF
target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-windows-msvc"
define i32 @main() {
ret i32 0
}