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