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