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