Index: include/clang/CodeGen/BackendUtil.h =================================================================== --- include/clang/CodeGen/BackendUtil.h +++ include/clang/CodeGen/BackendUtil.h @@ -12,6 +12,7 @@ #include "clang/Basic/LLVM.h" #include "llvm/IR/ModuleSummaryIndex.h" +#include #include namespace llvm { @@ -34,10 +35,14 @@ Backend_EmitObj ///< Emit native object files }; - void EmitBackendOutput(DiagnosticsEngine &Diags, const CodeGenOptions &CGOpts, - const TargetOptions &TOpts, const LangOptions &LOpts, - const llvm::DataLayout &TDesc, llvm::Module *M, - BackendAction Action, raw_pwrite_stream *OS); + // LinkCallBack is a call back function for linking the input module with + // other modules. + void EmitBackendOutput( + DiagnosticsEngine &Diags, const CodeGenOptions &CGOpts, + const TargetOptions &TOpts, const LangOptions &LOpts, + const llvm::DataLayout &TDesc, llvm::Module *M, + BackendAction Action, raw_pwrite_stream *OS, + std::function *LinkCallBack = nullptr); void EmbedBitcode(llvm::Module *M, const CodeGenOptions &CGOpts, llvm::MemoryBufferRef Buf); Index: lib/CodeGen/BackendUtil.cpp =================================================================== --- lib/CodeGen/BackendUtil.cpp +++ lib/CodeGen/BackendUtil.cpp @@ -59,8 +59,10 @@ const LangOptions &LangOpts; Module *TheModule; + Timer PreLinkTime; Timer CodeGenerationTime; + mutable legacy::PassManager *PreLinkPasses; mutable legacy::PassManager *CodeGenPasses; mutable legacy::PassManager *PerModulePasses; mutable legacy::FunctionPassManager *PerFunctionPasses; @@ -100,8 +102,14 @@ return PerFunctionPasses; } - /// Set LLVM command line options passed through -backend-option. - void setCommandLineOpts(); + legacy::PassManager *getPreLinkPasses() const { + if (!PreLinkPasses) { + PreLinkPasses = new legacy::PassManager(); + PreLinkPasses->add( + createTargetTransformInfoWrapperPass(getTargetIRAnalysis())); + } + return PreLinkPasses; + } void CreatePasses(ModuleSummaryIndex *ModuleSummary); @@ -120,16 +128,21 @@ /// \return True on success. bool AddEmitPasses(BackendAction Action, raw_pwrite_stream &OS); + /// Add target specific pre-linking passes. + void AddPreLinkPasses(raw_pwrite_stream &OS); + public: EmitAssemblyHelper(DiagnosticsEngine &_Diags, const CodeGenOptions &CGOpts, const clang::TargetOptions &TOpts, const LangOptions &LOpts, Module *M) : Diags(_Diags), CodeGenOpts(CGOpts), TargetOpts(TOpts), LangOpts(LOpts), - TheModule(M), CodeGenerationTime("Code Generation Time"), + TheModule(M), PreLinkTime("Pre-Linking Passes Time"), + CodeGenerationTime("Code Generation Time"), PreLinkPasses(nullptr), CodeGenPasses(nullptr), PerModulePasses(nullptr), PerFunctionPasses(nullptr) {} ~EmitAssemblyHelper() { + delete PreLinkPasses; delete CodeGenPasses; delete PerModulePasses; delete PerFunctionPasses; @@ -140,6 +153,14 @@ std::unique_ptr TM; void EmitAssembly(BackendAction Action, raw_pwrite_stream *OS); + void DoPreLinkPasses(raw_pwrite_stream *OS); + + /// Set LLVM command line options passed through -backend-option. + void setCommandLineOpts(); + + /// Set up target for target specific pre-linking passes and LLVM code + /// generation. + void setTarget(BackendAction Action); }; // We need this wrapper to access LangOpts and CGOpts from extension functions @@ -504,6 +525,14 @@ BackendArgs.data()); } +void EmitAssemblyHelper::setTarget(BackendAction Action) { + bool UsesCodeGen = (Action != Backend_EmitNothing && + Action != Backend_EmitBC && + Action != Backend_EmitLL); + if (!TM) + TM.reset(CreateTargetMachine(UsesCodeGen)); +} + TargetMachine *EmitAssemblyHelper::CreateTargetMachine(bool MustCreateTM) { // Create the TargetMachine for generating code. std::string Error; @@ -625,6 +654,7 @@ return TM; } + bool EmitAssemblyHelper::AddEmitPasses(BackendAction Action, raw_pwrite_stream &OS) { @@ -662,17 +692,18 @@ return true; } +void EmitAssemblyHelper::AddPreLinkPasses(raw_pwrite_stream &OS) { + legacy::PassManager *PM = getPreLinkPasses(); + TM->addPreLinkPasses(*PM, OS); +} + void EmitAssemblyHelper::EmitAssembly(BackendAction Action, raw_pwrite_stream *OS) { TimeRegion Region(llvm::TimePassesIsEnabled ? &CodeGenerationTime : nullptr); - setCommandLineOpts(); - bool UsesCodeGen = (Action != Backend_EmitNothing && Action != Backend_EmitBC && Action != Backend_EmitLL); - if (!TM) - TM.reset(CreateTargetMachine(UsesCodeGen)); if (UsesCodeGen && !TM) return; @@ -748,14 +779,42 @@ } } -void clang::EmitBackendOutput(DiagnosticsEngine &Diags, - const CodeGenOptions &CGOpts, - const clang::TargetOptions &TOpts, - const LangOptions &LOpts, const llvm::DataLayout &TDesc, - Module *M, BackendAction Action, - raw_pwrite_stream *OS) { +void EmitAssemblyHelper::DoPreLinkPasses(raw_pwrite_stream *OS) { + TimeRegion Region(llvm::TimePassesIsEnabled ? &PreLinkTime : nullptr); + + if (!TM) + return; + + AddPreLinkPasses(*OS); + + // Before executing passes, print the final values of the LLVM options. + cl::PrintOptionValues(); + + if (PreLinkPasses) { + PrettyStackTraceString CrashInfo("Pre-linking passes"); + PreLinkPasses->run(*TheModule); + } +} + +void clang::EmitBackendOutput( + DiagnosticsEngine &Diags, const CodeGenOptions &CGOpts, + const clang::TargetOptions &TOpts, const LangOptions &LOpts, + const llvm::DataLayout &TDesc, Module *M, + BackendAction Action, raw_pwrite_stream *OS, + std::function *LinkCallBack) { EmitAssemblyHelper AsmHelper(Diags, CGOpts, TOpts, LOpts, M); + AsmHelper.setCommandLineOpts(); + AsmHelper.setTarget(Action); + + if (LinkCallBack) { + AsmHelper.DoPreLinkPasses(OS); + if ((*LinkCallBack)(M)) + return; + } + + EmbedBitcode(M, CGOpts, llvm::MemoryBufferRef()); + AsmHelper.EmitAssembly(Action, OS); // Verify clang's TargetInfo DataLayout against the LLVM TargetMachine's Index: lib/CodeGen/CodeGenAction.cpp =================================================================== --- lib/CodeGen/CodeGenAction.cpp +++ lib/CodeGen/CodeGenAction.cpp @@ -165,19 +165,20 @@ void *OldDiagnosticContext = Ctx.getDiagnosticContext(); Ctx.setDiagnosticHandler(DiagnosticHandler, this); - // Link LinkModule into this module if present, preserving its validity. - for (auto &I : LinkModules) { - unsigned LinkFlags = I.first; - CurLinkModule = I.second.get(); - if (Linker::linkModules(*getModule(), std::move(I.second), LinkFlags)) - return; - } - - EmbedBitcode(getModule(), CodeGenOpts, llvm::MemoryBufferRef()); - + std::function + LinkCallBack = [=](llvm::Module *M)->bool { + // Link LinkModule into this module if present, preserving its validity. + for (auto &I : LinkModules) { + unsigned LinkFlags = I.first; + CurLinkModule = I.second.get(); + if (Linker::linkModules(*getModule(), std::move(I.second), LinkFlags)) + return true; + } + return false; + }; EmitBackendOutput(Diags, CodeGenOpts, TargetOpts, LangOpts, C.getTargetInfo().getDataLayout(), - getModule(), Action, AsmOutStream); + getModule(), Action, AsmOutStream, &LinkCallBack); Ctx.setInlineAsmDiagnosticHandler(OldHandler, OldContext);