1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | #include "clang/CodeGen/CodeGenAction.h" |
10 | #include "CodeGenModule.h" |
11 | #include "CoverageMappingGen.h" |
12 | #include "MacroPPCallbacks.h" |
13 | #include "clang/AST/ASTConsumer.h" |
14 | #include "clang/AST/ASTContext.h" |
15 | #include "clang/AST/DeclCXX.h" |
16 | #include "clang/AST/DeclGroup.h" |
17 | #include "clang/Basic/FileManager.h" |
18 | #include "clang/Basic/SourceManager.h" |
19 | #include "clang/Basic/TargetInfo.h" |
20 | #include "clang/CodeGen/BackendUtil.h" |
21 | #include "clang/CodeGen/ModuleBuilder.h" |
22 | #include "clang/Driver/DriverDiagnostic.h" |
23 | #include "clang/Frontend/CompilerInstance.h" |
24 | #include "clang/Frontend/FrontendDiagnostic.h" |
25 | #include "clang/Lex/Preprocessor.h" |
26 | #include "llvm/Bitcode/BitcodeReader.h" |
27 | #include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h" |
28 | #include "llvm/IR/DebugInfo.h" |
29 | #include "llvm/IR/DiagnosticInfo.h" |
30 | #include "llvm/IR/DiagnosticPrinter.h" |
31 | #include "llvm/IR/GlobalValue.h" |
32 | #include "llvm/IR/LLVMContext.h" |
33 | #include "llvm/IR/Module.h" |
34 | #include "llvm/IR/RemarkStreamer.h" |
35 | #include "llvm/IRReader/IRReader.h" |
36 | #include "llvm/Linker/Linker.h" |
37 | #include "llvm/Pass.h" |
38 | #include "llvm/Support/MemoryBuffer.h" |
39 | #include "llvm/Support/SourceMgr.h" |
40 | #include "llvm/Support/Timer.h" |
41 | #include "llvm/Support/ToolOutputFile.h" |
42 | #include "llvm/Support/YAMLTraits.h" |
43 | #include "llvm/Transforms/IPO/Internalize.h" |
44 | |
45 | #include <memory> |
46 | using namespace clang; |
47 | using namespace llvm; |
48 | |
49 | namespace clang { |
50 | class BackendConsumer; |
51 | class ClangDiagnosticHandler final : public DiagnosticHandler { |
52 | public: |
53 | ClangDiagnosticHandler(const CodeGenOptions &CGOpts, BackendConsumer *BCon) |
54 | : CodeGenOpts(CGOpts), BackendCon(BCon) {} |
55 | |
56 | bool handleDiagnostics(const DiagnosticInfo &DI) override; |
57 | |
58 | bool isAnalysisRemarkEnabled(StringRef PassName) const override { |
59 | return (CodeGenOpts.OptimizationRemarkAnalysisPattern && |
60 | CodeGenOpts.OptimizationRemarkAnalysisPattern->match(PassName)); |
61 | } |
62 | bool isMissedOptRemarkEnabled(StringRef PassName) const override { |
63 | return (CodeGenOpts.OptimizationRemarkMissedPattern && |
64 | CodeGenOpts.OptimizationRemarkMissedPattern->match(PassName)); |
65 | } |
66 | bool isPassedOptRemarkEnabled(StringRef PassName) const override { |
67 | return (CodeGenOpts.OptimizationRemarkPattern && |
68 | CodeGenOpts.OptimizationRemarkPattern->match(PassName)); |
69 | } |
70 | |
71 | bool isAnyRemarkEnabled() const override { |
72 | return (CodeGenOpts.OptimizationRemarkAnalysisPattern || |
73 | CodeGenOpts.OptimizationRemarkMissedPattern || |
74 | CodeGenOpts.OptimizationRemarkPattern); |
75 | } |
76 | |
77 | private: |
78 | const CodeGenOptions &CodeGenOpts; |
79 | BackendConsumer *BackendCon; |
80 | }; |
81 | |
82 | class BackendConsumer : public ASTConsumer { |
83 | using LinkModule = CodeGenAction::LinkModule; |
84 | |
85 | virtual void anchor(); |
86 | DiagnosticsEngine &Diags; |
87 | BackendAction Action; |
88 | const HeaderSearchOptions &; |
89 | const CodeGenOptions &CodeGenOpts; |
90 | const TargetOptions &TargetOpts; |
91 | const LangOptions &LangOpts; |
92 | std::unique_ptr<raw_pwrite_stream> AsmOutStream; |
93 | ASTContext *Context; |
94 | |
95 | Timer LLVMIRGeneration; |
96 | unsigned LLVMIRGenerationRefCount; |
97 | |
98 | |
99 | |
100 | |
101 | bool IRGenFinished = false; |
102 | |
103 | std::unique_ptr<CodeGenerator> Gen; |
104 | |
105 | SmallVector<LinkModule, 4> LinkModules; |
106 | |
107 | |
108 | |
109 | llvm::Module *CurLinkModule = nullptr; |
110 | |
111 | public: |
112 | BackendConsumer(BackendAction Action, DiagnosticsEngine &Diags, |
113 | const HeaderSearchOptions &, |
114 | const PreprocessorOptions &PPOpts, |
115 | const CodeGenOptions &CodeGenOpts, |
116 | const TargetOptions &TargetOpts, |
117 | const LangOptions &LangOpts, bool TimePasses, |
118 | const std::string &InFile, |
119 | SmallVector<LinkModule, 4> LinkModules, |
120 | std::unique_ptr<raw_pwrite_stream> OS, LLVMContext &C, |
121 | CoverageSourceInfo *CoverageInfo = nullptr) |
122 | : Diags(Diags), Action(Action), HeaderSearchOpts(HeaderSearchOpts), |
123 | CodeGenOpts(CodeGenOpts), TargetOpts(TargetOpts), LangOpts(LangOpts), |
124 | AsmOutStream(std::move(OS)), Context(nullptr), |
125 | LLVMIRGeneration("irgen", "LLVM IR Generation Time"), |
126 | LLVMIRGenerationRefCount(0), |
127 | Gen(CreateLLVMCodeGen(Diags, InFile, HeaderSearchOpts, PPOpts, |
128 | CodeGenOpts, C, CoverageInfo)), |
129 | LinkModules(std::move(LinkModules)) { |
130 | FrontendTimesIsEnabled = TimePasses; |
131 | llvm::TimePassesIsEnabled = TimePasses; |
132 | } |
133 | llvm::Module *getModule() const { return Gen->GetModule(); } |
134 | std::unique_ptr<llvm::Module> takeModule() { |
135 | return std::unique_ptr<llvm::Module>(Gen->ReleaseModule()); |
136 | } |
137 | |
138 | CodeGenerator *getCodeGenerator() { return Gen.get(); } |
139 | |
140 | void HandleCXXStaticMemberVarInstantiation(VarDecl *VD) override { |
141 | Gen->HandleCXXStaticMemberVarInstantiation(VD); |
142 | } |
143 | |
144 | void Initialize(ASTContext &Ctx) override { |
145 | (0) . __assert_fail ("!Context && \"initialized multiple times\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/CodeGenAction.cpp", 145, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(!Context && "initialized multiple times"); |
146 | |
147 | Context = &Ctx; |
148 | |
149 | if (FrontendTimesIsEnabled) |
150 | LLVMIRGeneration.startTimer(); |
151 | |
152 | Gen->Initialize(Ctx); |
153 | |
154 | if (FrontendTimesIsEnabled) |
155 | LLVMIRGeneration.stopTimer(); |
156 | } |
157 | |
158 | bool HandleTopLevelDecl(DeclGroupRef D) override { |
159 | PrettyStackTraceDecl CrashInfo(*D.begin(), SourceLocation(), |
160 | Context->getSourceManager(), |
161 | "LLVM IR generation of declaration"); |
162 | |
163 | |
164 | if (FrontendTimesIsEnabled) { |
165 | LLVMIRGenerationRefCount += 1; |
166 | if (LLVMIRGenerationRefCount == 1) |
167 | LLVMIRGeneration.startTimer(); |
168 | } |
169 | |
170 | Gen->HandleTopLevelDecl(D); |
171 | |
172 | if (FrontendTimesIsEnabled) { |
173 | LLVMIRGenerationRefCount -= 1; |
174 | if (LLVMIRGenerationRefCount == 0) |
175 | LLVMIRGeneration.stopTimer(); |
176 | } |
177 | |
178 | return true; |
179 | } |
180 | |
181 | void HandleInlineFunctionDefinition(FunctionDecl *D) override { |
182 | PrettyStackTraceDecl CrashInfo(D, SourceLocation(), |
183 | Context->getSourceManager(), |
184 | "LLVM IR generation of inline function"); |
185 | if (FrontendTimesIsEnabled) |
186 | LLVMIRGeneration.startTimer(); |
187 | |
188 | Gen->HandleInlineFunctionDefinition(D); |
189 | |
190 | if (FrontendTimesIsEnabled) |
191 | LLVMIRGeneration.stopTimer(); |
192 | } |
193 | |
194 | void HandleInterestingDecl(DeclGroupRef D) override { |
195 | |
196 | if (!IRGenFinished) |
197 | HandleTopLevelDecl(D); |
198 | } |
199 | |
200 | |
201 | bool LinkInModules() { |
202 | for (auto &LM : LinkModules) { |
203 | if (LM.PropagateAttrs) |
204 | for (Function &F : *LM.Module) |
205 | Gen->CGM().AddDefaultFnAttrs(F); |
206 | |
207 | CurLinkModule = LM.Module.get(); |
208 | |
209 | bool Err; |
210 | if (LM.Internalize) { |
211 | Err = Linker::linkModules( |
212 | *getModule(), std::move(LM.Module), LM.LinkFlags, |
213 | [](llvm::Module &M, const llvm::StringSet<> &GVS) { |
214 | internalizeModule(M, [&GVS](const llvm::GlobalValue &GV) { |
215 | return !GV.hasName() || (GVS.count(GV.getName()) == 0); |
216 | }); |
217 | }); |
218 | } else { |
219 | Err = Linker::linkModules(*getModule(), std::move(LM.Module), |
220 | LM.LinkFlags); |
221 | } |
222 | |
223 | if (Err) |
224 | return true; |
225 | } |
226 | return false; |
227 | } |
228 | |
229 | void HandleTranslationUnit(ASTContext &C) override { |
230 | { |
231 | PrettyStackTraceString CrashInfo("Per-file LLVM IR generation"); |
232 | if (FrontendTimesIsEnabled) { |
233 | LLVMIRGenerationRefCount += 1; |
234 | if (LLVMIRGenerationRefCount == 1) |
235 | LLVMIRGeneration.startTimer(); |
236 | } |
237 | |
238 | Gen->HandleTranslationUnit(C); |
239 | |
240 | if (FrontendTimesIsEnabled) { |
241 | LLVMIRGenerationRefCount -= 1; |
242 | if (LLVMIRGenerationRefCount == 0) |
243 | LLVMIRGeneration.stopTimer(); |
244 | } |
245 | |
246 | IRGenFinished = true; |
247 | } |
248 | |
249 | |
250 | if (!getModule()) |
251 | return; |
252 | |
253 | |
254 | |
255 | LLVMContext &Ctx = getModule()->getContext(); |
256 | LLVMContext::InlineAsmDiagHandlerTy OldHandler = |
257 | Ctx.getInlineAsmDiagnosticHandler(); |
258 | void *OldContext = Ctx.getInlineAsmDiagnosticContext(); |
259 | Ctx.setInlineAsmDiagnosticHandler(InlineAsmDiagHandler, this); |
260 | |
261 | std::unique_ptr<DiagnosticHandler> OldDiagnosticHandler = |
262 | Ctx.getDiagnosticHandler(); |
263 | Ctx.setDiagnosticHandler(llvm::make_unique<ClangDiagnosticHandler>( |
264 | CodeGenOpts, this)); |
265 | Ctx.setDiagnosticsHotnessRequested(CodeGenOpts.DiagnosticsWithHotness); |
266 | if (CodeGenOpts.DiagnosticsHotnessThreshold != 0) |
267 | Ctx.setDiagnosticsHotnessThreshold( |
268 | CodeGenOpts.DiagnosticsHotnessThreshold); |
269 | |
270 | std::unique_ptr<llvm::ToolOutputFile> OptRecordFile; |
271 | if (!CodeGenOpts.OptRecordFile.empty()) { |
272 | std::error_code EC; |
273 | OptRecordFile = llvm::make_unique<llvm::ToolOutputFile>( |
274 | CodeGenOpts.OptRecordFile, EC, sys::fs::F_None); |
275 | if (EC) { |
276 | Diags.Report(diag::err_cannot_open_file) << |
277 | CodeGenOpts.OptRecordFile << EC.message(); |
278 | return; |
279 | } |
280 | |
281 | Ctx.setRemarkStreamer(llvm::make_unique<RemarkStreamer>( |
282 | CodeGenOpts.OptRecordFile, OptRecordFile->os())); |
283 | |
284 | if (!CodeGenOpts.OptRecordPasses.empty()) |
285 | if (Error E = Ctx.getRemarkStreamer()->setFilter( |
286 | CodeGenOpts.OptRecordPasses)) |
287 | Diags.Report(diag::err_drv_optimization_remark_pattern) |
288 | << toString(std::move(E)) << CodeGenOpts.OptRecordPasses; |
289 | |
290 | if (CodeGenOpts.getProfileUse() != CodeGenOptions::ProfileNone) |
291 | Ctx.setDiagnosticsHotnessRequested(true); |
292 | } |
293 | |
294 | |
295 | if (LinkInModules()) |
296 | return; |
297 | |
298 | EmbedBitcode(getModule(), CodeGenOpts, llvm::MemoryBufferRef()); |
299 | |
300 | EmitBackendOutput(Diags, HeaderSearchOpts, CodeGenOpts, TargetOpts, |
301 | LangOpts, C.getTargetInfo().getDataLayout(), |
302 | getModule(), Action, std::move(AsmOutStream)); |
303 | |
304 | Ctx.setInlineAsmDiagnosticHandler(OldHandler, OldContext); |
305 | |
306 | Ctx.setDiagnosticHandler(std::move(OldDiagnosticHandler)); |
307 | |
308 | if (OptRecordFile) |
309 | OptRecordFile->keep(); |
310 | } |
311 | |
312 | void HandleTagDeclDefinition(TagDecl *D) override { |
313 | PrettyStackTraceDecl CrashInfo(D, SourceLocation(), |
314 | Context->getSourceManager(), |
315 | "LLVM IR generation of declaration"); |
316 | Gen->HandleTagDeclDefinition(D); |
317 | } |
318 | |
319 | void HandleTagDeclRequiredDefinition(const TagDecl *D) override { |
320 | Gen->HandleTagDeclRequiredDefinition(D); |
321 | } |
322 | |
323 | void CompleteTentativeDefinition(VarDecl *D) override { |
324 | Gen->CompleteTentativeDefinition(D); |
325 | } |
326 | |
327 | void AssignInheritanceModel(CXXRecordDecl *RD) override { |
328 | Gen->AssignInheritanceModel(RD); |
329 | } |
330 | |
331 | void HandleVTable(CXXRecordDecl *RD) override { |
332 | Gen->HandleVTable(RD); |
333 | } |
334 | |
335 | static void InlineAsmDiagHandler(const llvm::SMDiagnostic &SM,void *Context, |
336 | unsigned LocCookie) { |
337 | SourceLocation Loc = SourceLocation::getFromRawEncoding(LocCookie); |
338 | ((BackendConsumer*)Context)->InlineAsmDiagHandler2(SM, Loc); |
339 | } |
340 | |
341 | |
342 | |
343 | const FullSourceLoc |
344 | getBestLocationFromDebugLoc(const llvm::DiagnosticInfoWithLocationBase &D, |
345 | bool &BadDebugInfo, StringRef &Filename, |
346 | unsigned &Line, unsigned &Column) const; |
347 | |
348 | void InlineAsmDiagHandler2(const llvm::SMDiagnostic &, |
349 | SourceLocation LocCookie); |
350 | |
351 | void DiagnosticHandlerImpl(const llvm::DiagnosticInfo &DI); |
352 | |
353 | |
354 | |
355 | bool InlineAsmDiagHandler(const llvm::DiagnosticInfoInlineAsm &D); |
356 | |
357 | |
358 | |
359 | bool StackSizeDiagHandler(const llvm::DiagnosticInfoStackSize &D); |
360 | |
361 | void UnsupportedDiagHandler(const llvm::DiagnosticInfoUnsupported &D); |
362 | |
363 | |
364 | |
365 | void EmitOptimizationMessage(const llvm::DiagnosticInfoOptimizationBase &D, |
366 | unsigned DiagID); |
367 | void |
368 | OptimizationRemarkHandler(const llvm::DiagnosticInfoOptimizationBase &D); |
369 | void OptimizationRemarkHandler( |
370 | const llvm::OptimizationRemarkAnalysisFPCommute &D); |
371 | void OptimizationRemarkHandler( |
372 | const llvm::OptimizationRemarkAnalysisAliasing &D); |
373 | void OptimizationFailureHandler( |
374 | const llvm::DiagnosticInfoOptimizationFailure &D); |
375 | }; |
376 | |
377 | void BackendConsumer::anchor() {} |
378 | } |
379 | |
380 | bool ClangDiagnosticHandler::handleDiagnostics(const DiagnosticInfo &DI) { |
381 | BackendCon->DiagnosticHandlerImpl(DI); |
382 | return true; |
383 | } |
384 | |
385 | |
386 | |
387 | static FullSourceLoc ConvertBackendLocation(const llvm::SMDiagnostic &D, |
388 | SourceManager &CSM) { |
389 | |
390 | |
391 | |
392 | const llvm::SourceMgr &LSM = *D.getSourceMgr(); |
393 | |
394 | |
395 | |
396 | const MemoryBuffer *LBuf = |
397 | LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(D.getLoc())); |
398 | |
399 | |
400 | |
401 | std::unique_ptr<llvm::MemoryBuffer> CBuf = |
402 | llvm::MemoryBuffer::getMemBufferCopy(LBuf->getBuffer(), |
403 | LBuf->getBufferIdentifier()); |
404 | |
405 | FileID FID = CSM.createFileID(std::move(CBuf)); |
406 | |
407 | |
408 | unsigned Offset = D.getLoc().getPointer() - LBuf->getBufferStart(); |
409 | SourceLocation NewLoc = |
410 | CSM.getLocForStartOfFile(FID).getLocWithOffset(Offset); |
411 | return FullSourceLoc(NewLoc, CSM); |
412 | } |
413 | |
414 | |
415 | |
416 | |
417 | |
418 | void BackendConsumer::InlineAsmDiagHandler2(const llvm::SMDiagnostic &D, |
419 | SourceLocation LocCookie) { |
420 | |
421 | |
422 | |
423 | |
424 | StringRef Message = D.getMessage(); |
425 | if (Message.startswith("error: ")) |
426 | Message = Message.substr(7); |
427 | |
428 | |
429 | FullSourceLoc Loc; |
430 | if (D.getLoc() != SMLoc()) |
431 | Loc = ConvertBackendLocation(D, Context->getSourceManager()); |
432 | |
433 | unsigned DiagID; |
434 | switch (D.getKind()) { |
435 | case llvm::SourceMgr::DK_Error: |
436 | DiagID = diag::err_fe_inline_asm; |
437 | break; |
438 | case llvm::SourceMgr::DK_Warning: |
439 | DiagID = diag::warn_fe_inline_asm; |
440 | break; |
441 | case llvm::SourceMgr::DK_Note: |
442 | DiagID = diag::note_fe_inline_asm; |
443 | break; |
444 | case llvm::SourceMgr::DK_Remark: |
445 | llvm_unreachable("remarks unexpected"); |
446 | } |
447 | |
448 | |
449 | |
450 | if (LocCookie.isValid()) { |
451 | Diags.Report(LocCookie, DiagID).AddString(Message); |
452 | |
453 | if (D.getLoc().isValid()) { |
454 | DiagnosticBuilder B = Diags.Report(Loc, diag::note_fe_inline_asm_here); |
455 | |
456 | |
457 | for (const std::pair<unsigned, unsigned> &Range : D.getRanges()) { |
458 | unsigned Column = D.getColumnNo(); |
459 | B << SourceRange(Loc.getLocWithOffset(Range.first - Column), |
460 | Loc.getLocWithOffset(Range.second - Column)); |
461 | } |
462 | } |
463 | return; |
464 | } |
465 | |
466 | |
467 | |
468 | |
469 | Diags.Report(Loc, DiagID).AddString(Message); |
470 | } |
471 | |
472 | #define ComputeDiagID(Severity, GroupName, DiagID) \ |
473 | do { \ |
474 | switch (Severity) { \ |
475 | case llvm::DS_Error: \ |
476 | DiagID = diag::err_fe_##GroupName; \ |
477 | break; \ |
478 | case llvm::DS_Warning: \ |
479 | DiagID = diag::warn_fe_##GroupName; \ |
480 | break; \ |
481 | case llvm::DS_Remark: \ |
482 | llvm_unreachable("'remark' severity not expected"); \ |
483 | break; \ |
484 | case llvm::DS_Note: \ |
485 | DiagID = diag::note_fe_##GroupName; \ |
486 | break; \ |
487 | } \ |
488 | } while (false) |
489 | |
490 | #define (Severity, GroupName, DiagID) \ |
491 | do { \ |
492 | switch (Severity) { \ |
493 | case llvm::DS_Error: \ |
494 | DiagID = diag::err_fe_##GroupName; \ |
495 | break; \ |
496 | case llvm::DS_Warning: \ |
497 | DiagID = diag::warn_fe_##GroupName; \ |
498 | break; \ |
499 | case llvm::DS_Remark: \ |
500 | DiagID = diag::remark_fe_##GroupName; \ |
501 | break; \ |
502 | case llvm::DS_Note: \ |
503 | DiagID = diag::note_fe_##GroupName; \ |
504 | break; \ |
505 | } \ |
506 | } while (false) |
507 | |
508 | bool |
509 | BackendConsumer::InlineAsmDiagHandler(const llvm::DiagnosticInfoInlineAsm &D) { |
510 | unsigned DiagID; |
511 | ComputeDiagID(D.getSeverity(), inline_asm, DiagID); |
512 | std::string Message = D.getMsgStr().str(); |
513 | |
514 | |
515 | |
516 | |
517 | SourceLocation LocCookie = |
518 | SourceLocation::getFromRawEncoding(D.getLocCookie()); |
519 | if (LocCookie.isValid()) |
520 | Diags.Report(LocCookie, DiagID).AddString(Message); |
521 | else { |
522 | |
523 | |
524 | |
525 | |
526 | FullSourceLoc Loc; |
527 | Diags.Report(Loc, DiagID).AddString(Message); |
528 | } |
529 | |
530 | return true; |
531 | } |
532 | |
533 | bool |
534 | BackendConsumer::StackSizeDiagHandler(const llvm::DiagnosticInfoStackSize &D) { |
535 | if (D.getSeverity() != llvm::DS_Warning) |
536 | |
537 | |
538 | return false; |
539 | |
540 | if (const Decl *ND = Gen->GetDeclForMangledName(D.getFunction().getName())) { |
541 | |
542 | Diags.Report(ND->getASTContext().getFullLoc(ND->getLocation()), |
543 | diag::warn_fe_frame_larger_than) |
544 | << static_cast<uint32_t>(D.getStackSize()) << Decl::castToDeclContext(ND); |
545 | return true; |
546 | } |
547 | |
548 | return false; |
549 | } |
550 | |
551 | const FullSourceLoc BackendConsumer::getBestLocationFromDebugLoc( |
552 | const llvm::DiagnosticInfoWithLocationBase &D, bool &BadDebugInfo, |
553 | StringRef &Filename, unsigned &Line, unsigned &Column) const { |
554 | SourceManager &SourceMgr = Context->getSourceManager(); |
555 | FileManager &FileMgr = SourceMgr.getFileManager(); |
556 | SourceLocation DILoc; |
557 | |
558 | if (D.isLocationAvailable()) { |
559 | D.getLocation(Filename, Line, Column); |
560 | if (Line > 0) { |
561 | const FileEntry *FE = FileMgr.getFile(Filename); |
562 | if (!FE) |
563 | FE = FileMgr.getFile(D.getAbsolutePath()); |
564 | if (FE) { |
565 | |
566 | |
567 | DILoc = SourceMgr.translateFileLineCol(FE, Line, Column ? Column : 1); |
568 | } |
569 | } |
570 | BadDebugInfo = DILoc.isInvalid(); |
571 | } |
572 | |
573 | |
574 | |
575 | |
576 | FullSourceLoc Loc(DILoc, SourceMgr); |
577 | if (Loc.isInvalid()) |
578 | if (const Decl *FD = Gen->GetDeclForMangledName(D.getFunction().getName())) |
579 | Loc = FD->getASTContext().getFullLoc(FD->getLocation()); |
580 | |
581 | if (DILoc.isInvalid() && D.isLocationAvailable()) |
582 | |
583 | |
584 | |
585 | |
586 | Diags.Report(Loc, diag::note_fe_backend_invalid_loc) |
587 | << Filename << Line << Column; |
588 | |
589 | return Loc; |
590 | } |
591 | |
592 | void BackendConsumer::UnsupportedDiagHandler( |
593 | const llvm::DiagnosticInfoUnsupported &D) { |
594 | |
595 | assert(D.getSeverity() == llvm::DS_Error); |
596 | |
597 | StringRef Filename; |
598 | unsigned Line, Column; |
599 | bool BadDebugInfo = false; |
600 | FullSourceLoc Loc = |
601 | getBestLocationFromDebugLoc(D, BadDebugInfo, Filename, Line, Column); |
602 | |
603 | Diags.Report(Loc, diag::err_fe_backend_unsupported) << D.getMessage().str(); |
604 | |
605 | if (BadDebugInfo) |
606 | |
607 | |
608 | |
609 | |
610 | Diags.Report(Loc, diag::note_fe_backend_invalid_loc) |
611 | << Filename << Line << Column; |
612 | } |
613 | |
614 | void BackendConsumer::EmitOptimizationMessage( |
615 | const llvm::DiagnosticInfoOptimizationBase &D, unsigned DiagID) { |
616 | |
617 | assert(D.getSeverity() == llvm::DS_Remark || |
618 | D.getSeverity() == llvm::DS_Warning); |
619 | |
620 | StringRef Filename; |
621 | unsigned Line, Column; |
622 | bool BadDebugInfo = false; |
623 | FullSourceLoc Loc = |
624 | getBestLocationFromDebugLoc(D, BadDebugInfo, Filename, Line, Column); |
625 | |
626 | std::string Msg; |
627 | raw_string_ostream MsgStream(Msg); |
628 | MsgStream << D.getMsg(); |
629 | |
630 | if (D.getHotness()) |
631 | MsgStream << " (hotness: " << *D.getHotness() << ")"; |
632 | |
633 | Diags.Report(Loc, DiagID) |
634 | << AddFlagValue(D.getPassName()) |
635 | << MsgStream.str(); |
636 | |
637 | if (BadDebugInfo) |
638 | |
639 | |
640 | |
641 | |
642 | Diags.Report(Loc, diag::note_fe_backend_invalid_loc) |
643 | << Filename << Line << Column; |
644 | } |
645 | |
646 | void BackendConsumer::OptimizationRemarkHandler( |
647 | const llvm::DiagnosticInfoOptimizationBase &D) { |
648 | |
649 | if (D.isVerbose() && !D.getHotness()) |
650 | return; |
651 | |
652 | if (D.isPassed()) { |
653 | |
654 | |
655 | if (CodeGenOpts.OptimizationRemarkPattern && |
656 | CodeGenOpts.OptimizationRemarkPattern->match(D.getPassName())) |
657 | EmitOptimizationMessage(D, diag::remark_fe_backend_optimization_remark); |
658 | } else if (D.isMissed()) { |
659 | |
660 | |
661 | |
662 | if (CodeGenOpts.OptimizationRemarkMissedPattern && |
663 | CodeGenOpts.OptimizationRemarkMissedPattern->match(D.getPassName())) |
664 | EmitOptimizationMessage( |
665 | D, diag::remark_fe_backend_optimization_remark_missed); |
666 | } else { |
667 | (0) . __assert_fail ("D.isAnalysis() && \"Unknown remark type\"", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/CodeGenAction.cpp", 667, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(D.isAnalysis() && "Unknown remark type"); |
668 | |
669 | bool ShouldAlwaysPrint = false; |
670 | if (auto *ORA = dyn_cast<llvm::OptimizationRemarkAnalysis>(&D)) |
671 | ShouldAlwaysPrint = ORA->shouldAlwaysPrint(); |
672 | |
673 | if (ShouldAlwaysPrint || |
674 | (CodeGenOpts.OptimizationRemarkAnalysisPattern && |
675 | CodeGenOpts.OptimizationRemarkAnalysisPattern->match(D.getPassName()))) |
676 | EmitOptimizationMessage( |
677 | D, diag::remark_fe_backend_optimization_remark_analysis); |
678 | } |
679 | } |
680 | |
681 | void BackendConsumer::OptimizationRemarkHandler( |
682 | const llvm::OptimizationRemarkAnalysisFPCommute &D) { |
683 | |
684 | |
685 | |
686 | |
687 | if (D.shouldAlwaysPrint() || |
688 | (CodeGenOpts.OptimizationRemarkAnalysisPattern && |
689 | CodeGenOpts.OptimizationRemarkAnalysisPattern->match(D.getPassName()))) |
690 | EmitOptimizationMessage( |
691 | D, diag::remark_fe_backend_optimization_remark_analysis_fpcommute); |
692 | } |
693 | |
694 | void BackendConsumer::OptimizationRemarkHandler( |
695 | const llvm::OptimizationRemarkAnalysisAliasing &D) { |
696 | |
697 | |
698 | |
699 | |
700 | if (D.shouldAlwaysPrint() || |
701 | (CodeGenOpts.OptimizationRemarkAnalysisPattern && |
702 | CodeGenOpts.OptimizationRemarkAnalysisPattern->match(D.getPassName()))) |
703 | EmitOptimizationMessage( |
704 | D, diag::remark_fe_backend_optimization_remark_analysis_aliasing); |
705 | } |
706 | |
707 | void BackendConsumer::OptimizationFailureHandler( |
708 | const llvm::DiagnosticInfoOptimizationFailure &D) { |
709 | EmitOptimizationMessage(D, diag::warn_fe_backend_optimization_failure); |
710 | } |
711 | |
712 | |
713 | |
714 | void BackendConsumer::DiagnosticHandlerImpl(const DiagnosticInfo &DI) { |
715 | unsigned DiagID = diag::err_fe_inline_asm; |
716 | llvm::DiagnosticSeverity Severity = DI.getSeverity(); |
717 | |
718 | switch (DI.getKind()) { |
719 | case llvm::DK_InlineAsm: |
720 | if (InlineAsmDiagHandler(cast<DiagnosticInfoInlineAsm>(DI))) |
721 | return; |
722 | ComputeDiagID(Severity, inline_asm, DiagID); |
723 | break; |
724 | case llvm::DK_StackSize: |
725 | if (StackSizeDiagHandler(cast<DiagnosticInfoStackSize>(DI))) |
726 | return; |
727 | ComputeDiagID(Severity, backend_frame_larger_than, DiagID); |
728 | break; |
729 | case DK_Linker: |
730 | assert(CurLinkModule); |
731 | |
732 | if (Severity != DS_Error) |
733 | return; |
734 | DiagID = diag::err_fe_cannot_link_module; |
735 | break; |
736 | case llvm::DK_OptimizationRemark: |
737 | |
738 | |
739 | OptimizationRemarkHandler(cast<OptimizationRemark>(DI)); |
740 | return; |
741 | case llvm::DK_OptimizationRemarkMissed: |
742 | |
743 | |
744 | OptimizationRemarkHandler(cast<OptimizationRemarkMissed>(DI)); |
745 | return; |
746 | case llvm::DK_OptimizationRemarkAnalysis: |
747 | |
748 | |
749 | OptimizationRemarkHandler(cast<OptimizationRemarkAnalysis>(DI)); |
750 | return; |
751 | case llvm::DK_OptimizationRemarkAnalysisFPCommute: |
752 | |
753 | |
754 | OptimizationRemarkHandler(cast<OptimizationRemarkAnalysisFPCommute>(DI)); |
755 | return; |
756 | case llvm::DK_OptimizationRemarkAnalysisAliasing: |
757 | |
758 | |
759 | OptimizationRemarkHandler(cast<OptimizationRemarkAnalysisAliasing>(DI)); |
760 | return; |
761 | case llvm::DK_MachineOptimizationRemark: |
762 | |
763 | |
764 | OptimizationRemarkHandler(cast<MachineOptimizationRemark>(DI)); |
765 | return; |
766 | case llvm::DK_MachineOptimizationRemarkMissed: |
767 | |
768 | |
769 | OptimizationRemarkHandler(cast<MachineOptimizationRemarkMissed>(DI)); |
770 | return; |
771 | case llvm::DK_MachineOptimizationRemarkAnalysis: |
772 | |
773 | |
774 | OptimizationRemarkHandler(cast<MachineOptimizationRemarkAnalysis>(DI)); |
775 | return; |
776 | case llvm::DK_OptimizationFailure: |
777 | |
778 | |
779 | OptimizationFailureHandler(cast<DiagnosticInfoOptimizationFailure>(DI)); |
780 | return; |
781 | case llvm::DK_Unsupported: |
782 | UnsupportedDiagHandler(cast<DiagnosticInfoUnsupported>(DI)); |
783 | return; |
784 | default: |
785 | |
786 | ComputeDiagRemarkID(Severity, backend_plugin, DiagID); |
787 | break; |
788 | } |
789 | std::string MsgStorage; |
790 | { |
791 | raw_string_ostream Stream(MsgStorage); |
792 | DiagnosticPrinterRawOStream DP(Stream); |
793 | DI.print(DP); |
794 | } |
795 | |
796 | if (DiagID == diag::err_fe_cannot_link_module) { |
797 | Diags.Report(diag::err_fe_cannot_link_module) |
798 | << CurLinkModule->getModuleIdentifier() << MsgStorage; |
799 | return; |
800 | } |
801 | |
802 | |
803 | FullSourceLoc Loc; |
804 | Diags.Report(Loc, DiagID).AddString(MsgStorage); |
805 | } |
806 | #undef ComputeDiagID |
807 | |
808 | CodeGenAction::CodeGenAction(unsigned _Act, LLVMContext *_VMContext) |
809 | : Act(_Act), VMContext(_VMContext ? _VMContext : new LLVMContext), |
810 | OwnsVMContext(!_VMContext) {} |
811 | |
812 | CodeGenAction::~CodeGenAction() { |
813 | TheModule.reset(); |
814 | if (OwnsVMContext) |
815 | delete VMContext; |
816 | } |
817 | |
818 | bool CodeGenAction::hasIRSupport() const { return true; } |
819 | |
820 | void CodeGenAction::EndSourceFileAction() { |
821 | |
822 | if (!getCompilerInstance().hasASTConsumer()) |
823 | return; |
824 | |
825 | |
826 | TheModule = BEConsumer->takeModule(); |
827 | } |
828 | |
829 | std::unique_ptr<llvm::Module> CodeGenAction::takeModule() { |
830 | return std::move(TheModule); |
831 | } |
832 | |
833 | llvm::LLVMContext *CodeGenAction::takeLLVMContext() { |
834 | OwnsVMContext = false; |
835 | return VMContext; |
836 | } |
837 | |
838 | static std::unique_ptr<raw_pwrite_stream> |
839 | GetOutputStream(CompilerInstance &CI, StringRef InFile, BackendAction Action) { |
840 | switch (Action) { |
841 | case Backend_EmitAssembly: |
842 | return CI.createDefaultOutputFile(false, InFile, "s"); |
843 | case Backend_EmitLL: |
844 | return CI.createDefaultOutputFile(false, InFile, "ll"); |
845 | case Backend_EmitBC: |
846 | return CI.createDefaultOutputFile(true, InFile, "bc"); |
847 | case Backend_EmitNothing: |
848 | return nullptr; |
849 | case Backend_EmitMCNull: |
850 | return CI.createNullOutputFile(); |
851 | case Backend_EmitObj: |
852 | return CI.createDefaultOutputFile(true, InFile, "o"); |
853 | } |
854 | |
855 | llvm_unreachable("Invalid action!"); |
856 | } |
857 | |
858 | std::unique_ptr<ASTConsumer> |
859 | CodeGenAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { |
860 | BackendAction BA = static_cast<BackendAction>(Act); |
861 | std::unique_ptr<raw_pwrite_stream> OS = CI.takeOutputStream(); |
862 | if (!OS) |
863 | OS = GetOutputStream(CI, InFile, BA); |
864 | |
865 | if (BA != Backend_EmitNothing && !OS) |
866 | return nullptr; |
867 | |
868 | |
869 | if (LinkModules.empty()) |
870 | for (const CodeGenOptions::BitcodeFileToLink &F : |
871 | CI.getCodeGenOpts().LinkBitcodeFiles) { |
872 | auto BCBuf = CI.getFileManager().getBufferForFile(F.Filename); |
873 | if (!BCBuf) { |
874 | CI.getDiagnostics().Report(diag::err_cannot_open_file) |
875 | << F.Filename << BCBuf.getError().message(); |
876 | LinkModules.clear(); |
877 | return nullptr; |
878 | } |
879 | |
880 | Expected<std::unique_ptr<llvm::Module>> ModuleOrErr = |
881 | getOwningLazyBitcodeModule(std::move(*BCBuf), *VMContext); |
882 | if (!ModuleOrErr) { |
883 | handleAllErrors(ModuleOrErr.takeError(), [&](ErrorInfoBase &EIB) { |
884 | CI.getDiagnostics().Report(diag::err_cannot_open_file) |
885 | << F.Filename << EIB.message(); |
886 | }); |
887 | LinkModules.clear(); |
888 | return nullptr; |
889 | } |
890 | LinkModules.push_back({std::move(ModuleOrErr.get()), F.PropagateAttrs, |
891 | F.Internalize, F.LinkFlags}); |
892 | } |
893 | |
894 | CoverageSourceInfo *CoverageInfo = nullptr; |
895 | |
896 | if (CI.getCodeGenOpts().CoverageMapping) { |
897 | CoverageInfo = new CoverageSourceInfo; |
898 | CI.getPreprocessor().addPPCallbacks( |
899 | std::unique_ptr<PPCallbacks>(CoverageInfo)); |
900 | } |
901 | |
902 | std::unique_ptr<BackendConsumer> Result(new BackendConsumer( |
903 | BA, CI.getDiagnostics(), CI.getHeaderSearchOpts(), |
904 | CI.getPreprocessorOpts(), CI.getCodeGenOpts(), CI.getTargetOpts(), |
905 | CI.getLangOpts(), CI.getFrontendOpts().ShowTimers, InFile, |
906 | std::move(LinkModules), std::move(OS), *VMContext, CoverageInfo)); |
907 | BEConsumer = Result.get(); |
908 | |
909 | |
910 | |
911 | if (CI.getCodeGenOpts().getDebugInfo() != codegenoptions::NoDebugInfo && |
912 | CI.getCodeGenOpts().MacroDebugInfo) { |
913 | std::unique_ptr<PPCallbacks> Callbacks = |
914 | llvm::make_unique<MacroPPCallbacks>(BEConsumer->getCodeGenerator(), |
915 | CI.getPreprocessor()); |
916 | CI.getPreprocessor().addPPCallbacks(std::move(Callbacks)); |
917 | } |
918 | |
919 | return std::move(Result); |
920 | } |
921 | |
922 | static void BitcodeInlineAsmDiagHandler(const llvm::SMDiagnostic &SM, |
923 | void *Context, |
924 | unsigned LocCookie) { |
925 | SM.print(nullptr, llvm::errs()); |
926 | |
927 | auto Diags = static_cast<DiagnosticsEngine *>(Context); |
928 | unsigned DiagID; |
929 | switch (SM.getKind()) { |
930 | case llvm::SourceMgr::DK_Error: |
931 | DiagID = diag::err_fe_inline_asm; |
932 | break; |
933 | case llvm::SourceMgr::DK_Warning: |
934 | DiagID = diag::warn_fe_inline_asm; |
935 | break; |
936 | case llvm::SourceMgr::DK_Note: |
937 | DiagID = diag::note_fe_inline_asm; |
938 | break; |
939 | case llvm::SourceMgr::DK_Remark: |
940 | llvm_unreachable("remarks unexpected"); |
941 | } |
942 | |
943 | Diags->Report(DiagID).AddString("cannot compile inline asm"); |
944 | } |
945 | |
946 | std::unique_ptr<llvm::Module> CodeGenAction::loadModule(MemoryBufferRef MBRef) { |
947 | CompilerInstance &CI = getCompilerInstance(); |
948 | SourceManager &SM = CI.getSourceManager(); |
949 | |
950 | |
951 | |
952 | |
953 | if (!CI.getCodeGenOpts().ThinLTOIndexFile.empty()) { |
954 | VMContext->enableDebugTypeODRUniquing(); |
955 | |
956 | auto DiagErrors = [&](Error E) -> std::unique_ptr<llvm::Module> { |
957 | unsigned DiagID = |
958 | CI.getDiagnostics().getCustomDiagID(DiagnosticsEngine::Error, "%0"); |
959 | handleAllErrors(std::move(E), [&](ErrorInfoBase &EIB) { |
960 | CI.getDiagnostics().Report(DiagID) << EIB.message(); |
961 | }); |
962 | return {}; |
963 | }; |
964 | |
965 | Expected<std::vector<BitcodeModule>> BMsOrErr = getBitcodeModuleList(MBRef); |
966 | if (!BMsOrErr) |
967 | return DiagErrors(BMsOrErr.takeError()); |
968 | BitcodeModule *Bm = FindThinLTOModule(*BMsOrErr); |
969 | |
970 | |
971 | |
972 | |
973 | if (!Bm) { |
974 | auto M = llvm::make_unique<llvm::Module>("empty", *VMContext); |
975 | M->setTargetTriple(CI.getTargetOpts().Triple); |
976 | return M; |
977 | } |
978 | Expected<std::unique_ptr<llvm::Module>> MOrErr = |
979 | Bm->parseModule(*VMContext); |
980 | if (!MOrErr) |
981 | return DiagErrors(MOrErr.takeError()); |
982 | return std::move(*MOrErr); |
983 | } |
984 | |
985 | llvm::SMDiagnostic Err; |
986 | if (std::unique_ptr<llvm::Module> M = parseIR(MBRef, Err, *VMContext)) |
987 | return M; |
988 | |
989 | |
990 | |
991 | |
992 | SourceLocation Loc; |
993 | if (Err.getLineNo() > 0) { |
994 | = 0", "/home/seafit/code_projects/clang_source/clang/lib/CodeGen/CodeGenAction.cpp", 994, __PRETTY_FUNCTION__))" file_link="../../../include/assert.h.html#88" macro="true">assert(Err.getColumnNo() >= 0); |
995 | Loc = SM.translateFileLineCol(SM.getFileEntryForID(SM.getMainFileID()), |
996 | Err.getLineNo(), Err.getColumnNo() + 1); |
997 | } |
998 | |
999 | |
1000 | StringRef Msg = Err.getMessage(); |
1001 | if (Msg.startswith("error: ")) |
1002 | Msg = Msg.substr(7); |
1003 | |
1004 | unsigned DiagID = |
1005 | CI.getDiagnostics().getCustomDiagID(DiagnosticsEngine::Error, "%0"); |
1006 | |
1007 | CI.getDiagnostics().Report(Loc, DiagID) << Msg; |
1008 | return {}; |
1009 | } |
1010 | |
1011 | void CodeGenAction::ExecuteAction() { |
1012 | |
1013 | if (getCurrentFileKind().getLanguage() == InputKind::LLVM_IR) { |
1014 | BackendAction BA = static_cast<BackendAction>(Act); |
1015 | CompilerInstance &CI = getCompilerInstance(); |
1016 | std::unique_ptr<raw_pwrite_stream> OS = |
1017 | GetOutputStream(CI, getCurrentFile(), BA); |
1018 | if (BA != Backend_EmitNothing && !OS) |
1019 | return; |
1020 | |
1021 | bool Invalid; |
1022 | SourceManager &SM = CI.getSourceManager(); |
1023 | FileID FID = SM.getMainFileID(); |
1024 | llvm::MemoryBuffer *MainFile = SM.getBuffer(FID, &Invalid); |
1025 | if (Invalid) |
1026 | return; |
1027 | |
1028 | TheModule = loadModule(*MainFile); |
1029 | if (!TheModule) |
1030 | return; |
1031 | |
1032 | const TargetOptions &TargetOpts = CI.getTargetOpts(); |
1033 | if (TheModule->getTargetTriple() != TargetOpts.Triple) { |
1034 | CI.getDiagnostics().Report(SourceLocation(), |
1035 | diag::warn_fe_override_module) |
1036 | << TargetOpts.Triple; |
1037 | TheModule->setTargetTriple(TargetOpts.Triple); |
1038 | } |
1039 | |
1040 | EmbedBitcode(TheModule.get(), CI.getCodeGenOpts(), |
1041 | MainFile->getMemBufferRef()); |
1042 | |
1043 | LLVMContext &Ctx = TheModule->getContext(); |
1044 | Ctx.setInlineAsmDiagnosticHandler(BitcodeInlineAsmDiagHandler, |
1045 | &CI.getDiagnostics()); |
1046 | |
1047 | EmitBackendOutput(CI.getDiagnostics(), CI.getHeaderSearchOpts(), |
1048 | CI.getCodeGenOpts(), TargetOpts, CI.getLangOpts(), |
1049 | CI.getTarget().getDataLayout(), TheModule.get(), BA, |
1050 | std::move(OS)); |
1051 | return; |
1052 | } |
1053 | |
1054 | |
1055 | this->ASTFrontendAction::ExecuteAction(); |
1056 | } |
1057 | |
1058 | |
1059 | |
1060 | void EmitAssemblyAction::anchor() { } |
1061 | EmitAssemblyAction::EmitAssemblyAction(llvm::LLVMContext *_VMContext) |
1062 | : CodeGenAction(Backend_EmitAssembly, _VMContext) {} |
1063 | |
1064 | void EmitBCAction::anchor() { } |
1065 | EmitBCAction::EmitBCAction(llvm::LLVMContext *_VMContext) |
1066 | : CodeGenAction(Backend_EmitBC, _VMContext) {} |
1067 | |
1068 | void EmitLLVMAction::anchor() { } |
1069 | EmitLLVMAction::EmitLLVMAction(llvm::LLVMContext *_VMContext) |
1070 | : CodeGenAction(Backend_EmitLL, _VMContext) {} |
1071 | |
1072 | void EmitLLVMOnlyAction::anchor() { } |
1073 | EmitLLVMOnlyAction::EmitLLVMOnlyAction(llvm::LLVMContext *_VMContext) |
1074 | : CodeGenAction(Backend_EmitNothing, _VMContext) {} |
1075 | |
1076 | void EmitCodeGenOnlyAction::anchor() { } |
1077 | EmitCodeGenOnlyAction::EmitCodeGenOnlyAction(llvm::LLVMContext *_VMContext) |
1078 | : CodeGenAction(Backend_EmitMCNull, _VMContext) {} |
1079 | |
1080 | void EmitObjAction::anchor() { } |
1081 | EmitObjAction::EmitObjAction(llvm::LLVMContext *_VMContext) |
1082 | : CodeGenAction(Backend_EmitObj, _VMContext) {} |
1083 | |