Index: include/llvm/LTO/Config.h =================================================================== --- include/llvm/LTO/Config.h +++ include/llvm/LTO/Config.h @@ -17,6 +17,7 @@ #include "llvm/IR/DiagnosticInfo.h" #include "llvm/Support/CodeGen.h" +#include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" #include @@ -121,6 +122,9 @@ /// called for ThinLTO tasks. typedef std::function ModuleHookFn; + typedef std::function + ModuleAsmHookFn; + /// This module hook is called after linking (regular LTO) or loading /// (ThinLTO) the module, before modifying it. ModuleHookFn PreOptModuleHook; @@ -143,6 +147,10 @@ /// splitting the module. ModuleHookFn PreCodeGenModuleHook; + /// This module hook is called before code generation. It generates + /// assembly file by running all the codegen passes on module + ModuleAsmHookFn PostCodeGenModuleHook; + /// A combined index hook is called after all per-module indexes have been /// combined (ThinLTO-specific). It can be used to implement -save-temps for /// the combined index. @@ -175,6 +183,7 @@ PostImportModuleHook(std::move(X.PostImportModuleHook)), PostOptModuleHook(std::move(X.PostOptModuleHook)), PreCodeGenModuleHook(std::move(X.PreCodeGenModuleHook)), + PostCodeGenModuleHook(std::move(X.PostCodeGenModuleHook)), CombinedIndexHook(std::move(X.CombinedIndexHook)) {} // FIXME: Remove once MSVC can synthesize move ops. Config &operator=(Config &&X) { @@ -245,7 +254,6 @@ } DiagnosticHandlerFunction DiagHandler; }; - } } Index: lib/LTO/LTOBackend.cpp =================================================================== --- lib/LTO/LTOBackend.cpp +++ lib/LTO/LTOBackend.cpp @@ -28,6 +28,7 @@ #include "llvm/Target/TargetMachine.h" #include "llvm/Transforms/IPO.h" #include "llvm/Transforms/IPO/PassManagerBuilder.h" +#include "llvm/Transforms/Utils/Cloning.h" #include "llvm/Transforms/Utils/FunctionImportUtils.h" #include "llvm/Transforms/Utils/SplitModule.h" @@ -76,12 +77,57 @@ }; }; + auto setAsmHook = [&](std::string PathSuffix, ModuleAsmHookFn &Hook) { + // Keep track of the hook provided by the linker, which also needs to run. + ModuleAsmHookFn LinkerHook = Hook; + Hook = [=](unsigned Task, const Module &M, TargetMachine *TM) { + //// If the linker's hook returned false, we need to pass that result + //// through. + // if (LinkerHook && !LinkerHook(Task, M)) + // return false; + + auto AsmGenModule = CloneModule(&M); + std::string PathPrefix; + // If this is the combined module (not a ThinLTO backend compile) or the + // user hasn't requested using the input module's path, emit to a file + // named from the provided OutputFileName with the Task ID appended. + if (M.getModuleIdentifier() == "ld-temp.o" || !UseInputModulePath) { + PathPrefix = OutputFileName + utostr(Task); + } else + PathPrefix = M.getModuleIdentifier(); + std::string Path = PathPrefix + "." + PathSuffix + ".s"; + std::error_code EC; + int FD; + EC = sys::fs::openFileForWrite(StringRef(Path), FD, sys::fs::F_None); + if (EC) { + // Because -save-temps is a debugging feature, we report the error + // directly and exit. + llvm::errs() << "failed to open " << Path << ": " << EC.message() + << '\n'; + exit(1); + } + + std::unique_ptr OS = + llvm::make_unique(FD, true); + + legacy::PassManager CodeGenPasses; + + if (TM->addPassesToEmitFile(CodeGenPasses, *OS, + TargetMachine::CGFT_AssemblyFile)) + report_fatal_error("Failed to setup assembly gen in codegen"); + + CodeGenPasses.run(*AsmGenModule); + return true; + }; + }; + setHook("0.preopt", PreOptModuleHook); setHook("1.promote", PostPromoteModuleHook); setHook("2.internalize", PostInternalizeModuleHook); setHook("3.import", PostImportModuleHook); setHook("4.opt", PostOptModuleHook); setHook("5.precodegen", PreCodeGenModuleHook); + setAsmHook("6.postcodegen", PostCodeGenModuleHook); CombinedIndexHook = [=](const ModuleSummaryIndex &Index) { std::string Path = OutputFileName + "index.bc"; @@ -164,6 +210,11 @@ auto Output = AddOutput(Task); std::unique_ptr OS = Output->getStream(); legacy::PassManager CodeGenPasses; + + // Generate assembly file + if (C.PostCodeGenModuleHook && !C.PostCodeGenModuleHook(Task, M, TM)) + return; + if (TM->addPassesToEmitFile(CodeGenPasses, *OS, TargetMachine::CGFT_ObjectFile)) report_fatal_error("Failed to setup codegen"); @@ -227,7 +278,6 @@ return make_error(Msg, inconvertibleErrorCode()); return T; } - } Error lto::backend(Config &C, AddOutputFn AddOutput,