/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/CodeGen/CodeGenAction.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===--- CodeGenAction.cpp - LLVM Code Generation Frontend Action ---------===// |
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 | | #include "clang/CodeGen/CodeGenAction.h" |
10 | | #include "CodeGenModule.h" |
11 | | #include "CoverageMappingGen.h" |
12 | | #include "MacroPPCallbacks.h" |
13 | | #include "clang/AST/ASTConsumer.h" |
14 | | #include "clang/AST/ASTContext.h" |
15 | | #include "clang/AST/DeclCXX.h" |
16 | | #include "clang/AST/DeclGroup.h" |
17 | | #include "clang/Basic/DiagnosticFrontend.h" |
18 | | #include "clang/Basic/FileManager.h" |
19 | | #include "clang/Basic/LangStandard.h" |
20 | | #include "clang/Basic/SourceManager.h" |
21 | | #include "clang/Basic/TargetInfo.h" |
22 | | #include "clang/CodeGen/BackendUtil.h" |
23 | | #include "clang/CodeGen/ModuleBuilder.h" |
24 | | #include "clang/Driver/DriverDiagnostic.h" |
25 | | #include "clang/Frontend/CompilerInstance.h" |
26 | | #include "clang/Frontend/FrontendDiagnostic.h" |
27 | | #include "clang/Lex/Preprocessor.h" |
28 | | #include "llvm/ADT/Hashing.h" |
29 | | #include "llvm/Bitcode/BitcodeReader.h" |
30 | | #include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h" |
31 | | #include "llvm/Demangle/Demangle.h" |
32 | | #include "llvm/IR/DebugInfo.h" |
33 | | #include "llvm/IR/DiagnosticInfo.h" |
34 | | #include "llvm/IR/DiagnosticPrinter.h" |
35 | | #include "llvm/IR/GlobalValue.h" |
36 | | #include "llvm/IR/LLVMContext.h" |
37 | | #include "llvm/IR/LLVMRemarkStreamer.h" |
38 | | #include "llvm/IR/Module.h" |
39 | | #include "llvm/IRReader/IRReader.h" |
40 | | #include "llvm/LTO/LTOBackend.h" |
41 | | #include "llvm/Linker/Linker.h" |
42 | | #include "llvm/Pass.h" |
43 | | #include "llvm/Support/MemoryBuffer.h" |
44 | | #include "llvm/Support/SourceMgr.h" |
45 | | #include "llvm/Support/TimeProfiler.h" |
46 | | #include "llvm/Support/Timer.h" |
47 | | #include "llvm/Support/ToolOutputFile.h" |
48 | | #include "llvm/Support/YAMLTraits.h" |
49 | | #include "llvm/Transforms/IPO/Internalize.h" |
50 | | |
51 | | #include <memory> |
52 | | using namespace clang; |
53 | | using namespace llvm; |
54 | | |
55 | | #define DEBUG_TYPE "codegenaction" |
56 | | |
57 | | namespace clang { |
58 | | class BackendConsumer; |
59 | | class ClangDiagnosticHandler final : public DiagnosticHandler { |
60 | | public: |
61 | | ClangDiagnosticHandler(const CodeGenOptions &CGOpts, BackendConsumer *BCon) |
62 | 19.6k | : CodeGenOpts(CGOpts), BackendCon(BCon) {} |
63 | | |
64 | | bool handleDiagnostics(const DiagnosticInfo &DI) override; |
65 | | |
66 | 5.06M | bool isAnalysisRemarkEnabled(StringRef PassName) const override { |
67 | 5.06M | return CodeGenOpts.OptimizationRemarkAnalysis.patternMatches(PassName); |
68 | 5.06M | } |
69 | 423k | bool isMissedOptRemarkEnabled(StringRef PassName) const override { |
70 | 423k | return CodeGenOpts.OptimizationRemarkMissed.patternMatches(PassName); |
71 | 423k | } |
72 | 373k | bool isPassedOptRemarkEnabled(StringRef PassName) const override { |
73 | 373k | return CodeGenOpts.OptimizationRemark.patternMatches(PassName); |
74 | 373k | } |
75 | | |
76 | 130k | bool isAnyRemarkEnabled() const override { |
77 | 130k | return CodeGenOpts.OptimizationRemarkAnalysis.hasValidPattern() || |
78 | 130k | CodeGenOpts.OptimizationRemarkMissed.hasValidPattern()129k || |
79 | 130k | CodeGenOpts.OptimizationRemark.hasValidPattern()129k ; |
80 | 130k | } |
81 | | |
82 | | private: |
83 | | const CodeGenOptions &CodeGenOpts; |
84 | | BackendConsumer *BackendCon; |
85 | | }; |
86 | | |
87 | | static void reportOptRecordError(Error E, DiagnosticsEngine &Diags, |
88 | 2 | const CodeGenOptions CodeGenOpts) { |
89 | 2 | handleAllErrors( |
90 | 2 | std::move(E), |
91 | 2 | [&](const LLVMRemarkSetupFileError &E) { |
92 | 0 | Diags.Report(diag::err_cannot_open_file) |
93 | 0 | << CodeGenOpts.OptRecordFile << E.message(); |
94 | 0 | }, |
95 | 2 | [&](const LLVMRemarkSetupPatternError &E) { |
96 | 1 | Diags.Report(diag::err_drv_optimization_remark_pattern) |
97 | 1 | << E.message() << CodeGenOpts.OptRecordPasses; |
98 | 1 | }, |
99 | 2 | [&](const LLVMRemarkSetupFormatError &E) { |
100 | 1 | Diags.Report(diag::err_drv_optimization_remark_format) |
101 | 1 | << CodeGenOpts.OptRecordFormat; |
102 | 1 | }); |
103 | 2 | } |
104 | | |
105 | | class BackendConsumer : public ASTConsumer { |
106 | | using LinkModule = CodeGenAction::LinkModule; |
107 | | |
108 | | virtual void anchor(); |
109 | | DiagnosticsEngine &Diags; |
110 | | BackendAction Action; |
111 | | const HeaderSearchOptions &HeaderSearchOpts; |
112 | | const CodeGenOptions &CodeGenOpts; |
113 | | const TargetOptions &TargetOpts; |
114 | | const LangOptions &LangOpts; |
115 | | std::unique_ptr<raw_pwrite_stream> AsmOutStream; |
116 | | ASTContext *Context; |
117 | | |
118 | | Timer LLVMIRGeneration; |
119 | | unsigned LLVMIRGenerationRefCount; |
120 | | |
121 | | /// True if we've finished generating IR. This prevents us from generating |
122 | | /// additional LLVM IR after emitting output in HandleTranslationUnit. This |
123 | | /// can happen when Clang plugins trigger additional AST deserialization. |
124 | | bool IRGenFinished = false; |
125 | | |
126 | | bool TimerIsEnabled = false; |
127 | | |
128 | | std::unique_ptr<CodeGenerator> Gen; |
129 | | |
130 | | SmallVector<LinkModule, 4> LinkModules; |
131 | | |
132 | | // A map from mangled names to their function's source location, used for |
133 | | // backend diagnostics as the Clang AST may be unavailable. We actually use |
134 | | // the mangled name's hash as the key because mangled names can be very |
135 | | // long and take up lots of space. Using a hash can cause name collision, |
136 | | // but that is rare and the consequences are pointing to a wrong source |
137 | | // location which is not severe. This is a vector instead of an actual map |
138 | | // because we optimize for time building this map rather than time |
139 | | // retrieving an entry, as backend diagnostics are uncommon. |
140 | | std::vector<std::pair<llvm::hash_code, FullSourceLoc>> |
141 | | ManglingFullSourceLocs; |
142 | | |
143 | | // This is here so that the diagnostic printer knows the module a diagnostic |
144 | | // refers to. |
145 | | llvm::Module *CurLinkModule = nullptr; |
146 | | |
147 | | public: |
148 | | BackendConsumer(BackendAction Action, DiagnosticsEngine &Diags, |
149 | | const HeaderSearchOptions &HeaderSearchOpts, |
150 | | const PreprocessorOptions &PPOpts, |
151 | | const CodeGenOptions &CodeGenOpts, |
152 | | const TargetOptions &TargetOpts, |
153 | | const LangOptions &LangOpts, const std::string &InFile, |
154 | | SmallVector<LinkModule, 4> LinkModules, |
155 | | std::unique_ptr<raw_pwrite_stream> OS, LLVMContext &C, |
156 | | CoverageSourceInfo *CoverageInfo = nullptr) |
157 | | : Diags(Diags), Action(Action), HeaderSearchOpts(HeaderSearchOpts), |
158 | | CodeGenOpts(CodeGenOpts), TargetOpts(TargetOpts), LangOpts(LangOpts), |
159 | | AsmOutStream(std::move(OS)), Context(nullptr), |
160 | | LLVMIRGeneration("irgen", "LLVM IR Generation Time"), |
161 | | LLVMIRGenerationRefCount(0), |
162 | | Gen(CreateLLVMCodeGen(Diags, InFile, HeaderSearchOpts, PPOpts, |
163 | | CodeGenOpts, C, CoverageInfo)), |
164 | 19.7k | LinkModules(std::move(LinkModules)) { |
165 | 19.7k | TimerIsEnabled = CodeGenOpts.TimePasses; |
166 | 19.7k | llvm::TimePassesIsEnabled = CodeGenOpts.TimePasses; |
167 | 19.7k | llvm::TimePassesPerRun = CodeGenOpts.TimePassesPerRun; |
168 | 19.7k | } |
169 | | |
170 | | // This constructor is used in installing an empty BackendConsumer |
171 | | // to use the clang diagnostic handler for IR input files. It avoids |
172 | | // initializing the OS field. |
173 | | BackendConsumer(BackendAction Action, DiagnosticsEngine &Diags, |
174 | | const HeaderSearchOptions &HeaderSearchOpts, |
175 | | const PreprocessorOptions &PPOpts, |
176 | | const CodeGenOptions &CodeGenOpts, |
177 | | const TargetOptions &TargetOpts, |
178 | | const LangOptions &LangOpts, llvm::Module *Module, |
179 | | SmallVector<LinkModule, 4> LinkModules, LLVMContext &C, |
180 | | CoverageSourceInfo *CoverageInfo = nullptr) |
181 | | : Diags(Diags), Action(Action), HeaderSearchOpts(HeaderSearchOpts), |
182 | | CodeGenOpts(CodeGenOpts), TargetOpts(TargetOpts), LangOpts(LangOpts), |
183 | | Context(nullptr), |
184 | | LLVMIRGeneration("irgen", "LLVM IR Generation Time"), |
185 | | LLVMIRGenerationRefCount(0), |
186 | | Gen(CreateLLVMCodeGen(Diags, "", HeaderSearchOpts, PPOpts, |
187 | | CodeGenOpts, C, CoverageInfo)), |
188 | 101 | LinkModules(std::move(LinkModules)), CurLinkModule(Module) { |
189 | 101 | TimerIsEnabled = CodeGenOpts.TimePasses; |
190 | 101 | llvm::TimePassesIsEnabled = CodeGenOpts.TimePasses; |
191 | 101 | llvm::TimePassesPerRun = CodeGenOpts.TimePassesPerRun; |
192 | 101 | } |
193 | 98.1k | llvm::Module *getModule() const { return Gen->GetModule(); } |
194 | 19.7k | std::unique_ptr<llvm::Module> takeModule() { |
195 | 19.7k | return std::unique_ptr<llvm::Module>(Gen->ReleaseModule()); |
196 | 19.7k | } |
197 | | |
198 | 38 | CodeGenerator *getCodeGenerator() { return Gen.get(); } |
199 | | |
200 | 576k | void HandleCXXStaticMemberVarInstantiation(VarDecl *VD) override { |
201 | 576k | Gen->HandleCXXStaticMemberVarInstantiation(VD); |
202 | 576k | } |
203 | | |
204 | 19.7k | void Initialize(ASTContext &Ctx) override { |
205 | 19.7k | assert(!Context && "initialized multiple times"); |
206 | | |
207 | 0 | Context = &Ctx; |
208 | | |
209 | 19.7k | if (TimerIsEnabled) |
210 | 13 | LLVMIRGeneration.startTimer(); |
211 | | |
212 | 19.7k | Gen->Initialize(Ctx); |
213 | | |
214 | 19.7k | if (TimerIsEnabled) |
215 | 13 | LLVMIRGeneration.stopTimer(); |
216 | 19.7k | } |
217 | | |
218 | 16.6M | bool HandleTopLevelDecl(DeclGroupRef D) override { |
219 | 16.6M | PrettyStackTraceDecl CrashInfo(*D.begin(), SourceLocation(), |
220 | 16.6M | Context->getSourceManager(), |
221 | 16.6M | "LLVM IR generation of declaration"); |
222 | | |
223 | | // Recurse. |
224 | 16.6M | if (TimerIsEnabled) { |
225 | 85 | LLVMIRGenerationRefCount += 1; |
226 | 85 | if (LLVMIRGenerationRefCount == 1) |
227 | 85 | LLVMIRGeneration.startTimer(); |
228 | 85 | } |
229 | | |
230 | 16.6M | Gen->HandleTopLevelDecl(D); |
231 | | |
232 | 16.6M | if (TimerIsEnabled) { |
233 | 85 | LLVMIRGenerationRefCount -= 1; |
234 | 85 | if (LLVMIRGenerationRefCount == 0) |
235 | 85 | LLVMIRGeneration.stopTimer(); |
236 | 85 | } |
237 | | |
238 | 16.6M | return true; |
239 | 16.6M | } |
240 | | |
241 | 423k | void HandleInlineFunctionDefinition(FunctionDecl *D) override { |
242 | 423k | PrettyStackTraceDecl CrashInfo(D, SourceLocation(), |
243 | 423k | Context->getSourceManager(), |
244 | 423k | "LLVM IR generation of inline function"); |
245 | 423k | if (TimerIsEnabled) |
246 | 0 | LLVMIRGeneration.startTimer(); |
247 | | |
248 | 423k | Gen->HandleInlineFunctionDefinition(D); |
249 | | |
250 | 423k | if (TimerIsEnabled) |
251 | 0 | LLVMIRGeneration.stopTimer(); |
252 | 423k | } |
253 | | |
254 | 75.3k | void HandleInterestingDecl(DeclGroupRef D) override { |
255 | | // Ignore interesting decls from the AST reader after IRGen is finished. |
256 | 75.3k | if (!IRGenFinished) |
257 | 75.3k | HandleTopLevelDecl(D); |
258 | 75.3k | } |
259 | | |
260 | | // Links each entry in LinkModules into our module. Returns true on error. |
261 | 19.5k | bool LinkInModules() { |
262 | 19.5k | for (auto &LM : LinkModules) { |
263 | 8 | if (LM.PropagateAttrs) |
264 | 3 | for (Function &F : *LM.Module) { |
265 | | // Skip intrinsics. Keep consistent with how intrinsics are created |
266 | | // in LLVM IR. |
267 | 3 | if (F.isIntrinsic()) |
268 | 0 | continue; |
269 | 3 | Gen->CGM().addDefaultFunctionDefinitionAttributes(F); |
270 | 3 | } |
271 | | |
272 | 8 | CurLinkModule = LM.Module.get(); |
273 | | |
274 | 8 | bool Err; |
275 | 8 | if (LM.Internalize) { |
276 | 3 | Err = Linker::linkModules( |
277 | 3 | *getModule(), std::move(LM.Module), LM.LinkFlags, |
278 | 3 | [](llvm::Module &M, const llvm::StringSet<> &GVS) { |
279 | 6 | internalizeModule(M, [&GVS](const llvm::GlobalValue &GV) { |
280 | 6 | return !GV.hasName() || (GVS.count(GV.getName()) == 0); |
281 | 6 | }); |
282 | 3 | }); |
283 | 5 | } else { |
284 | 5 | Err = Linker::linkModules(*getModule(), std::move(LM.Module), |
285 | 5 | LM.LinkFlags); |
286 | 5 | } |
287 | | |
288 | 8 | if (Err) |
289 | 1 | return true; |
290 | 8 | } |
291 | 19.5k | return false; // success |
292 | 19.5k | } |
293 | | |
294 | 19.8k | void HandleTranslationUnit(ASTContext &C) override { |
295 | 19.8k | { |
296 | 19.8k | llvm::TimeTraceScope TimeScope("Frontend"); |
297 | 19.8k | PrettyStackTraceString CrashInfo("Per-file LLVM IR generation"); |
298 | 19.8k | if (TimerIsEnabled) { |
299 | 13 | LLVMIRGenerationRefCount += 1; |
300 | 13 | if (LLVMIRGenerationRefCount == 1) |
301 | 13 | LLVMIRGeneration.startTimer(); |
302 | 13 | } |
303 | | |
304 | 19.8k | Gen->HandleTranslationUnit(C); |
305 | | |
306 | 19.8k | if (TimerIsEnabled) { |
307 | 13 | LLVMIRGenerationRefCount -= 1; |
308 | 13 | if (LLVMIRGenerationRefCount == 0) |
309 | 13 | LLVMIRGeneration.stopTimer(); |
310 | 13 | } |
311 | | |
312 | 19.8k | IRGenFinished = true; |
313 | 19.8k | } |
314 | | |
315 | | // Silently ignore if we weren't initialized for some reason. |
316 | 19.8k | if (!getModule()) |
317 | 221 | return; |
318 | | |
319 | 19.5k | LLVMContext &Ctx = getModule()->getContext(); |
320 | 19.5k | std::unique_ptr<DiagnosticHandler> OldDiagnosticHandler = |
321 | 19.5k | Ctx.getDiagnosticHandler(); |
322 | 19.5k | Ctx.setDiagnosticHandler(std::make_unique<ClangDiagnosticHandler>( |
323 | 19.5k | CodeGenOpts, this)); |
324 | | |
325 | 19.5k | Expected<std::unique_ptr<llvm::ToolOutputFile>> OptRecordFileOrErr = |
326 | 19.5k | setupLLVMOptimizationRemarks( |
327 | 19.5k | Ctx, CodeGenOpts.OptRecordFile, CodeGenOpts.OptRecordPasses, |
328 | 19.5k | CodeGenOpts.OptRecordFormat, CodeGenOpts.DiagnosticsWithHotness, |
329 | 19.5k | CodeGenOpts.DiagnosticsHotnessThreshold); |
330 | | |
331 | 19.5k | if (Error E = OptRecordFileOrErr.takeError()) { |
332 | 2 | reportOptRecordError(std::move(E), Diags, CodeGenOpts); |
333 | 2 | return; |
334 | 2 | } |
335 | | |
336 | 19.5k | std::unique_ptr<llvm::ToolOutputFile> OptRecordFile = |
337 | 19.5k | std::move(*OptRecordFileOrErr); |
338 | | |
339 | 19.5k | if (OptRecordFile && |
340 | 19.5k | CodeGenOpts.getProfileUse() != CodeGenOptions::ProfileNone7 ) |
341 | 1 | Ctx.setDiagnosticsHotnessRequested(true); |
342 | | |
343 | 19.5k | if (CodeGenOpts.MisExpect) { |
344 | 10 | Ctx.setMisExpectWarningRequested(true); |
345 | 10 | } |
346 | | |
347 | 19.5k | if (CodeGenOpts.DiagnosticsMisExpectTolerance) { |
348 | 19.5k | Ctx.setDiagnosticsMisExpectTolerance( |
349 | 19.5k | CodeGenOpts.DiagnosticsMisExpectTolerance); |
350 | 19.5k | } |
351 | | |
352 | | // Link each LinkModule into our module. |
353 | 19.5k | if (LinkInModules()) |
354 | 1 | return; |
355 | | |
356 | 386k | for (auto &F : getModule()->functions())19.5k { |
357 | 386k | if (const Decl *FD = Gen->GetDeclForMangledName(F.getName())) { |
358 | 274k | auto Loc = FD->getASTContext().getFullLoc(FD->getLocation()); |
359 | | // TODO: use a fast content hash when available. |
360 | 274k | auto NameHash = llvm::hash_value(F.getName()); |
361 | 274k | ManglingFullSourceLocs.push_back(std::make_pair(NameHash, Loc)); |
362 | 274k | } |
363 | 386k | } |
364 | | |
365 | 19.5k | if (CodeGenOpts.ClearASTBeforeBackend) { |
366 | 4.24k | LLVM_DEBUG(llvm::dbgs() << "Clearing AST...\n"); |
367 | | // Access to the AST is no longer available after this. |
368 | | // Other things that the ASTContext manages are still available, e.g. |
369 | | // the SourceManager. It'd be nice if we could separate out all the |
370 | | // things in ASTContext used after this point and null out the |
371 | | // ASTContext, but too many various parts of the ASTContext are still |
372 | | // used in various parts. |
373 | 4.24k | C.cleanup(); |
374 | 4.24k | C.getAllocator().Reset(); |
375 | 4.24k | } |
376 | | |
377 | 19.5k | EmbedBitcode(getModule(), CodeGenOpts, llvm::MemoryBufferRef()); |
378 | | |
379 | 19.5k | EmitBackendOutput(Diags, HeaderSearchOpts, CodeGenOpts, TargetOpts, |
380 | 19.5k | LangOpts, C.getTargetInfo().getDataLayoutString(), |
381 | 19.5k | getModule(), Action, std::move(AsmOutStream)); |
382 | | |
383 | 19.5k | Ctx.setDiagnosticHandler(std::move(OldDiagnosticHandler)); |
384 | | |
385 | 19.5k | if (OptRecordFile) |
386 | 7 | OptRecordFile->keep(); |
387 | 19.5k | } |
388 | | |
389 | 2.02M | void HandleTagDeclDefinition(TagDecl *D) override { |
390 | 2.02M | PrettyStackTraceDecl CrashInfo(D, SourceLocation(), |
391 | 2.02M | Context->getSourceManager(), |
392 | 2.02M | "LLVM IR generation of declaration"); |
393 | 2.02M | Gen->HandleTagDeclDefinition(D); |
394 | 2.02M | } |
395 | | |
396 | 975k | void HandleTagDeclRequiredDefinition(const TagDecl *D) override { |
397 | 975k | Gen->HandleTagDeclRequiredDefinition(D); |
398 | 975k | } |
399 | | |
400 | 4.23k | void CompleteTentativeDefinition(VarDecl *D) override { |
401 | 4.23k | Gen->CompleteTentativeDefinition(D); |
402 | 4.23k | } |
403 | | |
404 | 7 | void CompleteExternalDeclaration(VarDecl *D) override { |
405 | 7 | Gen->CompleteExternalDeclaration(D); |
406 | 7 | } |
407 | | |
408 | 494 | void AssignInheritanceModel(CXXRecordDecl *RD) override { |
409 | 494 | Gen->AssignInheritanceModel(RD); |
410 | 494 | } |
411 | | |
412 | 795 | void HandleVTable(CXXRecordDecl *RD) override { |
413 | 795 | Gen->HandleVTable(RD); |
414 | 795 | } |
415 | | |
416 | | /// Get the best possible source location to represent a diagnostic that |
417 | | /// may have associated debug info. |
418 | | const FullSourceLoc |
419 | | getBestLocationFromDebugLoc(const llvm::DiagnosticInfoWithLocationBase &D, |
420 | | bool &BadDebugInfo, StringRef &Filename, |
421 | | unsigned &Line, unsigned &Column) const; |
422 | | |
423 | | Optional<FullSourceLoc> getFunctionSourceLocation(const Function &F) const; |
424 | | |
425 | | void DiagnosticHandlerImpl(const llvm::DiagnosticInfo &DI); |
426 | | /// Specialized handler for InlineAsm diagnostic. |
427 | | /// \return True if the diagnostic has been successfully reported, false |
428 | | /// otherwise. |
429 | | bool InlineAsmDiagHandler(const llvm::DiagnosticInfoInlineAsm &D); |
430 | | /// Specialized handler for diagnostics reported using SMDiagnostic. |
431 | | void SrcMgrDiagHandler(const llvm::DiagnosticInfoSrcMgr &D); |
432 | | /// Specialized handler for StackSize diagnostic. |
433 | | /// \return True if the diagnostic has been successfully reported, false |
434 | | /// otherwise. |
435 | | bool StackSizeDiagHandler(const llvm::DiagnosticInfoStackSize &D); |
436 | | /// Specialized handler for unsupported backend feature diagnostic. |
437 | | void UnsupportedDiagHandler(const llvm::DiagnosticInfoUnsupported &D); |
438 | | /// Specialized handlers for optimization remarks. |
439 | | /// Note that these handlers only accept remarks and they always handle |
440 | | /// them. |
441 | | void EmitOptimizationMessage(const llvm::DiagnosticInfoOptimizationBase &D, |
442 | | unsigned DiagID); |
443 | | void |
444 | | OptimizationRemarkHandler(const llvm::DiagnosticInfoOptimizationBase &D); |
445 | | void OptimizationRemarkHandler( |
446 | | const llvm::OptimizationRemarkAnalysisFPCommute &D); |
447 | | void OptimizationRemarkHandler( |
448 | | const llvm::OptimizationRemarkAnalysisAliasing &D); |
449 | | void OptimizationFailureHandler( |
450 | | const llvm::DiagnosticInfoOptimizationFailure &D); |
451 | | void DontCallDiagHandler(const DiagnosticInfoDontCall &D); |
452 | | /// Specialized handler for misexpect warnings. |
453 | | /// Note that misexpect remarks are emitted through ORE |
454 | | void MisExpectDiagHandler(const llvm::DiagnosticInfoMisExpect &D); |
455 | | }; |
456 | | |
457 | 0 | void BackendConsumer::anchor() {} |
458 | | } |
459 | | |
460 | 147k | bool ClangDiagnosticHandler::handleDiagnostics(const DiagnosticInfo &DI) { |
461 | 147k | BackendCon->DiagnosticHandlerImpl(DI); |
462 | 147k | return true; |
463 | 147k | } |
464 | | |
465 | | /// ConvertBackendLocation - Convert a location in a temporary llvm::SourceMgr |
466 | | /// buffer to be a valid FullSourceLoc. |
467 | | static FullSourceLoc ConvertBackendLocation(const llvm::SMDiagnostic &D, |
468 | 9 | SourceManager &CSM) { |
469 | | // Get both the clang and llvm source managers. The location is relative to |
470 | | // a memory buffer that the LLVM Source Manager is handling, we need to add |
471 | | // a copy to the Clang source manager. |
472 | 9 | const llvm::SourceMgr &LSM = *D.getSourceMgr(); |
473 | | |
474 | | // We need to copy the underlying LLVM memory buffer because llvm::SourceMgr |
475 | | // already owns its one and clang::SourceManager wants to own its one. |
476 | 9 | const MemoryBuffer *LBuf = |
477 | 9 | LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(D.getLoc())); |
478 | | |
479 | | // Create the copy and transfer ownership to clang::SourceManager. |
480 | | // TODO: Avoid copying files into memory. |
481 | 9 | std::unique_ptr<llvm::MemoryBuffer> CBuf = |
482 | 9 | llvm::MemoryBuffer::getMemBufferCopy(LBuf->getBuffer(), |
483 | 9 | LBuf->getBufferIdentifier()); |
484 | | // FIXME: Keep a file ID map instead of creating new IDs for each location. |
485 | 9 | FileID FID = CSM.createFileID(std::move(CBuf)); |
486 | | |
487 | | // Translate the offset into the file. |
488 | 9 | unsigned Offset = D.getLoc().getPointer() - LBuf->getBufferStart(); |
489 | 9 | SourceLocation NewLoc = |
490 | 9 | CSM.getLocForStartOfFile(FID).getLocWithOffset(Offset); |
491 | 9 | return FullSourceLoc(NewLoc, CSM); |
492 | 9 | } |
493 | | |
494 | | #define ComputeDiagID(Severity, GroupName, DiagID) \ |
495 | 32 | do { \ |
496 | 32 | switch (Severity) { \ |
497 | 23 | case llvm::DS_Error: \ |
498 | 23 | DiagID = diag::err_fe_##GroupName; \ |
499 | 23 | break; \ |
500 | 8 | case llvm::DS_Warning: \ |
501 | 8 | DiagID = diag::warn_fe_##GroupName; \ |
502 | 8 | break; \ |
503 | 0 | case llvm::DS_Remark: \ |
504 | 0 | llvm_unreachable("'remark' severity not expected"); \ |
505 | 0 | break; \ |
506 | 1 | case llvm::DS_Note: \ |
507 | 1 | DiagID = diag::note_fe_##GroupName; \ |
508 | 1 | break; \ |
509 | 32 | } \ |
510 | 32 | } while (false) |
511 | | |
512 | | #define ComputeDiagRemarkID(Severity, GroupName, DiagID) \ |
513 | 3 | do { \ |
514 | 3 | switch (Severity) { \ |
515 | 3 | case llvm::DS_Error: \ |
516 | 3 | DiagID = diag::err_fe_##GroupName; \ |
517 | 3 | break; \ |
518 | 0 | case llvm::DS_Warning: \ |
519 | 0 | DiagID = diag::warn_fe_##GroupName; \ |
520 | 0 | break; \ |
521 | 0 | case llvm::DS_Remark: \ |
522 | 0 | DiagID = diag::remark_fe_##GroupName; \ |
523 | 0 | break; \ |
524 | 0 | case llvm::DS_Note: \ |
525 | 0 | DiagID = diag::note_fe_##GroupName; \ |
526 | 0 | break; \ |
527 | 3 | } \ |
528 | 3 | } while (false) |
529 | | |
530 | 10 | void BackendConsumer::SrcMgrDiagHandler(const llvm::DiagnosticInfoSrcMgr &DI) { |
531 | 10 | const llvm::SMDiagnostic &D = DI.getSMDiag(); |
532 | | |
533 | 10 | unsigned DiagID; |
534 | 10 | if (DI.isInlineAsmDiag()) |
535 | 10 | ComputeDiagID(DI.getSeverity(), inline_asm, DiagID); |
536 | 0 | else |
537 | 0 | ComputeDiagID(DI.getSeverity(), source_mgr, DiagID); |
538 | | |
539 | | // This is for the empty BackendConsumer that uses the clang diagnostic |
540 | | // handler for IR input files. |
541 | 10 | if (!Context) { |
542 | 1 | D.print(nullptr, llvm::errs()); |
543 | 1 | Diags.Report(DiagID).AddString("cannot compile inline asm"); |
544 | 1 | return; |
545 | 1 | } |
546 | | |
547 | | // There are a couple of different kinds of errors we could get here. |
548 | | // First, we re-format the SMDiagnostic in terms of a clang diagnostic. |
549 | | |
550 | | // Strip "error: " off the start of the message string. |
551 | 9 | StringRef Message = D.getMessage(); |
552 | 9 | (void)Message.consume_front("error: "); |
553 | | |
554 | | // If the SMDiagnostic has an inline asm source location, translate it. |
555 | 9 | FullSourceLoc Loc; |
556 | 9 | if (D.getLoc() != SMLoc()) |
557 | 9 | Loc = ConvertBackendLocation(D, Context->getSourceManager()); |
558 | | |
559 | | // If this problem has clang-level source location information, report the |
560 | | // issue in the source with a note showing the instantiated |
561 | | // code. |
562 | 9 | if (DI.isInlineAsmDiag()) { |
563 | 9 | SourceLocation LocCookie = |
564 | 9 | SourceLocation::getFromRawEncoding(DI.getLocCookie()); |
565 | 9 | if (LocCookie.isValid()) { |
566 | 8 | Diags.Report(LocCookie, DiagID).AddString(Message); |
567 | | |
568 | 8 | if (D.getLoc().isValid()) { |
569 | 8 | DiagnosticBuilder B = Diags.Report(Loc, diag::note_fe_inline_asm_here); |
570 | | // Convert the SMDiagnostic ranges into SourceRange and attach them |
571 | | // to the diagnostic. |
572 | 8 | for (const std::pair<unsigned, unsigned> &Range : D.getRanges()) { |
573 | 1 | unsigned Column = D.getColumnNo(); |
574 | 1 | B << SourceRange(Loc.getLocWithOffset(Range.first - Column), |
575 | 1 | Loc.getLocWithOffset(Range.second - Column)); |
576 | 1 | } |
577 | 8 | } |
578 | 8 | return; |
579 | 8 | } |
580 | 9 | } |
581 | | |
582 | | // Otherwise, report the backend issue as occurring in the generated .s file. |
583 | | // If Loc is invalid, we still need to report the issue, it just gets no |
584 | | // location info. |
585 | 1 | Diags.Report(Loc, DiagID).AddString(Message); |
586 | 1 | } |
587 | | |
588 | | bool |
589 | 19 | BackendConsumer::InlineAsmDiagHandler(const llvm::DiagnosticInfoInlineAsm &D) { |
590 | 19 | unsigned DiagID; |
591 | 19 | ComputeDiagID(D.getSeverity(), inline_asm, DiagID); |
592 | 19 | std::string Message = D.getMsgStr().str(); |
593 | | |
594 | | // If this problem has clang-level source location information, report the |
595 | | // issue as being a problem in the source with a note showing the instantiated |
596 | | // code. |
597 | 19 | SourceLocation LocCookie = |
598 | 19 | SourceLocation::getFromRawEncoding(D.getLocCookie()); |
599 | 19 | if (LocCookie.isValid()) |
600 | 19 | Diags.Report(LocCookie, DiagID).AddString(Message); |
601 | 0 | else { |
602 | | // Otherwise, report the backend diagnostic as occurring in the generated |
603 | | // .s file. |
604 | | // If Loc is invalid, we still need to report the diagnostic, it just gets |
605 | | // no location info. |
606 | 0 | FullSourceLoc Loc; |
607 | 0 | Diags.Report(Loc, DiagID).AddString(Message); |
608 | 0 | } |
609 | | // We handled all the possible severities. |
610 | 19 | return true; |
611 | 19 | } |
612 | | |
613 | | bool |
614 | 16 | BackendConsumer::StackSizeDiagHandler(const llvm::DiagnosticInfoStackSize &D) { |
615 | 16 | if (D.getSeverity() != llvm::DS_Warning) |
616 | | // For now, the only support we have for StackSize diagnostic is warning. |
617 | | // We do not know how to format other severities. |
618 | 0 | return false; |
619 | | |
620 | 16 | auto Loc = getFunctionSourceLocation(D.getFunction()); |
621 | 16 | if (!Loc) |
622 | 1 | return false; |
623 | | |
624 | | // FIXME: Shouldn't need to truncate to uint32_t |
625 | 15 | Diags.Report(*Loc, diag::warn_fe_frame_larger_than) |
626 | 15 | << static_cast<uint32_t>(D.getStackSize()) |
627 | 15 | << static_cast<uint32_t>(D.getStackLimit()) |
628 | 15 | << llvm::demangle(D.getFunction().getName().str()); |
629 | 15 | return true; |
630 | 16 | } |
631 | | |
632 | | const FullSourceLoc BackendConsumer::getBestLocationFromDebugLoc( |
633 | | const llvm::DiagnosticInfoWithLocationBase &D, bool &BadDebugInfo, |
634 | 105 | StringRef &Filename, unsigned &Line, unsigned &Column) const { |
635 | 105 | SourceManager &SourceMgr = Context->getSourceManager(); |
636 | 105 | FileManager &FileMgr = SourceMgr.getFileManager(); |
637 | 105 | SourceLocation DILoc; |
638 | | |
639 | 105 | if (D.isLocationAvailable()) { |
640 | 82 | D.getLocation(Filename, Line, Column); |
641 | 82 | if (Line > 0) { |
642 | 82 | auto FE = FileMgr.getFile(Filename); |
643 | 82 | if (!FE) |
644 | 82 | FE = FileMgr.getFile(D.getAbsolutePath()); |
645 | 82 | if (FE) { |
646 | | // If -gcolumn-info was not used, Column will be 0. This upsets the |
647 | | // source manager, so pass 1 if Column is not set. |
648 | 81 | DILoc = SourceMgr.translateFileLineCol(*FE, Line, Column ? Column57 : 124 ); |
649 | 81 | } |
650 | 82 | } |
651 | 82 | BadDebugInfo = DILoc.isInvalid(); |
652 | 82 | } |
653 | | |
654 | | // If a location isn't available, try to approximate it using the associated |
655 | | // function definition. We use the definition's right brace to differentiate |
656 | | // from diagnostics that genuinely relate to the function itself. |
657 | 105 | FullSourceLoc Loc(DILoc, SourceMgr); |
658 | 105 | if (Loc.isInvalid()) { |
659 | 24 | if (auto MaybeLoc = getFunctionSourceLocation(D.getFunction())) |
660 | 24 | Loc = *MaybeLoc; |
661 | 24 | } |
662 | | |
663 | 105 | if (DILoc.isInvalid() && D.isLocationAvailable()24 ) |
664 | | // If we were not able to translate the file:line:col information |
665 | | // back to a SourceLocation, at least emit a note stating that |
666 | | // we could not translate this location. This can happen in the |
667 | | // case of #line directives. |
668 | 1 | Diags.Report(Loc, diag::note_fe_backend_invalid_loc) |
669 | 1 | << Filename << Line << Column; |
670 | | |
671 | 105 | return Loc; |
672 | 105 | } |
673 | | |
674 | | Optional<FullSourceLoc> |
675 | 40 | BackendConsumer::getFunctionSourceLocation(const Function &F) const { |
676 | 40 | auto Hash = llvm::hash_value(F.getName()); |
677 | 114 | for (const auto &Pair : ManglingFullSourceLocs) { |
678 | 114 | if (Pair.first == Hash) |
679 | 39 | return Pair.second; |
680 | 114 | } |
681 | 1 | return Optional<FullSourceLoc>(); |
682 | 40 | } |
683 | | |
684 | | void BackendConsumer::UnsupportedDiagHandler( |
685 | 5 | const llvm::DiagnosticInfoUnsupported &D) { |
686 | | // We only support warnings or errors. |
687 | 5 | assert(D.getSeverity() == llvm::DS_Error || |
688 | 5 | D.getSeverity() == llvm::DS_Warning); |
689 | | |
690 | 0 | StringRef Filename; |
691 | 5 | unsigned Line, Column; |
692 | 5 | bool BadDebugInfo = false; |
693 | 5 | FullSourceLoc Loc; |
694 | 5 | std::string Msg; |
695 | 5 | raw_string_ostream MsgStream(Msg); |
696 | | |
697 | | // Context will be nullptr for IR input files, we will construct the diag |
698 | | // message from llvm::DiagnosticInfoUnsupported. |
699 | 5 | if (Context != nullptr) { |
700 | 5 | Loc = getBestLocationFromDebugLoc(D, BadDebugInfo, Filename, Line, Column); |
701 | 5 | MsgStream << D.getMessage(); |
702 | 5 | } else { |
703 | 0 | DiagnosticPrinterRawOStream DP(MsgStream); |
704 | 0 | D.print(DP); |
705 | 0 | } |
706 | | |
707 | 5 | auto DiagType = D.getSeverity() == llvm::DS_Error |
708 | 5 | ? diag::err_fe_backend_unsupported |
709 | 5 | : diag::warn_fe_backend_unsupported0 ; |
710 | 5 | Diags.Report(Loc, DiagType) << MsgStream.str(); |
711 | | |
712 | 5 | if (BadDebugInfo) |
713 | | // If we were not able to translate the file:line:col information |
714 | | // back to a SourceLocation, at least emit a note stating that |
715 | | // we could not translate this location. This can happen in the |
716 | | // case of #line directives. |
717 | 0 | Diags.Report(Loc, diag::note_fe_backend_invalid_loc) |
718 | 0 | << Filename << Line << Column; |
719 | 5 | } |
720 | | |
721 | | void BackendConsumer::EmitOptimizationMessage( |
722 | 101 | const llvm::DiagnosticInfoOptimizationBase &D, unsigned DiagID) { |
723 | | // We only support warnings and remarks. |
724 | 101 | assert(D.getSeverity() == llvm::DS_Remark || |
725 | 101 | D.getSeverity() == llvm::DS_Warning); |
726 | | |
727 | 0 | StringRef Filename; |
728 | 101 | unsigned Line, Column; |
729 | 101 | bool BadDebugInfo = false; |
730 | 101 | FullSourceLoc Loc; |
731 | 101 | std::string Msg; |
732 | 101 | raw_string_ostream MsgStream(Msg); |
733 | | |
734 | | // Context will be nullptr for IR input files, we will construct the remark |
735 | | // message from llvm::DiagnosticInfoOptimizationBase. |
736 | 101 | if (Context != nullptr) { |
737 | 94 | Loc = getBestLocationFromDebugLoc(D, BadDebugInfo, Filename, Line, Column); |
738 | 94 | MsgStream << D.getMsg(); |
739 | 94 | } else { |
740 | 7 | DiagnosticPrinterRawOStream DP(MsgStream); |
741 | 7 | D.print(DP); |
742 | 7 | } |
743 | | |
744 | 101 | if (D.getHotness()) |
745 | 12 | MsgStream << " (hotness: " << *D.getHotness() << ")"; |
746 | | |
747 | 101 | Diags.Report(Loc, DiagID) |
748 | 101 | << AddFlagValue(D.getPassName()) |
749 | 101 | << MsgStream.str(); |
750 | | |
751 | 101 | if (BadDebugInfo) |
752 | | // If we were not able to translate the file:line:col information |
753 | | // back to a SourceLocation, at least emit a note stating that |
754 | | // we could not translate this location. This can happen in the |
755 | | // case of #line directives. |
756 | 1 | Diags.Report(Loc, diag::note_fe_backend_invalid_loc) |
757 | 1 | << Filename << Line << Column; |
758 | 101 | } |
759 | | |
760 | | void BackendConsumer::OptimizationRemarkHandler( |
761 | 147k | const llvm::DiagnosticInfoOptimizationBase &D) { |
762 | | // Without hotness information, don't show noisy remarks. |
763 | 147k | if (D.isVerbose() && !D.getHotness()414 ) |
764 | 412 | return; |
765 | | |
766 | 147k | if (D.isPassed()) { |
767 | | // Optimization remarks are active only if the -Rpass flag has a regular |
768 | | // expression that matches the name of the pass name in \p D. |
769 | 181 | if (CodeGenOpts.OptimizationRemark.patternMatches(D.getPassName())) |
770 | 54 | EmitOptimizationMessage(D, diag::remark_fe_backend_optimization_remark); |
771 | 147k | } else if (D.isMissed()) { |
772 | | // Missed optimization remarks are active only if the -Rpass-missed |
773 | | // flag has a regular expression that matches the name of the pass |
774 | | // name in \p D. |
775 | 50.3k | if (CodeGenOpts.OptimizationRemarkMissed.patternMatches(D.getPassName())) |
776 | 7 | EmitOptimizationMessage( |
777 | 7 | D, diag::remark_fe_backend_optimization_remark_missed); |
778 | 96.8k | } else { |
779 | 96.8k | assert(D.isAnalysis() && "Unknown remark type"); |
780 | | |
781 | 0 | bool ShouldAlwaysPrint = false; |
782 | 96.8k | if (auto *ORA = dyn_cast<llvm::OptimizationRemarkAnalysis>(&D)) |
783 | 51 | ShouldAlwaysPrint = ORA->shouldAlwaysPrint(); |
784 | | |
785 | 96.8k | if (ShouldAlwaysPrint || |
786 | 96.8k | CodeGenOpts.OptimizationRemarkAnalysis.patternMatches(D.getPassName())96.8k ) |
787 | 34 | EmitOptimizationMessage( |
788 | 34 | D, diag::remark_fe_backend_optimization_remark_analysis); |
789 | 96.8k | } |
790 | 147k | } |
791 | | |
792 | | void BackendConsumer::OptimizationRemarkHandler( |
793 | 1 | const llvm::OptimizationRemarkAnalysisFPCommute &D) { |
794 | | // Optimization analysis remarks are active if the pass name is set to |
795 | | // llvm::DiagnosticInfo::AlwasyPrint or if the -Rpass-analysis flag has a |
796 | | // regular expression that matches the name of the pass name in \p D. |
797 | | |
798 | 1 | if (D.shouldAlwaysPrint() || |
799 | 1 | CodeGenOpts.OptimizationRemarkAnalysis.patternMatches(D.getPassName())) |
800 | 1 | EmitOptimizationMessage( |
801 | 1 | D, diag::remark_fe_backend_optimization_remark_analysis_fpcommute); |
802 | 1 | } |
803 | | |
804 | | void BackendConsumer::OptimizationRemarkHandler( |
805 | 1 | const llvm::OptimizationRemarkAnalysisAliasing &D) { |
806 | | // Optimization analysis remarks are active if the pass name is set to |
807 | | // llvm::DiagnosticInfo::AlwasyPrint or if the -Rpass-analysis flag has a |
808 | | // regular expression that matches the name of the pass name in \p D. |
809 | | |
810 | 1 | if (D.shouldAlwaysPrint() || |
811 | 1 | CodeGenOpts.OptimizationRemarkAnalysis.patternMatches(D.getPassName())) |
812 | 1 | EmitOptimizationMessage( |
813 | 1 | D, diag::remark_fe_backend_optimization_remark_analysis_aliasing); |
814 | 1 | } |
815 | | |
816 | | void BackendConsumer::OptimizationFailureHandler( |
817 | 4 | const llvm::DiagnosticInfoOptimizationFailure &D) { |
818 | 4 | EmitOptimizationMessage(D, diag::warn_fe_backend_optimization_failure); |
819 | 4 | } |
820 | | |
821 | 38 | void BackendConsumer::DontCallDiagHandler(const DiagnosticInfoDontCall &D) { |
822 | 38 | SourceLocation LocCookie = |
823 | 38 | SourceLocation::getFromRawEncoding(D.getLocCookie()); |
824 | | |
825 | | // FIXME: we can't yet diagnose indirect calls. When/if we can, we |
826 | | // should instead assert that LocCookie.isValid(). |
827 | 38 | if (!LocCookie.isValid()) |
828 | 1 | return; |
829 | | |
830 | 37 | Diags.Report(LocCookie, D.getSeverity() == DiagnosticSeverity::DS_Error |
831 | 37 | ? diag::err_fe_backend_error_attr25 |
832 | 37 | : diag::warn_fe_backend_warning_attr12 ) |
833 | 37 | << llvm::demangle(D.getFunctionName().str()) << D.getNote(); |
834 | 37 | } |
835 | | |
836 | | void BackendConsumer::MisExpectDiagHandler( |
837 | 6 | const llvm::DiagnosticInfoMisExpect &D) { |
838 | 6 | StringRef Filename; |
839 | 6 | unsigned Line, Column; |
840 | 6 | bool BadDebugInfo = false; |
841 | 6 | FullSourceLoc Loc = |
842 | 6 | getBestLocationFromDebugLoc(D, BadDebugInfo, Filename, Line, Column); |
843 | | |
844 | 6 | Diags.Report(Loc, diag::warn_profile_data_misexpect) << D.getMsg().str(); |
845 | | |
846 | 6 | if (BadDebugInfo) |
847 | | // If we were not able to translate the file:line:col information |
848 | | // back to a SourceLocation, at least emit a note stating that |
849 | | // we could not translate this location. This can happen in the |
850 | | // case of #line directives. |
851 | 0 | Diags.Report(Loc, diag::note_fe_backend_invalid_loc) |
852 | 0 | << Filename << Line << Column; |
853 | 6 | } |
854 | | |
855 | | /// This function is invoked when the backend needs |
856 | | /// to report something to the user. |
857 | 147k | void BackendConsumer::DiagnosticHandlerImpl(const DiagnosticInfo &DI) { |
858 | 147k | unsigned DiagID = diag::err_fe_inline_asm; |
859 | 147k | llvm::DiagnosticSeverity Severity = DI.getSeverity(); |
860 | | // Get the diagnostic ID based. |
861 | 147k | switch (DI.getKind()) { |
862 | 19 | case llvm::DK_InlineAsm: |
863 | 19 | if (InlineAsmDiagHandler(cast<DiagnosticInfoInlineAsm>(DI))) |
864 | 19 | return; |
865 | 0 | ComputeDiagID(Severity, inline_asm, DiagID); |
866 | 0 | break; |
867 | 10 | case llvm::DK_SrcMgr: |
868 | 10 | SrcMgrDiagHandler(cast<DiagnosticInfoSrcMgr>(DI)); |
869 | 10 | return; |
870 | 16 | case llvm::DK_StackSize: |
871 | 16 | if (StackSizeDiagHandler(cast<DiagnosticInfoStackSize>(DI))) |
872 | 15 | return; |
873 | 1 | ComputeDiagID(Severity, backend_frame_larger_than, DiagID); |
874 | 1 | break; |
875 | 2 | case DK_Linker: |
876 | 2 | ComputeDiagID(Severity, linking_module, DiagID); |
877 | 2 | break; |
878 | 181 | case llvm::DK_OptimizationRemark: |
879 | | // Optimization remarks are always handled completely by this |
880 | | // handler. There is no generic way of emitting them. |
881 | 181 | OptimizationRemarkHandler(cast<OptimizationRemark>(DI)); |
882 | 181 | return; |
883 | 50.7k | case llvm::DK_OptimizationRemarkMissed: |
884 | | // Optimization remarks are always handled completely by this |
885 | | // handler. There is no generic way of emitting them. |
886 | 50.7k | OptimizationRemarkHandler(cast<OptimizationRemarkMissed>(DI)); |
887 | 50.7k | return; |
888 | 51 | case llvm::DK_OptimizationRemarkAnalysis: |
889 | | // Optimization remarks are always handled completely by this |
890 | | // handler. There is no generic way of emitting them. |
891 | 51 | OptimizationRemarkHandler(cast<OptimizationRemarkAnalysis>(DI)); |
892 | 51 | return; |
893 | 1 | case llvm::DK_OptimizationRemarkAnalysisFPCommute: |
894 | | // Optimization remarks are always handled completely by this |
895 | | // handler. There is no generic way of emitting them. |
896 | 1 | OptimizationRemarkHandler(cast<OptimizationRemarkAnalysisFPCommute>(DI)); |
897 | 1 | return; |
898 | 1 | case llvm::DK_OptimizationRemarkAnalysisAliasing: |
899 | | // Optimization remarks are always handled completely by this |
900 | | // handler. There is no generic way of emitting them. |
901 | 1 | OptimizationRemarkHandler(cast<OptimizationRemarkAnalysisAliasing>(DI)); |
902 | 1 | return; |
903 | 0 | case llvm::DK_MachineOptimizationRemark: |
904 | | // Optimization remarks are always handled completely by this |
905 | | // handler. There is no generic way of emitting them. |
906 | 0 | OptimizationRemarkHandler(cast<MachineOptimizationRemark>(DI)); |
907 | 0 | return; |
908 | 24 | case llvm::DK_MachineOptimizationRemarkMissed: |
909 | | // Optimization remarks are always handled completely by this |
910 | | // handler. There is no generic way of emitting them. |
911 | 24 | OptimizationRemarkHandler(cast<MachineOptimizationRemarkMissed>(DI)); |
912 | 24 | return; |
913 | 96.8k | case llvm::DK_MachineOptimizationRemarkAnalysis: |
914 | | // Optimization remarks are always handled completely by this |
915 | | // handler. There is no generic way of emitting them. |
916 | 96.8k | OptimizationRemarkHandler(cast<MachineOptimizationRemarkAnalysis>(DI)); |
917 | 96.8k | return; |
918 | 4 | case llvm::DK_OptimizationFailure: |
919 | | // Optimization failures are always handled completely by this |
920 | | // handler. |
921 | 4 | OptimizationFailureHandler(cast<DiagnosticInfoOptimizationFailure>(DI)); |
922 | 4 | return; |
923 | 5 | case llvm::DK_Unsupported: |
924 | 5 | UnsupportedDiagHandler(cast<DiagnosticInfoUnsupported>(DI)); |
925 | 5 | return; |
926 | 38 | case llvm::DK_DontCall: |
927 | 38 | DontCallDiagHandler(cast<DiagnosticInfoDontCall>(DI)); |
928 | 38 | return; |
929 | 6 | case llvm::DK_MisExpect: |
930 | 6 | MisExpectDiagHandler(cast<DiagnosticInfoMisExpect>(DI)); |
931 | 6 | return; |
932 | 3 | default: |
933 | | // Plugin IDs are not bound to any value as they are set dynamically. |
934 | 3 | ComputeDiagRemarkID(Severity, backend_plugin, DiagID); |
935 | 3 | break; |
936 | 147k | } |
937 | 6 | std::string MsgStorage; |
938 | 6 | { |
939 | 6 | raw_string_ostream Stream(MsgStorage); |
940 | 6 | DiagnosticPrinterRawOStream DP(Stream); |
941 | 6 | DI.print(DP); |
942 | 6 | } |
943 | | |
944 | 6 | if (DI.getKind() == DK_Linker) { |
945 | 2 | assert(CurLinkModule && "CurLinkModule must be set for linker diagnostics"); |
946 | 0 | Diags.Report(DiagID) << CurLinkModule->getModuleIdentifier() << MsgStorage; |
947 | 2 | return; |
948 | 2 | } |
949 | | |
950 | | // Report the backend message using the usual diagnostic mechanism. |
951 | 4 | FullSourceLoc Loc; |
952 | 4 | Diags.Report(Loc, DiagID).AddString(MsgStorage); |
953 | 4 | } |
954 | | #undef ComputeDiagID |
955 | | |
956 | | CodeGenAction::CodeGenAction(unsigned _Act, LLVMContext *_VMContext) |
957 | | : Act(_Act), VMContext(_VMContext ? _VMContext : new LLVMContext), |
958 | 19.9k | OwnsVMContext(!_VMContext) {} |
959 | | |
960 | 15.5k | CodeGenAction::~CodeGenAction() { |
961 | 15.5k | TheModule.reset(); |
962 | 15.5k | if (OwnsVMContext) |
963 | 15.5k | delete VMContext; |
964 | 15.5k | } |
965 | | |
966 | 135 | bool CodeGenAction::hasIRSupport() const { return true; } |
967 | | |
968 | 19.8k | void CodeGenAction::EndSourceFileAction() { |
969 | | // If the consumer creation failed, do nothing. |
970 | 19.8k | if (!getCompilerInstance().hasASTConsumer()) |
971 | 102 | return; |
972 | | |
973 | | // Steal the module from the consumer. |
974 | 19.7k | TheModule = BEConsumer->takeModule(); |
975 | 19.7k | } |
976 | | |
977 | 0 | std::unique_ptr<llvm::Module> CodeGenAction::takeModule() { |
978 | 0 | return std::move(TheModule); |
979 | 0 | } |
980 | | |
981 | 0 | llvm::LLVMContext *CodeGenAction::takeLLVMContext() { |
982 | 0 | OwnsVMContext = false; |
983 | 0 | return VMContext; |
984 | 0 | } |
985 | | |
986 | 33 | CodeGenerator *CodeGenAction::getCodeGenerator() const { |
987 | 33 | return BEConsumer->getCodeGenerator(); |
988 | 33 | } |
989 | | |
990 | | static std::unique_ptr<raw_pwrite_stream> |
991 | 19.8k | GetOutputStream(CompilerInstance &CI, StringRef InFile, BackendAction Action) { |
992 | 19.8k | switch (Action) { |
993 | 530 | case Backend_EmitAssembly: |
994 | 530 | return CI.createDefaultOutputFile(false, InFile, "s"); |
995 | 14.9k | case Backend_EmitLL: |
996 | 14.9k | return CI.createDefaultOutputFile(false, InFile, "ll"); |
997 | 547 | case Backend_EmitBC: |
998 | 547 | return CI.createDefaultOutputFile(true, InFile, "bc"); |
999 | 253 | case Backend_EmitNothing: |
1000 | 253 | return nullptr; |
1001 | 8 | case Backend_EmitMCNull: |
1002 | 8 | return CI.createNullOutputFile(); |
1003 | 3.63k | case Backend_EmitObj: |
1004 | 3.63k | return CI.createDefaultOutputFile(true, InFile, "o"); |
1005 | 19.8k | } |
1006 | | |
1007 | 0 | llvm_unreachable("Invalid action!"); |
1008 | 0 | } |
1009 | | |
1010 | | std::unique_ptr<ASTConsumer> |
1011 | 19.7k | CodeGenAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { |
1012 | 19.7k | BackendAction BA = static_cast<BackendAction>(Act); |
1013 | 19.7k | std::unique_ptr<raw_pwrite_stream> OS = CI.takeOutputStream(); |
1014 | 19.7k | if (!OS) |
1015 | 19.7k | OS = GetOutputStream(CI, InFile, BA); |
1016 | | |
1017 | 19.7k | if (BA != Backend_EmitNothing && !OS19.5k ) |
1018 | 2 | return nullptr; |
1019 | | |
1020 | 19.7k | if (CI.getCodeGenOpts().OpaquePointers) |
1021 | 10.5k | VMContext->setOpaquePointers(true); |
1022 | | |
1023 | | // Load bitcode modules to link with, if we need to. |
1024 | 19.7k | if (LinkModules.empty()) |
1025 | 19.7k | for (const CodeGenOptions::BitcodeFileToLink &F : |
1026 | 19.7k | CI.getCodeGenOpts().LinkBitcodeFiles) { |
1027 | 9 | auto BCBuf = CI.getFileManager().getBufferForFile(F.Filename); |
1028 | 9 | if (!BCBuf) { |
1029 | 1 | CI.getDiagnostics().Report(diag::err_cannot_open_file) |
1030 | 1 | << F.Filename << BCBuf.getError().message(); |
1031 | 1 | LinkModules.clear(); |
1032 | 1 | return nullptr; |
1033 | 1 | } |
1034 | | |
1035 | 8 | Expected<std::unique_ptr<llvm::Module>> ModuleOrErr = |
1036 | 8 | getOwningLazyBitcodeModule(std::move(*BCBuf), *VMContext); |
1037 | 8 | if (!ModuleOrErr) { |
1038 | 0 | handleAllErrors(ModuleOrErr.takeError(), [&](ErrorInfoBase &EIB) { |
1039 | 0 | CI.getDiagnostics().Report(diag::err_cannot_open_file) |
1040 | 0 | << F.Filename << EIB.message(); |
1041 | 0 | }); |
1042 | 0 | LinkModules.clear(); |
1043 | 0 | return nullptr; |
1044 | 0 | } |
1045 | 8 | LinkModules.push_back({std::move(ModuleOrErr.get()), F.PropagateAttrs, |
1046 | 8 | F.Internalize, F.LinkFlags}); |
1047 | 8 | } |
1048 | | |
1049 | 19.7k | CoverageSourceInfo *CoverageInfo = nullptr; |
1050 | | // Add the preprocessor callback only when the coverage mapping is generated. |
1051 | 19.7k | if (CI.getCodeGenOpts().CoverageMapping) |
1052 | 81 | CoverageInfo = CodeGen::CoverageMappingModuleGen::setUpCoverageCallbacks( |
1053 | 81 | CI.getPreprocessor()); |
1054 | | |
1055 | 19.7k | std::unique_ptr<BackendConsumer> Result(new BackendConsumer( |
1056 | 19.7k | BA, CI.getDiagnostics(), CI.getHeaderSearchOpts(), |
1057 | 19.7k | CI.getPreprocessorOpts(), CI.getCodeGenOpts(), CI.getTargetOpts(), |
1058 | 19.7k | CI.getLangOpts(), std::string(InFile), std::move(LinkModules), |
1059 | 19.7k | std::move(OS), *VMContext, CoverageInfo)); |
1060 | 19.7k | BEConsumer = Result.get(); |
1061 | | |
1062 | | // Enable generating macro debug info only when debug info is not disabled and |
1063 | | // also macro debug info is enabled. |
1064 | 19.7k | if (CI.getCodeGenOpts().getDebugInfo() != codegenoptions::NoDebugInfo && |
1065 | 19.7k | CI.getCodeGenOpts().MacroDebugInfo4.19k ) { |
1066 | 5 | std::unique_ptr<PPCallbacks> Callbacks = |
1067 | 5 | std::make_unique<MacroPPCallbacks>(BEConsumer->getCodeGenerator(), |
1068 | 5 | CI.getPreprocessor()); |
1069 | 5 | CI.getPreprocessor().addPPCallbacks(std::move(Callbacks)); |
1070 | 5 | } |
1071 | | |
1072 | 19.7k | return std::move(Result); |
1073 | 19.7k | } |
1074 | | |
1075 | | std::unique_ptr<llvm::Module> |
1076 | 102 | CodeGenAction::loadModule(MemoryBufferRef MBRef) { |
1077 | 102 | CompilerInstance &CI = getCompilerInstance(); |
1078 | 102 | SourceManager &SM = CI.getSourceManager(); |
1079 | | |
1080 | | // For ThinLTO backend invocations, ensure that the context |
1081 | | // merges types based on ODR identifiers. We also need to read |
1082 | | // the correct module out of a multi-module bitcode file. |
1083 | 102 | if (!CI.getCodeGenOpts().ThinLTOIndexFile.empty()) { |
1084 | 50 | VMContext->enableDebugTypeODRUniquing(); |
1085 | | |
1086 | 50 | auto DiagErrors = [&](Error E) -> std::unique_ptr<llvm::Module> { |
1087 | 0 | unsigned DiagID = |
1088 | 0 | CI.getDiagnostics().getCustomDiagID(DiagnosticsEngine::Error, "%0"); |
1089 | 0 | handleAllErrors(std::move(E), [&](ErrorInfoBase &EIB) { |
1090 | 0 | CI.getDiagnostics().Report(DiagID) << EIB.message(); |
1091 | 0 | }); |
1092 | 0 | return {}; |
1093 | 0 | }; |
1094 | | |
1095 | 50 | Expected<std::vector<BitcodeModule>> BMsOrErr = getBitcodeModuleList(MBRef); |
1096 | 50 | if (!BMsOrErr) |
1097 | 0 | return DiagErrors(BMsOrErr.takeError()); |
1098 | 50 | BitcodeModule *Bm = llvm::lto::findThinLTOModule(*BMsOrErr); |
1099 | | // We have nothing to do if the file contains no ThinLTO module. This is |
1100 | | // possible if ThinLTO compilation was not able to split module. Content of |
1101 | | // the file was already processed by indexing and will be passed to the |
1102 | | // linker using merged object file. |
1103 | 50 | if (!Bm) { |
1104 | 1 | auto M = std::make_unique<llvm::Module>("empty", *VMContext); |
1105 | 1 | M->setTargetTriple(CI.getTargetOpts().Triple); |
1106 | 1 | return M; |
1107 | 1 | } |
1108 | 49 | Expected<std::unique_ptr<llvm::Module>> MOrErr = |
1109 | 49 | Bm->parseModule(*VMContext); |
1110 | 49 | if (!MOrErr) |
1111 | 0 | return DiagErrors(MOrErr.takeError()); |
1112 | 49 | return std::move(*MOrErr); |
1113 | 49 | } |
1114 | | |
1115 | 52 | llvm::SMDiagnostic Err; |
1116 | 52 | if (std::unique_ptr<llvm::Module> M = parseIR(MBRef, Err, *VMContext)) |
1117 | 51 | return M; |
1118 | | |
1119 | | // Translate from the diagnostic info to the SourceManager location if |
1120 | | // available. |
1121 | | // TODO: Unify this with ConvertBackendLocation() |
1122 | 1 | SourceLocation Loc; |
1123 | 1 | if (Err.getLineNo() > 0) { |
1124 | 1 | assert(Err.getColumnNo() >= 0); |
1125 | 0 | Loc = SM.translateFileLineCol(SM.getFileEntryForID(SM.getMainFileID()), |
1126 | 1 | Err.getLineNo(), Err.getColumnNo() + 1); |
1127 | 1 | } |
1128 | | |
1129 | | // Strip off a leading diagnostic code if there is one. |
1130 | 0 | StringRef Msg = Err.getMessage(); |
1131 | 1 | if (Msg.startswith("error: ")) |
1132 | 0 | Msg = Msg.substr(7); |
1133 | | |
1134 | 1 | unsigned DiagID = |
1135 | 1 | CI.getDiagnostics().getCustomDiagID(DiagnosticsEngine::Error, "%0"); |
1136 | | |
1137 | 1 | CI.getDiagnostics().Report(Loc, DiagID) << Msg; |
1138 | 1 | return {}; |
1139 | 52 | } |
1140 | | |
1141 | 19.8k | void CodeGenAction::ExecuteAction() { |
1142 | 19.8k | if (getCurrentFileKind().getLanguage() != Language::LLVM_IR) { |
1143 | 19.7k | this->ASTFrontendAction::ExecuteAction(); |
1144 | 19.7k | return; |
1145 | 19.7k | } |
1146 | | |
1147 | | // If this is an IR file, we have to treat it specially. |
1148 | 102 | BackendAction BA = static_cast<BackendAction>(Act); |
1149 | 102 | CompilerInstance &CI = getCompilerInstance(); |
1150 | 102 | auto &CodeGenOpts = CI.getCodeGenOpts(); |
1151 | 102 | auto &Diagnostics = CI.getDiagnostics(); |
1152 | 102 | std::unique_ptr<raw_pwrite_stream> OS = |
1153 | 102 | GetOutputStream(CI, getCurrentFileOrBufferName(), BA); |
1154 | 102 | if (BA != Backend_EmitNothing && !OS101 ) |
1155 | 0 | return; |
1156 | | |
1157 | 102 | SourceManager &SM = CI.getSourceManager(); |
1158 | 102 | FileID FID = SM.getMainFileID(); |
1159 | 102 | Optional<MemoryBufferRef> MainFile = SM.getBufferOrNone(FID); |
1160 | 102 | if (!MainFile) |
1161 | 0 | return; |
1162 | | |
1163 | 102 | TheModule = loadModule(*MainFile); |
1164 | 102 | if (!TheModule) |
1165 | 1 | return; |
1166 | | |
1167 | 101 | const TargetOptions &TargetOpts = CI.getTargetOpts(); |
1168 | 101 | if (TheModule->getTargetTriple() != TargetOpts.Triple) { |
1169 | 35 | Diagnostics.Report(SourceLocation(), diag::warn_fe_override_module) |
1170 | 35 | << TargetOpts.Triple; |
1171 | 35 | TheModule->setTargetTriple(TargetOpts.Triple); |
1172 | 35 | } |
1173 | | |
1174 | 101 | EmbedObject(TheModule.get(), CodeGenOpts, Diagnostics); |
1175 | 101 | EmbedBitcode(TheModule.get(), CodeGenOpts, *MainFile); |
1176 | | |
1177 | 101 | LLVMContext &Ctx = TheModule->getContext(); |
1178 | | |
1179 | | // Restore any diagnostic handler previously set before returning from this |
1180 | | // function. |
1181 | 101 | struct RAII { |
1182 | 101 | LLVMContext &Ctx; |
1183 | 101 | std::unique_ptr<DiagnosticHandler> PrevHandler = Ctx.getDiagnosticHandler(); |
1184 | 101 | ~RAII() { Ctx.setDiagnosticHandler(std::move(PrevHandler)); } |
1185 | 101 | } _{Ctx}; |
1186 | | |
1187 | | // Set clang diagnostic handler. To do this we need to create a fake |
1188 | | // BackendConsumer. |
1189 | 101 | BackendConsumer Result(BA, CI.getDiagnostics(), CI.getHeaderSearchOpts(), |
1190 | 101 | CI.getPreprocessorOpts(), CI.getCodeGenOpts(), |
1191 | 101 | CI.getTargetOpts(), CI.getLangOpts(), TheModule.get(), |
1192 | 101 | std::move(LinkModules), *VMContext, nullptr); |
1193 | | // PR44896: Force DiscardValueNames as false. DiscardValueNames cannot be |
1194 | | // true here because the valued names are needed for reading textual IR. |
1195 | 101 | Ctx.setDiscardValueNames(false); |
1196 | 101 | Ctx.setDiagnosticHandler( |
1197 | 101 | std::make_unique<ClangDiagnosticHandler>(CodeGenOpts, &Result)); |
1198 | | |
1199 | 101 | Expected<std::unique_ptr<llvm::ToolOutputFile>> OptRecordFileOrErr = |
1200 | 101 | setupLLVMOptimizationRemarks( |
1201 | 101 | Ctx, CodeGenOpts.OptRecordFile, CodeGenOpts.OptRecordPasses, |
1202 | 101 | CodeGenOpts.OptRecordFormat, CodeGenOpts.DiagnosticsWithHotness, |
1203 | 101 | CodeGenOpts.DiagnosticsHotnessThreshold); |
1204 | | |
1205 | 101 | if (Error E = OptRecordFileOrErr.takeError()) { |
1206 | 0 | reportOptRecordError(std::move(E), Diagnostics, CodeGenOpts); |
1207 | 0 | return; |
1208 | 0 | } |
1209 | 101 | std::unique_ptr<llvm::ToolOutputFile> OptRecordFile = |
1210 | 101 | std::move(*OptRecordFileOrErr); |
1211 | | |
1212 | 101 | EmitBackendOutput(Diagnostics, CI.getHeaderSearchOpts(), CodeGenOpts, |
1213 | 101 | TargetOpts, CI.getLangOpts(), |
1214 | 101 | CI.getTarget().getDataLayoutString(), TheModule.get(), BA, |
1215 | 101 | std::move(OS)); |
1216 | 101 | if (OptRecordFile) |
1217 | 2 | OptRecordFile->keep(); |
1218 | 101 | } |
1219 | | |
1220 | | // |
1221 | | |
1222 | 0 | void EmitAssemblyAction::anchor() { } |
1223 | | EmitAssemblyAction::EmitAssemblyAction(llvm::LLVMContext *_VMContext) |
1224 | 541 | : CodeGenAction(Backend_EmitAssembly, _VMContext) {} |
1225 | | |
1226 | 0 | void EmitBCAction::anchor() { } |
1227 | | EmitBCAction::EmitBCAction(llvm::LLVMContext *_VMContext) |
1228 | 550 | : CodeGenAction(Backend_EmitBC, _VMContext) {} |
1229 | | |
1230 | 0 | void EmitLLVMAction::anchor() { } |
1231 | | EmitLLVMAction::EmitLLVMAction(llvm::LLVMContext *_VMContext) |
1232 | 14.9k | : CodeGenAction(Backend_EmitLL, _VMContext) {} |
1233 | | |
1234 | 0 | void EmitLLVMOnlyAction::anchor() { } |
1235 | | EmitLLVMOnlyAction::EmitLLVMOnlyAction(llvm::LLVMContext *_VMContext) |
1236 | 253 | : CodeGenAction(Backend_EmitNothing, _VMContext) {} |
1237 | | |
1238 | 0 | void EmitCodeGenOnlyAction::anchor() { } |
1239 | | EmitCodeGenOnlyAction::EmitCodeGenOnlyAction(llvm::LLVMContext *_VMContext) |
1240 | 7 | : CodeGenAction(Backend_EmitMCNull, _VMContext) {} |
1241 | | |
1242 | 0 | void EmitObjAction::anchor() { } |
1243 | | EmitObjAction::EmitObjAction(llvm::LLVMContext *_VMContext) |
1244 | 3.64k | : CodeGenAction(Backend_EmitObj, _VMContext) {} |