1*5f757f3fSDimitry Andric //===--- BackendConsumer.h - LLVM BackendConsumer Header File -------------===// 2*5f757f3fSDimitry Andric // 3*5f757f3fSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*5f757f3fSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*5f757f3fSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*5f757f3fSDimitry Andric // 7*5f757f3fSDimitry Andric //===----------------------------------------------------------------------===// 8*5f757f3fSDimitry Andric 9*5f757f3fSDimitry Andric #ifndef LLVM_CLANG_LIB_CODEGEN_BACKENDCONSUMER_H 10*5f757f3fSDimitry Andric #define LLVM_CLANG_LIB_CODEGEN_BACKENDCONSUMER_H 11*5f757f3fSDimitry Andric 12*5f757f3fSDimitry Andric #include "clang/CodeGen/BackendUtil.h" 13*5f757f3fSDimitry Andric #include "clang/CodeGen/CodeGenAction.h" 14*5f757f3fSDimitry Andric 15*5f757f3fSDimitry Andric #include "llvm/IR/DiagnosticInfo.h" 16*5f757f3fSDimitry Andric #include "llvm/Support/Timer.h" 17*5f757f3fSDimitry Andric 18*5f757f3fSDimitry Andric namespace llvm { 19*5f757f3fSDimitry Andric class DiagnosticInfoDontCall; 20*5f757f3fSDimitry Andric } 21*5f757f3fSDimitry Andric 22*5f757f3fSDimitry Andric namespace clang { 23*5f757f3fSDimitry Andric class ASTContext; 24*5f757f3fSDimitry Andric class CodeGenAction; 25*5f757f3fSDimitry Andric class CoverageSourceInfo; 26*5f757f3fSDimitry Andric 27*5f757f3fSDimitry Andric class BackendConsumer : public ASTConsumer { 28*5f757f3fSDimitry Andric using LinkModule = CodeGenAction::LinkModule; 29*5f757f3fSDimitry Andric 30*5f757f3fSDimitry Andric virtual void anchor(); 31*5f757f3fSDimitry Andric DiagnosticsEngine &Diags; 32*5f757f3fSDimitry Andric BackendAction Action; 33*5f757f3fSDimitry Andric const HeaderSearchOptions &HeaderSearchOpts; 34*5f757f3fSDimitry Andric const CodeGenOptions &CodeGenOpts; 35*5f757f3fSDimitry Andric const TargetOptions &TargetOpts; 36*5f757f3fSDimitry Andric const LangOptions &LangOpts; 37*5f757f3fSDimitry Andric std::unique_ptr<raw_pwrite_stream> AsmOutStream; 38*5f757f3fSDimitry Andric ASTContext *Context; 39*5f757f3fSDimitry Andric IntrusiveRefCntPtr<llvm::vfs::FileSystem> FS; 40*5f757f3fSDimitry Andric 41*5f757f3fSDimitry Andric llvm::Timer LLVMIRGeneration; 42*5f757f3fSDimitry Andric unsigned LLVMIRGenerationRefCount; 43*5f757f3fSDimitry Andric 44*5f757f3fSDimitry Andric /// True if we've finished generating IR. This prevents us from generating 45*5f757f3fSDimitry Andric /// additional LLVM IR after emitting output in HandleTranslationUnit. This 46*5f757f3fSDimitry Andric /// can happen when Clang plugins trigger additional AST deserialization. 47*5f757f3fSDimitry Andric bool IRGenFinished = false; 48*5f757f3fSDimitry Andric 49*5f757f3fSDimitry Andric bool TimerIsEnabled = false; 50*5f757f3fSDimitry Andric 51*5f757f3fSDimitry Andric std::unique_ptr<CodeGenerator> Gen; 52*5f757f3fSDimitry Andric 53*5f757f3fSDimitry Andric SmallVector<LinkModule, 4> LinkModules; 54*5f757f3fSDimitry Andric 55*5f757f3fSDimitry Andric // A map from mangled names to their function's source location, used for 56*5f757f3fSDimitry Andric // backend diagnostics as the Clang AST may be unavailable. We actually use 57*5f757f3fSDimitry Andric // the mangled name's hash as the key because mangled names can be very 58*5f757f3fSDimitry Andric // long and take up lots of space. Using a hash can cause name collision, 59*5f757f3fSDimitry Andric // but that is rare and the consequences are pointing to a wrong source 60*5f757f3fSDimitry Andric // location which is not severe. This is a vector instead of an actual map 61*5f757f3fSDimitry Andric // because we optimize for time building this map rather than time 62*5f757f3fSDimitry Andric // retrieving an entry, as backend diagnostics are uncommon. 63*5f757f3fSDimitry Andric std::vector<std::pair<llvm::hash_code, FullSourceLoc>> 64*5f757f3fSDimitry Andric ManglingFullSourceLocs; 65*5f757f3fSDimitry Andric 66*5f757f3fSDimitry Andric 67*5f757f3fSDimitry Andric // This is here so that the diagnostic printer knows the module a diagnostic 68*5f757f3fSDimitry Andric // refers to. 69*5f757f3fSDimitry Andric llvm::Module *CurLinkModule = nullptr; 70*5f757f3fSDimitry Andric 71*5f757f3fSDimitry Andric public: 72*5f757f3fSDimitry Andric BackendConsumer(BackendAction Action, DiagnosticsEngine &Diags, 73*5f757f3fSDimitry Andric IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS, 74*5f757f3fSDimitry Andric const HeaderSearchOptions &HeaderSearchOpts, 75*5f757f3fSDimitry Andric const PreprocessorOptions &PPOpts, 76*5f757f3fSDimitry Andric const CodeGenOptions &CodeGenOpts, 77*5f757f3fSDimitry Andric const TargetOptions &TargetOpts, 78*5f757f3fSDimitry Andric const LangOptions &LangOpts, const std::string &InFile, 79*5f757f3fSDimitry Andric SmallVector<LinkModule, 4> LinkModules, 80*5f757f3fSDimitry Andric std::unique_ptr<raw_pwrite_stream> OS, llvm::LLVMContext &C, 81*5f757f3fSDimitry Andric CoverageSourceInfo *CoverageInfo = nullptr); 82*5f757f3fSDimitry Andric 83*5f757f3fSDimitry Andric // This constructor is used in installing an empty BackendConsumer 84*5f757f3fSDimitry Andric // to use the clang diagnostic handler for IR input files. It avoids 85*5f757f3fSDimitry Andric // initializing the OS field. 86*5f757f3fSDimitry Andric BackendConsumer(BackendAction Action, DiagnosticsEngine &Diags, 87*5f757f3fSDimitry Andric IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS, 88*5f757f3fSDimitry Andric const HeaderSearchOptions &HeaderSearchOpts, 89*5f757f3fSDimitry Andric const PreprocessorOptions &PPOpts, 90*5f757f3fSDimitry Andric const CodeGenOptions &CodeGenOpts, 91*5f757f3fSDimitry Andric const TargetOptions &TargetOpts, 92*5f757f3fSDimitry Andric const LangOptions &LangOpts, llvm::Module *Module, 93*5f757f3fSDimitry Andric SmallVector<LinkModule, 4> LinkModules, llvm::LLVMContext &C, 94*5f757f3fSDimitry Andric CoverageSourceInfo *CoverageInfo = nullptr); 95*5f757f3fSDimitry Andric 96*5f757f3fSDimitry Andric llvm::Module *getModule() const; 97*5f757f3fSDimitry Andric std::unique_ptr<llvm::Module> takeModule(); 98*5f757f3fSDimitry Andric 99*5f757f3fSDimitry Andric CodeGenerator *getCodeGenerator(); 100*5f757f3fSDimitry Andric 101*5f757f3fSDimitry Andric void HandleCXXStaticMemberVarInstantiation(VarDecl *VD) override; 102*5f757f3fSDimitry Andric void Initialize(ASTContext &Ctx) override; 103*5f757f3fSDimitry Andric bool HandleTopLevelDecl(DeclGroupRef D) override; 104*5f757f3fSDimitry Andric void HandleInlineFunctionDefinition(FunctionDecl *D) override; 105*5f757f3fSDimitry Andric void HandleInterestingDecl(DeclGroupRef D) override; 106*5f757f3fSDimitry Andric void HandleTranslationUnit(ASTContext &C) override; 107*5f757f3fSDimitry Andric void HandleTagDeclDefinition(TagDecl *D) override; 108*5f757f3fSDimitry Andric void HandleTagDeclRequiredDefinition(const TagDecl *D) override; 109*5f757f3fSDimitry Andric void CompleteTentativeDefinition(VarDecl *D) override; 110*5f757f3fSDimitry Andric void CompleteExternalDeclaration(VarDecl *D) override; 111*5f757f3fSDimitry Andric void AssignInheritanceModel(CXXRecordDecl *RD) override; 112*5f757f3fSDimitry Andric void HandleVTable(CXXRecordDecl *RD) override; 113*5f757f3fSDimitry Andric 114*5f757f3fSDimitry Andric 115*5f757f3fSDimitry Andric // Links each entry in LinkModules into our module. Returns true on error. 116*5f757f3fSDimitry Andric bool LinkInModules(llvm::Module *M, bool ShouldLinkFiles = true); 117*5f757f3fSDimitry Andric 118*5f757f3fSDimitry Andric /// Get the best possible source location to represent a diagnostic that 119*5f757f3fSDimitry Andric /// may have associated debug info. 120*5f757f3fSDimitry Andric const FullSourceLoc getBestLocationFromDebugLoc( 121*5f757f3fSDimitry Andric const llvm::DiagnosticInfoWithLocationBase &D, 122*5f757f3fSDimitry Andric bool &BadDebugInfo, StringRef &Filename, 123*5f757f3fSDimitry Andric unsigned &Line, unsigned &Column) const; 124*5f757f3fSDimitry Andric 125*5f757f3fSDimitry Andric std::optional<FullSourceLoc> getFunctionSourceLocation( 126*5f757f3fSDimitry Andric const llvm::Function &F) const; 127*5f757f3fSDimitry Andric 128*5f757f3fSDimitry Andric void DiagnosticHandlerImpl(const llvm::DiagnosticInfo &DI); 129*5f757f3fSDimitry Andric /// Specialized handler for InlineAsm diagnostic. 130*5f757f3fSDimitry Andric /// \return True if the diagnostic has been successfully reported, false 131*5f757f3fSDimitry Andric /// otherwise. 132*5f757f3fSDimitry Andric bool InlineAsmDiagHandler(const llvm::DiagnosticInfoInlineAsm &D); 133*5f757f3fSDimitry Andric /// Specialized handler for diagnostics reported using SMDiagnostic. 134*5f757f3fSDimitry Andric void SrcMgrDiagHandler(const llvm::DiagnosticInfoSrcMgr &D); 135*5f757f3fSDimitry Andric /// Specialized handler for StackSize diagnostic. 136*5f757f3fSDimitry Andric /// \return True if the diagnostic has been successfully reported, false 137*5f757f3fSDimitry Andric /// otherwise. 138*5f757f3fSDimitry Andric bool StackSizeDiagHandler(const llvm::DiagnosticInfoStackSize &D); 139*5f757f3fSDimitry Andric /// Specialized handler for ResourceLimit diagnostic. 140*5f757f3fSDimitry Andric /// \return True if the diagnostic has been successfully reported, false 141*5f757f3fSDimitry Andric /// otherwise. 142*5f757f3fSDimitry Andric bool ResourceLimitDiagHandler(const llvm::DiagnosticInfoResourceLimit &D); 143*5f757f3fSDimitry Andric 144*5f757f3fSDimitry Andric /// Specialized handler for unsupported backend feature diagnostic. 145*5f757f3fSDimitry Andric void UnsupportedDiagHandler(const llvm::DiagnosticInfoUnsupported &D); 146*5f757f3fSDimitry Andric /// Specialized handlers for optimization remarks. 147*5f757f3fSDimitry Andric /// Note that these handlers only accept remarks and they always handle 148*5f757f3fSDimitry Andric /// them. 149*5f757f3fSDimitry Andric void EmitOptimizationMessage(const llvm::DiagnosticInfoOptimizationBase &D, 150*5f757f3fSDimitry Andric unsigned DiagID); 151*5f757f3fSDimitry Andric void 152*5f757f3fSDimitry Andric OptimizationRemarkHandler(const llvm::DiagnosticInfoOptimizationBase &D); 153*5f757f3fSDimitry Andric void OptimizationRemarkHandler( 154*5f757f3fSDimitry Andric const llvm::OptimizationRemarkAnalysisFPCommute &D); 155*5f757f3fSDimitry Andric void OptimizationRemarkHandler( 156*5f757f3fSDimitry Andric const llvm::OptimizationRemarkAnalysisAliasing &D); 157*5f757f3fSDimitry Andric void OptimizationFailureHandler( 158*5f757f3fSDimitry Andric const llvm::DiagnosticInfoOptimizationFailure &D); 159*5f757f3fSDimitry Andric void DontCallDiagHandler(const llvm::DiagnosticInfoDontCall &D); 160*5f757f3fSDimitry Andric /// Specialized handler for misexpect warnings. 161*5f757f3fSDimitry Andric /// Note that misexpect remarks are emitted through ORE 162*5f757f3fSDimitry Andric void MisExpectDiagHandler(const llvm::DiagnosticInfoMisExpect &D); 163*5f757f3fSDimitry Andric }; 164*5f757f3fSDimitry Andric 165*5f757f3fSDimitry Andric } // namespace clang 166*5f757f3fSDimitry Andric #endif 167