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