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