1ffd1746dSEd Schouten //===--- CodeGenAction.cpp - LLVM Code Generation Frontend Action ---------===//
2ffd1746dSEd Schouten //
3ffd1746dSEd Schouten //                     The LLVM Compiler Infrastructure
4ffd1746dSEd Schouten //
5ffd1746dSEd Schouten // This file is distributed under the University of Illinois Open Source
6ffd1746dSEd Schouten // License. See LICENSE.TXT for details.
7ffd1746dSEd Schouten //
8ffd1746dSEd Schouten //===----------------------------------------------------------------------===//
9ffd1746dSEd Schouten 
1020e90f04SDimitry Andric #include "clang/CodeGen/CodeGenAction.h"
1120e90f04SDimitry Andric #include "CodeGenModule.h"
1239d628a0SDimitry Andric #include "CoverageMappingGen.h"
1320e90f04SDimitry Andric #include "MacroPPCallbacks.h"
14ffd1746dSEd Schouten #include "clang/AST/ASTConsumer.h"
15ffd1746dSEd Schouten #include "clang/AST/ASTContext.h"
1659d1ed5bSDimitry Andric #include "clang/AST/DeclCXX.h"
1739d628a0SDimitry Andric #include "clang/AST/DeclGroup.h"
18139f7f9bSDimitry Andric #include "clang/Basic/FileManager.h"
19139f7f9bSDimitry Andric #include "clang/Basic/SourceManager.h"
20139f7f9bSDimitry Andric #include "clang/Basic/TargetInfo.h"
21ffd1746dSEd Schouten #include "clang/CodeGen/BackendUtil.h"
22ffd1746dSEd Schouten #include "clang/CodeGen/ModuleBuilder.h"
23ffd1746dSEd Schouten #include "clang/Frontend/CompilerInstance.h"
24ffd1746dSEd Schouten #include "clang/Frontend/FrontendDiagnostic.h"
2539d628a0SDimitry Andric #include "clang/Lex/Preprocessor.h"
2644290647SDimitry Andric #include "llvm/Bitcode/BitcodeReader.h"
2720e90f04SDimitry Andric #include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h"
2859d1ed5bSDimitry Andric #include "llvm/IR/DebugInfo.h"
2959d1ed5bSDimitry Andric #include "llvm/IR/DiagnosticInfo.h"
3059d1ed5bSDimitry Andric #include "llvm/IR/DiagnosticPrinter.h"
3120e90f04SDimitry Andric #include "llvm/IR/GlobalValue.h"
32139f7f9bSDimitry Andric #include "llvm/IR/LLVMContext.h"
33139f7f9bSDimitry Andric #include "llvm/IR/Module.h"
34139f7f9bSDimitry Andric #include "llvm/IRReader/IRReader.h"
3559d1ed5bSDimitry Andric #include "llvm/Linker/Linker.h"
36139f7f9bSDimitry Andric #include "llvm/Pass.h"
37ffd1746dSEd Schouten #include "llvm/Support/MemoryBuffer.h"
38ffd1746dSEd Schouten #include "llvm/Support/SourceMgr.h"
39ffd1746dSEd Schouten #include "llvm/Support/Timer.h"
4044290647SDimitry Andric #include "llvm/Support/ToolOutputFile.h"
4144290647SDimitry Andric #include "llvm/Support/YAMLTraits.h"
4220e90f04SDimitry Andric #include "llvm/Transforms/IPO/Internalize.h"
4320e90f04SDimitry Andric 
4459d1ed5bSDimitry Andric #include <memory>
45ffd1746dSEd Schouten using namespace clang;
46ffd1746dSEd Schouten using namespace llvm;
47ffd1746dSEd Schouten 
482754fe60SDimitry Andric namespace clang {
499a199699SDimitry Andric   class BackendConsumer;
509a199699SDimitry Andric   class ClangDiagnosticHandler final : public DiagnosticHandler {
519a199699SDimitry Andric   public:
ClangDiagnosticHandler(const CodeGenOptions & CGOpts,BackendConsumer * BCon)529a199699SDimitry Andric     ClangDiagnosticHandler(const CodeGenOptions &CGOpts, BackendConsumer *BCon)
539a199699SDimitry Andric         : CodeGenOpts(CGOpts), BackendCon(BCon) {}
549a199699SDimitry Andric 
559a199699SDimitry Andric     bool handleDiagnostics(const DiagnosticInfo &DI) override;
569a199699SDimitry Andric 
isAnalysisRemarkEnabled(StringRef PassName) const579a199699SDimitry Andric     bool isAnalysisRemarkEnabled(StringRef PassName) const override {
589a199699SDimitry Andric       return (CodeGenOpts.OptimizationRemarkAnalysisPattern &&
599a199699SDimitry Andric               CodeGenOpts.OptimizationRemarkAnalysisPattern->match(PassName));
609a199699SDimitry Andric     }
isMissedOptRemarkEnabled(StringRef PassName) const619a199699SDimitry Andric     bool isMissedOptRemarkEnabled(StringRef PassName) const override {
629a199699SDimitry Andric       return (CodeGenOpts.OptimizationRemarkMissedPattern &&
639a199699SDimitry Andric               CodeGenOpts.OptimizationRemarkMissedPattern->match(PassName));
649a199699SDimitry Andric     }
isPassedOptRemarkEnabled(StringRef PassName) const659a199699SDimitry Andric     bool isPassedOptRemarkEnabled(StringRef PassName) const override {
669a199699SDimitry Andric       return (CodeGenOpts.OptimizationRemarkPattern &&
679a199699SDimitry Andric               CodeGenOpts.OptimizationRemarkPattern->match(PassName));
689a199699SDimitry Andric     }
699a199699SDimitry Andric 
isAnyRemarkEnabled() const709a199699SDimitry Andric     bool isAnyRemarkEnabled() const override {
719a199699SDimitry Andric       return (CodeGenOpts.OptimizationRemarkAnalysisPattern ||
729a199699SDimitry Andric               CodeGenOpts.OptimizationRemarkMissedPattern ||
739a199699SDimitry Andric               CodeGenOpts.OptimizationRemarkPattern);
749a199699SDimitry Andric     }
759a199699SDimitry Andric 
769a199699SDimitry Andric   private:
779a199699SDimitry Andric     const CodeGenOptions &CodeGenOpts;
789a199699SDimitry Andric     BackendConsumer *BackendCon;
799a199699SDimitry Andric   };
809a199699SDimitry Andric 
81ffd1746dSEd Schouten   class BackendConsumer : public ASTConsumer {
8220e90f04SDimitry Andric     using LinkModule = CodeGenAction::LinkModule;
8320e90f04SDimitry Andric 
84dff0c46cSDimitry Andric     virtual void anchor();
856122f3e6SDimitry Andric     DiagnosticsEngine &Diags;
86ffd1746dSEd Schouten     BackendAction Action;
8795ec533aSDimitry Andric     const HeaderSearchOptions &HeaderSearchOpts;
88ffd1746dSEd Schouten     const CodeGenOptions &CodeGenOpts;
89ffd1746dSEd Schouten     const TargetOptions &TargetOpts;
9017a519f9SDimitry Andric     const LangOptions &LangOpts;
91e7145dcbSDimitry Andric     std::unique_ptr<raw_pwrite_stream> AsmOutStream;
92ffd1746dSEd Schouten     ASTContext *Context;
93ffd1746dSEd Schouten 
94ffd1746dSEd Schouten     Timer LLVMIRGeneration;
9544290647SDimitry Andric     unsigned LLVMIRGenerationRefCount;
9644290647SDimitry Andric 
9744290647SDimitry Andric     /// True if we've finished generating IR. This prevents us from generating
9844290647SDimitry Andric     /// additional LLVM IR after emitting output in HandleTranslationUnit. This
9944290647SDimitry Andric     /// can happen when Clang plugins trigger additional AST deserialization.
10044290647SDimitry Andric     bool IRGenFinished = false;
101ffd1746dSEd Schouten 
10259d1ed5bSDimitry Andric     std::unique_ptr<CodeGenerator> Gen;
103ffd1746dSEd Schouten 
10420e90f04SDimitry Andric     SmallVector<LinkModule, 4> LinkModules;
1050623d748SDimitry Andric 
1060623d748SDimitry Andric     // This is here so that the diagnostic printer knows the module a diagnostic
1070623d748SDimitry Andric     // refers to.
1080623d748SDimitry Andric     llvm::Module *CurLinkModule = nullptr;
109ffd1746dSEd Schouten 
110ffd1746dSEd Schouten   public:
BackendConsumer(BackendAction Action,DiagnosticsEngine & Diags,const HeaderSearchOptions & HeaderSearchOpts,const PreprocessorOptions & PPOpts,const CodeGenOptions & CodeGenOpts,const TargetOptions & TargetOpts,const LangOptions & LangOpts,bool TimePasses,const std::string & InFile,SmallVector<LinkModule,4> LinkModules,std::unique_ptr<raw_pwrite_stream> OS,LLVMContext & C,CoverageSourceInfo * CoverageInfo=nullptr)11120e90f04SDimitry Andric     BackendConsumer(BackendAction Action, DiagnosticsEngine &Diags,
1123dac3a9bSDimitry Andric                     const HeaderSearchOptions &HeaderSearchOpts,
11320e90f04SDimitry Andric                     const PreprocessorOptions &PPOpts,
11420e90f04SDimitry Andric                     const CodeGenOptions &CodeGenOpts,
11520e90f04SDimitry Andric                     const TargetOptions &TargetOpts,
11620e90f04SDimitry Andric                     const LangOptions &LangOpts, bool TimePasses,
11720e90f04SDimitry Andric                     const std::string &InFile,
11820e90f04SDimitry Andric                     SmallVector<LinkModule, 4> LinkModules,
119e7145dcbSDimitry Andric                     std::unique_ptr<raw_pwrite_stream> OS, LLVMContext &C,
12039d628a0SDimitry Andric                     CoverageSourceInfo *CoverageInfo = nullptr)
12195ec533aSDimitry Andric         : Diags(Diags), Action(Action), HeaderSearchOpts(HeaderSearchOpts),
12295ec533aSDimitry Andric           CodeGenOpts(CodeGenOpts), TargetOpts(TargetOpts), LangOpts(LangOpts),
123e7145dcbSDimitry Andric           AsmOutStream(std::move(OS)), Context(nullptr),
12444290647SDimitry Andric           LLVMIRGeneration("irgen", "LLVM IR Generation Time"),
12544290647SDimitry Andric           LLVMIRGenerationRefCount(0),
1263dac3a9bSDimitry Andric           Gen(CreateLLVMCodeGen(Diags, InFile, HeaderSearchOpts, PPOpts,
12720e90f04SDimitry Andric                                 CodeGenOpts, C, CoverageInfo)),
12820e90f04SDimitry Andric           LinkModules(std::move(LinkModules)) {
1294ba319b5SDimitry Andric       FrontendTimesIsEnabled = TimePasses;
130ffd1746dSEd Schouten       llvm::TimePassesIsEnabled = TimePasses;
131ffd1746dSEd Schouten     }
getModule() const132e7145dcbSDimitry Andric     llvm::Module *getModule() const { return Gen->GetModule(); }
takeModule()133e7145dcbSDimitry Andric     std::unique_ptr<llvm::Module> takeModule() {
134e7145dcbSDimitry Andric       return std::unique_ptr<llvm::Module>(Gen->ReleaseModule());
135e7145dcbSDimitry Andric     }
13620e90f04SDimitry Andric 
getCodeGenerator()13720e90f04SDimitry Andric     CodeGenerator *getCodeGenerator() { return Gen.get(); }
138dff0c46cSDimitry Andric 
HandleCXXStaticMemberVarInstantiation(VarDecl * VD)13959d1ed5bSDimitry Andric     void HandleCXXStaticMemberVarInstantiation(VarDecl *VD) override {
140dff0c46cSDimitry Andric       Gen->HandleCXXStaticMemberVarInstantiation(VD);
141dff0c46cSDimitry Andric     }
142ffd1746dSEd Schouten 
Initialize(ASTContext & Ctx)14359d1ed5bSDimitry Andric     void Initialize(ASTContext &Ctx) override {
1440623d748SDimitry Andric       assert(!Context && "initialized multiple times");
14533956c43SDimitry Andric 
146ffd1746dSEd Schouten       Context = &Ctx;
147ffd1746dSEd Schouten 
1484ba319b5SDimitry Andric       if (FrontendTimesIsEnabled)
149ffd1746dSEd Schouten         LLVMIRGeneration.startTimer();
150ffd1746dSEd Schouten 
151ffd1746dSEd Schouten       Gen->Initialize(Ctx);
152ffd1746dSEd Schouten 
1534ba319b5SDimitry Andric       if (FrontendTimesIsEnabled)
154ffd1746dSEd Schouten         LLVMIRGeneration.stopTimer();
155ffd1746dSEd Schouten     }
156ffd1746dSEd Schouten 
HandleTopLevelDecl(DeclGroupRef D)15759d1ed5bSDimitry Andric     bool HandleTopLevelDecl(DeclGroupRef D) override {
158ffd1746dSEd Schouten       PrettyStackTraceDecl CrashInfo(*D.begin(), SourceLocation(),
159ffd1746dSEd Schouten                                      Context->getSourceManager(),
160ffd1746dSEd Schouten                                      "LLVM IR generation of declaration");
161ffd1746dSEd Schouten 
16244290647SDimitry Andric       // Recurse.
1634ba319b5SDimitry Andric       if (FrontendTimesIsEnabled) {
16444290647SDimitry Andric         LLVMIRGenerationRefCount += 1;
16544290647SDimitry Andric         if (LLVMIRGenerationRefCount == 1)
166ffd1746dSEd Schouten           LLVMIRGeneration.startTimer();
16744290647SDimitry Andric       }
168ffd1746dSEd Schouten 
169ffd1746dSEd Schouten       Gen->HandleTopLevelDecl(D);
170ffd1746dSEd Schouten 
1714ba319b5SDimitry Andric       if (FrontendTimesIsEnabled) {
17244290647SDimitry Andric         LLVMIRGenerationRefCount -= 1;
17344290647SDimitry Andric         if (LLVMIRGenerationRefCount == 0)
174ffd1746dSEd Schouten           LLVMIRGeneration.stopTimer();
17544290647SDimitry Andric       }
176dff0c46cSDimitry Andric 
177dff0c46cSDimitry Andric       return true;
178ffd1746dSEd Schouten     }
179ffd1746dSEd Schouten 
HandleInlineFunctionDefinition(FunctionDecl * D)180e7145dcbSDimitry Andric     void HandleInlineFunctionDefinition(FunctionDecl *D) override {
18159d1ed5bSDimitry Andric       PrettyStackTraceDecl CrashInfo(D, SourceLocation(),
18259d1ed5bSDimitry Andric                                      Context->getSourceManager(),
183e7145dcbSDimitry Andric                                      "LLVM IR generation of inline function");
1844ba319b5SDimitry Andric       if (FrontendTimesIsEnabled)
18559d1ed5bSDimitry Andric         LLVMIRGeneration.startTimer();
18659d1ed5bSDimitry Andric 
187e7145dcbSDimitry Andric       Gen->HandleInlineFunctionDefinition(D);
18859d1ed5bSDimitry Andric 
1894ba319b5SDimitry Andric       if (FrontendTimesIsEnabled)
19059d1ed5bSDimitry Andric         LLVMIRGeneration.stopTimer();
19159d1ed5bSDimitry Andric     }
19259d1ed5bSDimitry Andric 
HandleInterestingDecl(DeclGroupRef D)19344290647SDimitry Andric     void HandleInterestingDecl(DeclGroupRef D) override {
19444290647SDimitry Andric       // Ignore interesting decls from the AST reader after IRGen is finished.
19544290647SDimitry Andric       if (!IRGenFinished)
19644290647SDimitry Andric         HandleTopLevelDecl(D);
19744290647SDimitry Andric     }
19844290647SDimitry Andric 
19920e90f04SDimitry Andric     // Links each entry in LinkModules into our module.  Returns true on error.
LinkInModules()20020e90f04SDimitry Andric     bool LinkInModules() {
20120e90f04SDimitry Andric       for (auto &LM : LinkModules) {
20220e90f04SDimitry Andric         if (LM.PropagateAttrs)
20320e90f04SDimitry Andric           for (Function &F : *LM.Module)
20420e90f04SDimitry Andric             Gen->CGM().AddDefaultFnAttrs(F);
20520e90f04SDimitry Andric 
20620e90f04SDimitry Andric         CurLinkModule = LM.Module.get();
20720e90f04SDimitry Andric 
20820e90f04SDimitry Andric         bool Err;
20920e90f04SDimitry Andric         if (LM.Internalize) {
21020e90f04SDimitry Andric           Err = Linker::linkModules(
21120e90f04SDimitry Andric               *getModule(), std::move(LM.Module), LM.LinkFlags,
21220e90f04SDimitry Andric               [](llvm::Module &M, const llvm::StringSet<> &GVS) {
21320e90f04SDimitry Andric                 internalizeModule(M, [&GVS](const llvm::GlobalValue &GV) {
21420e90f04SDimitry Andric                   return !GV.hasName() || (GVS.count(GV.getName()) == 0);
21520e90f04SDimitry Andric                 });
21620e90f04SDimitry Andric               });
21720e90f04SDimitry Andric         } else {
21820e90f04SDimitry Andric           Err = Linker::linkModules(*getModule(), std::move(LM.Module),
21920e90f04SDimitry Andric                                     LM.LinkFlags);
22020e90f04SDimitry Andric         }
22120e90f04SDimitry Andric 
22220e90f04SDimitry Andric         if (Err)
22320e90f04SDimitry Andric           return true;
22420e90f04SDimitry Andric       }
22520e90f04SDimitry Andric       return false; // success
22620e90f04SDimitry Andric     }
22720e90f04SDimitry Andric 
HandleTranslationUnit(ASTContext & C)22859d1ed5bSDimitry Andric     void HandleTranslationUnit(ASTContext &C) override {
229ffd1746dSEd Schouten       {
230ffd1746dSEd Schouten         PrettyStackTraceString CrashInfo("Per-file LLVM IR generation");
2314ba319b5SDimitry Andric         if (FrontendTimesIsEnabled) {
23244290647SDimitry Andric           LLVMIRGenerationRefCount += 1;
23344290647SDimitry Andric           if (LLVMIRGenerationRefCount == 1)
234ffd1746dSEd Schouten             LLVMIRGeneration.startTimer();
23544290647SDimitry Andric         }
236ffd1746dSEd Schouten 
237ffd1746dSEd Schouten         Gen->HandleTranslationUnit(C);
238ffd1746dSEd Schouten 
2394ba319b5SDimitry Andric         if (FrontendTimesIsEnabled) {
24044290647SDimitry Andric           LLVMIRGenerationRefCount -= 1;
24144290647SDimitry Andric           if (LLVMIRGenerationRefCount == 0)
242ffd1746dSEd Schouten             LLVMIRGeneration.stopTimer();
243ffd1746dSEd Schouten         }
244ffd1746dSEd Schouten 
24544290647SDimitry Andric         IRGenFinished = true;
24644290647SDimitry Andric       }
24744290647SDimitry Andric 
248ffd1746dSEd Schouten       // Silently ignore if we weren't initialized for some reason.
249e7145dcbSDimitry Andric       if (!getModule())
250ffd1746dSEd Schouten         return;
251ffd1746dSEd Schouten 
252ffd1746dSEd Schouten       // Install an inline asm handler so that diagnostics get printed through
253ffd1746dSEd Schouten       // our diagnostics hooks.
254e7145dcbSDimitry Andric       LLVMContext &Ctx = getModule()->getContext();
2552754fe60SDimitry Andric       LLVMContext::InlineAsmDiagHandlerTy OldHandler =
2562754fe60SDimitry Andric         Ctx.getInlineAsmDiagnosticHandler();
257ffd1746dSEd Schouten       void *OldContext = Ctx.getInlineAsmDiagnosticContext();
2582754fe60SDimitry Andric       Ctx.setInlineAsmDiagnosticHandler(InlineAsmDiagHandler, this);
259ffd1746dSEd Schouten 
2609a199699SDimitry Andric       std::unique_ptr<DiagnosticHandler> OldDiagnosticHandler =
26159d1ed5bSDimitry Andric           Ctx.getDiagnosticHandler();
2629a199699SDimitry Andric       Ctx.setDiagnosticHandler(llvm::make_unique<ClangDiagnosticHandler>(
2639a199699SDimitry Andric         CodeGenOpts, this));
264a580b014SDimitry Andric       Ctx.setDiagnosticsHotnessRequested(CodeGenOpts.DiagnosticsWithHotness);
265a580b014SDimitry Andric       if (CodeGenOpts.DiagnosticsHotnessThreshold != 0)
266a580b014SDimitry Andric         Ctx.setDiagnosticsHotnessThreshold(
267a580b014SDimitry Andric             CodeGenOpts.DiagnosticsHotnessThreshold);
26844290647SDimitry Andric 
2699a199699SDimitry Andric       std::unique_ptr<llvm::ToolOutputFile> OptRecordFile;
27044290647SDimitry Andric       if (!CodeGenOpts.OptRecordFile.empty()) {
27144290647SDimitry Andric         std::error_code EC;
2729a199699SDimitry Andric         OptRecordFile = llvm::make_unique<llvm::ToolOutputFile>(
2739a199699SDimitry Andric             CodeGenOpts.OptRecordFile, EC, sys::fs::F_None);
27444290647SDimitry Andric         if (EC) {
27544290647SDimitry Andric           Diags.Report(diag::err_cannot_open_file) <<
27644290647SDimitry Andric             CodeGenOpts.OptRecordFile << EC.message();
27744290647SDimitry Andric           return;
27844290647SDimitry Andric         }
27944290647SDimitry Andric 
28044290647SDimitry Andric         Ctx.setDiagnosticsOutputFile(
28144290647SDimitry Andric             llvm::make_unique<yaml::Output>(OptRecordFile->os()));
28244290647SDimitry Andric 
28344290647SDimitry Andric         if (CodeGenOpts.getProfileUse() != CodeGenOptions::ProfileNone)
284a580b014SDimitry Andric           Ctx.setDiagnosticsHotnessRequested(true);
28544290647SDimitry Andric       }
28659d1ed5bSDimitry Andric 
28720e90f04SDimitry Andric       // Link each LinkModule into our module.
28820e90f04SDimitry Andric       if (LinkInModules())
2890623d748SDimitry Andric         return;
2900623d748SDimitry Andric 
291e7145dcbSDimitry Andric       EmbedBitcode(getModule(), CodeGenOpts, llvm::MemoryBufferRef());
292e7145dcbSDimitry Andric 
29395ec533aSDimitry Andric       EmitBackendOutput(Diags, HeaderSearchOpts, CodeGenOpts, TargetOpts,
29495ec533aSDimitry Andric                         LangOpts, C.getTargetInfo().getDataLayout(),
295e7145dcbSDimitry Andric                         getModule(), Action, std::move(AsmOutStream));
296ffd1746dSEd Schouten 
297ffd1746dSEd Schouten       Ctx.setInlineAsmDiagnosticHandler(OldHandler, OldContext);
29859d1ed5bSDimitry Andric 
2999a199699SDimitry Andric       Ctx.setDiagnosticHandler(std::move(OldDiagnosticHandler));
30044290647SDimitry Andric 
30144290647SDimitry Andric       if (OptRecordFile)
30244290647SDimitry Andric         OptRecordFile->keep();
303ffd1746dSEd Schouten     }
304ffd1746dSEd Schouten 
HandleTagDeclDefinition(TagDecl * D)30559d1ed5bSDimitry Andric     void HandleTagDeclDefinition(TagDecl *D) override {
306ffd1746dSEd Schouten       PrettyStackTraceDecl CrashInfo(D, SourceLocation(),
307ffd1746dSEd Schouten                                      Context->getSourceManager(),
308ffd1746dSEd Schouten                                      "LLVM IR generation of declaration");
309ffd1746dSEd Schouten       Gen->HandleTagDeclDefinition(D);
310ffd1746dSEd Schouten     }
311ffd1746dSEd Schouten 
HandleTagDeclRequiredDefinition(const TagDecl * D)31259d1ed5bSDimitry Andric     void HandleTagDeclRequiredDefinition(const TagDecl *D) override {
313f785676fSDimitry Andric       Gen->HandleTagDeclRequiredDefinition(D);
314f785676fSDimitry Andric     }
315f785676fSDimitry Andric 
CompleteTentativeDefinition(VarDecl * D)31659d1ed5bSDimitry Andric     void CompleteTentativeDefinition(VarDecl *D) override {
317ffd1746dSEd Schouten       Gen->CompleteTentativeDefinition(D);
318ffd1746dSEd Schouten     }
319ffd1746dSEd Schouten 
AssignInheritanceModel(CXXRecordDecl * RD)320e7145dcbSDimitry Andric     void AssignInheritanceModel(CXXRecordDecl *RD) override {
321e7145dcbSDimitry Andric       Gen->AssignInheritanceModel(RD);
322e7145dcbSDimitry Andric     }
323e7145dcbSDimitry Andric 
HandleVTable(CXXRecordDecl * RD)32433956c43SDimitry Andric     void HandleVTable(CXXRecordDecl *RD) override {
32533956c43SDimitry Andric       Gen->HandleVTable(RD);
326ffd1746dSEd Schouten     }
327ffd1746dSEd Schouten 
InlineAsmDiagHandler(const llvm::SMDiagnostic & SM,void * Context,unsigned LocCookie)328ffd1746dSEd Schouten     static void InlineAsmDiagHandler(const llvm::SMDiagnostic &SM,void *Context,
329ffd1746dSEd Schouten                                      unsigned LocCookie) {
330ffd1746dSEd Schouten       SourceLocation Loc = SourceLocation::getFromRawEncoding(LocCookie);
331ffd1746dSEd Schouten       ((BackendConsumer*)Context)->InlineAsmDiagHandler2(SM, Loc);
332ffd1746dSEd Schouten     }
333ffd1746dSEd Schouten 
334e7145dcbSDimitry Andric     /// Get the best possible source location to represent a diagnostic that
335e7145dcbSDimitry Andric     /// may have associated debug info.
336e7145dcbSDimitry Andric     const FullSourceLoc
33720e90f04SDimitry Andric     getBestLocationFromDebugLoc(const llvm::DiagnosticInfoWithLocationBase &D,
338e7145dcbSDimitry Andric                                 bool &BadDebugInfo, StringRef &Filename,
339e7145dcbSDimitry Andric                                 unsigned &Line, unsigned &Column) const;
340e7145dcbSDimitry Andric 
341ffd1746dSEd Schouten     void InlineAsmDiagHandler2(const llvm::SMDiagnostic &,
342ffd1746dSEd Schouten                                SourceLocation LocCookie);
34359d1ed5bSDimitry Andric 
34459d1ed5bSDimitry Andric     void DiagnosticHandlerImpl(const llvm::DiagnosticInfo &DI);
3454ba319b5SDimitry Andric     /// Specialized handler for InlineAsm diagnostic.
34659d1ed5bSDimitry Andric     /// \return True if the diagnostic has been successfully reported, false
34759d1ed5bSDimitry Andric     /// otherwise.
34859d1ed5bSDimitry Andric     bool InlineAsmDiagHandler(const llvm::DiagnosticInfoInlineAsm &D);
3494ba319b5SDimitry Andric     /// Specialized handler for StackSize diagnostic.
35059d1ed5bSDimitry Andric     /// \return True if the diagnostic has been successfully reported, false
35159d1ed5bSDimitry Andric     /// otherwise.
35259d1ed5bSDimitry Andric     bool StackSizeDiagHandler(const llvm::DiagnosticInfoStackSize &D);
3534ba319b5SDimitry Andric     /// Specialized handler for unsupported backend feature diagnostic.
354e7145dcbSDimitry Andric     void UnsupportedDiagHandler(const llvm::DiagnosticInfoUnsupported &D);
3554ba319b5SDimitry Andric     /// Specialized handlers for optimization remarks.
35659d1ed5bSDimitry Andric     /// Note that these handlers only accept remarks and they always handle
35759d1ed5bSDimitry Andric     /// them.
35859d1ed5bSDimitry Andric     void EmitOptimizationMessage(const llvm::DiagnosticInfoOptimizationBase &D,
35959d1ed5bSDimitry Andric                                  unsigned DiagID);
36020e90f04SDimitry Andric     void
36120e90f04SDimitry Andric     OptimizationRemarkHandler(const llvm::DiagnosticInfoOptimizationBase &D);
36259d1ed5bSDimitry Andric     void OptimizationRemarkHandler(
36344290647SDimitry Andric         const llvm::OptimizationRemarkAnalysisFPCommute &D);
36459d1ed5bSDimitry Andric     void OptimizationRemarkHandler(
36544290647SDimitry Andric         const llvm::OptimizationRemarkAnalysisAliasing &D);
36659d1ed5bSDimitry Andric     void OptimizationFailureHandler(
36759d1ed5bSDimitry Andric         const llvm::DiagnosticInfoOptimizationFailure &D);
368ffd1746dSEd Schouten   };
369dff0c46cSDimitry Andric 
anchor()370dff0c46cSDimitry Andric   void BackendConsumer::anchor() {}
371ffd1746dSEd Schouten }
372ffd1746dSEd Schouten 
handleDiagnostics(const DiagnosticInfo & DI)3739a199699SDimitry Andric bool ClangDiagnosticHandler::handleDiagnostics(const DiagnosticInfo &DI) {
3749a199699SDimitry Andric   BackendCon->DiagnosticHandlerImpl(DI);
3759a199699SDimitry Andric   return true;
3769a199699SDimitry Andric }
3779a199699SDimitry Andric 
378ffd1746dSEd Schouten /// ConvertBackendLocation - Convert a location in a temporary llvm::SourceMgr
379ffd1746dSEd Schouten /// buffer to be a valid FullSourceLoc.
ConvertBackendLocation(const llvm::SMDiagnostic & D,SourceManager & CSM)380ffd1746dSEd Schouten static FullSourceLoc ConvertBackendLocation(const llvm::SMDiagnostic &D,
381ffd1746dSEd Schouten                                             SourceManager &CSM) {
382ffd1746dSEd Schouten   // Get both the clang and llvm source managers.  The location is relative to
383ffd1746dSEd Schouten   // a memory buffer that the LLVM Source Manager is handling, we need to add
384ffd1746dSEd Schouten   // a copy to the Clang source manager.
385ffd1746dSEd Schouten   const llvm::SourceMgr &LSM = *D.getSourceMgr();
386ffd1746dSEd Schouten 
387ffd1746dSEd Schouten   // We need to copy the underlying LLVM memory buffer because llvm::SourceMgr
388ffd1746dSEd Schouten   // already owns its one and clang::SourceManager wants to own its one.
389ffd1746dSEd Schouten   const MemoryBuffer *LBuf =
390ffd1746dSEd Schouten   LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(D.getLoc()));
391ffd1746dSEd Schouten 
392ffd1746dSEd Schouten   // Create the copy and transfer ownership to clang::SourceManager.
39359d1ed5bSDimitry Andric   // TODO: Avoid copying files into memory.
39439d628a0SDimitry Andric   std::unique_ptr<llvm::MemoryBuffer> CBuf =
395ffd1746dSEd Schouten       llvm::MemoryBuffer::getMemBufferCopy(LBuf->getBuffer(),
396ffd1746dSEd Schouten                                            LBuf->getBufferIdentifier());
39759d1ed5bSDimitry Andric   // FIXME: Keep a file ID map instead of creating new IDs for each location.
39839d628a0SDimitry Andric   FileID FID = CSM.createFileID(std::move(CBuf));
399ffd1746dSEd Schouten 
400ffd1746dSEd Schouten   // Translate the offset into the file.
401ffd1746dSEd Schouten   unsigned Offset = D.getLoc().getPointer() - LBuf->getBufferStart();
402ffd1746dSEd Schouten   SourceLocation NewLoc =
4036122f3e6SDimitry Andric   CSM.getLocForStartOfFile(FID).getLocWithOffset(Offset);
404ffd1746dSEd Schouten   return FullSourceLoc(NewLoc, CSM);
405ffd1746dSEd Schouten }
406ffd1746dSEd Schouten 
407ffd1746dSEd Schouten 
408ffd1746dSEd Schouten /// InlineAsmDiagHandler2 - This function is invoked when the backend hits an
409ffd1746dSEd Schouten /// error parsing inline asm.  The SMDiagnostic indicates the error relative to
410ffd1746dSEd Schouten /// the temporary memory buffer that the inline asm parser has set up.
InlineAsmDiagHandler2(const llvm::SMDiagnostic & D,SourceLocation LocCookie)411ffd1746dSEd Schouten void BackendConsumer::InlineAsmDiagHandler2(const llvm::SMDiagnostic &D,
412ffd1746dSEd Schouten                                             SourceLocation LocCookie) {
413ffd1746dSEd Schouten   // There are a couple of different kinds of errors we could get here.  First,
414ffd1746dSEd Schouten   // we re-format the SMDiagnostic in terms of a clang diagnostic.
415ffd1746dSEd Schouten 
416ffd1746dSEd Schouten   // Strip "error: " off the start of the message string.
4176122f3e6SDimitry Andric   StringRef Message = D.getMessage();
418ffd1746dSEd Schouten   if (Message.startswith("error: "))
419ffd1746dSEd Schouten     Message = Message.substr(7);
420ffd1746dSEd Schouten 
421ffd1746dSEd Schouten   // If the SMDiagnostic has an inline asm source location, translate it.
422ffd1746dSEd Schouten   FullSourceLoc Loc;
423ffd1746dSEd Schouten   if (D.getLoc() != SMLoc())
424ffd1746dSEd Schouten     Loc = ConvertBackendLocation(D, Context->getSourceManager());
425ffd1746dSEd Schouten 
42659d1ed5bSDimitry Andric   unsigned DiagID;
42759d1ed5bSDimitry Andric   switch (D.getKind()) {
42859d1ed5bSDimitry Andric   case llvm::SourceMgr::DK_Error:
42959d1ed5bSDimitry Andric     DiagID = diag::err_fe_inline_asm;
43059d1ed5bSDimitry Andric     break;
43159d1ed5bSDimitry Andric   case llvm::SourceMgr::DK_Warning:
43259d1ed5bSDimitry Andric     DiagID = diag::warn_fe_inline_asm;
43359d1ed5bSDimitry Andric     break;
43459d1ed5bSDimitry Andric   case llvm::SourceMgr::DK_Note:
43559d1ed5bSDimitry Andric     DiagID = diag::note_fe_inline_asm;
43659d1ed5bSDimitry Andric     break;
4379a199699SDimitry Andric   case llvm::SourceMgr::DK_Remark:
4389a199699SDimitry Andric     llvm_unreachable("remarks unexpected");
43959d1ed5bSDimitry Andric   }
440ffd1746dSEd Schouten   // If this problem has clang-level source location information, report the
44159d1ed5bSDimitry Andric   // issue in the source with a note showing the instantiated
442ffd1746dSEd Schouten   // code.
443ffd1746dSEd Schouten   if (LocCookie.isValid()) {
44459d1ed5bSDimitry Andric     Diags.Report(LocCookie, DiagID).AddString(Message);
445ffd1746dSEd Schouten 
446dff0c46cSDimitry Andric     if (D.getLoc().isValid()) {
447dff0c46cSDimitry Andric       DiagnosticBuilder B = Diags.Report(Loc, diag::note_fe_inline_asm_here);
448dff0c46cSDimitry Andric       // Convert the SMDiagnostic ranges into SourceRange and attach them
449dff0c46cSDimitry Andric       // to the diagnostic.
4500623d748SDimitry Andric       for (const std::pair<unsigned, unsigned> &Range : D.getRanges()) {
451dff0c46cSDimitry Andric         unsigned Column = D.getColumnNo();
452dff0c46cSDimitry Andric         B << SourceRange(Loc.getLocWithOffset(Range.first - Column),
453dff0c46cSDimitry Andric                          Loc.getLocWithOffset(Range.second - Column));
454dff0c46cSDimitry Andric       }
455dff0c46cSDimitry Andric     }
456ffd1746dSEd Schouten     return;
457ffd1746dSEd Schouten   }
458ffd1746dSEd Schouten 
45959d1ed5bSDimitry Andric   // Otherwise, report the backend issue as occurring in the generated .s file.
46059d1ed5bSDimitry Andric   // If Loc is invalid, we still need to report the issue, it just gets no
461ffd1746dSEd Schouten   // location info.
46259d1ed5bSDimitry Andric   Diags.Report(Loc, DiagID).AddString(Message);
463ffd1746dSEd Schouten }
464ffd1746dSEd Schouten 
46559d1ed5bSDimitry Andric #define ComputeDiagID(Severity, GroupName, DiagID)                             \
46659d1ed5bSDimitry Andric   do {                                                                         \
46759d1ed5bSDimitry Andric     switch (Severity) {                                                        \
46859d1ed5bSDimitry Andric     case llvm::DS_Error:                                                       \
46959d1ed5bSDimitry Andric       DiagID = diag::err_fe_##GroupName;                                       \
47059d1ed5bSDimitry Andric       break;                                                                   \
47159d1ed5bSDimitry Andric     case llvm::DS_Warning:                                                     \
47259d1ed5bSDimitry Andric       DiagID = diag::warn_fe_##GroupName;                                      \
47359d1ed5bSDimitry Andric       break;                                                                   \
47459d1ed5bSDimitry Andric     case llvm::DS_Remark:                                                      \
47559d1ed5bSDimitry Andric       llvm_unreachable("'remark' severity not expected");                      \
47659d1ed5bSDimitry Andric       break;                                                                   \
47759d1ed5bSDimitry Andric     case llvm::DS_Note:                                                        \
47859d1ed5bSDimitry Andric       DiagID = diag::note_fe_##GroupName;                                      \
47959d1ed5bSDimitry Andric       break;                                                                   \
48059d1ed5bSDimitry Andric     }                                                                          \
48159d1ed5bSDimitry Andric   } while (false)
48259d1ed5bSDimitry Andric 
48359d1ed5bSDimitry Andric #define ComputeDiagRemarkID(Severity, GroupName, DiagID)                       \
48459d1ed5bSDimitry Andric   do {                                                                         \
48559d1ed5bSDimitry Andric     switch (Severity) {                                                        \
48659d1ed5bSDimitry Andric     case llvm::DS_Error:                                                       \
48759d1ed5bSDimitry Andric       DiagID = diag::err_fe_##GroupName;                                       \
48859d1ed5bSDimitry Andric       break;                                                                   \
48959d1ed5bSDimitry Andric     case llvm::DS_Warning:                                                     \
49059d1ed5bSDimitry Andric       DiagID = diag::warn_fe_##GroupName;                                      \
49159d1ed5bSDimitry Andric       break;                                                                   \
49259d1ed5bSDimitry Andric     case llvm::DS_Remark:                                                      \
49359d1ed5bSDimitry Andric       DiagID = diag::remark_fe_##GroupName;                                    \
49459d1ed5bSDimitry Andric       break;                                                                   \
49559d1ed5bSDimitry Andric     case llvm::DS_Note:                                                        \
49659d1ed5bSDimitry Andric       DiagID = diag::note_fe_##GroupName;                                      \
49759d1ed5bSDimitry Andric       break;                                                                   \
49859d1ed5bSDimitry Andric     }                                                                          \
49959d1ed5bSDimitry Andric   } while (false)
50059d1ed5bSDimitry Andric 
50159d1ed5bSDimitry Andric bool
InlineAsmDiagHandler(const llvm::DiagnosticInfoInlineAsm & D)50259d1ed5bSDimitry Andric BackendConsumer::InlineAsmDiagHandler(const llvm::DiagnosticInfoInlineAsm &D) {
50359d1ed5bSDimitry Andric   unsigned DiagID;
50459d1ed5bSDimitry Andric   ComputeDiagID(D.getSeverity(), inline_asm, DiagID);
50559d1ed5bSDimitry Andric   std::string Message = D.getMsgStr().str();
50659d1ed5bSDimitry Andric 
50759d1ed5bSDimitry Andric   // If this problem has clang-level source location information, report the
50859d1ed5bSDimitry Andric   // issue as being a problem in the source with a note showing the instantiated
50959d1ed5bSDimitry Andric   // code.
51059d1ed5bSDimitry Andric   SourceLocation LocCookie =
51159d1ed5bSDimitry Andric       SourceLocation::getFromRawEncoding(D.getLocCookie());
51259d1ed5bSDimitry Andric   if (LocCookie.isValid())
51359d1ed5bSDimitry Andric     Diags.Report(LocCookie, DiagID).AddString(Message);
51459d1ed5bSDimitry Andric   else {
51559d1ed5bSDimitry Andric     // Otherwise, report the backend diagnostic as occurring in the generated
51659d1ed5bSDimitry Andric     // .s file.
51759d1ed5bSDimitry Andric     // If Loc is invalid, we still need to report the diagnostic, it just gets
51859d1ed5bSDimitry Andric     // no location info.
51959d1ed5bSDimitry Andric     FullSourceLoc Loc;
52059d1ed5bSDimitry Andric     Diags.Report(Loc, DiagID).AddString(Message);
52159d1ed5bSDimitry Andric   }
52259d1ed5bSDimitry Andric   // We handled all the possible severities.
52359d1ed5bSDimitry Andric   return true;
52459d1ed5bSDimitry Andric }
52559d1ed5bSDimitry Andric 
52659d1ed5bSDimitry Andric bool
StackSizeDiagHandler(const llvm::DiagnosticInfoStackSize & D)52759d1ed5bSDimitry Andric BackendConsumer::StackSizeDiagHandler(const llvm::DiagnosticInfoStackSize &D) {
52859d1ed5bSDimitry Andric   if (D.getSeverity() != llvm::DS_Warning)
52959d1ed5bSDimitry Andric     // For now, the only support we have for StackSize diagnostic is warning.
53059d1ed5bSDimitry Andric     // We do not know how to format other severities.
53159d1ed5bSDimitry Andric     return false;
53259d1ed5bSDimitry Andric 
53359d1ed5bSDimitry Andric   if (const Decl *ND = Gen->GetDeclForMangledName(D.getFunction().getName())) {
534e7145dcbSDimitry Andric     // FIXME: Shouldn't need to truncate to uint32_t
53559d1ed5bSDimitry Andric     Diags.Report(ND->getASTContext().getFullLoc(ND->getLocation()),
53659d1ed5bSDimitry Andric                  diag::warn_fe_frame_larger_than)
537e7145dcbSDimitry Andric       << static_cast<uint32_t>(D.getStackSize()) << Decl::castToDeclContext(ND);
53859d1ed5bSDimitry Andric     return true;
53959d1ed5bSDimitry Andric   }
54059d1ed5bSDimitry Andric 
54159d1ed5bSDimitry Andric   return false;
54259d1ed5bSDimitry Andric }
54359d1ed5bSDimitry Andric 
getBestLocationFromDebugLoc(const llvm::DiagnosticInfoWithLocationBase & D,bool & BadDebugInfo,StringRef & Filename,unsigned & Line,unsigned & Column) const544e7145dcbSDimitry Andric const FullSourceLoc BackendConsumer::getBestLocationFromDebugLoc(
54520e90f04SDimitry Andric     const llvm::DiagnosticInfoWithLocationBase &D, bool &BadDebugInfo,
54620e90f04SDimitry Andric     StringRef &Filename, unsigned &Line, unsigned &Column) const {
54759d1ed5bSDimitry Andric   SourceManager &SourceMgr = Context->getSourceManager();
54859d1ed5bSDimitry Andric   FileManager &FileMgr = SourceMgr.getFileManager();
54959d1ed5bSDimitry Andric   SourceLocation DILoc;
55033956c43SDimitry Andric 
55133956c43SDimitry Andric   if (D.isLocationAvailable()) {
552*b5893f02SDimitry Andric     D.getLocation(Filename, Line, Column);
553*b5893f02SDimitry Andric     if (Line > 0) {
55459d1ed5bSDimitry Andric       const FileEntry *FE = FileMgr.getFile(Filename);
555*b5893f02SDimitry Andric       if (!FE)
556*b5893f02SDimitry Andric         FE = FileMgr.getFile(D.getAbsolutePath());
557*b5893f02SDimitry Andric       if (FE) {
55859d1ed5bSDimitry Andric         // If -gcolumn-info was not used, Column will be 0. This upsets the
55959d1ed5bSDimitry Andric         // source manager, so pass 1 if Column is not set.
56059d1ed5bSDimitry Andric         DILoc = SourceMgr.translateFileLineCol(FE, Line, Column ? Column : 1);
56159d1ed5bSDimitry Andric       }
562*b5893f02SDimitry Andric     }
563e7145dcbSDimitry Andric     BadDebugInfo = DILoc.isInvalid();
56433956c43SDimitry Andric   }
56559d1ed5bSDimitry Andric 
56659d1ed5bSDimitry Andric   // If a location isn't available, try to approximate it using the associated
56759d1ed5bSDimitry Andric   // function definition. We use the definition's right brace to differentiate
56859d1ed5bSDimitry Andric   // from diagnostics that genuinely relate to the function itself.
56959d1ed5bSDimitry Andric   FullSourceLoc Loc(DILoc, SourceMgr);
57059d1ed5bSDimitry Andric   if (Loc.isInvalid())
57159d1ed5bSDimitry Andric     if (const Decl *FD = Gen->GetDeclForMangledName(D.getFunction().getName()))
572e7145dcbSDimitry Andric       Loc = FD->getASTContext().getFullLoc(FD->getLocation());
57359d1ed5bSDimitry Andric 
57433956c43SDimitry Andric   if (DILoc.isInvalid() && D.isLocationAvailable())
57559d1ed5bSDimitry Andric     // If we were not able to translate the file:line:col information
57659d1ed5bSDimitry Andric     // back to a SourceLocation, at least emit a note stating that
57759d1ed5bSDimitry Andric     // we could not translate this location. This can happen in the
57859d1ed5bSDimitry Andric     // case of #line directives.
579e7145dcbSDimitry Andric     Diags.Report(Loc, diag::note_fe_backend_invalid_loc)
580e7145dcbSDimitry Andric         << Filename << Line << Column;
581e7145dcbSDimitry Andric 
582e7145dcbSDimitry Andric   return Loc;
583e7145dcbSDimitry Andric }
584e7145dcbSDimitry Andric 
UnsupportedDiagHandler(const llvm::DiagnosticInfoUnsupported & D)585e7145dcbSDimitry Andric void BackendConsumer::UnsupportedDiagHandler(
586e7145dcbSDimitry Andric     const llvm::DiagnosticInfoUnsupported &D) {
587e7145dcbSDimitry Andric   // We only support errors.
588e7145dcbSDimitry Andric   assert(D.getSeverity() == llvm::DS_Error);
589e7145dcbSDimitry Andric 
590e7145dcbSDimitry Andric   StringRef Filename;
591e7145dcbSDimitry Andric   unsigned Line, Column;
5925517e702SDimitry Andric   bool BadDebugInfo = false;
5935517e702SDimitry Andric   FullSourceLoc Loc =
5945517e702SDimitry Andric       getBestLocationFromDebugLoc(D, BadDebugInfo, Filename, Line, Column);
595e7145dcbSDimitry Andric 
596e7145dcbSDimitry Andric   Diags.Report(Loc, diag::err_fe_backend_unsupported) << D.getMessage().str();
597e7145dcbSDimitry Andric 
598e7145dcbSDimitry Andric   if (BadDebugInfo)
599e7145dcbSDimitry Andric     // If we were not able to translate the file:line:col information
600e7145dcbSDimitry Andric     // back to a SourceLocation, at least emit a note stating that
601e7145dcbSDimitry Andric     // we could not translate this location. This can happen in the
602e7145dcbSDimitry Andric     // case of #line directives.
603e7145dcbSDimitry Andric     Diags.Report(Loc, diag::note_fe_backend_invalid_loc)
604e7145dcbSDimitry Andric         << Filename << Line << Column;
605e7145dcbSDimitry Andric }
606e7145dcbSDimitry Andric 
EmitOptimizationMessage(const llvm::DiagnosticInfoOptimizationBase & D,unsigned DiagID)607e7145dcbSDimitry Andric void BackendConsumer::EmitOptimizationMessage(
608e7145dcbSDimitry Andric     const llvm::DiagnosticInfoOptimizationBase &D, unsigned DiagID) {
609e7145dcbSDimitry Andric   // We only support warnings and remarks.
610e7145dcbSDimitry Andric   assert(D.getSeverity() == llvm::DS_Remark ||
611e7145dcbSDimitry Andric          D.getSeverity() == llvm::DS_Warning);
612e7145dcbSDimitry Andric 
613e7145dcbSDimitry Andric   StringRef Filename;
614e7145dcbSDimitry Andric   unsigned Line, Column;
615e7145dcbSDimitry Andric   bool BadDebugInfo = false;
6165517e702SDimitry Andric   FullSourceLoc Loc =
6175517e702SDimitry Andric       getBestLocationFromDebugLoc(D, BadDebugInfo, Filename, Line, Column);
618e7145dcbSDimitry Andric 
61944290647SDimitry Andric   std::string Msg;
62044290647SDimitry Andric   raw_string_ostream MsgStream(Msg);
62144290647SDimitry Andric   MsgStream << D.getMsg();
62244290647SDimitry Andric 
62344290647SDimitry Andric   if (D.getHotness())
62444290647SDimitry Andric     MsgStream << " (hotness: " << *D.getHotness() << ")";
62544290647SDimitry Andric 
626e7145dcbSDimitry Andric   Diags.Report(Loc, DiagID)
62744290647SDimitry Andric       << AddFlagValue(D.getPassName())
62844290647SDimitry Andric       << MsgStream.str();
629e7145dcbSDimitry Andric 
630e7145dcbSDimitry Andric   if (BadDebugInfo)
631e7145dcbSDimitry Andric     // If we were not able to translate the file:line:col information
632e7145dcbSDimitry Andric     // back to a SourceLocation, at least emit a note stating that
633e7145dcbSDimitry Andric     // we could not translate this location. This can happen in the
634e7145dcbSDimitry Andric     // case of #line directives.
635e7145dcbSDimitry Andric     Diags.Report(Loc, diag::note_fe_backend_invalid_loc)
63659d1ed5bSDimitry Andric         << Filename << Line << Column;
63759d1ed5bSDimitry Andric }
63859d1ed5bSDimitry Andric 
OptimizationRemarkHandler(const llvm::DiagnosticInfoOptimizationBase & D)63959d1ed5bSDimitry Andric void BackendConsumer::OptimizationRemarkHandler(
64020e90f04SDimitry Andric     const llvm::DiagnosticInfoOptimizationBase &D) {
6419a199699SDimitry Andric   // Without hotness information, don't show noisy remarks.
6429a199699SDimitry Andric   if (D.isVerbose() && !D.getHotness())
6439a199699SDimitry Andric     return;
6449a199699SDimitry Andric 
64520e90f04SDimitry Andric   if (D.isPassed()) {
64659d1ed5bSDimitry Andric     // Optimization remarks are active only if the -Rpass flag has a regular
64759d1ed5bSDimitry Andric     // expression that matches the name of the pass name in \p D.
64859d1ed5bSDimitry Andric     if (CodeGenOpts.OptimizationRemarkPattern &&
64959d1ed5bSDimitry Andric         CodeGenOpts.OptimizationRemarkPattern->match(D.getPassName()))
65059d1ed5bSDimitry Andric       EmitOptimizationMessage(D, diag::remark_fe_backend_optimization_remark);
65120e90f04SDimitry Andric   } else if (D.isMissed()) {
65259d1ed5bSDimitry Andric     // Missed optimization remarks are active only if the -Rpass-missed
65359d1ed5bSDimitry Andric     // flag has a regular expression that matches the name of the pass
65459d1ed5bSDimitry Andric     // name in \p D.
65559d1ed5bSDimitry Andric     if (CodeGenOpts.OptimizationRemarkMissedPattern &&
65659d1ed5bSDimitry Andric         CodeGenOpts.OptimizationRemarkMissedPattern->match(D.getPassName()))
65720e90f04SDimitry Andric       EmitOptimizationMessage(
65820e90f04SDimitry Andric           D, diag::remark_fe_backend_optimization_remark_missed);
65920e90f04SDimitry Andric   } else {
66020e90f04SDimitry Andric     assert(D.isAnalysis() && "Unknown remark type");
66159d1ed5bSDimitry Andric 
66220e90f04SDimitry Andric     bool ShouldAlwaysPrint = false;
66320e90f04SDimitry Andric     if (auto *ORA = dyn_cast<llvm::OptimizationRemarkAnalysis>(&D))
66420e90f04SDimitry Andric       ShouldAlwaysPrint = ORA->shouldAlwaysPrint();
6650623d748SDimitry Andric 
66620e90f04SDimitry Andric     if (ShouldAlwaysPrint ||
6670623d748SDimitry Andric         (CodeGenOpts.OptimizationRemarkAnalysisPattern &&
6680623d748SDimitry Andric          CodeGenOpts.OptimizationRemarkAnalysisPattern->match(D.getPassName())))
66959d1ed5bSDimitry Andric       EmitOptimizationMessage(
67059d1ed5bSDimitry Andric           D, diag::remark_fe_backend_optimization_remark_analysis);
67159d1ed5bSDimitry Andric   }
67220e90f04SDimitry Andric }
67359d1ed5bSDimitry Andric 
OptimizationRemarkHandler(const llvm::OptimizationRemarkAnalysisFPCommute & D)6740623d748SDimitry Andric void BackendConsumer::OptimizationRemarkHandler(
67544290647SDimitry Andric     const llvm::OptimizationRemarkAnalysisFPCommute &D) {
6760623d748SDimitry Andric   // Optimization analysis remarks are active if the pass name is set to
6770623d748SDimitry Andric   // llvm::DiagnosticInfo::AlwasyPrint or if the -Rpass-analysis flag has a
6780623d748SDimitry Andric   // regular expression that matches the name of the pass name in \p D.
6790623d748SDimitry Andric 
680e7145dcbSDimitry Andric   if (D.shouldAlwaysPrint() ||
6810623d748SDimitry Andric       (CodeGenOpts.OptimizationRemarkAnalysisPattern &&
6820623d748SDimitry Andric        CodeGenOpts.OptimizationRemarkAnalysisPattern->match(D.getPassName())))
6830623d748SDimitry Andric     EmitOptimizationMessage(
6840623d748SDimitry Andric         D, diag::remark_fe_backend_optimization_remark_analysis_fpcommute);
6850623d748SDimitry Andric }
6860623d748SDimitry Andric 
OptimizationRemarkHandler(const llvm::OptimizationRemarkAnalysisAliasing & D)6870623d748SDimitry Andric void BackendConsumer::OptimizationRemarkHandler(
68844290647SDimitry Andric     const llvm::OptimizationRemarkAnalysisAliasing &D) {
6890623d748SDimitry Andric   // Optimization analysis remarks are active if the pass name is set to
6900623d748SDimitry Andric   // llvm::DiagnosticInfo::AlwasyPrint or if the -Rpass-analysis flag has a
6910623d748SDimitry Andric   // regular expression that matches the name of the pass name in \p D.
6920623d748SDimitry Andric 
693e7145dcbSDimitry Andric   if (D.shouldAlwaysPrint() ||
6940623d748SDimitry Andric       (CodeGenOpts.OptimizationRemarkAnalysisPattern &&
6950623d748SDimitry Andric        CodeGenOpts.OptimizationRemarkAnalysisPattern->match(D.getPassName())))
6960623d748SDimitry Andric     EmitOptimizationMessage(
6970623d748SDimitry Andric         D, diag::remark_fe_backend_optimization_remark_analysis_aliasing);
6980623d748SDimitry Andric }
6990623d748SDimitry Andric 
OptimizationFailureHandler(const llvm::DiagnosticInfoOptimizationFailure & D)70059d1ed5bSDimitry Andric void BackendConsumer::OptimizationFailureHandler(
70159d1ed5bSDimitry Andric     const llvm::DiagnosticInfoOptimizationFailure &D) {
70259d1ed5bSDimitry Andric   EmitOptimizationMessage(D, diag::warn_fe_backend_optimization_failure);
70359d1ed5bSDimitry Andric }
70459d1ed5bSDimitry Andric 
7054ba319b5SDimitry Andric /// This function is invoked when the backend needs
70659d1ed5bSDimitry Andric /// to report something to the user.
DiagnosticHandlerImpl(const DiagnosticInfo & DI)70759d1ed5bSDimitry Andric void BackendConsumer::DiagnosticHandlerImpl(const DiagnosticInfo &DI) {
70859d1ed5bSDimitry Andric   unsigned DiagID = diag::err_fe_inline_asm;
70959d1ed5bSDimitry Andric   llvm::DiagnosticSeverity Severity = DI.getSeverity();
71059d1ed5bSDimitry Andric   // Get the diagnostic ID based.
71159d1ed5bSDimitry Andric   switch (DI.getKind()) {
71259d1ed5bSDimitry Andric   case llvm::DK_InlineAsm:
71359d1ed5bSDimitry Andric     if (InlineAsmDiagHandler(cast<DiagnosticInfoInlineAsm>(DI)))
71459d1ed5bSDimitry Andric       return;
71559d1ed5bSDimitry Andric     ComputeDiagID(Severity, inline_asm, DiagID);
71659d1ed5bSDimitry Andric     break;
71759d1ed5bSDimitry Andric   case llvm::DK_StackSize:
71859d1ed5bSDimitry Andric     if (StackSizeDiagHandler(cast<DiagnosticInfoStackSize>(DI)))
71959d1ed5bSDimitry Andric       return;
72059d1ed5bSDimitry Andric     ComputeDiagID(Severity, backend_frame_larger_than, DiagID);
72159d1ed5bSDimitry Andric     break;
7220623d748SDimitry Andric   case DK_Linker:
7230623d748SDimitry Andric     assert(CurLinkModule);
7240623d748SDimitry Andric     // FIXME: stop eating the warnings and notes.
7250623d748SDimitry Andric     if (Severity != DS_Error)
7260623d748SDimitry Andric       return;
7270623d748SDimitry Andric     DiagID = diag::err_fe_cannot_link_module;
7280623d748SDimitry Andric     break;
72959d1ed5bSDimitry Andric   case llvm::DK_OptimizationRemark:
73059d1ed5bSDimitry Andric     // Optimization remarks are always handled completely by this
73159d1ed5bSDimitry Andric     // handler. There is no generic way of emitting them.
73244290647SDimitry Andric     OptimizationRemarkHandler(cast<OptimizationRemark>(DI));
73359d1ed5bSDimitry Andric     return;
73459d1ed5bSDimitry Andric   case llvm::DK_OptimizationRemarkMissed:
73559d1ed5bSDimitry Andric     // Optimization remarks are always handled completely by this
73659d1ed5bSDimitry Andric     // handler. There is no generic way of emitting them.
73744290647SDimitry Andric     OptimizationRemarkHandler(cast<OptimizationRemarkMissed>(DI));
73859d1ed5bSDimitry Andric     return;
73959d1ed5bSDimitry Andric   case llvm::DK_OptimizationRemarkAnalysis:
74059d1ed5bSDimitry Andric     // Optimization remarks are always handled completely by this
74159d1ed5bSDimitry Andric     // handler. There is no generic way of emitting them.
74244290647SDimitry Andric     OptimizationRemarkHandler(cast<OptimizationRemarkAnalysis>(DI));
74359d1ed5bSDimitry Andric     return;
7440623d748SDimitry Andric   case llvm::DK_OptimizationRemarkAnalysisFPCommute:
7450623d748SDimitry Andric     // Optimization remarks are always handled completely by this
7460623d748SDimitry Andric     // handler. There is no generic way of emitting them.
74744290647SDimitry Andric     OptimizationRemarkHandler(cast<OptimizationRemarkAnalysisFPCommute>(DI));
7480623d748SDimitry Andric     return;
7490623d748SDimitry Andric   case llvm::DK_OptimizationRemarkAnalysisAliasing:
7500623d748SDimitry Andric     // Optimization remarks are always handled completely by this
7510623d748SDimitry Andric     // handler. There is no generic way of emitting them.
75244290647SDimitry Andric     OptimizationRemarkHandler(cast<OptimizationRemarkAnalysisAliasing>(DI));
7530623d748SDimitry Andric     return;
75420e90f04SDimitry Andric   case llvm::DK_MachineOptimizationRemark:
75520e90f04SDimitry Andric     // Optimization remarks are always handled completely by this
75620e90f04SDimitry Andric     // handler. There is no generic way of emitting them.
75720e90f04SDimitry Andric     OptimizationRemarkHandler(cast<MachineOptimizationRemark>(DI));
75820e90f04SDimitry Andric     return;
75920e90f04SDimitry Andric   case llvm::DK_MachineOptimizationRemarkMissed:
76020e90f04SDimitry Andric     // Optimization remarks are always handled completely by this
76120e90f04SDimitry Andric     // handler. There is no generic way of emitting them.
76220e90f04SDimitry Andric     OptimizationRemarkHandler(cast<MachineOptimizationRemarkMissed>(DI));
76320e90f04SDimitry Andric     return;
76420e90f04SDimitry Andric   case llvm::DK_MachineOptimizationRemarkAnalysis:
76520e90f04SDimitry Andric     // Optimization remarks are always handled completely by this
76620e90f04SDimitry Andric     // handler. There is no generic way of emitting them.
76720e90f04SDimitry Andric     OptimizationRemarkHandler(cast<MachineOptimizationRemarkAnalysis>(DI));
76820e90f04SDimitry Andric     return;
76959d1ed5bSDimitry Andric   case llvm::DK_OptimizationFailure:
77059d1ed5bSDimitry Andric     // Optimization failures are always handled completely by this
77159d1ed5bSDimitry Andric     // handler.
77259d1ed5bSDimitry Andric     OptimizationFailureHandler(cast<DiagnosticInfoOptimizationFailure>(DI));
77359d1ed5bSDimitry Andric     return;
774e7145dcbSDimitry Andric   case llvm::DK_Unsupported:
775e7145dcbSDimitry Andric     UnsupportedDiagHandler(cast<DiagnosticInfoUnsupported>(DI));
776e7145dcbSDimitry Andric     return;
77759d1ed5bSDimitry Andric   default:
77859d1ed5bSDimitry Andric     // Plugin IDs are not bound to any value as they are set dynamically.
77959d1ed5bSDimitry Andric     ComputeDiagRemarkID(Severity, backend_plugin, DiagID);
78059d1ed5bSDimitry Andric     break;
78159d1ed5bSDimitry Andric   }
78259d1ed5bSDimitry Andric   std::string MsgStorage;
78359d1ed5bSDimitry Andric   {
78459d1ed5bSDimitry Andric     raw_string_ostream Stream(MsgStorage);
78559d1ed5bSDimitry Andric     DiagnosticPrinterRawOStream DP(Stream);
78659d1ed5bSDimitry Andric     DI.print(DP);
78759d1ed5bSDimitry Andric   }
78859d1ed5bSDimitry Andric 
7890623d748SDimitry Andric   if (DiagID == diag::err_fe_cannot_link_module) {
7900623d748SDimitry Andric     Diags.Report(diag::err_fe_cannot_link_module)
7910623d748SDimitry Andric         << CurLinkModule->getModuleIdentifier() << MsgStorage;
7920623d748SDimitry Andric     return;
7930623d748SDimitry Andric   }
7940623d748SDimitry Andric 
79559d1ed5bSDimitry Andric   // Report the backend message using the usual diagnostic mechanism.
79659d1ed5bSDimitry Andric   FullSourceLoc Loc;
79759d1ed5bSDimitry Andric   Diags.Report(Loc, DiagID).AddString(MsgStorage);
79859d1ed5bSDimitry Andric }
79959d1ed5bSDimitry Andric #undef ComputeDiagID
800ffd1746dSEd Schouten 
CodeGenAction(unsigned _Act,LLVMContext * _VMContext)8012754fe60SDimitry Andric CodeGenAction::CodeGenAction(unsigned _Act, LLVMContext *_VMContext)
8020623d748SDimitry Andric     : Act(_Act), VMContext(_VMContext ? _VMContext : new LLVMContext),
8032754fe60SDimitry Andric       OwnsVMContext(!_VMContext) {}
804ffd1746dSEd Schouten 
~CodeGenAction()8052754fe60SDimitry Andric CodeGenAction::~CodeGenAction() {
8062754fe60SDimitry Andric   TheModule.reset();
8072754fe60SDimitry Andric   if (OwnsVMContext)
8082754fe60SDimitry Andric     delete VMContext;
8092754fe60SDimitry Andric }
810ffd1746dSEd Schouten 
hasIRSupport() const811ffd1746dSEd Schouten bool CodeGenAction::hasIRSupport() const { return true; }
812ffd1746dSEd Schouten 
EndSourceFileAction()813ffd1746dSEd Schouten void CodeGenAction::EndSourceFileAction() {
814ffd1746dSEd Schouten   // If the consumer creation failed, do nothing.
815ffd1746dSEd Schouten   if (!getCompilerInstance().hasASTConsumer())
816ffd1746dSEd Schouten     return;
817ffd1746dSEd Schouten 
818ffd1746dSEd Schouten   // Steal the module from the consumer.
81939d628a0SDimitry Andric   TheModule = BEConsumer->takeModule();
820ffd1746dSEd Schouten }
821ffd1746dSEd Schouten 
takeModule()82239d628a0SDimitry Andric std::unique_ptr<llvm::Module> CodeGenAction::takeModule() {
82339d628a0SDimitry Andric   return std::move(TheModule);
82439d628a0SDimitry Andric }
825ffd1746dSEd Schouten 
takeLLVMContext()8262754fe60SDimitry Andric llvm::LLVMContext *CodeGenAction::takeLLVMContext() {
8272754fe60SDimitry Andric   OwnsVMContext = false;
8282754fe60SDimitry Andric   return VMContext;
8292754fe60SDimitry Andric }
8302754fe60SDimitry Andric 
831e7145dcbSDimitry Andric static std::unique_ptr<raw_pwrite_stream>
GetOutputStream(CompilerInstance & CI,StringRef InFile,BackendAction Action)83233956c43SDimitry Andric GetOutputStream(CompilerInstance &CI, StringRef InFile, BackendAction Action) {
833ffd1746dSEd Schouten   switch (Action) {
834ffd1746dSEd Schouten   case Backend_EmitAssembly:
835ffd1746dSEd Schouten     return CI.createDefaultOutputFile(false, InFile, "s");
836ffd1746dSEd Schouten   case Backend_EmitLL:
837ffd1746dSEd Schouten     return CI.createDefaultOutputFile(false, InFile, "ll");
838ffd1746dSEd Schouten   case Backend_EmitBC:
839ffd1746dSEd Schouten     return CI.createDefaultOutputFile(true, InFile, "bc");
840ffd1746dSEd Schouten   case Backend_EmitNothing:
84159d1ed5bSDimitry Andric     return nullptr;
842ffd1746dSEd Schouten   case Backend_EmitMCNull:
84359d1ed5bSDimitry Andric     return CI.createNullOutputFile();
844ffd1746dSEd Schouten   case Backend_EmitObj:
845ffd1746dSEd Schouten     return CI.createDefaultOutputFile(true, InFile, "o");
846ffd1746dSEd Schouten   }
847ffd1746dSEd Schouten 
8486122f3e6SDimitry Andric   llvm_unreachable("Invalid action!");
849ffd1746dSEd Schouten }
850ffd1746dSEd Schouten 
85139d628a0SDimitry Andric std::unique_ptr<ASTConsumer>
CreateASTConsumer(CompilerInstance & CI,StringRef InFile)85239d628a0SDimitry Andric CodeGenAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
853ffd1746dSEd Schouten   BackendAction BA = static_cast<BackendAction>(Act);
8544ba319b5SDimitry Andric   std::unique_ptr<raw_pwrite_stream> OS = CI.takeOutputStream();
8554ba319b5SDimitry Andric   if (!OS)
8564ba319b5SDimitry Andric     OS = GetOutputStream(CI, InFile, BA);
8574ba319b5SDimitry Andric 
858ffd1746dSEd Schouten   if (BA != Backend_EmitNothing && !OS)
85959d1ed5bSDimitry Andric     return nullptr;
860ffd1746dSEd Schouten 
8610623d748SDimitry Andric   // Load bitcode modules to link with, if we need to.
8620623d748SDimitry Andric   if (LinkModules.empty())
86320e90f04SDimitry Andric     for (const CodeGenOptions::BitcodeFileToLink &F :
86420e90f04SDimitry Andric          CI.getCodeGenOpts().LinkBitcodeFiles) {
86520e90f04SDimitry Andric       auto BCBuf = CI.getFileManager().getBufferForFile(F.Filename);
866dff0c46cSDimitry Andric       if (!BCBuf) {
867dff0c46cSDimitry Andric         CI.getDiagnostics().Report(diag::err_cannot_open_file)
86820e90f04SDimitry Andric             << F.Filename << BCBuf.getError().message();
8690623d748SDimitry Andric         LinkModules.clear();
87059d1ed5bSDimitry Andric         return nullptr;
871dff0c46cSDimitry Andric       }
872dff0c46cSDimitry Andric 
87344290647SDimitry Andric       Expected<std::unique_ptr<llvm::Module>> ModuleOrErr =
87444290647SDimitry Andric           getOwningLazyBitcodeModule(std::move(*BCBuf), *VMContext);
87544290647SDimitry Andric       if (!ModuleOrErr) {
87644290647SDimitry Andric         handleAllErrors(ModuleOrErr.takeError(), [&](ErrorInfoBase &EIB) {
87744290647SDimitry Andric           CI.getDiagnostics().Report(diag::err_cannot_open_file)
87820e90f04SDimitry Andric               << F.Filename << EIB.message();
87944290647SDimitry Andric         });
8800623d748SDimitry Andric         LinkModules.clear();
88159d1ed5bSDimitry Andric         return nullptr;
882dff0c46cSDimitry Andric       }
88320e90f04SDimitry Andric       LinkModules.push_back({std::move(ModuleOrErr.get()), F.PropagateAttrs,
88420e90f04SDimitry Andric                              F.Internalize, F.LinkFlags});
885dff0c46cSDimitry Andric     }
886dff0c46cSDimitry Andric 
88739d628a0SDimitry Andric   CoverageSourceInfo *CoverageInfo = nullptr;
88839d628a0SDimitry Andric   // Add the preprocessor callback only when the coverage mapping is generated.
88939d628a0SDimitry Andric   if (CI.getCodeGenOpts().CoverageMapping) {
89039d628a0SDimitry Andric     CoverageInfo = new CoverageSourceInfo;
89139d628a0SDimitry Andric     CI.getPreprocessor().addPPCallbacks(
89239d628a0SDimitry Andric                                     std::unique_ptr<PPCallbacks>(CoverageInfo));
89339d628a0SDimitry Andric   }
8940623d748SDimitry Andric 
89539d628a0SDimitry Andric   std::unique_ptr<BackendConsumer> Result(new BackendConsumer(
8963dac3a9bSDimitry Andric       BA, CI.getDiagnostics(), CI.getHeaderSearchOpts(),
8973dac3a9bSDimitry Andric       CI.getPreprocessorOpts(), CI.getCodeGenOpts(), CI.getTargetOpts(),
89820e90f04SDimitry Andric       CI.getLangOpts(), CI.getFrontendOpts().ShowTimers, InFile,
89920e90f04SDimitry Andric       std::move(LinkModules), std::move(OS), *VMContext, CoverageInfo));
90039d628a0SDimitry Andric   BEConsumer = Result.get();
90120e90f04SDimitry Andric 
90220e90f04SDimitry Andric   // Enable generating macro debug info only when debug info is not disabled and
90320e90f04SDimitry Andric   // also macro debug info is enabled.
90420e90f04SDimitry Andric   if (CI.getCodeGenOpts().getDebugInfo() != codegenoptions::NoDebugInfo &&
90520e90f04SDimitry Andric       CI.getCodeGenOpts().MacroDebugInfo) {
90620e90f04SDimitry Andric     std::unique_ptr<PPCallbacks> Callbacks =
90720e90f04SDimitry Andric         llvm::make_unique<MacroPPCallbacks>(BEConsumer->getCodeGenerator(),
90820e90f04SDimitry Andric                                             CI.getPreprocessor());
90920e90f04SDimitry Andric     CI.getPreprocessor().addPPCallbacks(std::move(Callbacks));
91020e90f04SDimitry Andric   }
91120e90f04SDimitry Andric 
91239d628a0SDimitry Andric   return std::move(Result);
913ffd1746dSEd Schouten }
914ffd1746dSEd Schouten 
BitcodeInlineAsmDiagHandler(const llvm::SMDiagnostic & SM,void * Context,unsigned LocCookie)91533956c43SDimitry Andric static void BitcodeInlineAsmDiagHandler(const llvm::SMDiagnostic &SM,
91633956c43SDimitry Andric                                          void *Context,
91733956c43SDimitry Andric                                          unsigned LocCookie) {
91833956c43SDimitry Andric   SM.print(nullptr, llvm::errs());
919e7145dcbSDimitry Andric 
920e7145dcbSDimitry Andric   auto Diags = static_cast<DiagnosticsEngine *>(Context);
921e7145dcbSDimitry Andric   unsigned DiagID;
922e7145dcbSDimitry Andric   switch (SM.getKind()) {
923e7145dcbSDimitry Andric   case llvm::SourceMgr::DK_Error:
924e7145dcbSDimitry Andric     DiagID = diag::err_fe_inline_asm;
925e7145dcbSDimitry Andric     break;
926e7145dcbSDimitry Andric   case llvm::SourceMgr::DK_Warning:
927e7145dcbSDimitry Andric     DiagID = diag::warn_fe_inline_asm;
928e7145dcbSDimitry Andric     break;
929e7145dcbSDimitry Andric   case llvm::SourceMgr::DK_Note:
930e7145dcbSDimitry Andric     DiagID = diag::note_fe_inline_asm;
931e7145dcbSDimitry Andric     break;
9329a199699SDimitry Andric   case llvm::SourceMgr::DK_Remark:
9339a199699SDimitry Andric     llvm_unreachable("remarks unexpected");
934e7145dcbSDimitry Andric   }
935e7145dcbSDimitry Andric 
936e7145dcbSDimitry Andric   Diags->Report(DiagID).AddString("cannot compile inline asm");
93733956c43SDimitry Andric }
93833956c43SDimitry Andric 
loadModule(MemoryBufferRef MBRef)93920e90f04SDimitry Andric std::unique_ptr<llvm::Module> CodeGenAction::loadModule(MemoryBufferRef MBRef) {
94020e90f04SDimitry Andric   CompilerInstance &CI = getCompilerInstance();
94120e90f04SDimitry Andric   SourceManager &SM = CI.getSourceManager();
94220e90f04SDimitry Andric 
94320e90f04SDimitry Andric   // For ThinLTO backend invocations, ensure that the context
94420e90f04SDimitry Andric   // merges types based on ODR identifiers. We also need to read
94520e90f04SDimitry Andric   // the correct module out of a multi-module bitcode file.
94620e90f04SDimitry Andric   if (!CI.getCodeGenOpts().ThinLTOIndexFile.empty()) {
94720e90f04SDimitry Andric     VMContext->enableDebugTypeODRUniquing();
94820e90f04SDimitry Andric 
94920e90f04SDimitry Andric     auto DiagErrors = [&](Error E) -> std::unique_ptr<llvm::Module> {
95020e90f04SDimitry Andric       unsigned DiagID =
95120e90f04SDimitry Andric           CI.getDiagnostics().getCustomDiagID(DiagnosticsEngine::Error, "%0");
95220e90f04SDimitry Andric       handleAllErrors(std::move(E), [&](ErrorInfoBase &EIB) {
95320e90f04SDimitry Andric         CI.getDiagnostics().Report(DiagID) << EIB.message();
95420e90f04SDimitry Andric       });
95520e90f04SDimitry Andric       return {};
95620e90f04SDimitry Andric     };
95720e90f04SDimitry Andric 
9584ba319b5SDimitry Andric     Expected<std::vector<BitcodeModule>> BMsOrErr = getBitcodeModuleList(MBRef);
9594ba319b5SDimitry Andric     if (!BMsOrErr)
9604ba319b5SDimitry Andric       return DiagErrors(BMsOrErr.takeError());
9614ba319b5SDimitry Andric     BitcodeModule *Bm = FindThinLTOModule(*BMsOrErr);
9624ba319b5SDimitry Andric     // We have nothing to do if the file contains no ThinLTO module. This is
9634ba319b5SDimitry Andric     // possible if ThinLTO compilation was not able to split module. Content of
9644ba319b5SDimitry Andric     // the file was already processed by indexing and will be passed to the
9654ba319b5SDimitry Andric     // linker using merged object file.
9664ba319b5SDimitry Andric     if (!Bm) {
9674ba319b5SDimitry Andric       auto M = llvm::make_unique<llvm::Module>("empty", *VMContext);
9684ba319b5SDimitry Andric       M->setTargetTriple(CI.getTargetOpts().Triple);
9694ba319b5SDimitry Andric       return M;
9704ba319b5SDimitry Andric     }
97120e90f04SDimitry Andric     Expected<std::unique_ptr<llvm::Module>> MOrErr =
9724ba319b5SDimitry Andric         Bm->parseModule(*VMContext);
97320e90f04SDimitry Andric     if (!MOrErr)
97420e90f04SDimitry Andric       return DiagErrors(MOrErr.takeError());
97520e90f04SDimitry Andric     return std::move(*MOrErr);
97620e90f04SDimitry Andric   }
97720e90f04SDimitry Andric 
97820e90f04SDimitry Andric   llvm::SMDiagnostic Err;
97920e90f04SDimitry Andric   if (std::unique_ptr<llvm::Module> M = parseIR(MBRef, Err, *VMContext))
98020e90f04SDimitry Andric     return M;
98120e90f04SDimitry Andric 
98220e90f04SDimitry Andric   // Translate from the diagnostic info to the SourceManager location if
98320e90f04SDimitry Andric   // available.
98420e90f04SDimitry Andric   // TODO: Unify this with ConvertBackendLocation()
98520e90f04SDimitry Andric   SourceLocation Loc;
98620e90f04SDimitry Andric   if (Err.getLineNo() > 0) {
98720e90f04SDimitry Andric     assert(Err.getColumnNo() >= 0);
98820e90f04SDimitry Andric     Loc = SM.translateFileLineCol(SM.getFileEntryForID(SM.getMainFileID()),
98920e90f04SDimitry Andric                                   Err.getLineNo(), Err.getColumnNo() + 1);
99020e90f04SDimitry Andric   }
99120e90f04SDimitry Andric 
99220e90f04SDimitry Andric   // Strip off a leading diagnostic code if there is one.
99320e90f04SDimitry Andric   StringRef Msg = Err.getMessage();
99420e90f04SDimitry Andric   if (Msg.startswith("error: "))
99520e90f04SDimitry Andric     Msg = Msg.substr(7);
99620e90f04SDimitry Andric 
99720e90f04SDimitry Andric   unsigned DiagID =
99820e90f04SDimitry Andric       CI.getDiagnostics().getCustomDiagID(DiagnosticsEngine::Error, "%0");
99920e90f04SDimitry Andric 
100020e90f04SDimitry Andric   CI.getDiagnostics().Report(Loc, DiagID) << Msg;
100120e90f04SDimitry Andric   return {};
100220e90f04SDimitry Andric }
100320e90f04SDimitry Andric 
ExecuteAction()1004ffd1746dSEd Schouten void CodeGenAction::ExecuteAction() {
1005ffd1746dSEd Schouten   // If this is an IR file, we have to treat it specially.
1006f37b6182SDimitry Andric   if (getCurrentFileKind().getLanguage() == InputKind::LLVM_IR) {
1007ffd1746dSEd Schouten     BackendAction BA = static_cast<BackendAction>(Act);
1008ffd1746dSEd Schouten     CompilerInstance &CI = getCompilerInstance();
1009e7145dcbSDimitry Andric     std::unique_ptr<raw_pwrite_stream> OS =
1010e7145dcbSDimitry Andric         GetOutputStream(CI, getCurrentFile(), BA);
1011ffd1746dSEd Schouten     if (BA != Backend_EmitNothing && !OS)
1012ffd1746dSEd Schouten       return;
1013ffd1746dSEd Schouten 
1014ffd1746dSEd Schouten     bool Invalid;
1015ffd1746dSEd Schouten     SourceManager &SM = CI.getSourceManager();
101659d1ed5bSDimitry Andric     FileID FID = SM.getMainFileID();
101759d1ed5bSDimitry Andric     llvm::MemoryBuffer *MainFile = SM.getBuffer(FID, &Invalid);
1018ffd1746dSEd Schouten     if (Invalid)
1019ffd1746dSEd Schouten       return;
1020ffd1746dSEd Schouten 
102120e90f04SDimitry Andric     TheModule = loadModule(*MainFile);
102220e90f04SDimitry Andric     if (!TheModule)
1023ffd1746dSEd Schouten       return;
102420e90f04SDimitry Andric 
102559d1ed5bSDimitry Andric     const TargetOptions &TargetOpts = CI.getTargetOpts();
102659d1ed5bSDimitry Andric     if (TheModule->getTargetTriple() != TargetOpts.Triple) {
102733956c43SDimitry Andric       CI.getDiagnostics().Report(SourceLocation(),
102833956c43SDimitry Andric                                  diag::warn_fe_override_module)
102933956c43SDimitry Andric           << TargetOpts.Triple;
103059d1ed5bSDimitry Andric       TheModule->setTargetTriple(TargetOpts.Triple);
103159d1ed5bSDimitry Andric     }
103259d1ed5bSDimitry Andric 
1033e7145dcbSDimitry Andric     EmbedBitcode(TheModule.get(), CI.getCodeGenOpts(),
1034e7145dcbSDimitry Andric                  MainFile->getMemBufferRef());
1035e7145dcbSDimitry Andric 
103633956c43SDimitry Andric     LLVMContext &Ctx = TheModule->getContext();
1037e7145dcbSDimitry Andric     Ctx.setInlineAsmDiagnosticHandler(BitcodeInlineAsmDiagHandler,
1038e7145dcbSDimitry Andric                                       &CI.getDiagnostics());
1039e7145dcbSDimitry Andric 
104095ec533aSDimitry Andric     EmitBackendOutput(CI.getDiagnostics(), CI.getHeaderSearchOpts(),
104195ec533aSDimitry Andric                       CI.getCodeGenOpts(), TargetOpts, CI.getLangOpts(),
104295ec533aSDimitry Andric                       CI.getTarget().getDataLayout(), TheModule.get(), BA,
104395ec533aSDimitry Andric                       std::move(OS));
1044ffd1746dSEd Schouten     return;
1045ffd1746dSEd Schouten   }
1046ffd1746dSEd Schouten 
1047ffd1746dSEd Schouten   // Otherwise follow the normal AST path.
1048ffd1746dSEd Schouten   this->ASTFrontendAction::ExecuteAction();
1049ffd1746dSEd Schouten }
1050ffd1746dSEd Schouten 
1051ffd1746dSEd Schouten //
1052ffd1746dSEd Schouten 
anchor()1053dff0c46cSDimitry Andric void EmitAssemblyAction::anchor() { }
EmitAssemblyAction(llvm::LLVMContext * _VMContext)10542754fe60SDimitry Andric EmitAssemblyAction::EmitAssemblyAction(llvm::LLVMContext *_VMContext)
10552754fe60SDimitry Andric   : CodeGenAction(Backend_EmitAssembly, _VMContext) {}
1056ffd1746dSEd Schouten 
anchor()1057dff0c46cSDimitry Andric void EmitBCAction::anchor() { }
EmitBCAction(llvm::LLVMContext * _VMContext)10582754fe60SDimitry Andric EmitBCAction::EmitBCAction(llvm::LLVMContext *_VMContext)
10592754fe60SDimitry Andric   : CodeGenAction(Backend_EmitBC, _VMContext) {}
1060ffd1746dSEd Schouten 
anchor()1061dff0c46cSDimitry Andric void EmitLLVMAction::anchor() { }
EmitLLVMAction(llvm::LLVMContext * _VMContext)10622754fe60SDimitry Andric EmitLLVMAction::EmitLLVMAction(llvm::LLVMContext *_VMContext)
10632754fe60SDimitry Andric   : CodeGenAction(Backend_EmitLL, _VMContext) {}
1064ffd1746dSEd Schouten 
anchor()1065dff0c46cSDimitry Andric void EmitLLVMOnlyAction::anchor() { }
EmitLLVMOnlyAction(llvm::LLVMContext * _VMContext)10662754fe60SDimitry Andric EmitLLVMOnlyAction::EmitLLVMOnlyAction(llvm::LLVMContext *_VMContext)
10672754fe60SDimitry Andric   : CodeGenAction(Backend_EmitNothing, _VMContext) {}
1068ffd1746dSEd Schouten 
anchor()1069dff0c46cSDimitry Andric void EmitCodeGenOnlyAction::anchor() { }
EmitCodeGenOnlyAction(llvm::LLVMContext * _VMContext)10702754fe60SDimitry Andric EmitCodeGenOnlyAction::EmitCodeGenOnlyAction(llvm::LLVMContext *_VMContext)
10712754fe60SDimitry Andric   : CodeGenAction(Backend_EmitMCNull, _VMContext) {}
1072ffd1746dSEd Schouten 
anchor()1073dff0c46cSDimitry Andric void EmitObjAction::anchor() { }
EmitObjAction(llvm::LLVMContext * _VMContext)10742754fe60SDimitry Andric EmitObjAction::EmitObjAction(llvm::LLVMContext *_VMContext)
10752754fe60SDimitry Andric   : CodeGenAction(Backend_EmitObj, _VMContext) {}
1076