diff --git a/clang/include/clang/CodeGen/BackendUtil.h b/clang/include/clang/CodeGen/BackendUtil.h index cdbfe4ca5e654..fc8ed4f011f92 100644 --- a/clang/include/clang/CodeGen/BackendUtil.h +++ b/clang/include/clang/CodeGen/BackendUtil.h @@ -30,6 +30,7 @@ namespace clang { class CodeGenOptions; class TargetOptions; class LangOptions; + class BackendConsumer; enum BackendAction { Backend_EmitAssembly, ///< Emit native assembly files @@ -45,7 +46,8 @@ namespace clang { const TargetOptions &TOpts, const LangOptions &LOpts, StringRef TDesc, llvm::Module *M, BackendAction Action, llvm::IntrusiveRefCntPtr VFS, - std::unique_ptr OS); + std::unique_ptr OS, + BackendConsumer *BC = nullptr); void EmbedBitcode(llvm::Module *M, const CodeGenOptions &CGOpts, llvm::MemoryBufferRef Buf); diff --git a/clang/lib/CodeGen/BackendConsumer.h b/clang/lib/CodeGen/BackendConsumer.h new file mode 100644 index 0000000000000..72a814cd43d73 --- /dev/null +++ b/clang/lib/CodeGen/BackendConsumer.h @@ -0,0 +1,166 @@ +//===--- BackendConsumer.h - LLVM BackendConsumer Header File -------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_LIB_CODEGEN_BACKENDCONSUMER_H +#define LLVM_CLANG_LIB_CODEGEN_BACKENDCONSUMER_H + +#include "clang/CodeGen/BackendUtil.h" +#include "clang/CodeGen/CodeGenAction.h" + +#include "llvm/IR/DiagnosticInfo.h" +#include "llvm/Support/Timer.h" + +namespace llvm { + class DiagnosticInfoDontCall; +} + +namespace clang { +class ASTContext; +class CodeGenAction; +class CoverageSourceInfo; + +class BackendConsumer : public ASTConsumer { + using LinkModule = CodeGenAction::LinkModule; + + virtual void anchor(); + DiagnosticsEngine &Diags; + BackendAction Action; + const HeaderSearchOptions &HeaderSearchOpts; + const CodeGenOptions &CodeGenOpts; + const TargetOptions &TargetOpts; + const LangOptions &LangOpts; + std::unique_ptr AsmOutStream; + ASTContext *Context; + IntrusiveRefCntPtr FS; + + llvm::Timer LLVMIRGeneration; + unsigned LLVMIRGenerationRefCount; + + /// True if we've finished generating IR. This prevents us from generating + /// additional LLVM IR after emitting output in HandleTranslationUnit. This + /// can happen when Clang plugins trigger additional AST deserialization. + bool IRGenFinished = false; + + bool TimerIsEnabled = false; + + std::unique_ptr Gen; + + SmallVector LinkModules; + + // A map from mangled names to their function's source location, used for + // backend diagnostics as the Clang AST may be unavailable. We actually use + // the mangled name's hash as the key because mangled names can be very + // long and take up lots of space. Using a hash can cause name collision, + // but that is rare and the consequences are pointing to a wrong source + // location which is not severe. This is a vector instead of an actual map + // because we optimize for time building this map rather than time + // retrieving an entry, as backend diagnostics are uncommon. + std::vector> + ManglingFullSourceLocs; + + + // This is here so that the diagnostic printer knows the module a diagnostic + // refers to. + llvm::Module *CurLinkModule = nullptr; + +public: + BackendConsumer(BackendAction Action, DiagnosticsEngine &Diags, + IntrusiveRefCntPtr VFS, + const HeaderSearchOptions &HeaderSearchOpts, + const PreprocessorOptions &PPOpts, + const CodeGenOptions &CodeGenOpts, + const TargetOptions &TargetOpts, + const LangOptions &LangOpts, const std::string &InFile, + SmallVector LinkModules, + std::unique_ptr OS, llvm::LLVMContext &C, + CoverageSourceInfo *CoverageInfo = nullptr); + + // This constructor is used in installing an empty BackendConsumer + // to use the clang diagnostic handler for IR input files. It avoids + // initializing the OS field. + BackendConsumer(BackendAction Action, DiagnosticsEngine &Diags, + IntrusiveRefCntPtr VFS, + const HeaderSearchOptions &HeaderSearchOpts, + const PreprocessorOptions &PPOpts, + const CodeGenOptions &CodeGenOpts, + const TargetOptions &TargetOpts, + const LangOptions &LangOpts, llvm::Module *Module, + SmallVector LinkModules, llvm::LLVMContext &C, + CoverageSourceInfo *CoverageInfo = nullptr); + + llvm::Module *getModule() const; + std::unique_ptr takeModule(); + + CodeGenerator *getCodeGenerator(); + + void HandleCXXStaticMemberVarInstantiation(VarDecl *VD) override; + void Initialize(ASTContext &Ctx) override; + bool HandleTopLevelDecl(DeclGroupRef D) override; + void HandleInlineFunctionDefinition(FunctionDecl *D) override; + void HandleInterestingDecl(DeclGroupRef D) override; + void HandleTranslationUnit(ASTContext &C) override; + void HandleTagDeclDefinition(TagDecl *D) override; + void HandleTagDeclRequiredDefinition(const TagDecl *D) override; + void CompleteTentativeDefinition(VarDecl *D) override; + void CompleteExternalDeclaration(VarDecl *D) override; + void AssignInheritanceModel(CXXRecordDecl *RD) override; + void HandleVTable(CXXRecordDecl *RD) override; + + + // Links each entry in LinkModules into our module. Returns true on error. + bool LinkInModules(llvm::Module *M, bool ShouldLinkFiles = true); + + /// Get the best possible source location to represent a diagnostic that + /// may have associated debug info. + const FullSourceLoc getBestLocationFromDebugLoc( + const llvm::DiagnosticInfoWithLocationBase &D, + bool &BadDebugInfo, StringRef &Filename, + unsigned &Line, unsigned &Column) const; + + std::optional getFunctionSourceLocation( + const llvm::Function &F) const; + + void DiagnosticHandlerImpl(const llvm::DiagnosticInfo &DI); + /// Specialized handler for InlineAsm diagnostic. + /// \return True if the diagnostic has been successfully reported, false + /// otherwise. + bool InlineAsmDiagHandler(const llvm::DiagnosticInfoInlineAsm &D); + /// Specialized handler for diagnostics reported using SMDiagnostic. + void SrcMgrDiagHandler(const llvm::DiagnosticInfoSrcMgr &D); + /// Specialized handler for StackSize diagnostic. + /// \return True if the diagnostic has been successfully reported, false + /// otherwise. + bool StackSizeDiagHandler(const llvm::DiagnosticInfoStackSize &D); + /// Specialized handler for ResourceLimit diagnostic. + /// \return True if the diagnostic has been successfully reported, false + /// otherwise. + bool ResourceLimitDiagHandler(const llvm::DiagnosticInfoResourceLimit &D); + + /// Specialized handler for unsupported backend feature diagnostic. + void UnsupportedDiagHandler(const llvm::DiagnosticInfoUnsupported &D); + /// Specialized handlers for optimization remarks. + /// Note that these handlers only accept remarks and they always handle + /// them. + void EmitOptimizationMessage(const llvm::DiagnosticInfoOptimizationBase &D, + unsigned DiagID); + void + OptimizationRemarkHandler(const llvm::DiagnosticInfoOptimizationBase &D); + void OptimizationRemarkHandler( + const llvm::OptimizationRemarkAnalysisFPCommute &D); + void OptimizationRemarkHandler( + const llvm::OptimizationRemarkAnalysisAliasing &D); + void OptimizationFailureHandler( + const llvm::DiagnosticInfoOptimizationFailure &D); + void DontCallDiagHandler(const llvm::DiagnosticInfoDontCall &D); + /// Specialized handler for misexpect warnings. + /// Note that misexpect remarks are emitted through ORE + void MisExpectDiagHandler(const llvm::DiagnosticInfoMisExpect &D); +}; + +} // namespace clang +#endif diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp index 46c84da4c74a0..bd4a5b0e78887 100644 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -7,6 +7,8 @@ //===----------------------------------------------------------------------===// #include "clang/CodeGen/BackendUtil.h" +#include "BackendConsumer.h" +#include "LinkInModulesPass.h" #include "clang/Basic/CodeGenOptions.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/LangOptions.h" @@ -98,6 +100,11 @@ extern cl::opt PrintPipelinePasses; static cl::opt ClSanitizeOnOptimizerEarlyEP( "sanitizer-early-opt-ep", cl::Optional, cl::desc("Insert sanitizers on OptimizerEarlyEP."), cl::init(false)); + +// Re-link builtin bitcodes after optimization +static cl::opt ClRelinkBuiltinBitcodePostop( + "relink-builtin-bitcode-postop", cl::Optional, + cl::desc("Re-link builtin bitcodes after optimization."), cl::init(false)); } namespace { @@ -113,7 +120,7 @@ class EmitAssemblyHelper { const CodeGenOptions &CodeGenOpts; const clang::TargetOptions &TargetOpts; const LangOptions &LangOpts; - Module *TheModule; + llvm::Module *TheModule; IntrusiveRefCntPtr VFS; Timer CodeGenerationTime; @@ -156,10 +163,9 @@ class EmitAssemblyHelper { return F; } - void - RunOptimizationPipeline(BackendAction Action, - std::unique_ptr &OS, - std::unique_ptr &ThinLinkOS); + void RunOptimizationPipeline( + BackendAction Action, std::unique_ptr &OS, + std::unique_ptr &ThinLinkOS, BackendConsumer *BC); void RunCodegenPipeline(BackendAction Action, std::unique_ptr &OS, std::unique_ptr &DwoOS); @@ -179,7 +185,7 @@ class EmitAssemblyHelper { const HeaderSearchOptions &HeaderSearchOpts, const CodeGenOptions &CGOpts, const clang::TargetOptions &TOpts, - const LangOptions &LOpts, Module *M, + const LangOptions &LOpts, llvm::Module *M, IntrusiveRefCntPtr VFS) : Diags(_Diags), HSOpts(HeaderSearchOpts), CodeGenOpts(CGOpts), TargetOpts(TOpts), LangOpts(LOpts), TheModule(M), VFS(std::move(VFS)), @@ -194,8 +200,8 @@ class EmitAssemblyHelper { std::unique_ptr TM; // Emit output using the new pass manager for the optimization pipeline. - void EmitAssembly(BackendAction Action, - std::unique_ptr OS); + void EmitAssembly(BackendAction Action, std::unique_ptr OS, + BackendConsumer *BC); }; } @@ -693,7 +699,7 @@ static void addSanitizers(const Triple &TargetTriple, // the logic of the original code, but operates on "shadow" values. It // can benefit from re-running some general purpose optimization // passes. - MPM.addPass(RequireAnalysisPass()); + MPM.addPass(RequireAnalysisPass()); FunctionPassManager FPM; FPM.addPass(EarlyCSEPass(true /* Enable mem-ssa. */)); FPM.addPass(InstCombinePass()); @@ -752,7 +758,7 @@ static void addSanitizers(const Triple &TargetTriple, SanitizersCallback(NewMPM, Level); if (!NewMPM.isEmpty()) { // Sanitizers can abandon. - NewMPM.addPass(RequireAnalysisPass()); + NewMPM.addPass(RequireAnalysisPass()); MPM.addPass(std::move(NewMPM)); } }); @@ -764,7 +770,7 @@ static void addSanitizers(const Triple &TargetTriple, void EmitAssemblyHelper::RunOptimizationPipeline( BackendAction Action, std::unique_ptr &OS, - std::unique_ptr &ThinLinkOS) { + std::unique_ptr &ThinLinkOS, BackendConsumer *BC) { std::optional PGOOpt; if (CodeGenOpts.hasProfileIRInstr()) @@ -1040,6 +1046,13 @@ void EmitAssemblyHelper::RunOptimizationPipeline( } } + // Re-link against any bitcodes supplied via the -mlink-builtin-bitcode option + // Some optimizations may generate new function calls that would not have + // been linked pre-optimization (i.e. fused sincos calls generated by + // AMDGPULibCalls::fold_sincos.) + if (ClRelinkBuiltinBitcodePostop) + MPM.addPass(LinkInModulesPass(BC, false)); + // Add a verifier pass if requested. We don't have to do this if the action // requires code generation because there will already be a verifier pass in // the code-generation pipeline. @@ -1051,7 +1064,7 @@ void EmitAssemblyHelper::RunOptimizationPipeline( if (Action == Backend_EmitBC || Action == Backend_EmitLL) { if (CodeGenOpts.PrepareForThinLTO && !CodeGenOpts.DisableLLVMPasses) { if (!TheModule->getModuleFlag("EnableSplitLTOUnit")) - TheModule->addModuleFlag(Module::Error, "EnableSplitLTOUnit", + TheModule->addModuleFlag(llvm::Module::Error, "EnableSplitLTOUnit", CodeGenOpts.EnableSplitLTOUnit); if (Action == Backend_EmitBC) { if (!CodeGenOpts.ThinLinkBitcodeFile.empty()) { @@ -1060,7 +1073,7 @@ void EmitAssemblyHelper::RunOptimizationPipeline( return; } if (CodeGenOpts.UnifiedLTO) - TheModule->addModuleFlag(Module::Error, "UnifiedLTO", uint32_t(1)); + TheModule->addModuleFlag(llvm::Module::Error, "UnifiedLTO", uint32_t(1)); MPM.addPass(ThinLTOBitcodeWriterPass( *OS, ThinLinkOS ? &ThinLinkOS->os() : nullptr)); } else { @@ -1074,12 +1087,12 @@ void EmitAssemblyHelper::RunOptimizationPipeline( bool EmitLTOSummary = shouldEmitRegularLTOSummary(); if (EmitLTOSummary) { if (!TheModule->getModuleFlag("ThinLTO") && !CodeGenOpts.UnifiedLTO) - TheModule->addModuleFlag(Module::Error, "ThinLTO", uint32_t(0)); + TheModule->addModuleFlag(llvm::Module::Error, "ThinLTO", uint32_t(0)); if (!TheModule->getModuleFlag("EnableSplitLTOUnit")) - TheModule->addModuleFlag(Module::Error, "EnableSplitLTOUnit", + TheModule->addModuleFlag(llvm::Module::Error, "EnableSplitLTOUnit", uint32_t(1)); if (CodeGenOpts.UnifiedLTO) - TheModule->addModuleFlag(Module::Error, "UnifiedLTO", uint32_t(1)); + TheModule->addModuleFlag(llvm::Module::Error, "UnifiedLTO", uint32_t(1)); } if (Action == Backend_EmitBC) MPM.addPass(BitcodeWriterPass(*OS, CodeGenOpts.EmitLLVMUseLists, @@ -1093,13 +1106,13 @@ void EmitAssemblyHelper::RunOptimizationPipeline( // Set module flags, like EnableSplitLTOUnit and UnifiedLTO, since FatLTO // uses a different action than Backend_EmitBC or Backend_EmitLL. if (!TheModule->getModuleFlag("ThinLTO")) - TheModule->addModuleFlag(Module::Error, "ThinLTO", + TheModule->addModuleFlag(llvm::Module::Error, "ThinLTO", uint32_t(CodeGenOpts.PrepareForThinLTO)); if (!TheModule->getModuleFlag("EnableSplitLTOUnit")) - TheModule->addModuleFlag(Module::Error, "EnableSplitLTOUnit", + TheModule->addModuleFlag(llvm::Module::Error, "EnableSplitLTOUnit", uint32_t(CodeGenOpts.EnableSplitLTOUnit)); if (CodeGenOpts.UnifiedLTO && !TheModule->getModuleFlag("UnifiedLTO")) - TheModule->addModuleFlag(Module::Error, "UnifiedLTO", uint32_t(1)); + TheModule->addModuleFlag(llvm::Module::Error, "UnifiedLTO", uint32_t(1)); } // Print a textual, '-passes=' compatible, representation of pipeline if @@ -1169,7 +1182,8 @@ void EmitAssemblyHelper::RunCodegenPipeline( } void EmitAssemblyHelper::EmitAssembly(BackendAction Action, - std::unique_ptr OS) { + std::unique_ptr OS, + BackendConsumer *BC) { TimeRegion Region(CodeGenOpts.TimePasses ? &CodeGenerationTime : nullptr); setCommandLineOpts(CodeGenOpts); @@ -1185,7 +1199,7 @@ void EmitAssemblyHelper::EmitAssembly(BackendAction Action, cl::PrintOptionValues(); std::unique_ptr ThinLinkOS, DwoOS; - RunOptimizationPipeline(Action, OS, ThinLinkOS); + RunOptimizationPipeline(Action, OS, ThinLinkOS, BC); RunCodegenPipeline(Action, OS, DwoOS); if (ThinLinkOS) @@ -1195,11 +1209,12 @@ void EmitAssemblyHelper::EmitAssembly(BackendAction Action, } static void runThinLTOBackend( - DiagnosticsEngine &Diags, ModuleSummaryIndex *CombinedIndex, Module *M, - const HeaderSearchOptions &HeaderOpts, const CodeGenOptions &CGOpts, - const clang::TargetOptions &TOpts, const LangOptions &LOpts, - std::unique_ptr OS, std::string SampleProfile, - std::string ProfileRemapping, BackendAction Action) { + DiagnosticsEngine &Diags, ModuleSummaryIndex *CombinedIndex, + llvm::Module *M, const HeaderSearchOptions &HeaderOpts, + const CodeGenOptions &CGOpts, const clang::TargetOptions &TOpts, + const LangOptions &LOpts, std::unique_ptr OS, + std::string SampleProfile, std::string ProfileRemapping, + BackendAction Action) { DenseMap> ModuleToDefinedGVSummaries; CombinedIndex->collectDefinedGVSummariesPerModule(ModuleToDefinedGVSummaries); @@ -1268,18 +1283,18 @@ static void runThinLTOBackend( Conf.SplitDwarfOutput = CGOpts.SplitDwarfOutput; switch (Action) { case Backend_EmitNothing: - Conf.PreCodeGenModuleHook = [](size_t Task, const Module &Mod) { + Conf.PreCodeGenModuleHook = [](size_t Task, const llvm::Module &Mod) { return false; }; break; case Backend_EmitLL: - Conf.PreCodeGenModuleHook = [&](size_t Task, const Module &Mod) { + Conf.PreCodeGenModuleHook = [&](size_t Task, const llvm::Module &Mod) { M->print(*OS, nullptr, CGOpts.EmitLLVMUseLists); return false; }; break; case Backend_EmitBC: - Conf.PreCodeGenModuleHook = [&](size_t Task, const Module &Mod) { + Conf.PreCodeGenModuleHook = [&](size_t Task, const llvm::Module &Mod) { WriteBitcodeToFile(*M, *OS, CGOpts.EmitLLVMUseLists); return false; }; @@ -1298,14 +1313,12 @@ static void runThinLTOBackend( } } -void clang::EmitBackendOutput(DiagnosticsEngine &Diags, - const HeaderSearchOptions &HeaderOpts, - const CodeGenOptions &CGOpts, - const clang::TargetOptions &TOpts, - const LangOptions &LOpts, StringRef TDesc, - Module *M, BackendAction Action, - IntrusiveRefCntPtr VFS, - std::unique_ptr OS) { +void clang::EmitBackendOutput( + DiagnosticsEngine &Diags, const HeaderSearchOptions &HeaderOpts, + const CodeGenOptions &CGOpts, const clang::TargetOptions &TOpts, + const LangOptions &LOpts, StringRef TDesc, llvm::Module *M, + BackendAction Action, IntrusiveRefCntPtr VFS, + std::unique_ptr OS, BackendConsumer *BC) { llvm::TimeTraceScope TimeScope("Backend"); @@ -1348,7 +1361,7 @@ void clang::EmitBackendOutput(DiagnosticsEngine &Diags, } EmitAssemblyHelper AsmHelper(Diags, HeaderOpts, CGOpts, TOpts, LOpts, M, VFS); - AsmHelper.EmitAssembly(Action, std::move(OS)); + AsmHelper.EmitAssembly(Action, std::move(OS), BC); // Verify clang's TargetInfo DataLayout against the LLVM TargetMachine's // DataLayout. diff --git a/clang/lib/CodeGen/CMakeLists.txt b/clang/lib/CodeGen/CMakeLists.txt index da98848e3b443..b807af9379731 100644 --- a/clang/lib/CodeGen/CMakeLists.txt +++ b/clang/lib/CodeGen/CMakeLists.txt @@ -103,6 +103,7 @@ add_clang_library(clangCodeGen ConstantInitBuilder.cpp CoverageMappingGen.cpp ItaniumCXXABI.cpp + LinkInModulesPass.cpp MacroPPCallbacks.cpp MicrosoftCXXABI.cpp ModuleBuilder.cpp diff --git a/clang/lib/CodeGen/CodeGenAction.cpp b/clang/lib/CodeGen/CodeGenAction.cpp index a3b72381d73fc..a31a271ed77d1 100644 --- a/clang/lib/CodeGen/CodeGenAction.cpp +++ b/clang/lib/CodeGen/CodeGenAction.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "clang/CodeGen/CodeGenAction.h" +#include "BackendConsumer.h" #include "CGCall.h" #include "CodeGenModule.h" #include "CoverageMappingGen.h" @@ -48,8 +49,8 @@ #include "llvm/Support/ToolOutputFile.h" #include "llvm/Support/YAMLTraits.h" #include "llvm/Transforms/IPO/Internalize.h" +#include "llvm/Transforms/Utils/Cloning.h" -#include #include using namespace clang; using namespace llvm; @@ -57,419 +58,356 @@ using namespace llvm; #define DEBUG_TYPE "codegenaction" namespace clang { - class BackendConsumer; - class ClangDiagnosticHandler final : public DiagnosticHandler { - public: - ClangDiagnosticHandler(const CodeGenOptions &CGOpts, BackendConsumer *BCon) - : CodeGenOpts(CGOpts), BackendCon(BCon) {} +class BackendConsumer; +class ClangDiagnosticHandler final : public DiagnosticHandler { +public: + ClangDiagnosticHandler(const CodeGenOptions &CGOpts, BackendConsumer *BCon) + : CodeGenOpts(CGOpts), BackendCon(BCon) {} - bool handleDiagnostics(const DiagnosticInfo &DI) override; + bool handleDiagnostics(const DiagnosticInfo &DI) override; - bool isAnalysisRemarkEnabled(StringRef PassName) const override { - return CodeGenOpts.OptimizationRemarkAnalysis.patternMatches(PassName); - } - bool isMissedOptRemarkEnabled(StringRef PassName) const override { - return CodeGenOpts.OptimizationRemarkMissed.patternMatches(PassName); - } - bool isPassedOptRemarkEnabled(StringRef PassName) const override { - return CodeGenOpts.OptimizationRemark.patternMatches(PassName); - } + bool isAnalysisRemarkEnabled(StringRef PassName) const override { + return CodeGenOpts.OptimizationRemarkAnalysis.patternMatches(PassName); + } + bool isMissedOptRemarkEnabled(StringRef PassName) const override { + return CodeGenOpts.OptimizationRemarkMissed.patternMatches(PassName); + } + bool isPassedOptRemarkEnabled(StringRef PassName) const override { + return CodeGenOpts.OptimizationRemark.patternMatches(PassName); + } - bool isAnyRemarkEnabled() const override { - return CodeGenOpts.OptimizationRemarkAnalysis.hasValidPattern() || - CodeGenOpts.OptimizationRemarkMissed.hasValidPattern() || - CodeGenOpts.OptimizationRemark.hasValidPattern(); - } + bool isAnyRemarkEnabled() const override { + return CodeGenOpts.OptimizationRemarkAnalysis.hasValidPattern() || + CodeGenOpts.OptimizationRemarkMissed.hasValidPattern() || + CodeGenOpts.OptimizationRemark.hasValidPattern(); + } - private: - const CodeGenOptions &CodeGenOpts; - BackendConsumer *BackendCon; - }; +private: + const CodeGenOptions &CodeGenOpts; + BackendConsumer *BackendCon; +}; + +static void reportOptRecordError(Error E, DiagnosticsEngine &Diags, + const CodeGenOptions &CodeGenOpts) { + handleAllErrors( + std::move(E), + [&](const LLVMRemarkSetupFileError &E) { + Diags.Report(diag::err_cannot_open_file) + << CodeGenOpts.OptRecordFile << E.message(); + }, + [&](const LLVMRemarkSetupPatternError &E) { + Diags.Report(diag::err_drv_optimization_remark_pattern) + << E.message() << CodeGenOpts.OptRecordPasses; + }, + [&](const LLVMRemarkSetupFormatError &E) { + Diags.Report(diag::err_drv_optimization_remark_format) + << CodeGenOpts.OptRecordFormat; + }); +} - static void reportOptRecordError(Error E, DiagnosticsEngine &Diags, - const CodeGenOptions &CodeGenOpts) { - handleAllErrors( - std::move(E), - [&](const LLVMRemarkSetupFileError &E) { - Diags.Report(diag::err_cannot_open_file) - << CodeGenOpts.OptRecordFile << E.message(); - }, - [&](const LLVMRemarkSetupPatternError &E) { - Diags.Report(diag::err_drv_optimization_remark_pattern) - << E.message() << CodeGenOpts.OptRecordPasses; - }, - [&](const LLVMRemarkSetupFormatError &E) { - Diags.Report(diag::err_drv_optimization_remark_format) - << CodeGenOpts.OptRecordFormat; - }); - } +BackendConsumer::BackendConsumer(BackendAction Action, DiagnosticsEngine &Diags, + IntrusiveRefCntPtr VFS, + const HeaderSearchOptions &HeaderSearchOpts, + const PreprocessorOptions &PPOpts, + const CodeGenOptions &CodeGenOpts, + const TargetOptions &TargetOpts, + const LangOptions &LangOpts, + const std::string &InFile, + SmallVector LinkModules, + std::unique_ptr OS, + LLVMContext &C, + CoverageSourceInfo *CoverageInfo) + : Diags(Diags), Action(Action), HeaderSearchOpts(HeaderSearchOpts), + CodeGenOpts(CodeGenOpts), TargetOpts(TargetOpts), LangOpts(LangOpts), + AsmOutStream(std::move(OS)), Context(nullptr), FS(VFS), + LLVMIRGeneration("irgen", "LLVM IR Generation Time"), + LLVMIRGenerationRefCount(0), + Gen(CreateLLVMCodeGen(Diags, InFile, std::move(VFS), HeaderSearchOpts, + PPOpts, CodeGenOpts, C, CoverageInfo)), + LinkModules(std::move(LinkModules)) { + TimerIsEnabled = CodeGenOpts.TimePasses; + llvm::TimePassesIsEnabled = CodeGenOpts.TimePasses; + llvm::TimePassesPerRun = CodeGenOpts.TimePassesPerRun; +} - class BackendConsumer : public ASTConsumer { - using LinkModule = CodeGenAction::LinkModule; - - virtual void anchor(); - DiagnosticsEngine &Diags; - BackendAction Action; - const HeaderSearchOptions &HeaderSearchOpts; - const CodeGenOptions &CodeGenOpts; - const TargetOptions &TargetOpts; - const LangOptions &LangOpts; - std::unique_ptr AsmOutStream; - ASTContext *Context; - IntrusiveRefCntPtr FS; - - Timer LLVMIRGeneration; - unsigned LLVMIRGenerationRefCount; - - /// True if we've finished generating IR. This prevents us from generating - /// additional LLVM IR after emitting output in HandleTranslationUnit. This - /// can happen when Clang plugins trigger additional AST deserialization. - bool IRGenFinished = false; - - bool TimerIsEnabled = false; - - std::unique_ptr Gen; - - SmallVector LinkModules; - - // A map from mangled names to their function's source location, used for - // backend diagnostics as the Clang AST may be unavailable. We actually use - // the mangled name's hash as the key because mangled names can be very - // long and take up lots of space. Using a hash can cause name collision, - // but that is rare and the consequences are pointing to a wrong source - // location which is not severe. This is a vector instead of an actual map - // because we optimize for time building this map rather than time - // retrieving an entry, as backend diagnostics are uncommon. - std::vector> - ManglingFullSourceLocs; - - // This is here so that the diagnostic printer knows the module a diagnostic - // refers to. - llvm::Module *CurLinkModule = nullptr; - - public: - BackendConsumer(BackendAction Action, DiagnosticsEngine &Diags, - IntrusiveRefCntPtr VFS, - const HeaderSearchOptions &HeaderSearchOpts, - const PreprocessorOptions &PPOpts, - const CodeGenOptions &CodeGenOpts, - const TargetOptions &TargetOpts, - const LangOptions &LangOpts, const std::string &InFile, - SmallVector LinkModules, - std::unique_ptr OS, LLVMContext &C, - CoverageSourceInfo *CoverageInfo = nullptr) - : Diags(Diags), Action(Action), HeaderSearchOpts(HeaderSearchOpts), - CodeGenOpts(CodeGenOpts), TargetOpts(TargetOpts), LangOpts(LangOpts), - AsmOutStream(std::move(OS)), Context(nullptr), FS(VFS), - LLVMIRGeneration("irgen", "LLVM IR Generation Time"), - LLVMIRGenerationRefCount(0), - Gen(CreateLLVMCodeGen(Diags, InFile, std::move(VFS), HeaderSearchOpts, - PPOpts, CodeGenOpts, C, CoverageInfo)), - LinkModules(std::move(LinkModules)) { - TimerIsEnabled = CodeGenOpts.TimePasses; - llvm::TimePassesIsEnabled = CodeGenOpts.TimePasses; - llvm::TimePassesPerRun = CodeGenOpts.TimePassesPerRun; - } +// This constructor is used in installing an empty BackendConsumer +// to use the clang diagnostic handler for IR input files. It avoids +// initializing the OS field. +BackendConsumer::BackendConsumer(BackendAction Action, DiagnosticsEngine &Diags, + IntrusiveRefCntPtr VFS, + const HeaderSearchOptions &HeaderSearchOpts, + const PreprocessorOptions &PPOpts, + const CodeGenOptions &CodeGenOpts, + const TargetOptions &TargetOpts, + const LangOptions &LangOpts, + llvm::Module *Module, + SmallVector LinkModules, + LLVMContext &C, + CoverageSourceInfo *CoverageInfo) + : Diags(Diags), Action(Action), HeaderSearchOpts(HeaderSearchOpts), + CodeGenOpts(CodeGenOpts), TargetOpts(TargetOpts), LangOpts(LangOpts), + Context(nullptr), FS(VFS), + LLVMIRGeneration("irgen", "LLVM IR Generation Time"), + LLVMIRGenerationRefCount(0), + Gen(CreateLLVMCodeGen(Diags, "", std::move(VFS), HeaderSearchOpts, + PPOpts, CodeGenOpts, C, CoverageInfo)), + LinkModules(std::move(LinkModules)), CurLinkModule(Module) { + TimerIsEnabled = CodeGenOpts.TimePasses; + llvm::TimePassesIsEnabled = CodeGenOpts.TimePasses; + llvm::TimePassesPerRun = CodeGenOpts.TimePassesPerRun; +} - // This constructor is used in installing an empty BackendConsumer - // to use the clang diagnostic handler for IR input files. It avoids - // initializing the OS field. - BackendConsumer(BackendAction Action, DiagnosticsEngine &Diags, - IntrusiveRefCntPtr VFS, - const HeaderSearchOptions &HeaderSearchOpts, - const PreprocessorOptions &PPOpts, - const CodeGenOptions &CodeGenOpts, - const TargetOptions &TargetOpts, - const LangOptions &LangOpts, llvm::Module *Module, - SmallVector LinkModules, LLVMContext &C, - CoverageSourceInfo *CoverageInfo = nullptr) - : Diags(Diags), Action(Action), HeaderSearchOpts(HeaderSearchOpts), - CodeGenOpts(CodeGenOpts), TargetOpts(TargetOpts), LangOpts(LangOpts), - Context(nullptr), FS(VFS), - LLVMIRGeneration("irgen", "LLVM IR Generation Time"), - LLVMIRGenerationRefCount(0), - Gen(CreateLLVMCodeGen(Diags, "", std::move(VFS), HeaderSearchOpts, - PPOpts, CodeGenOpts, C, CoverageInfo)), - LinkModules(std::move(LinkModules)), CurLinkModule(Module) { - TimerIsEnabled = CodeGenOpts.TimePasses; - llvm::TimePassesIsEnabled = CodeGenOpts.TimePasses; - llvm::TimePassesPerRun = CodeGenOpts.TimePassesPerRun; - } - llvm::Module *getModule() const { return Gen->GetModule(); } - std::unique_ptr takeModule() { - return std::unique_ptr(Gen->ReleaseModule()); - } +llvm::Module* BackendConsumer::getModule() const { + return Gen->GetModule(); +} - CodeGenerator *getCodeGenerator() { return Gen.get(); } +std::unique_ptr BackendConsumer::takeModule() { + return std::unique_ptr(Gen->ReleaseModule()); +} - void HandleCXXStaticMemberVarInstantiation(VarDecl *VD) override { - Gen->HandleCXXStaticMemberVarInstantiation(VD); - } +CodeGenerator* BackendConsumer::getCodeGenerator() { + return Gen.get(); +} - void Initialize(ASTContext &Ctx) override { - assert(!Context && "initialized multiple times"); +void BackendConsumer::HandleCXXStaticMemberVarInstantiation(VarDecl *VD) { + Gen->HandleCXXStaticMemberVarInstantiation(VD); +} - Context = &Ctx; +void BackendConsumer::Initialize(ASTContext &Ctx) { + assert(!Context && "initialized multiple times"); - if (TimerIsEnabled) - LLVMIRGeneration.startTimer(); + Context = &Ctx; - Gen->Initialize(Ctx); + if (TimerIsEnabled) + LLVMIRGeneration.startTimer(); - if (TimerIsEnabled) - LLVMIRGeneration.stopTimer(); - } + Gen->Initialize(Ctx); - bool HandleTopLevelDecl(DeclGroupRef D) override { - PrettyStackTraceDecl CrashInfo(*D.begin(), SourceLocation(), - Context->getSourceManager(), - "LLVM IR generation of declaration"); + if (TimerIsEnabled) + LLVMIRGeneration.stopTimer(); +} - // Recurse. - if (TimerIsEnabled) { - LLVMIRGenerationRefCount += 1; - if (LLVMIRGenerationRefCount == 1) - LLVMIRGeneration.startTimer(); - } +bool BackendConsumer::HandleTopLevelDecl(DeclGroupRef D) { + PrettyStackTraceDecl CrashInfo(*D.begin(), SourceLocation(), + Context->getSourceManager(), + "LLVM IR generation of declaration"); - Gen->HandleTopLevelDecl(D); + // Recurse. + if (TimerIsEnabled) { + LLVMIRGenerationRefCount += 1; + if (LLVMIRGenerationRefCount == 1) + LLVMIRGeneration.startTimer(); + } - if (TimerIsEnabled) { - LLVMIRGenerationRefCount -= 1; - if (LLVMIRGenerationRefCount == 0) - LLVMIRGeneration.stopTimer(); - } + Gen->HandleTopLevelDecl(D); - return true; - } + if (TimerIsEnabled) { + LLVMIRGenerationRefCount -= 1; + if (LLVMIRGenerationRefCount == 0) + LLVMIRGeneration.stopTimer(); + } - void HandleInlineFunctionDefinition(FunctionDecl *D) override { - PrettyStackTraceDecl CrashInfo(D, SourceLocation(), - Context->getSourceManager(), - "LLVM IR generation of inline function"); - if (TimerIsEnabled) - LLVMIRGeneration.startTimer(); + return true; +} - Gen->HandleInlineFunctionDefinition(D); +void BackendConsumer::HandleInlineFunctionDefinition(FunctionDecl *D) { + PrettyStackTraceDecl CrashInfo(D, SourceLocation(), + Context->getSourceManager(), + "LLVM IR generation of inline function"); + if (TimerIsEnabled) + LLVMIRGeneration.startTimer(); - if (TimerIsEnabled) - LLVMIRGeneration.stopTimer(); - } + Gen->HandleInlineFunctionDefinition(D); - void HandleInterestingDecl(DeclGroupRef D) override { - // Ignore interesting decls from the AST reader after IRGen is finished. - if (!IRGenFinished) - HandleTopLevelDecl(D); - } + if (TimerIsEnabled) + LLVMIRGeneration.stopTimer(); +} - // Links each entry in LinkModules into our module. Returns true on error. - bool LinkInModules(llvm::Module *M) { - for (auto &LM : LinkModules) { - assert(LM.Module && "LinkModule does not actually have a module"); - if (LM.PropagateAttrs) - for (Function &F : *LM.Module) { - // Skip intrinsics. Keep consistent with how intrinsics are created - // in LLVM IR. - if (F.isIntrinsic()) - continue; - CodeGen::mergeDefaultFunctionDefinitionAttributes( - F, CodeGenOpts, LangOpts, TargetOpts, LM.Internalize); - } - - CurLinkModule = LM.Module.get(); - - bool Err; - if (LM.Internalize) { - Err = Linker::linkModules( - *M, std::move(LM.Module), LM.LinkFlags, - [](llvm::Module &M, const llvm::StringSet<> &GVS) { - internalizeModule(M, [&GVS](const llvm::GlobalValue &GV) { - return !GV.hasName() || (GVS.count(GV.getName()) == 0); - }); - }); - } else { - Err = Linker::linkModules(*M, std::move(LM.Module), LM.LinkFlags); - } +void BackendConsumer::HandleInterestingDecl(DeclGroupRef D) { + // Ignore interesting decls from the AST reader after IRGen is finished. + if (!IRGenFinished) + HandleTopLevelDecl(D); +} - if (Err) - return true; +// Links each entry in LinkModules into our module. Returns true on error. +bool BackendConsumer::LinkInModules(llvm::Module *M, bool ShouldLinkFiles) { + + for (auto &LM : LinkModules) { + assert(LM.Module && "LinkModule does not actually have a module"); + + // If ShouldLinkFiles is not set, skip files added via the + // -mlink-bitcode-files, only linking -mlink-builtin-bitcode + if (!LM.Internalize && !ShouldLinkFiles) + continue; + + if (LM.PropagateAttrs) + for (Function &F : *LM.Module) { + // Skip intrinsics. Keep consistent with how intrinsics are created + // in LLVM IR. + if (F.isIntrinsic()) + continue; + CodeGen::mergeDefaultFunctionDefinitionAttributes( + F, CodeGenOpts, LangOpts, TargetOpts, LM.Internalize); } - LinkModules.clear(); - return false; // success - } - void HandleTranslationUnit(ASTContext &C) override { - { - llvm::TimeTraceScope TimeScope("Frontend"); - PrettyStackTraceString CrashInfo("Per-file LLVM IR generation"); - if (TimerIsEnabled) { - LLVMIRGenerationRefCount += 1; - if (LLVMIRGenerationRefCount == 1) - LLVMIRGeneration.startTimer(); - } + CurLinkModule = LM.Module.get(); + + // TODO: If CloneModule() is updated to support cloning of unmaterialized + // modules, we can remove this + bool Err; + if (Error E = CurLinkModule->materializeAll()) + return false; + + // Create a Clone to move to the linker, which preserves the original + // linking modules, allowing them to be linked again in the future + // TODO: Add a ShouldCleanup option to make Cloning optional. When + // set, we can pass the original modules to the linker for cleanup + std::unique_ptr Clone = llvm::CloneModule(*LM.Module); + + if (LM.Internalize) { + Err = Linker::linkModules( + *M, std::move(Clone), LM.LinkFlags, + [](llvm::Module &M, const llvm::StringSet<> &GVS) { + internalizeModule(M, [&GVS](const llvm::GlobalValue &GV) { + return !GV.hasName() || (GVS.count(GV.getName()) == 0); + }); + }); + } else + Err = Linker::linkModules(*M, std::move(Clone), LM.LinkFlags); + + if (Err) + return true; + } - Gen->HandleTranslationUnit(C); + return false; // success +} - if (TimerIsEnabled) { - LLVMIRGenerationRefCount -= 1; - if (LLVMIRGenerationRefCount == 0) - LLVMIRGeneration.stopTimer(); - } +void BackendConsumer::HandleTranslationUnit(ASTContext &C) { + { + llvm::TimeTraceScope TimeScope("Frontend"); + PrettyStackTraceString CrashInfo("Per-file LLVM IR generation"); + if (TimerIsEnabled) { + LLVMIRGenerationRefCount += 1; + if (LLVMIRGenerationRefCount == 1) + LLVMIRGeneration.startTimer(); + } - IRGenFinished = true; - } + Gen->HandleTranslationUnit(C); - // Silently ignore if we weren't initialized for some reason. - if (!getModule()) - return; - - LLVMContext &Ctx = getModule()->getContext(); - std::unique_ptr OldDiagnosticHandler = - Ctx.getDiagnosticHandler(); - Ctx.setDiagnosticHandler(std::make_unique( - CodeGenOpts, this)); - - Expected> OptRecordFileOrErr = - setupLLVMOptimizationRemarks( - Ctx, CodeGenOpts.OptRecordFile, CodeGenOpts.OptRecordPasses, - CodeGenOpts.OptRecordFormat, CodeGenOpts.DiagnosticsWithHotness, - CodeGenOpts.DiagnosticsHotnessThreshold); - - if (Error E = OptRecordFileOrErr.takeError()) { - reportOptRecordError(std::move(E), Diags, CodeGenOpts); - return; - } + if (TimerIsEnabled) { + LLVMIRGenerationRefCount -= 1; + if (LLVMIRGenerationRefCount == 0) + LLVMIRGeneration.stopTimer(); + } - std::unique_ptr OptRecordFile = - std::move(*OptRecordFileOrErr); + IRGenFinished = true; + } - if (OptRecordFile && - CodeGenOpts.getProfileUse() != CodeGenOptions::ProfileNone) - Ctx.setDiagnosticsHotnessRequested(true); + // Silently ignore if we weren't initialized for some reason. + if (!getModule()) + return; - if (CodeGenOpts.MisExpect) { - Ctx.setMisExpectWarningRequested(true); - } + LLVMContext &Ctx = getModule()->getContext(); + std::unique_ptr OldDiagnosticHandler = + Ctx.getDiagnosticHandler(); + Ctx.setDiagnosticHandler(std::make_unique( + CodeGenOpts, this)); - if (CodeGenOpts.DiagnosticsMisExpectTolerance) { - Ctx.setDiagnosticsMisExpectTolerance( - CodeGenOpts.DiagnosticsMisExpectTolerance); - } + Expected> OptRecordFileOrErr = + setupLLVMOptimizationRemarks( + Ctx, CodeGenOpts.OptRecordFile, CodeGenOpts.OptRecordPasses, + CodeGenOpts.OptRecordFormat, CodeGenOpts.DiagnosticsWithHotness, + CodeGenOpts.DiagnosticsHotnessThreshold); - // Link each LinkModule into our module. - if (LinkInModules(getModule())) - return; + if (Error E = OptRecordFileOrErr.takeError()) { + reportOptRecordError(std::move(E), Diags, CodeGenOpts); + return; + } - for (auto &F : getModule()->functions()) { - if (const Decl *FD = Gen->GetDeclForMangledName(F.getName())) { - auto Loc = FD->getASTContext().getFullLoc(FD->getLocation()); - // TODO: use a fast content hash when available. - auto NameHash = llvm::hash_value(F.getName()); - ManglingFullSourceLocs.push_back(std::make_pair(NameHash, Loc)); - } - } + std::unique_ptr OptRecordFile = + std::move(*OptRecordFileOrErr); - if (CodeGenOpts.ClearASTBeforeBackend) { - LLVM_DEBUG(llvm::dbgs() << "Clearing AST...\n"); - // Access to the AST is no longer available after this. - // Other things that the ASTContext manages are still available, e.g. - // the SourceManager. It'd be nice if we could separate out all the - // things in ASTContext used after this point and null out the - // ASTContext, but too many various parts of the ASTContext are still - // used in various parts. - C.cleanup(); - C.getAllocator().Reset(); - } + if (OptRecordFile && + CodeGenOpts.getProfileUse() != CodeGenOptions::ProfileNone) + Ctx.setDiagnosticsHotnessRequested(true); - EmbedBitcode(getModule(), CodeGenOpts, llvm::MemoryBufferRef()); + if (CodeGenOpts.MisExpect) { + Ctx.setMisExpectWarningRequested(true); + } - EmitBackendOutput(Diags, HeaderSearchOpts, CodeGenOpts, TargetOpts, - LangOpts, C.getTargetInfo().getDataLayoutString(), - getModule(), Action, FS, std::move(AsmOutStream)); + if (CodeGenOpts.DiagnosticsMisExpectTolerance) { + Ctx.setDiagnosticsMisExpectTolerance( + CodeGenOpts.DiagnosticsMisExpectTolerance); + } - Ctx.setDiagnosticHandler(std::move(OldDiagnosticHandler)); + // Link each LinkModule into our module. + if (LinkInModules(getModule())) + return; - if (OptRecordFile) - OptRecordFile->keep(); + for (auto &F : getModule()->functions()) { + if (const Decl *FD = Gen->GetDeclForMangledName(F.getName())) { + auto Loc = FD->getASTContext().getFullLoc(FD->getLocation()); + // TODO: use a fast content hash when available. + auto NameHash = llvm::hash_value(F.getName()); + ManglingFullSourceLocs.push_back(std::make_pair(NameHash, Loc)); } + } - void HandleTagDeclDefinition(TagDecl *D) override { - PrettyStackTraceDecl CrashInfo(D, SourceLocation(), - Context->getSourceManager(), - "LLVM IR generation of declaration"); - Gen->HandleTagDeclDefinition(D); - } + if (CodeGenOpts.ClearASTBeforeBackend) { + LLVM_DEBUG(llvm::dbgs() << "Clearing AST...\n"); + // Access to the AST is no longer available after this. + // Other things that the ASTContext manages are still available, e.g. + // the SourceManager. It'd be nice if we could separate out all the + // things in ASTContext used after this point and null out the + // ASTContext, but too many various parts of the ASTContext are still + // used in various parts. + C.cleanup(); + C.getAllocator().Reset(); + } - void HandleTagDeclRequiredDefinition(const TagDecl *D) override { - Gen->HandleTagDeclRequiredDefinition(D); - } + EmbedBitcode(getModule(), CodeGenOpts, llvm::MemoryBufferRef()); - void CompleteTentativeDefinition(VarDecl *D) override { - Gen->CompleteTentativeDefinition(D); - } + EmitBackendOutput(Diags, HeaderSearchOpts, CodeGenOpts, TargetOpts, LangOpts, + C.getTargetInfo().getDataLayoutString(), getModule(), + Action, FS, std::move(AsmOutStream), this); - void CompleteExternalDeclaration(VarDecl *D) override { - Gen->CompleteExternalDeclaration(D); - } + Ctx.setDiagnosticHandler(std::move(OldDiagnosticHandler)); - void AssignInheritanceModel(CXXRecordDecl *RD) override { - Gen->AssignInheritanceModel(RD); - } + if (OptRecordFile) + OptRecordFile->keep(); +} - void HandleVTable(CXXRecordDecl *RD) override { - Gen->HandleVTable(RD); - } +void BackendConsumer::HandleTagDeclDefinition(TagDecl *D) { + PrettyStackTraceDecl CrashInfo(D, SourceLocation(), + Context->getSourceManager(), + "LLVM IR generation of declaration"); + Gen->HandleTagDeclDefinition(D); +} - /// Get the best possible source location to represent a diagnostic that - /// may have associated debug info. - const FullSourceLoc - getBestLocationFromDebugLoc(const llvm::DiagnosticInfoWithLocationBase &D, - bool &BadDebugInfo, StringRef &Filename, - unsigned &Line, unsigned &Column) const; - - std::optional - getFunctionSourceLocation(const Function &F) const; - - void DiagnosticHandlerImpl(const llvm::DiagnosticInfo &DI); - /// Specialized handler for InlineAsm diagnostic. - /// \return True if the diagnostic has been successfully reported, false - /// otherwise. - bool InlineAsmDiagHandler(const llvm::DiagnosticInfoInlineAsm &D); - /// Specialized handler for diagnostics reported using SMDiagnostic. - void SrcMgrDiagHandler(const llvm::DiagnosticInfoSrcMgr &D); - /// Specialized handler for StackSize diagnostic. - /// \return True if the diagnostic has been successfully reported, false - /// otherwise. - bool StackSizeDiagHandler(const llvm::DiagnosticInfoStackSize &D); - /// Specialized handler for ResourceLimit diagnostic. - /// \return True if the diagnostic has been successfully reported, false - /// otherwise. - bool ResourceLimitDiagHandler(const llvm::DiagnosticInfoResourceLimit &D); - - /// Specialized handler for unsupported backend feature diagnostic. - void UnsupportedDiagHandler(const llvm::DiagnosticInfoUnsupported &D); - /// Specialized handlers for optimization remarks. - /// Note that these handlers only accept remarks and they always handle - /// them. - void EmitOptimizationMessage(const llvm::DiagnosticInfoOptimizationBase &D, - unsigned DiagID); - void - OptimizationRemarkHandler(const llvm::DiagnosticInfoOptimizationBase &D); - void OptimizationRemarkHandler( - const llvm::OptimizationRemarkAnalysisFPCommute &D); - void OptimizationRemarkHandler( - const llvm::OptimizationRemarkAnalysisAliasing &D); - void OptimizationFailureHandler( - const llvm::DiagnosticInfoOptimizationFailure &D); - void DontCallDiagHandler(const DiagnosticInfoDontCall &D); - /// Specialized handler for misexpect warnings. - /// Note that misexpect remarks are emitted through ORE - void MisExpectDiagHandler(const llvm::DiagnosticInfoMisExpect &D); - }; +void BackendConsumer::HandleTagDeclRequiredDefinition(const TagDecl *D) { + Gen->HandleTagDeclRequiredDefinition(D); +} - void BackendConsumer::anchor() {} +void BackendConsumer::CompleteTentativeDefinition(VarDecl *D) { + Gen->CompleteTentativeDefinition(D); } +void BackendConsumer::CompleteExternalDeclaration(VarDecl *D) { + Gen->CompleteExternalDeclaration(D); +} + +void BackendConsumer::AssignInheritanceModel(CXXRecordDecl *RD) { + Gen->AssignInheritanceModel(RD); +} + +void BackendConsumer::HandleVTable(CXXRecordDecl *RD) { + Gen->HandleVTable(RD); +} + +void BackendConsumer::anchor() { } + +} // namespace clang + bool ClangDiagnosticHandler::handleDiagnostics(const DiagnosticInfo &DI) { BackendCon->DiagnosticHandlerImpl(DI); return true; diff --git a/clang/lib/CodeGen/LinkInModulesPass.cpp b/clang/lib/CodeGen/LinkInModulesPass.cpp new file mode 100644 index 0000000000000..6ce2b94c1db82 --- /dev/null +++ b/clang/lib/CodeGen/LinkInModulesPass.cpp @@ -0,0 +1,29 @@ +//===-- LinkInModulesPass.cpp - Module Linking pass --------------- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// \file +/// +/// LinkInModulesPass implementation. +/// +//===----------------------------------------------------------------------===// + +#include "LinkInModulesPass.h" +#include "BackendConsumer.h" + +using namespace llvm; + +LinkInModulesPass::LinkInModulesPass(clang::BackendConsumer *BC, + bool ShouldLinkFiles) + : BC(BC), ShouldLinkFiles(ShouldLinkFiles) {} + +PreservedAnalyses LinkInModulesPass::run(Module &M, ModuleAnalysisManager &AM) { + + if (BC && BC->LinkInModules(&M, ShouldLinkFiles)) + report_fatal_error("Bitcode module linking failed, compilation aborted!"); + + return PreservedAnalyses::all(); +} diff --git a/clang/lib/CodeGen/LinkInModulesPass.h b/clang/lib/CodeGen/LinkInModulesPass.h new file mode 100644 index 0000000000000..7fe94d6250583 --- /dev/null +++ b/clang/lib/CodeGen/LinkInModulesPass.h @@ -0,0 +1,42 @@ +//===-- LinkInModulesPass.h - Module Linking pass ----------------- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// \file +/// +/// This file provides a pass to link in Modules from a provided +/// BackendConsumer. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_BITCODE_LINKINMODULESPASS_H +#define LLVM_BITCODE_LINKINMODULESPASS_H + +#include "BackendConsumer.h" +#include "llvm/IR/PassManager.h" + +namespace llvm { +class Module; +class ModulePass; +class Pass; + +/// Create and return a pass that links in Moduels from a provided +/// BackendConsumer to a given primary Module. Note that this pass is designed +/// for use with the legacy pass manager. +class LinkInModulesPass : public PassInfoMixin { + clang::BackendConsumer *BC; + bool ShouldLinkFiles; + +public: + LinkInModulesPass(clang::BackendConsumer *BC, bool ShouldLinkFiles = true); + + PreservedAnalyses run(Module &M, AnalysisManager &); + static bool isRequired() { return true; } +}; + +} // namespace llvm + +#endif