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