Index: lld/trunk/ELF/Config.h =================================================================== --- lld/trunk/ELF/Config.h +++ lld/trunk/ELF/Config.h @@ -69,6 +69,7 @@ bool NoinhibitExec; bool PrintGcSections; bool Relocatable; + bool SaveTemps; bool Shared; bool Static = false; bool StripAll; Index: lld/trunk/ELF/Driver.cpp =================================================================== --- lld/trunk/ELF/Driver.cpp +++ lld/trunk/ELF/Driver.cpp @@ -239,6 +239,7 @@ Config->NoinhibitExec = Args.hasArg(OPT_noinhibit_exec); Config->PrintGcSections = Args.hasArg(OPT_print_gc_sections); Config->Relocatable = Args.hasArg(OPT_relocatable); + Config->SaveTemps = Args.hasArg(OPT_save_temps); Config->Shared = Args.hasArg(OPT_shared); Config->StripAll = Args.hasArg(OPT_strip_all); Config->Verbose = Args.hasArg(OPT_verbose); Index: lld/trunk/ELF/Options.td =================================================================== --- lld/trunk/ELF/Options.td +++ lld/trunk/ELF/Options.td @@ -182,3 +182,6 @@ // Aliases for ignored options def alias_version_script_version_script : Joined<["--"], "version-script=">, Alias; + +// Debugging options +def save_temps : Flag<["-"], "save-temps">; Index: lld/trunk/ELF/SymbolTable.cpp =================================================================== --- lld/trunk/ELF/SymbolTable.cpp +++ lld/trunk/ELF/SymbolTable.cpp @@ -147,6 +147,13 @@ Mover.move(std::move(M), Keep, [](GlobalValue &, IRMover::ValueAdder) {}); } +static void saveBCFile(std::string Path, Module &M) { + std::error_code EC; + raw_fd_ostream OS(Path, EC, sys::fs::OpenFlags::F_None); + check(EC); + WriteBitcodeToFile(&M, OS, /* ShouldPreserveUseListOrder */ true); +} + // Merge all the bitcode files we have seen, codegen the result and return // the resulting ObjectFile. template @@ -156,6 +163,8 @@ IRMover Mover(Combined); for (const std::unique_ptr &F : BitcodeFiles) addBitcodeFile(Mover, *F, Context); + if (Config->SaveTemps) + saveBCFile(Config->OutputFile.str() + ".lto.bc", Combined); std::unique_ptr F = codegen(Combined); ObjectFiles.emplace_back(cast>(F.release())); return &*ObjectFiles.back(); Index: lld/trunk/test/ELF/lto/Inputs/save-temps.ll =================================================================== --- lld/trunk/test/ELF/lto/Inputs/save-temps.ll +++ lld/trunk/test/ELF/lto/Inputs/save-temps.ll @@ -0,0 +1,6 @@ +target triple = "x86_64-unknown-linux-gnu" +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" + +define void @bar() { + ret void +} Index: lld/trunk/test/ELF/lto/save-temps.ll =================================================================== --- lld/trunk/test/ELF/lto/save-temps.ll +++ lld/trunk/test/ELF/lto/save-temps.ll @@ -0,0 +1,17 @@ +; REQUIRES: x86 +; RUN: rm -f %t.so %t.so.lto.bc +; RUN: llvm-as %s -o %t.o +; RUN: llvm-as %p/Inputs/save-temps.ll -o %t2.o +; RUN: ld.lld -shared -m elf_x86_64 %t.o %t2.o -o %t.so -save-temps +; RUN: llvm-nm %t.so | FileCheck %s +; RUN: llvm-nm %t.so.lto.bc | FileCheck %s + +target triple = "x86_64-unknown-linux-gnu" +target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" + +define void @foo() { + ret void +} + +; CHECK-DAG: T bar +; CHECK-DAG: T foo