10b57cec5SDimitry Andric //===--- CodeGenAction.cpp - LLVM Code Generation Frontend Action ---------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "clang/CodeGen/CodeGenAction.h"
100b57cec5SDimitry Andric #include "CodeGenModule.h"
110b57cec5SDimitry Andric #include "CoverageMappingGen.h"
120b57cec5SDimitry Andric #include "MacroPPCallbacks.h"
130b57cec5SDimitry Andric #include "clang/AST/ASTConsumer.h"
140b57cec5SDimitry Andric #include "clang/AST/ASTContext.h"
150b57cec5SDimitry Andric #include "clang/AST/DeclCXX.h"
160b57cec5SDimitry Andric #include "clang/AST/DeclGroup.h"
17a7dea167SDimitry Andric #include "clang/Basic/DiagnosticFrontend.h"
180b57cec5SDimitry Andric #include "clang/Basic/FileManager.h"
19a7dea167SDimitry Andric #include "clang/Basic/LangStandard.h"
200b57cec5SDimitry Andric #include "clang/Basic/SourceManager.h"
210b57cec5SDimitry Andric #include "clang/Basic/TargetInfo.h"
220b57cec5SDimitry Andric #include "clang/CodeGen/BackendUtil.h"
230b57cec5SDimitry Andric #include "clang/CodeGen/ModuleBuilder.h"
240b57cec5SDimitry Andric #include "clang/Driver/DriverDiagnostic.h"
250b57cec5SDimitry Andric #include "clang/Frontend/CompilerInstance.h"
260b57cec5SDimitry Andric #include "clang/Frontend/FrontendDiagnostic.h"
270b57cec5SDimitry Andric #include "clang/Lex/Preprocessor.h"
280b57cec5SDimitry Andric #include "llvm/Bitcode/BitcodeReader.h"
290b57cec5SDimitry Andric #include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h"
300b57cec5SDimitry Andric #include "llvm/IR/DebugInfo.h"
310b57cec5SDimitry Andric #include "llvm/IR/DiagnosticInfo.h"
320b57cec5SDimitry Andric #include "llvm/IR/DiagnosticPrinter.h"
330b57cec5SDimitry Andric #include "llvm/IR/GlobalValue.h"
340b57cec5SDimitry Andric #include "llvm/IR/LLVMContext.h"
355ffd83dbSDimitry Andric #include "llvm/IR/LLVMRemarkStreamer.h"
360b57cec5SDimitry Andric #include "llvm/IR/Module.h"
370b57cec5SDimitry Andric #include "llvm/IRReader/IRReader.h"
38af732203SDimitry Andric #include "llvm/LTO/LTOBackend.h"
390b57cec5SDimitry Andric #include "llvm/Linker/Linker.h"
400b57cec5SDimitry Andric #include "llvm/Pass.h"
410b57cec5SDimitry Andric #include "llvm/Support/MemoryBuffer.h"
420b57cec5SDimitry Andric #include "llvm/Support/SourceMgr.h"
43a7dea167SDimitry Andric #include "llvm/Support/TimeProfiler.h"
440b57cec5SDimitry Andric #include "llvm/Support/Timer.h"
450b57cec5SDimitry Andric #include "llvm/Support/ToolOutputFile.h"
460b57cec5SDimitry Andric #include "llvm/Support/YAMLTraits.h"
470b57cec5SDimitry Andric #include "llvm/Transforms/IPO/Internalize.h"
480b57cec5SDimitry Andric 
490b57cec5SDimitry Andric #include <memory>
500b57cec5SDimitry Andric using namespace clang;
510b57cec5SDimitry Andric using namespace llvm;
520b57cec5SDimitry Andric 
530b57cec5SDimitry Andric namespace clang {
540b57cec5SDimitry Andric   class BackendConsumer;
550b57cec5SDimitry Andric   class ClangDiagnosticHandler final : public DiagnosticHandler {
560b57cec5SDimitry Andric   public:
ClangDiagnosticHandler(const CodeGenOptions & CGOpts,BackendConsumer * BCon)570b57cec5SDimitry Andric     ClangDiagnosticHandler(const CodeGenOptions &CGOpts, BackendConsumer *BCon)
580b57cec5SDimitry Andric         : CodeGenOpts(CGOpts), BackendCon(BCon) {}
590b57cec5SDimitry Andric 
600b57cec5SDimitry Andric     bool handleDiagnostics(const DiagnosticInfo &DI) override;
610b57cec5SDimitry Andric 
isAnalysisRemarkEnabled(StringRef PassName) const620b57cec5SDimitry Andric     bool isAnalysisRemarkEnabled(StringRef PassName) const override {
63*5f7ddb14SDimitry Andric       return CodeGenOpts.OptimizationRemarkAnalysis.patternMatches(PassName);
640b57cec5SDimitry Andric     }
isMissedOptRemarkEnabled(StringRef PassName) const650b57cec5SDimitry Andric     bool isMissedOptRemarkEnabled(StringRef PassName) const override {
66*5f7ddb14SDimitry Andric       return CodeGenOpts.OptimizationRemarkMissed.patternMatches(PassName);
670b57cec5SDimitry Andric     }
isPassedOptRemarkEnabled(StringRef PassName) const680b57cec5SDimitry Andric     bool isPassedOptRemarkEnabled(StringRef PassName) const override {
69*5f7ddb14SDimitry Andric       return CodeGenOpts.OptimizationRemark.patternMatches(PassName);
700b57cec5SDimitry Andric     }
710b57cec5SDimitry Andric 
isAnyRemarkEnabled() const720b57cec5SDimitry Andric     bool isAnyRemarkEnabled() const override {
73*5f7ddb14SDimitry Andric       return CodeGenOpts.OptimizationRemarkAnalysis.hasValidPattern() ||
74*5f7ddb14SDimitry Andric              CodeGenOpts.OptimizationRemarkMissed.hasValidPattern() ||
75*5f7ddb14SDimitry Andric              CodeGenOpts.OptimizationRemark.hasValidPattern();
760b57cec5SDimitry Andric     }
770b57cec5SDimitry Andric 
780b57cec5SDimitry Andric   private:
790b57cec5SDimitry Andric     const CodeGenOptions &CodeGenOpts;
800b57cec5SDimitry Andric     BackendConsumer *BackendCon;
810b57cec5SDimitry Andric   };
820b57cec5SDimitry Andric 
reportOptRecordError(Error E,DiagnosticsEngine & Diags,const CodeGenOptions CodeGenOpts)83480093f4SDimitry Andric   static void reportOptRecordError(Error E, DiagnosticsEngine &Diags,
84480093f4SDimitry Andric                                    const CodeGenOptions CodeGenOpts) {
85480093f4SDimitry Andric     handleAllErrors(
86480093f4SDimitry Andric         std::move(E),
875ffd83dbSDimitry Andric       [&](const LLVMRemarkSetupFileError &E) {
88480093f4SDimitry Andric           Diags.Report(diag::err_cannot_open_file)
89480093f4SDimitry Andric               << CodeGenOpts.OptRecordFile << E.message();
90480093f4SDimitry Andric         },
915ffd83dbSDimitry Andric       [&](const LLVMRemarkSetupPatternError &E) {
92480093f4SDimitry Andric           Diags.Report(diag::err_drv_optimization_remark_pattern)
93480093f4SDimitry Andric               << E.message() << CodeGenOpts.OptRecordPasses;
94480093f4SDimitry Andric         },
955ffd83dbSDimitry Andric       [&](const LLVMRemarkSetupFormatError &E) {
96480093f4SDimitry Andric           Diags.Report(diag::err_drv_optimization_remark_format)
97480093f4SDimitry Andric               << CodeGenOpts.OptRecordFormat;
98480093f4SDimitry Andric         });
99480093f4SDimitry Andric     }
100480093f4SDimitry Andric 
1010b57cec5SDimitry Andric   class BackendConsumer : public ASTConsumer {
1020b57cec5SDimitry Andric     using LinkModule = CodeGenAction::LinkModule;
1030b57cec5SDimitry Andric 
1040b57cec5SDimitry Andric     virtual void anchor();
1050b57cec5SDimitry Andric     DiagnosticsEngine &Diags;
1060b57cec5SDimitry Andric     BackendAction Action;
1070b57cec5SDimitry Andric     const HeaderSearchOptions &HeaderSearchOpts;
1080b57cec5SDimitry Andric     const CodeGenOptions &CodeGenOpts;
1090b57cec5SDimitry Andric     const TargetOptions &TargetOpts;
1100b57cec5SDimitry Andric     const LangOptions &LangOpts;
1110b57cec5SDimitry Andric     std::unique_ptr<raw_pwrite_stream> AsmOutStream;
1120b57cec5SDimitry Andric     ASTContext *Context;
1130b57cec5SDimitry Andric 
1140b57cec5SDimitry Andric     Timer LLVMIRGeneration;
1150b57cec5SDimitry Andric     unsigned LLVMIRGenerationRefCount;
1160b57cec5SDimitry Andric 
1170b57cec5SDimitry Andric     /// True if we've finished generating IR. This prevents us from generating
1180b57cec5SDimitry Andric     /// additional LLVM IR after emitting output in HandleTranslationUnit. This
1190b57cec5SDimitry Andric     /// can happen when Clang plugins trigger additional AST deserialization.
1200b57cec5SDimitry Andric     bool IRGenFinished = false;
1210b57cec5SDimitry Andric 
122af732203SDimitry Andric     bool TimerIsEnabled = false;
123af732203SDimitry Andric 
1240b57cec5SDimitry Andric     std::unique_ptr<CodeGenerator> Gen;
1250b57cec5SDimitry Andric 
1260b57cec5SDimitry Andric     SmallVector<LinkModule, 4> LinkModules;
1270b57cec5SDimitry Andric 
1280b57cec5SDimitry Andric     // This is here so that the diagnostic printer knows the module a diagnostic
1290b57cec5SDimitry Andric     // refers to.
1300b57cec5SDimitry Andric     llvm::Module *CurLinkModule = nullptr;
1310b57cec5SDimitry Andric 
1320b57cec5SDimitry Andric   public:
BackendConsumer(BackendAction Action,DiagnosticsEngine & Diags,const HeaderSearchOptions & HeaderSearchOpts,const PreprocessorOptions & PPOpts,const CodeGenOptions & CodeGenOpts,const TargetOptions & TargetOpts,const LangOptions & LangOpts,const std::string & InFile,SmallVector<LinkModule,4> LinkModules,std::unique_ptr<raw_pwrite_stream> OS,LLVMContext & C,CoverageSourceInfo * CoverageInfo=nullptr)1330b57cec5SDimitry Andric     BackendConsumer(BackendAction Action, DiagnosticsEngine &Diags,
1340b57cec5SDimitry Andric                     const HeaderSearchOptions &HeaderSearchOpts,
1350b57cec5SDimitry Andric                     const PreprocessorOptions &PPOpts,
1360b57cec5SDimitry Andric                     const CodeGenOptions &CodeGenOpts,
1370b57cec5SDimitry Andric                     const TargetOptions &TargetOpts,
138af732203SDimitry Andric                     const LangOptions &LangOpts, const std::string &InFile,
1390b57cec5SDimitry Andric                     SmallVector<LinkModule, 4> LinkModules,
1400b57cec5SDimitry Andric                     std::unique_ptr<raw_pwrite_stream> OS, LLVMContext &C,
1410b57cec5SDimitry Andric                     CoverageSourceInfo *CoverageInfo = nullptr)
1420b57cec5SDimitry Andric         : Diags(Diags), Action(Action), HeaderSearchOpts(HeaderSearchOpts),
1430b57cec5SDimitry Andric           CodeGenOpts(CodeGenOpts), TargetOpts(TargetOpts), LangOpts(LangOpts),
1440b57cec5SDimitry Andric           AsmOutStream(std::move(OS)), Context(nullptr),
1450b57cec5SDimitry Andric           LLVMIRGeneration("irgen", "LLVM IR Generation Time"),
1460b57cec5SDimitry Andric           LLVMIRGenerationRefCount(0),
1470b57cec5SDimitry Andric           Gen(CreateLLVMCodeGen(Diags, InFile, HeaderSearchOpts, PPOpts,
1480b57cec5SDimitry Andric                                 CodeGenOpts, C, CoverageInfo)),
1490b57cec5SDimitry Andric           LinkModules(std::move(LinkModules)) {
150af732203SDimitry Andric       TimerIsEnabled = CodeGenOpts.TimePasses;
151af732203SDimitry Andric       llvm::TimePassesIsEnabled = CodeGenOpts.TimePasses;
152af732203SDimitry Andric       llvm::TimePassesPerRun = CodeGenOpts.TimePassesPerRun;
1530b57cec5SDimitry Andric     }
154480093f4SDimitry Andric 
155480093f4SDimitry Andric     // This constructor is used in installing an empty BackendConsumer
156480093f4SDimitry Andric     // to use the clang diagnostic handler for IR input files. It avoids
157480093f4SDimitry Andric     // initializing the OS field.
BackendConsumer(BackendAction Action,DiagnosticsEngine & Diags,const HeaderSearchOptions & HeaderSearchOpts,const PreprocessorOptions & PPOpts,const CodeGenOptions & CodeGenOpts,const TargetOptions & TargetOpts,const LangOptions & LangOpts,SmallVector<LinkModule,4> LinkModules,LLVMContext & C,CoverageSourceInfo * CoverageInfo=nullptr)158480093f4SDimitry Andric     BackendConsumer(BackendAction Action, DiagnosticsEngine &Diags,
159480093f4SDimitry Andric                     const HeaderSearchOptions &HeaderSearchOpts,
160480093f4SDimitry Andric                     const PreprocessorOptions &PPOpts,
161480093f4SDimitry Andric                     const CodeGenOptions &CodeGenOpts,
162480093f4SDimitry Andric                     const TargetOptions &TargetOpts,
163af732203SDimitry Andric                     const LangOptions &LangOpts,
164480093f4SDimitry Andric                     SmallVector<LinkModule, 4> LinkModules, LLVMContext &C,
165480093f4SDimitry Andric                     CoverageSourceInfo *CoverageInfo = nullptr)
166480093f4SDimitry Andric         : Diags(Diags), Action(Action), HeaderSearchOpts(HeaderSearchOpts),
167480093f4SDimitry Andric           CodeGenOpts(CodeGenOpts), TargetOpts(TargetOpts), LangOpts(LangOpts),
168480093f4SDimitry Andric           Context(nullptr),
169480093f4SDimitry Andric           LLVMIRGeneration("irgen", "LLVM IR Generation Time"),
170480093f4SDimitry Andric           LLVMIRGenerationRefCount(0),
171480093f4SDimitry Andric           Gen(CreateLLVMCodeGen(Diags, "", HeaderSearchOpts, PPOpts,
172480093f4SDimitry Andric                                 CodeGenOpts, C, CoverageInfo)),
173480093f4SDimitry Andric           LinkModules(std::move(LinkModules)) {
174af732203SDimitry Andric       TimerIsEnabled = CodeGenOpts.TimePasses;
175af732203SDimitry Andric       llvm::TimePassesIsEnabled = CodeGenOpts.TimePasses;
176af732203SDimitry Andric       llvm::TimePassesPerRun = CodeGenOpts.TimePassesPerRun;
177480093f4SDimitry Andric     }
getModule() const1780b57cec5SDimitry Andric     llvm::Module *getModule() const { return Gen->GetModule(); }
takeModule()1790b57cec5SDimitry Andric     std::unique_ptr<llvm::Module> takeModule() {
1800b57cec5SDimitry Andric       return std::unique_ptr<llvm::Module>(Gen->ReleaseModule());
1810b57cec5SDimitry Andric     }
1820b57cec5SDimitry Andric 
getCodeGenerator()1830b57cec5SDimitry Andric     CodeGenerator *getCodeGenerator() { return Gen.get(); }
1840b57cec5SDimitry Andric 
HandleCXXStaticMemberVarInstantiation(VarDecl * VD)1850b57cec5SDimitry Andric     void HandleCXXStaticMemberVarInstantiation(VarDecl *VD) override {
1860b57cec5SDimitry Andric       Gen->HandleCXXStaticMemberVarInstantiation(VD);
1870b57cec5SDimitry Andric     }
1880b57cec5SDimitry Andric 
Initialize(ASTContext & Ctx)1890b57cec5SDimitry Andric     void Initialize(ASTContext &Ctx) override {
1900b57cec5SDimitry Andric       assert(!Context && "initialized multiple times");
1910b57cec5SDimitry Andric 
1920b57cec5SDimitry Andric       Context = &Ctx;
1930b57cec5SDimitry Andric 
194af732203SDimitry Andric       if (TimerIsEnabled)
1950b57cec5SDimitry Andric         LLVMIRGeneration.startTimer();
1960b57cec5SDimitry Andric 
1970b57cec5SDimitry Andric       Gen->Initialize(Ctx);
1980b57cec5SDimitry Andric 
199af732203SDimitry Andric       if (TimerIsEnabled)
2000b57cec5SDimitry Andric         LLVMIRGeneration.stopTimer();
2010b57cec5SDimitry Andric     }
2020b57cec5SDimitry Andric 
HandleTopLevelDecl(DeclGroupRef D)2030b57cec5SDimitry Andric     bool HandleTopLevelDecl(DeclGroupRef D) override {
2040b57cec5SDimitry Andric       PrettyStackTraceDecl CrashInfo(*D.begin(), SourceLocation(),
2050b57cec5SDimitry Andric                                      Context->getSourceManager(),
2060b57cec5SDimitry Andric                                      "LLVM IR generation of declaration");
2070b57cec5SDimitry Andric 
2080b57cec5SDimitry Andric       // Recurse.
209af732203SDimitry Andric       if (TimerIsEnabled) {
2100b57cec5SDimitry Andric         LLVMIRGenerationRefCount += 1;
2110b57cec5SDimitry Andric         if (LLVMIRGenerationRefCount == 1)
2120b57cec5SDimitry Andric           LLVMIRGeneration.startTimer();
2130b57cec5SDimitry Andric       }
2140b57cec5SDimitry Andric 
2150b57cec5SDimitry Andric       Gen->HandleTopLevelDecl(D);
2160b57cec5SDimitry Andric 
217af732203SDimitry Andric       if (TimerIsEnabled) {
2180b57cec5SDimitry Andric         LLVMIRGenerationRefCount -= 1;
2190b57cec5SDimitry Andric         if (LLVMIRGenerationRefCount == 0)
2200b57cec5SDimitry Andric           LLVMIRGeneration.stopTimer();
2210b57cec5SDimitry Andric       }
2220b57cec5SDimitry Andric 
2230b57cec5SDimitry Andric       return true;
2240b57cec5SDimitry Andric     }
2250b57cec5SDimitry Andric 
HandleInlineFunctionDefinition(FunctionDecl * D)2260b57cec5SDimitry Andric     void HandleInlineFunctionDefinition(FunctionDecl *D) override {
2270b57cec5SDimitry Andric       PrettyStackTraceDecl CrashInfo(D, SourceLocation(),
2280b57cec5SDimitry Andric                                      Context->getSourceManager(),
2290b57cec5SDimitry Andric                                      "LLVM IR generation of inline function");
230af732203SDimitry Andric       if (TimerIsEnabled)
2310b57cec5SDimitry Andric         LLVMIRGeneration.startTimer();
2320b57cec5SDimitry Andric 
2330b57cec5SDimitry Andric       Gen->HandleInlineFunctionDefinition(D);
2340b57cec5SDimitry Andric 
235af732203SDimitry Andric       if (TimerIsEnabled)
2360b57cec5SDimitry Andric         LLVMIRGeneration.stopTimer();
2370b57cec5SDimitry Andric     }
2380b57cec5SDimitry Andric 
HandleInterestingDecl(DeclGroupRef D)2390b57cec5SDimitry Andric     void HandleInterestingDecl(DeclGroupRef D) override {
2400b57cec5SDimitry Andric       // Ignore interesting decls from the AST reader after IRGen is finished.
2410b57cec5SDimitry Andric       if (!IRGenFinished)
2420b57cec5SDimitry Andric         HandleTopLevelDecl(D);
2430b57cec5SDimitry Andric     }
2440b57cec5SDimitry Andric 
2450b57cec5SDimitry Andric     // Links each entry in LinkModules into our module.  Returns true on error.
LinkInModules()2460b57cec5SDimitry Andric     bool LinkInModules() {
2470b57cec5SDimitry Andric       for (auto &LM : LinkModules) {
2480b57cec5SDimitry Andric         if (LM.PropagateAttrs)
249af732203SDimitry Andric           for (Function &F : *LM.Module) {
250af732203SDimitry Andric             // Skip intrinsics. Keep consistent with how intrinsics are created
251af732203SDimitry Andric             // in LLVM IR.
252af732203SDimitry Andric             if (F.isIntrinsic())
253af732203SDimitry Andric               continue;
2545ffd83dbSDimitry Andric             Gen->CGM().addDefaultFunctionDefinitionAttributes(F);
255af732203SDimitry Andric           }
2560b57cec5SDimitry Andric 
2570b57cec5SDimitry Andric         CurLinkModule = LM.Module.get();
2580b57cec5SDimitry Andric 
2590b57cec5SDimitry Andric         bool Err;
2600b57cec5SDimitry Andric         if (LM.Internalize) {
2610b57cec5SDimitry Andric           Err = Linker::linkModules(
2620b57cec5SDimitry Andric               *getModule(), std::move(LM.Module), LM.LinkFlags,
2630b57cec5SDimitry Andric               [](llvm::Module &M, const llvm::StringSet<> &GVS) {
2640b57cec5SDimitry Andric                 internalizeModule(M, [&GVS](const llvm::GlobalValue &GV) {
2650b57cec5SDimitry Andric                   return !GV.hasName() || (GVS.count(GV.getName()) == 0);
2660b57cec5SDimitry Andric                 });
2670b57cec5SDimitry Andric               });
2680b57cec5SDimitry Andric         } else {
2690b57cec5SDimitry Andric           Err = Linker::linkModules(*getModule(), std::move(LM.Module),
2700b57cec5SDimitry Andric                                     LM.LinkFlags);
2710b57cec5SDimitry Andric         }
2720b57cec5SDimitry Andric 
2730b57cec5SDimitry Andric         if (Err)
2740b57cec5SDimitry Andric           return true;
2750b57cec5SDimitry Andric       }
2760b57cec5SDimitry Andric       return false; // success
2770b57cec5SDimitry Andric     }
2780b57cec5SDimitry Andric 
HandleTranslationUnit(ASTContext & C)2790b57cec5SDimitry Andric     void HandleTranslationUnit(ASTContext &C) override {
2800b57cec5SDimitry Andric       {
281480093f4SDimitry Andric         llvm::TimeTraceScope TimeScope("Frontend");
2820b57cec5SDimitry Andric         PrettyStackTraceString CrashInfo("Per-file LLVM IR generation");
283af732203SDimitry Andric         if (TimerIsEnabled) {
2840b57cec5SDimitry Andric           LLVMIRGenerationRefCount += 1;
2850b57cec5SDimitry Andric           if (LLVMIRGenerationRefCount == 1)
2860b57cec5SDimitry Andric             LLVMIRGeneration.startTimer();
2870b57cec5SDimitry Andric         }
2880b57cec5SDimitry Andric 
2890b57cec5SDimitry Andric         Gen->HandleTranslationUnit(C);
2900b57cec5SDimitry Andric 
291af732203SDimitry Andric         if (TimerIsEnabled) {
2920b57cec5SDimitry Andric           LLVMIRGenerationRefCount -= 1;
2930b57cec5SDimitry Andric           if (LLVMIRGenerationRefCount == 0)
2940b57cec5SDimitry Andric             LLVMIRGeneration.stopTimer();
2950b57cec5SDimitry Andric         }
2960b57cec5SDimitry Andric 
2970b57cec5SDimitry Andric         IRGenFinished = true;
2980b57cec5SDimitry Andric       }
2990b57cec5SDimitry Andric 
3000b57cec5SDimitry Andric       // Silently ignore if we weren't initialized for some reason.
3010b57cec5SDimitry Andric       if (!getModule())
3020b57cec5SDimitry Andric         return;
3030b57cec5SDimitry Andric 
3040b57cec5SDimitry Andric       LLVMContext &Ctx = getModule()->getContext();
3050b57cec5SDimitry Andric       std::unique_ptr<DiagnosticHandler> OldDiagnosticHandler =
3060b57cec5SDimitry Andric           Ctx.getDiagnosticHandler();
307a7dea167SDimitry Andric       Ctx.setDiagnosticHandler(std::make_unique<ClangDiagnosticHandler>(
3080b57cec5SDimitry Andric         CodeGenOpts, this));
3090b57cec5SDimitry Andric 
3100b57cec5SDimitry Andric       Expected<std::unique_ptr<llvm::ToolOutputFile>> OptRecordFileOrErr =
3115ffd83dbSDimitry Andric           setupLLVMOptimizationRemarks(
312480093f4SDimitry Andric               Ctx, CodeGenOpts.OptRecordFile, CodeGenOpts.OptRecordPasses,
313480093f4SDimitry Andric               CodeGenOpts.OptRecordFormat, CodeGenOpts.DiagnosticsWithHotness,
3140b57cec5SDimitry Andric               CodeGenOpts.DiagnosticsHotnessThreshold);
3150b57cec5SDimitry Andric 
3160b57cec5SDimitry Andric       if (Error E = OptRecordFileOrErr.takeError()) {
317480093f4SDimitry Andric         reportOptRecordError(std::move(E), Diags, CodeGenOpts);
3180b57cec5SDimitry Andric         return;
3190b57cec5SDimitry Andric       }
320480093f4SDimitry Andric 
3210b57cec5SDimitry Andric       std::unique_ptr<llvm::ToolOutputFile> OptRecordFile =
3220b57cec5SDimitry Andric           std::move(*OptRecordFileOrErr);
3230b57cec5SDimitry Andric 
3240b57cec5SDimitry Andric       if (OptRecordFile &&
3250b57cec5SDimitry Andric           CodeGenOpts.getProfileUse() != CodeGenOptions::ProfileNone)
3260b57cec5SDimitry Andric         Ctx.setDiagnosticsHotnessRequested(true);
3270b57cec5SDimitry Andric 
3280b57cec5SDimitry Andric       // Link each LinkModule into our module.
3290b57cec5SDimitry Andric       if (LinkInModules())
3300b57cec5SDimitry Andric         return;
3310b57cec5SDimitry Andric 
3320b57cec5SDimitry Andric       EmbedBitcode(getModule(), CodeGenOpts, llvm::MemoryBufferRef());
3330b57cec5SDimitry Andric 
3340b57cec5SDimitry Andric       EmitBackendOutput(Diags, HeaderSearchOpts, CodeGenOpts, TargetOpts,
335*5f7ddb14SDimitry Andric                         LangOpts, C.getTargetInfo().getDataLayoutString(),
3360b57cec5SDimitry Andric                         getModule(), Action, std::move(AsmOutStream));
3370b57cec5SDimitry Andric 
3380b57cec5SDimitry Andric       Ctx.setDiagnosticHandler(std::move(OldDiagnosticHandler));
3390b57cec5SDimitry Andric 
3400b57cec5SDimitry Andric       if (OptRecordFile)
3410b57cec5SDimitry Andric         OptRecordFile->keep();
3420b57cec5SDimitry Andric     }
3430b57cec5SDimitry Andric 
HandleTagDeclDefinition(TagDecl * D)3440b57cec5SDimitry Andric     void HandleTagDeclDefinition(TagDecl *D) override {
3450b57cec5SDimitry Andric       PrettyStackTraceDecl CrashInfo(D, SourceLocation(),
3460b57cec5SDimitry Andric                                      Context->getSourceManager(),
3470b57cec5SDimitry Andric                                      "LLVM IR generation of declaration");
3480b57cec5SDimitry Andric       Gen->HandleTagDeclDefinition(D);
3490b57cec5SDimitry Andric     }
3500b57cec5SDimitry Andric 
HandleTagDeclRequiredDefinition(const TagDecl * D)3510b57cec5SDimitry Andric     void HandleTagDeclRequiredDefinition(const TagDecl *D) override {
3520b57cec5SDimitry Andric       Gen->HandleTagDeclRequiredDefinition(D);
3530b57cec5SDimitry Andric     }
3540b57cec5SDimitry Andric 
CompleteTentativeDefinition(VarDecl * D)3550b57cec5SDimitry Andric     void CompleteTentativeDefinition(VarDecl *D) override {
3560b57cec5SDimitry Andric       Gen->CompleteTentativeDefinition(D);
3570b57cec5SDimitry Andric     }
3580b57cec5SDimitry Andric 
CompleteExternalDeclaration(VarDecl * D)359480093f4SDimitry Andric     void CompleteExternalDeclaration(VarDecl *D) override {
360480093f4SDimitry Andric       Gen->CompleteExternalDeclaration(D);
361480093f4SDimitry Andric     }
362480093f4SDimitry Andric 
AssignInheritanceModel(CXXRecordDecl * RD)3630b57cec5SDimitry Andric     void AssignInheritanceModel(CXXRecordDecl *RD) override {
3640b57cec5SDimitry Andric       Gen->AssignInheritanceModel(RD);
3650b57cec5SDimitry Andric     }
3660b57cec5SDimitry Andric 
HandleVTable(CXXRecordDecl * RD)3670b57cec5SDimitry Andric     void HandleVTable(CXXRecordDecl *RD) override {
3680b57cec5SDimitry Andric       Gen->HandleVTable(RD);
3690b57cec5SDimitry Andric     }
3700b57cec5SDimitry Andric 
3710b57cec5SDimitry Andric     /// Get the best possible source location to represent a diagnostic that
3720b57cec5SDimitry Andric     /// may have associated debug info.
3730b57cec5SDimitry Andric     const FullSourceLoc
3740b57cec5SDimitry Andric     getBestLocationFromDebugLoc(const llvm::DiagnosticInfoWithLocationBase &D,
3750b57cec5SDimitry Andric                                 bool &BadDebugInfo, StringRef &Filename,
3760b57cec5SDimitry Andric                                 unsigned &Line, unsigned &Column) const;
3770b57cec5SDimitry Andric 
3780b57cec5SDimitry Andric     void DiagnosticHandlerImpl(const llvm::DiagnosticInfo &DI);
3790b57cec5SDimitry Andric     /// Specialized handler for InlineAsm diagnostic.
3800b57cec5SDimitry Andric     /// \return True if the diagnostic has been successfully reported, false
3810b57cec5SDimitry Andric     /// otherwise.
3820b57cec5SDimitry Andric     bool InlineAsmDiagHandler(const llvm::DiagnosticInfoInlineAsm &D);
383*5f7ddb14SDimitry Andric     /// Specialized handler for diagnostics reported using SMDiagnostic.
384*5f7ddb14SDimitry Andric     void SrcMgrDiagHandler(const llvm::DiagnosticInfoSrcMgr &D);
3850b57cec5SDimitry Andric     /// Specialized handler for StackSize diagnostic.
3860b57cec5SDimitry Andric     /// \return True if the diagnostic has been successfully reported, false
3870b57cec5SDimitry Andric     /// otherwise.
3880b57cec5SDimitry Andric     bool StackSizeDiagHandler(const llvm::DiagnosticInfoStackSize &D);
3890b57cec5SDimitry Andric     /// Specialized handler for unsupported backend feature diagnostic.
3900b57cec5SDimitry Andric     void UnsupportedDiagHandler(const llvm::DiagnosticInfoUnsupported &D);
3910b57cec5SDimitry Andric     /// Specialized handlers for optimization remarks.
3920b57cec5SDimitry Andric     /// Note that these handlers only accept remarks and they always handle
3930b57cec5SDimitry Andric     /// them.
3940b57cec5SDimitry Andric     void EmitOptimizationMessage(const llvm::DiagnosticInfoOptimizationBase &D,
3950b57cec5SDimitry Andric                                  unsigned DiagID);
3960b57cec5SDimitry Andric     void
3970b57cec5SDimitry Andric     OptimizationRemarkHandler(const llvm::DiagnosticInfoOptimizationBase &D);
3980b57cec5SDimitry Andric     void OptimizationRemarkHandler(
3990b57cec5SDimitry Andric         const llvm::OptimizationRemarkAnalysisFPCommute &D);
4000b57cec5SDimitry Andric     void OptimizationRemarkHandler(
4010b57cec5SDimitry Andric         const llvm::OptimizationRemarkAnalysisAliasing &D);
4020b57cec5SDimitry Andric     void OptimizationFailureHandler(
4030b57cec5SDimitry Andric         const llvm::DiagnosticInfoOptimizationFailure &D);
4040b57cec5SDimitry Andric   };
4050b57cec5SDimitry Andric 
anchor()4060b57cec5SDimitry Andric   void BackendConsumer::anchor() {}
4070b57cec5SDimitry Andric }
4080b57cec5SDimitry Andric 
handleDiagnostics(const DiagnosticInfo & DI)4090b57cec5SDimitry Andric bool ClangDiagnosticHandler::handleDiagnostics(const DiagnosticInfo &DI) {
4100b57cec5SDimitry Andric   BackendCon->DiagnosticHandlerImpl(DI);
4110b57cec5SDimitry Andric   return true;
4120b57cec5SDimitry Andric }
4130b57cec5SDimitry Andric 
4140b57cec5SDimitry Andric /// ConvertBackendLocation - Convert a location in a temporary llvm::SourceMgr
4150b57cec5SDimitry Andric /// buffer to be a valid FullSourceLoc.
ConvertBackendLocation(const llvm::SMDiagnostic & D,SourceManager & CSM)4160b57cec5SDimitry Andric static FullSourceLoc ConvertBackendLocation(const llvm::SMDiagnostic &D,
4170b57cec5SDimitry Andric                                             SourceManager &CSM) {
4180b57cec5SDimitry Andric   // Get both the clang and llvm source managers.  The location is relative to
4190b57cec5SDimitry Andric   // a memory buffer that the LLVM Source Manager is handling, we need to add
4200b57cec5SDimitry Andric   // a copy to the Clang source manager.
4210b57cec5SDimitry Andric   const llvm::SourceMgr &LSM = *D.getSourceMgr();
4220b57cec5SDimitry Andric 
4230b57cec5SDimitry Andric   // We need to copy the underlying LLVM memory buffer because llvm::SourceMgr
4240b57cec5SDimitry Andric   // already owns its one and clang::SourceManager wants to own its one.
4250b57cec5SDimitry Andric   const MemoryBuffer *LBuf =
4260b57cec5SDimitry Andric   LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(D.getLoc()));
4270b57cec5SDimitry Andric 
4280b57cec5SDimitry Andric   // Create the copy and transfer ownership to clang::SourceManager.
4290b57cec5SDimitry Andric   // TODO: Avoid copying files into memory.
4300b57cec5SDimitry Andric   std::unique_ptr<llvm::MemoryBuffer> CBuf =
4310b57cec5SDimitry Andric       llvm::MemoryBuffer::getMemBufferCopy(LBuf->getBuffer(),
4320b57cec5SDimitry Andric                                            LBuf->getBufferIdentifier());
4330b57cec5SDimitry Andric   // FIXME: Keep a file ID map instead of creating new IDs for each location.
4340b57cec5SDimitry Andric   FileID FID = CSM.createFileID(std::move(CBuf));
4350b57cec5SDimitry Andric 
4360b57cec5SDimitry Andric   // Translate the offset into the file.
4370b57cec5SDimitry Andric   unsigned Offset = D.getLoc().getPointer() - LBuf->getBufferStart();
4380b57cec5SDimitry Andric   SourceLocation NewLoc =
4390b57cec5SDimitry Andric   CSM.getLocForStartOfFile(FID).getLocWithOffset(Offset);
4400b57cec5SDimitry Andric   return FullSourceLoc(NewLoc, CSM);
4410b57cec5SDimitry Andric }
4420b57cec5SDimitry Andric 
4430b57cec5SDimitry Andric #define ComputeDiagID(Severity, GroupName, DiagID)                             \
4440b57cec5SDimitry Andric   do {                                                                         \
4450b57cec5SDimitry Andric     switch (Severity) {                                                        \
4460b57cec5SDimitry Andric     case llvm::DS_Error:                                                       \
4470b57cec5SDimitry Andric       DiagID = diag::err_fe_##GroupName;                                       \
4480b57cec5SDimitry Andric       break;                                                                   \
4490b57cec5SDimitry Andric     case llvm::DS_Warning:                                                     \
4500b57cec5SDimitry Andric       DiagID = diag::warn_fe_##GroupName;                                      \
4510b57cec5SDimitry Andric       break;                                                                   \
4520b57cec5SDimitry Andric     case llvm::DS_Remark:                                                      \
4530b57cec5SDimitry Andric       llvm_unreachable("'remark' severity not expected");                      \
4540b57cec5SDimitry Andric       break;                                                                   \
4550b57cec5SDimitry Andric     case llvm::DS_Note:                                                        \
4560b57cec5SDimitry Andric       DiagID = diag::note_fe_##GroupName;                                      \
4570b57cec5SDimitry Andric       break;                                                                   \
4580b57cec5SDimitry Andric     }                                                                          \
4590b57cec5SDimitry Andric   } while (false)
4600b57cec5SDimitry Andric 
4610b57cec5SDimitry Andric #define ComputeDiagRemarkID(Severity, GroupName, DiagID)                       \
4620b57cec5SDimitry Andric   do {                                                                         \
4630b57cec5SDimitry Andric     switch (Severity) {                                                        \
4640b57cec5SDimitry Andric     case llvm::DS_Error:                                                       \
4650b57cec5SDimitry Andric       DiagID = diag::err_fe_##GroupName;                                       \
4660b57cec5SDimitry Andric       break;                                                                   \
4670b57cec5SDimitry Andric     case llvm::DS_Warning:                                                     \
4680b57cec5SDimitry Andric       DiagID = diag::warn_fe_##GroupName;                                      \
4690b57cec5SDimitry Andric       break;                                                                   \
4700b57cec5SDimitry Andric     case llvm::DS_Remark:                                                      \
4710b57cec5SDimitry Andric       DiagID = diag::remark_fe_##GroupName;                                    \
4720b57cec5SDimitry Andric       break;                                                                   \
4730b57cec5SDimitry Andric     case llvm::DS_Note:                                                        \
4740b57cec5SDimitry Andric       DiagID = diag::note_fe_##GroupName;                                      \
4750b57cec5SDimitry Andric       break;                                                                   \
4760b57cec5SDimitry Andric     }                                                                          \
4770b57cec5SDimitry Andric   } while (false)
4780b57cec5SDimitry Andric 
SrcMgrDiagHandler(const llvm::DiagnosticInfoSrcMgr & DI)479*5f7ddb14SDimitry Andric void BackendConsumer::SrcMgrDiagHandler(const llvm::DiagnosticInfoSrcMgr &DI) {
480*5f7ddb14SDimitry Andric   const llvm::SMDiagnostic &D = DI.getSMDiag();
481*5f7ddb14SDimitry Andric 
482*5f7ddb14SDimitry Andric   unsigned DiagID;
483*5f7ddb14SDimitry Andric   if (DI.isInlineAsmDiag())
484*5f7ddb14SDimitry Andric     ComputeDiagID(DI.getSeverity(), inline_asm, DiagID);
485*5f7ddb14SDimitry Andric   else
486*5f7ddb14SDimitry Andric     ComputeDiagID(DI.getSeverity(), source_mgr, DiagID);
487*5f7ddb14SDimitry Andric 
488*5f7ddb14SDimitry Andric   // This is for the empty BackendConsumer that uses the clang diagnostic
489*5f7ddb14SDimitry Andric   // handler for IR input files.
490*5f7ddb14SDimitry Andric   if (!Context) {
491*5f7ddb14SDimitry Andric     D.print(nullptr, llvm::errs());
492*5f7ddb14SDimitry Andric     Diags.Report(DiagID).AddString("cannot compile inline asm");
493*5f7ddb14SDimitry Andric     return;
494*5f7ddb14SDimitry Andric   }
495*5f7ddb14SDimitry Andric 
496*5f7ddb14SDimitry Andric   // There are a couple of different kinds of errors we could get here.
497*5f7ddb14SDimitry Andric   // First, we re-format the SMDiagnostic in terms of a clang diagnostic.
498*5f7ddb14SDimitry Andric 
499*5f7ddb14SDimitry Andric   // Strip "error: " off the start of the message string.
500*5f7ddb14SDimitry Andric   StringRef Message = D.getMessage();
501*5f7ddb14SDimitry Andric   (void)Message.consume_front("error: ");
502*5f7ddb14SDimitry Andric 
503*5f7ddb14SDimitry Andric   // If the SMDiagnostic has an inline asm source location, translate it.
504*5f7ddb14SDimitry Andric   FullSourceLoc Loc;
505*5f7ddb14SDimitry Andric   if (D.getLoc() != SMLoc())
506*5f7ddb14SDimitry Andric     Loc = ConvertBackendLocation(D, Context->getSourceManager());
507*5f7ddb14SDimitry Andric 
508*5f7ddb14SDimitry Andric   // If this problem has clang-level source location information, report the
509*5f7ddb14SDimitry Andric   // issue in the source with a note showing the instantiated
510*5f7ddb14SDimitry Andric   // code.
511*5f7ddb14SDimitry Andric   if (DI.isInlineAsmDiag()) {
512*5f7ddb14SDimitry Andric     SourceLocation LocCookie =
513*5f7ddb14SDimitry Andric         SourceLocation::getFromRawEncoding(DI.getLocCookie());
514*5f7ddb14SDimitry Andric     if (LocCookie.isValid()) {
515*5f7ddb14SDimitry Andric       Diags.Report(LocCookie, DiagID).AddString(Message);
516*5f7ddb14SDimitry Andric 
517*5f7ddb14SDimitry Andric       if (D.getLoc().isValid()) {
518*5f7ddb14SDimitry Andric         DiagnosticBuilder B = Diags.Report(Loc, diag::note_fe_inline_asm_here);
519*5f7ddb14SDimitry Andric         // Convert the SMDiagnostic ranges into SourceRange and attach them
520*5f7ddb14SDimitry Andric         // to the diagnostic.
521*5f7ddb14SDimitry Andric         for (const std::pair<unsigned, unsigned> &Range : D.getRanges()) {
522*5f7ddb14SDimitry Andric           unsigned Column = D.getColumnNo();
523*5f7ddb14SDimitry Andric           B << SourceRange(Loc.getLocWithOffset(Range.first - Column),
524*5f7ddb14SDimitry Andric                            Loc.getLocWithOffset(Range.second - Column));
525*5f7ddb14SDimitry Andric         }
526*5f7ddb14SDimitry Andric       }
527*5f7ddb14SDimitry Andric       return;
528*5f7ddb14SDimitry Andric     }
529*5f7ddb14SDimitry Andric   }
530*5f7ddb14SDimitry Andric 
531*5f7ddb14SDimitry Andric   // Otherwise, report the backend issue as occurring in the generated .s file.
532*5f7ddb14SDimitry Andric   // If Loc is invalid, we still need to report the issue, it just gets no
533*5f7ddb14SDimitry Andric   // location info.
534*5f7ddb14SDimitry Andric   Diags.Report(Loc, DiagID).AddString(Message);
535*5f7ddb14SDimitry Andric   return;
536*5f7ddb14SDimitry Andric }
537*5f7ddb14SDimitry Andric 
5380b57cec5SDimitry Andric bool
InlineAsmDiagHandler(const llvm::DiagnosticInfoInlineAsm & D)5390b57cec5SDimitry Andric BackendConsumer::InlineAsmDiagHandler(const llvm::DiagnosticInfoInlineAsm &D) {
5400b57cec5SDimitry Andric   unsigned DiagID;
5410b57cec5SDimitry Andric   ComputeDiagID(D.getSeverity(), inline_asm, DiagID);
5420b57cec5SDimitry Andric   std::string Message = D.getMsgStr().str();
5430b57cec5SDimitry Andric 
5440b57cec5SDimitry Andric   // If this problem has clang-level source location information, report the
5450b57cec5SDimitry Andric   // issue as being a problem in the source with a note showing the instantiated
5460b57cec5SDimitry Andric   // code.
5470b57cec5SDimitry Andric   SourceLocation LocCookie =
5480b57cec5SDimitry Andric       SourceLocation::getFromRawEncoding(D.getLocCookie());
5490b57cec5SDimitry Andric   if (LocCookie.isValid())
5500b57cec5SDimitry Andric     Diags.Report(LocCookie, DiagID).AddString(Message);
5510b57cec5SDimitry Andric   else {
5520b57cec5SDimitry Andric     // Otherwise, report the backend diagnostic as occurring in the generated
5530b57cec5SDimitry Andric     // .s file.
5540b57cec5SDimitry Andric     // If Loc is invalid, we still need to report the diagnostic, it just gets
5550b57cec5SDimitry Andric     // no location info.
5560b57cec5SDimitry Andric     FullSourceLoc Loc;
5570b57cec5SDimitry Andric     Diags.Report(Loc, DiagID).AddString(Message);
5580b57cec5SDimitry Andric   }
5590b57cec5SDimitry Andric   // We handled all the possible severities.
5600b57cec5SDimitry Andric   return true;
5610b57cec5SDimitry Andric }
5620b57cec5SDimitry Andric 
5630b57cec5SDimitry Andric bool
StackSizeDiagHandler(const llvm::DiagnosticInfoStackSize & D)5640b57cec5SDimitry Andric BackendConsumer::StackSizeDiagHandler(const llvm::DiagnosticInfoStackSize &D) {
5650b57cec5SDimitry Andric   if (D.getSeverity() != llvm::DS_Warning)
5660b57cec5SDimitry Andric     // For now, the only support we have for StackSize diagnostic is warning.
5670b57cec5SDimitry Andric     // We do not know how to format other severities.
5680b57cec5SDimitry Andric     return false;
5690b57cec5SDimitry Andric 
5700b57cec5SDimitry Andric   if (const Decl *ND = Gen->GetDeclForMangledName(D.getFunction().getName())) {
5710b57cec5SDimitry Andric     // FIXME: Shouldn't need to truncate to uint32_t
5720b57cec5SDimitry Andric     Diags.Report(ND->getASTContext().getFullLoc(ND->getLocation()),
5730b57cec5SDimitry Andric                  diag::warn_fe_frame_larger_than)
574*5f7ddb14SDimitry Andric         << static_cast<uint32_t>(D.getStackSize())
575*5f7ddb14SDimitry Andric         << static_cast<uint32_t>(D.getStackLimit())
576*5f7ddb14SDimitry Andric         << Decl::castToDeclContext(ND);
5770b57cec5SDimitry Andric     return true;
5780b57cec5SDimitry Andric   }
5790b57cec5SDimitry Andric 
5800b57cec5SDimitry Andric   return false;
5810b57cec5SDimitry Andric }
5820b57cec5SDimitry Andric 
getBestLocationFromDebugLoc(const llvm::DiagnosticInfoWithLocationBase & D,bool & BadDebugInfo,StringRef & Filename,unsigned & Line,unsigned & Column) const5830b57cec5SDimitry Andric const FullSourceLoc BackendConsumer::getBestLocationFromDebugLoc(
5840b57cec5SDimitry Andric     const llvm::DiagnosticInfoWithLocationBase &D, bool &BadDebugInfo,
5850b57cec5SDimitry Andric     StringRef &Filename, unsigned &Line, unsigned &Column) const {
5860b57cec5SDimitry Andric   SourceManager &SourceMgr = Context->getSourceManager();
5870b57cec5SDimitry Andric   FileManager &FileMgr = SourceMgr.getFileManager();
5880b57cec5SDimitry Andric   SourceLocation DILoc;
5890b57cec5SDimitry Andric 
5900b57cec5SDimitry Andric   if (D.isLocationAvailable()) {
5910b57cec5SDimitry Andric     D.getLocation(Filename, Line, Column);
5920b57cec5SDimitry Andric     if (Line > 0) {
593a7dea167SDimitry Andric       auto FE = FileMgr.getFile(Filename);
5940b57cec5SDimitry Andric       if (!FE)
5950b57cec5SDimitry Andric         FE = FileMgr.getFile(D.getAbsolutePath());
5960b57cec5SDimitry Andric       if (FE) {
5970b57cec5SDimitry Andric         // If -gcolumn-info was not used, Column will be 0. This upsets the
5980b57cec5SDimitry Andric         // source manager, so pass 1 if Column is not set.
599a7dea167SDimitry Andric         DILoc = SourceMgr.translateFileLineCol(*FE, Line, Column ? Column : 1);
6000b57cec5SDimitry Andric       }
6010b57cec5SDimitry Andric     }
6020b57cec5SDimitry Andric     BadDebugInfo = DILoc.isInvalid();
6030b57cec5SDimitry Andric   }
6040b57cec5SDimitry Andric 
6050b57cec5SDimitry Andric   // If a location isn't available, try to approximate it using the associated
6060b57cec5SDimitry Andric   // function definition. We use the definition's right brace to differentiate
6070b57cec5SDimitry Andric   // from diagnostics that genuinely relate to the function itself.
6080b57cec5SDimitry Andric   FullSourceLoc Loc(DILoc, SourceMgr);
6090b57cec5SDimitry Andric   if (Loc.isInvalid())
6100b57cec5SDimitry Andric     if (const Decl *FD = Gen->GetDeclForMangledName(D.getFunction().getName()))
6110b57cec5SDimitry Andric       Loc = FD->getASTContext().getFullLoc(FD->getLocation());
6120b57cec5SDimitry Andric 
6130b57cec5SDimitry Andric   if (DILoc.isInvalid() && D.isLocationAvailable())
6140b57cec5SDimitry Andric     // If we were not able to translate the file:line:col information
6150b57cec5SDimitry Andric     // back to a SourceLocation, at least emit a note stating that
6160b57cec5SDimitry Andric     // we could not translate this location. This can happen in the
6170b57cec5SDimitry Andric     // case of #line directives.
6180b57cec5SDimitry Andric     Diags.Report(Loc, diag::note_fe_backend_invalid_loc)
6190b57cec5SDimitry Andric         << Filename << Line << Column;
6200b57cec5SDimitry Andric 
6210b57cec5SDimitry Andric   return Loc;
6220b57cec5SDimitry Andric }
6230b57cec5SDimitry Andric 
UnsupportedDiagHandler(const llvm::DiagnosticInfoUnsupported & D)6240b57cec5SDimitry Andric void BackendConsumer::UnsupportedDiagHandler(
6250b57cec5SDimitry Andric     const llvm::DiagnosticInfoUnsupported &D) {
6265ffd83dbSDimitry Andric   // We only support warnings or errors.
6275ffd83dbSDimitry Andric   assert(D.getSeverity() == llvm::DS_Error ||
6285ffd83dbSDimitry Andric          D.getSeverity() == llvm::DS_Warning);
6290b57cec5SDimitry Andric 
6300b57cec5SDimitry Andric   StringRef Filename;
6310b57cec5SDimitry Andric   unsigned Line, Column;
6320b57cec5SDimitry Andric   bool BadDebugInfo = false;
633480093f4SDimitry Andric   FullSourceLoc Loc;
634480093f4SDimitry Andric   std::string Msg;
635480093f4SDimitry Andric   raw_string_ostream MsgStream(Msg);
6360b57cec5SDimitry Andric 
637480093f4SDimitry Andric   // Context will be nullptr for IR input files, we will construct the diag
638480093f4SDimitry Andric   // message from llvm::DiagnosticInfoUnsupported.
639480093f4SDimitry Andric   if (Context != nullptr) {
640480093f4SDimitry Andric     Loc = getBestLocationFromDebugLoc(D, BadDebugInfo, Filename, Line, Column);
641480093f4SDimitry Andric     MsgStream << D.getMessage();
642480093f4SDimitry Andric   } else {
643480093f4SDimitry Andric     DiagnosticPrinterRawOStream DP(MsgStream);
644480093f4SDimitry Andric     D.print(DP);
645480093f4SDimitry Andric   }
6465ffd83dbSDimitry Andric 
6475ffd83dbSDimitry Andric   auto DiagType = D.getSeverity() == llvm::DS_Error
6485ffd83dbSDimitry Andric                       ? diag::err_fe_backend_unsupported
6495ffd83dbSDimitry Andric                       : diag::warn_fe_backend_unsupported;
6505ffd83dbSDimitry Andric   Diags.Report(Loc, DiagType) << MsgStream.str();
6510b57cec5SDimitry Andric 
6520b57cec5SDimitry Andric   if (BadDebugInfo)
6530b57cec5SDimitry Andric     // If we were not able to translate the file:line:col information
6540b57cec5SDimitry Andric     // back to a SourceLocation, at least emit a note stating that
6550b57cec5SDimitry Andric     // we could not translate this location. This can happen in the
6560b57cec5SDimitry Andric     // case of #line directives.
6570b57cec5SDimitry Andric     Diags.Report(Loc, diag::note_fe_backend_invalid_loc)
6580b57cec5SDimitry Andric         << Filename << Line << Column;
6590b57cec5SDimitry Andric }
6600b57cec5SDimitry Andric 
EmitOptimizationMessage(const llvm::DiagnosticInfoOptimizationBase & D,unsigned DiagID)6610b57cec5SDimitry Andric void BackendConsumer::EmitOptimizationMessage(
6620b57cec5SDimitry Andric     const llvm::DiagnosticInfoOptimizationBase &D, unsigned DiagID) {
6630b57cec5SDimitry Andric   // We only support warnings and remarks.
6640b57cec5SDimitry Andric   assert(D.getSeverity() == llvm::DS_Remark ||
6650b57cec5SDimitry Andric          D.getSeverity() == llvm::DS_Warning);
6660b57cec5SDimitry Andric 
6670b57cec5SDimitry Andric   StringRef Filename;
6680b57cec5SDimitry Andric   unsigned Line, Column;
6690b57cec5SDimitry Andric   bool BadDebugInfo = false;
670480093f4SDimitry Andric   FullSourceLoc Loc;
6710b57cec5SDimitry Andric   std::string Msg;
6720b57cec5SDimitry Andric   raw_string_ostream MsgStream(Msg);
673480093f4SDimitry Andric 
674480093f4SDimitry Andric   // Context will be nullptr for IR input files, we will construct the remark
675480093f4SDimitry Andric   // message from llvm::DiagnosticInfoOptimizationBase.
676480093f4SDimitry Andric   if (Context != nullptr) {
677480093f4SDimitry Andric     Loc = getBestLocationFromDebugLoc(D, BadDebugInfo, Filename, Line, Column);
6780b57cec5SDimitry Andric     MsgStream << D.getMsg();
679480093f4SDimitry Andric   } else {
680480093f4SDimitry Andric     DiagnosticPrinterRawOStream DP(MsgStream);
681480093f4SDimitry Andric     D.print(DP);
682480093f4SDimitry Andric   }
6830b57cec5SDimitry Andric 
6840b57cec5SDimitry Andric   if (D.getHotness())
6850b57cec5SDimitry Andric     MsgStream << " (hotness: " << *D.getHotness() << ")";
6860b57cec5SDimitry Andric 
6870b57cec5SDimitry Andric   Diags.Report(Loc, DiagID)
6880b57cec5SDimitry Andric       << AddFlagValue(D.getPassName())
6890b57cec5SDimitry Andric       << MsgStream.str();
6900b57cec5SDimitry Andric 
6910b57cec5SDimitry Andric   if (BadDebugInfo)
6920b57cec5SDimitry Andric     // If we were not able to translate the file:line:col information
6930b57cec5SDimitry Andric     // back to a SourceLocation, at least emit a note stating that
6940b57cec5SDimitry Andric     // we could not translate this location. This can happen in the
6950b57cec5SDimitry Andric     // case of #line directives.
6960b57cec5SDimitry Andric     Diags.Report(Loc, diag::note_fe_backend_invalid_loc)
6970b57cec5SDimitry Andric         << Filename << Line << Column;
6980b57cec5SDimitry Andric }
6990b57cec5SDimitry Andric 
OptimizationRemarkHandler(const llvm::DiagnosticInfoOptimizationBase & D)7000b57cec5SDimitry Andric void BackendConsumer::OptimizationRemarkHandler(
7010b57cec5SDimitry Andric     const llvm::DiagnosticInfoOptimizationBase &D) {
7020b57cec5SDimitry Andric   // Without hotness information, don't show noisy remarks.
7030b57cec5SDimitry Andric   if (D.isVerbose() && !D.getHotness())
7040b57cec5SDimitry Andric     return;
7050b57cec5SDimitry Andric 
7060b57cec5SDimitry Andric   if (D.isPassed()) {
7070b57cec5SDimitry Andric     // Optimization remarks are active only if the -Rpass flag has a regular
7080b57cec5SDimitry Andric     // expression that matches the name of the pass name in \p D.
709*5f7ddb14SDimitry Andric     if (CodeGenOpts.OptimizationRemark.patternMatches(D.getPassName()))
7100b57cec5SDimitry Andric       EmitOptimizationMessage(D, diag::remark_fe_backend_optimization_remark);
7110b57cec5SDimitry Andric   } else if (D.isMissed()) {
7120b57cec5SDimitry Andric     // Missed optimization remarks are active only if the -Rpass-missed
7130b57cec5SDimitry Andric     // flag has a regular expression that matches the name of the pass
7140b57cec5SDimitry Andric     // name in \p D.
715*5f7ddb14SDimitry Andric     if (CodeGenOpts.OptimizationRemarkMissed.patternMatches(D.getPassName()))
7160b57cec5SDimitry Andric       EmitOptimizationMessage(
7170b57cec5SDimitry Andric           D, diag::remark_fe_backend_optimization_remark_missed);
7180b57cec5SDimitry Andric   } else {
7190b57cec5SDimitry Andric     assert(D.isAnalysis() && "Unknown remark type");
7200b57cec5SDimitry Andric 
7210b57cec5SDimitry Andric     bool ShouldAlwaysPrint = false;
7220b57cec5SDimitry Andric     if (auto *ORA = dyn_cast<llvm::OptimizationRemarkAnalysis>(&D))
7230b57cec5SDimitry Andric       ShouldAlwaysPrint = ORA->shouldAlwaysPrint();
7240b57cec5SDimitry Andric 
7250b57cec5SDimitry Andric     if (ShouldAlwaysPrint ||
726*5f7ddb14SDimitry Andric         CodeGenOpts.OptimizationRemarkAnalysis.patternMatches(D.getPassName()))
7270b57cec5SDimitry Andric       EmitOptimizationMessage(
7280b57cec5SDimitry Andric           D, diag::remark_fe_backend_optimization_remark_analysis);
7290b57cec5SDimitry Andric   }
7300b57cec5SDimitry Andric }
7310b57cec5SDimitry Andric 
OptimizationRemarkHandler(const llvm::OptimizationRemarkAnalysisFPCommute & D)7320b57cec5SDimitry Andric void BackendConsumer::OptimizationRemarkHandler(
7330b57cec5SDimitry Andric     const llvm::OptimizationRemarkAnalysisFPCommute &D) {
7340b57cec5SDimitry Andric   // Optimization analysis remarks are active if the pass name is set to
7350b57cec5SDimitry Andric   // llvm::DiagnosticInfo::AlwasyPrint or if the -Rpass-analysis flag has a
7360b57cec5SDimitry Andric   // regular expression that matches the name of the pass name in \p D.
7370b57cec5SDimitry Andric 
7380b57cec5SDimitry Andric   if (D.shouldAlwaysPrint() ||
739*5f7ddb14SDimitry Andric       CodeGenOpts.OptimizationRemarkAnalysis.patternMatches(D.getPassName()))
7400b57cec5SDimitry Andric     EmitOptimizationMessage(
7410b57cec5SDimitry Andric         D, diag::remark_fe_backend_optimization_remark_analysis_fpcommute);
7420b57cec5SDimitry Andric }
7430b57cec5SDimitry Andric 
OptimizationRemarkHandler(const llvm::OptimizationRemarkAnalysisAliasing & D)7440b57cec5SDimitry Andric void BackendConsumer::OptimizationRemarkHandler(
7450b57cec5SDimitry Andric     const llvm::OptimizationRemarkAnalysisAliasing &D) {
7460b57cec5SDimitry Andric   // Optimization analysis remarks are active if the pass name is set to
7470b57cec5SDimitry Andric   // llvm::DiagnosticInfo::AlwasyPrint or if the -Rpass-analysis flag has a
7480b57cec5SDimitry Andric   // regular expression that matches the name of the pass name in \p D.
7490b57cec5SDimitry Andric 
7500b57cec5SDimitry Andric   if (D.shouldAlwaysPrint() ||
751*5f7ddb14SDimitry Andric       CodeGenOpts.OptimizationRemarkAnalysis.patternMatches(D.getPassName()))
7520b57cec5SDimitry Andric     EmitOptimizationMessage(
7530b57cec5SDimitry Andric         D, diag::remark_fe_backend_optimization_remark_analysis_aliasing);
7540b57cec5SDimitry Andric }
7550b57cec5SDimitry Andric 
OptimizationFailureHandler(const llvm::DiagnosticInfoOptimizationFailure & D)7560b57cec5SDimitry Andric void BackendConsumer::OptimizationFailureHandler(
7570b57cec5SDimitry Andric     const llvm::DiagnosticInfoOptimizationFailure &D) {
7580b57cec5SDimitry Andric   EmitOptimizationMessage(D, diag::warn_fe_backend_optimization_failure);
7590b57cec5SDimitry Andric }
7600b57cec5SDimitry Andric 
7610b57cec5SDimitry Andric /// This function is invoked when the backend needs
7620b57cec5SDimitry Andric /// to report something to the user.
DiagnosticHandlerImpl(const DiagnosticInfo & DI)7630b57cec5SDimitry Andric void BackendConsumer::DiagnosticHandlerImpl(const DiagnosticInfo &DI) {
7640b57cec5SDimitry Andric   unsigned DiagID = diag::err_fe_inline_asm;
7650b57cec5SDimitry Andric   llvm::DiagnosticSeverity Severity = DI.getSeverity();
7660b57cec5SDimitry Andric   // Get the diagnostic ID based.
7670b57cec5SDimitry Andric   switch (DI.getKind()) {
7680b57cec5SDimitry Andric   case llvm::DK_InlineAsm:
7690b57cec5SDimitry Andric     if (InlineAsmDiagHandler(cast<DiagnosticInfoInlineAsm>(DI)))
7700b57cec5SDimitry Andric       return;
7710b57cec5SDimitry Andric     ComputeDiagID(Severity, inline_asm, DiagID);
7720b57cec5SDimitry Andric     break;
773*5f7ddb14SDimitry Andric   case llvm::DK_SrcMgr:
774*5f7ddb14SDimitry Andric     SrcMgrDiagHandler(cast<DiagnosticInfoSrcMgr>(DI));
775*5f7ddb14SDimitry Andric     return;
7760b57cec5SDimitry Andric   case llvm::DK_StackSize:
7770b57cec5SDimitry Andric     if (StackSizeDiagHandler(cast<DiagnosticInfoStackSize>(DI)))
7780b57cec5SDimitry Andric       return;
7790b57cec5SDimitry Andric     ComputeDiagID(Severity, backend_frame_larger_than, DiagID);
7800b57cec5SDimitry Andric     break;
7810b57cec5SDimitry Andric   case DK_Linker:
7820b57cec5SDimitry Andric     assert(CurLinkModule);
7830b57cec5SDimitry Andric     // FIXME: stop eating the warnings and notes.
7840b57cec5SDimitry Andric     if (Severity != DS_Error)
7850b57cec5SDimitry Andric       return;
7860b57cec5SDimitry Andric     DiagID = diag::err_fe_cannot_link_module;
7870b57cec5SDimitry Andric     break;
7880b57cec5SDimitry Andric   case llvm::DK_OptimizationRemark:
7890b57cec5SDimitry Andric     // Optimization remarks are always handled completely by this
7900b57cec5SDimitry Andric     // handler. There is no generic way of emitting them.
7910b57cec5SDimitry Andric     OptimizationRemarkHandler(cast<OptimizationRemark>(DI));
7920b57cec5SDimitry Andric     return;
7930b57cec5SDimitry Andric   case llvm::DK_OptimizationRemarkMissed:
7940b57cec5SDimitry Andric     // Optimization remarks are always handled completely by this
7950b57cec5SDimitry Andric     // handler. There is no generic way of emitting them.
7960b57cec5SDimitry Andric     OptimizationRemarkHandler(cast<OptimizationRemarkMissed>(DI));
7970b57cec5SDimitry Andric     return;
7980b57cec5SDimitry Andric   case llvm::DK_OptimizationRemarkAnalysis:
7990b57cec5SDimitry Andric     // Optimization remarks are always handled completely by this
8000b57cec5SDimitry Andric     // handler. There is no generic way of emitting them.
8010b57cec5SDimitry Andric     OptimizationRemarkHandler(cast<OptimizationRemarkAnalysis>(DI));
8020b57cec5SDimitry Andric     return;
8030b57cec5SDimitry Andric   case llvm::DK_OptimizationRemarkAnalysisFPCommute:
8040b57cec5SDimitry Andric     // Optimization remarks are always handled completely by this
8050b57cec5SDimitry Andric     // handler. There is no generic way of emitting them.
8060b57cec5SDimitry Andric     OptimizationRemarkHandler(cast<OptimizationRemarkAnalysisFPCommute>(DI));
8070b57cec5SDimitry Andric     return;
8080b57cec5SDimitry Andric   case llvm::DK_OptimizationRemarkAnalysisAliasing:
8090b57cec5SDimitry Andric     // Optimization remarks are always handled completely by this
8100b57cec5SDimitry Andric     // handler. There is no generic way of emitting them.
8110b57cec5SDimitry Andric     OptimizationRemarkHandler(cast<OptimizationRemarkAnalysisAliasing>(DI));
8120b57cec5SDimitry Andric     return;
8130b57cec5SDimitry Andric   case llvm::DK_MachineOptimizationRemark:
8140b57cec5SDimitry Andric     // Optimization remarks are always handled completely by this
8150b57cec5SDimitry Andric     // handler. There is no generic way of emitting them.
8160b57cec5SDimitry Andric     OptimizationRemarkHandler(cast<MachineOptimizationRemark>(DI));
8170b57cec5SDimitry Andric     return;
8180b57cec5SDimitry Andric   case llvm::DK_MachineOptimizationRemarkMissed:
8190b57cec5SDimitry Andric     // Optimization remarks are always handled completely by this
8200b57cec5SDimitry Andric     // handler. There is no generic way of emitting them.
8210b57cec5SDimitry Andric     OptimizationRemarkHandler(cast<MachineOptimizationRemarkMissed>(DI));
8220b57cec5SDimitry Andric     return;
8230b57cec5SDimitry Andric   case llvm::DK_MachineOptimizationRemarkAnalysis:
8240b57cec5SDimitry Andric     // Optimization remarks are always handled completely by this
8250b57cec5SDimitry Andric     // handler. There is no generic way of emitting them.
8260b57cec5SDimitry Andric     OptimizationRemarkHandler(cast<MachineOptimizationRemarkAnalysis>(DI));
8270b57cec5SDimitry Andric     return;
8280b57cec5SDimitry Andric   case llvm::DK_OptimizationFailure:
8290b57cec5SDimitry Andric     // Optimization failures are always handled completely by this
8300b57cec5SDimitry Andric     // handler.
8310b57cec5SDimitry Andric     OptimizationFailureHandler(cast<DiagnosticInfoOptimizationFailure>(DI));
8320b57cec5SDimitry Andric     return;
8330b57cec5SDimitry Andric   case llvm::DK_Unsupported:
8340b57cec5SDimitry Andric     UnsupportedDiagHandler(cast<DiagnosticInfoUnsupported>(DI));
8350b57cec5SDimitry Andric     return;
8360b57cec5SDimitry Andric   default:
8370b57cec5SDimitry Andric     // Plugin IDs are not bound to any value as they are set dynamically.
8380b57cec5SDimitry Andric     ComputeDiagRemarkID(Severity, backend_plugin, DiagID);
8390b57cec5SDimitry Andric     break;
8400b57cec5SDimitry Andric   }
8410b57cec5SDimitry Andric   std::string MsgStorage;
8420b57cec5SDimitry Andric   {
8430b57cec5SDimitry Andric     raw_string_ostream Stream(MsgStorage);
8440b57cec5SDimitry Andric     DiagnosticPrinterRawOStream DP(Stream);
8450b57cec5SDimitry Andric     DI.print(DP);
8460b57cec5SDimitry Andric   }
8470b57cec5SDimitry Andric 
8480b57cec5SDimitry Andric   if (DiagID == diag::err_fe_cannot_link_module) {
8490b57cec5SDimitry Andric     Diags.Report(diag::err_fe_cannot_link_module)
8500b57cec5SDimitry Andric         << CurLinkModule->getModuleIdentifier() << MsgStorage;
8510b57cec5SDimitry Andric     return;
8520b57cec5SDimitry Andric   }
8530b57cec5SDimitry Andric 
8540b57cec5SDimitry Andric   // Report the backend message using the usual diagnostic mechanism.
8550b57cec5SDimitry Andric   FullSourceLoc Loc;
8560b57cec5SDimitry Andric   Diags.Report(Loc, DiagID).AddString(MsgStorage);
8570b57cec5SDimitry Andric }
8580b57cec5SDimitry Andric #undef ComputeDiagID
8590b57cec5SDimitry Andric 
CodeGenAction(unsigned _Act,LLVMContext * _VMContext)8600b57cec5SDimitry Andric CodeGenAction::CodeGenAction(unsigned _Act, LLVMContext *_VMContext)
8610b57cec5SDimitry Andric     : Act(_Act), VMContext(_VMContext ? _VMContext : new LLVMContext),
8620b57cec5SDimitry Andric       OwnsVMContext(!_VMContext) {}
8630b57cec5SDimitry Andric 
~CodeGenAction()8640b57cec5SDimitry Andric CodeGenAction::~CodeGenAction() {
8650b57cec5SDimitry Andric   TheModule.reset();
8660b57cec5SDimitry Andric   if (OwnsVMContext)
8670b57cec5SDimitry Andric     delete VMContext;
8680b57cec5SDimitry Andric }
8690b57cec5SDimitry Andric 
hasIRSupport() const8700b57cec5SDimitry Andric bool CodeGenAction::hasIRSupport() const { return true; }
8710b57cec5SDimitry Andric 
EndSourceFileAction()8720b57cec5SDimitry Andric void CodeGenAction::EndSourceFileAction() {
8730b57cec5SDimitry Andric   // If the consumer creation failed, do nothing.
8740b57cec5SDimitry Andric   if (!getCompilerInstance().hasASTConsumer())
8750b57cec5SDimitry Andric     return;
8760b57cec5SDimitry Andric 
8770b57cec5SDimitry Andric   // Steal the module from the consumer.
8780b57cec5SDimitry Andric   TheModule = BEConsumer->takeModule();
8790b57cec5SDimitry Andric }
8800b57cec5SDimitry Andric 
takeModule()8810b57cec5SDimitry Andric std::unique_ptr<llvm::Module> CodeGenAction::takeModule() {
8820b57cec5SDimitry Andric   return std::move(TheModule);
8830b57cec5SDimitry Andric }
8840b57cec5SDimitry Andric 
takeLLVMContext()8850b57cec5SDimitry Andric llvm::LLVMContext *CodeGenAction::takeLLVMContext() {
8860b57cec5SDimitry Andric   OwnsVMContext = false;
8870b57cec5SDimitry Andric   return VMContext;
8880b57cec5SDimitry Andric }
8890b57cec5SDimitry Andric 
getCodeGenerator() const890*5f7ddb14SDimitry Andric CodeGenerator *CodeGenAction::getCodeGenerator() const {
891*5f7ddb14SDimitry Andric   return BEConsumer->getCodeGenerator();
892*5f7ddb14SDimitry Andric }
893*5f7ddb14SDimitry Andric 
8940b57cec5SDimitry Andric static std::unique_ptr<raw_pwrite_stream>
GetOutputStream(CompilerInstance & CI,StringRef InFile,BackendAction Action)8950b57cec5SDimitry Andric GetOutputStream(CompilerInstance &CI, StringRef InFile, BackendAction Action) {
8960b57cec5SDimitry Andric   switch (Action) {
8970b57cec5SDimitry Andric   case Backend_EmitAssembly:
8980b57cec5SDimitry Andric     return CI.createDefaultOutputFile(false, InFile, "s");
8990b57cec5SDimitry Andric   case Backend_EmitLL:
9000b57cec5SDimitry Andric     return CI.createDefaultOutputFile(false, InFile, "ll");
9010b57cec5SDimitry Andric   case Backend_EmitBC:
9020b57cec5SDimitry Andric     return CI.createDefaultOutputFile(true, InFile, "bc");
9030b57cec5SDimitry Andric   case Backend_EmitNothing:
9040b57cec5SDimitry Andric     return nullptr;
9050b57cec5SDimitry Andric   case Backend_EmitMCNull:
9060b57cec5SDimitry Andric     return CI.createNullOutputFile();
9070b57cec5SDimitry Andric   case Backend_EmitObj:
9080b57cec5SDimitry Andric     return CI.createDefaultOutputFile(true, InFile, "o");
9090b57cec5SDimitry Andric   }
9100b57cec5SDimitry Andric 
9110b57cec5SDimitry Andric   llvm_unreachable("Invalid action!");
9120b57cec5SDimitry Andric }
9130b57cec5SDimitry Andric 
9140b57cec5SDimitry Andric std::unique_ptr<ASTConsumer>
CreateASTConsumer(CompilerInstance & CI,StringRef InFile)9150b57cec5SDimitry Andric CodeGenAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
9160b57cec5SDimitry Andric   BackendAction BA = static_cast<BackendAction>(Act);
9170b57cec5SDimitry Andric   std::unique_ptr<raw_pwrite_stream> OS = CI.takeOutputStream();
9180b57cec5SDimitry Andric   if (!OS)
9190b57cec5SDimitry Andric     OS = GetOutputStream(CI, InFile, BA);
9200b57cec5SDimitry Andric 
9210b57cec5SDimitry Andric   if (BA != Backend_EmitNothing && !OS)
9220b57cec5SDimitry Andric     return nullptr;
9230b57cec5SDimitry Andric 
9240b57cec5SDimitry Andric   // Load bitcode modules to link with, if we need to.
9250b57cec5SDimitry Andric   if (LinkModules.empty())
9260b57cec5SDimitry Andric     for (const CodeGenOptions::BitcodeFileToLink &F :
9270b57cec5SDimitry Andric          CI.getCodeGenOpts().LinkBitcodeFiles) {
9280b57cec5SDimitry Andric       auto BCBuf = CI.getFileManager().getBufferForFile(F.Filename);
9290b57cec5SDimitry Andric       if (!BCBuf) {
9300b57cec5SDimitry Andric         CI.getDiagnostics().Report(diag::err_cannot_open_file)
9310b57cec5SDimitry Andric             << F.Filename << BCBuf.getError().message();
9320b57cec5SDimitry Andric         LinkModules.clear();
9330b57cec5SDimitry Andric         return nullptr;
9340b57cec5SDimitry Andric       }
9350b57cec5SDimitry Andric 
9360b57cec5SDimitry Andric       Expected<std::unique_ptr<llvm::Module>> ModuleOrErr =
9370b57cec5SDimitry Andric           getOwningLazyBitcodeModule(std::move(*BCBuf), *VMContext);
9380b57cec5SDimitry Andric       if (!ModuleOrErr) {
9390b57cec5SDimitry Andric         handleAllErrors(ModuleOrErr.takeError(), [&](ErrorInfoBase &EIB) {
9400b57cec5SDimitry Andric           CI.getDiagnostics().Report(diag::err_cannot_open_file)
9410b57cec5SDimitry Andric               << F.Filename << EIB.message();
9420b57cec5SDimitry Andric         });
9430b57cec5SDimitry Andric         LinkModules.clear();
9440b57cec5SDimitry Andric         return nullptr;
9450b57cec5SDimitry Andric       }
9460b57cec5SDimitry Andric       LinkModules.push_back({std::move(ModuleOrErr.get()), F.PropagateAttrs,
9470b57cec5SDimitry Andric                              F.Internalize, F.LinkFlags});
9480b57cec5SDimitry Andric     }
9490b57cec5SDimitry Andric 
9500b57cec5SDimitry Andric   CoverageSourceInfo *CoverageInfo = nullptr;
9510b57cec5SDimitry Andric   // Add the preprocessor callback only when the coverage mapping is generated.
952af732203SDimitry Andric   if (CI.getCodeGenOpts().CoverageMapping)
953af732203SDimitry Andric     CoverageInfo = CodeGen::CoverageMappingModuleGen::setUpCoverageCallbacks(
954af732203SDimitry Andric         CI.getPreprocessor());
9550b57cec5SDimitry Andric 
9560b57cec5SDimitry Andric   std::unique_ptr<BackendConsumer> Result(new BackendConsumer(
9570b57cec5SDimitry Andric       BA, CI.getDiagnostics(), CI.getHeaderSearchOpts(),
9580b57cec5SDimitry Andric       CI.getPreprocessorOpts(), CI.getCodeGenOpts(), CI.getTargetOpts(),
959af732203SDimitry Andric       CI.getLangOpts(), std::string(InFile), std::move(LinkModules),
960af732203SDimitry Andric       std::move(OS), *VMContext, CoverageInfo));
9610b57cec5SDimitry Andric   BEConsumer = Result.get();
9620b57cec5SDimitry Andric 
9630b57cec5SDimitry Andric   // Enable generating macro debug info only when debug info is not disabled and
9640b57cec5SDimitry Andric   // also macro debug info is enabled.
9650b57cec5SDimitry Andric   if (CI.getCodeGenOpts().getDebugInfo() != codegenoptions::NoDebugInfo &&
9660b57cec5SDimitry Andric       CI.getCodeGenOpts().MacroDebugInfo) {
9670b57cec5SDimitry Andric     std::unique_ptr<PPCallbacks> Callbacks =
968a7dea167SDimitry Andric         std::make_unique<MacroPPCallbacks>(BEConsumer->getCodeGenerator(),
9690b57cec5SDimitry Andric                                             CI.getPreprocessor());
9700b57cec5SDimitry Andric     CI.getPreprocessor().addPPCallbacks(std::move(Callbacks));
9710b57cec5SDimitry Andric   }
9720b57cec5SDimitry Andric 
9730b57cec5SDimitry Andric   return std::move(Result);
9740b57cec5SDimitry Andric }
9750b57cec5SDimitry Andric 
9760b57cec5SDimitry Andric std::unique_ptr<llvm::Module>
loadModule(MemoryBufferRef MBRef)9770b57cec5SDimitry Andric CodeGenAction::loadModule(MemoryBufferRef MBRef) {
9780b57cec5SDimitry Andric   CompilerInstance &CI = getCompilerInstance();
9790b57cec5SDimitry Andric   SourceManager &SM = CI.getSourceManager();
9800b57cec5SDimitry Andric 
9810b57cec5SDimitry Andric   // For ThinLTO backend invocations, ensure that the context
9820b57cec5SDimitry Andric   // merges types based on ODR identifiers. We also need to read
9830b57cec5SDimitry Andric   // the correct module out of a multi-module bitcode file.
9840b57cec5SDimitry Andric   if (!CI.getCodeGenOpts().ThinLTOIndexFile.empty()) {
9850b57cec5SDimitry Andric     VMContext->enableDebugTypeODRUniquing();
9860b57cec5SDimitry Andric 
9870b57cec5SDimitry Andric     auto DiagErrors = [&](Error E) -> std::unique_ptr<llvm::Module> {
9880b57cec5SDimitry Andric       unsigned DiagID =
9890b57cec5SDimitry Andric           CI.getDiagnostics().getCustomDiagID(DiagnosticsEngine::Error, "%0");
9900b57cec5SDimitry Andric       handleAllErrors(std::move(E), [&](ErrorInfoBase &EIB) {
9910b57cec5SDimitry Andric         CI.getDiagnostics().Report(DiagID) << EIB.message();
9920b57cec5SDimitry Andric       });
9930b57cec5SDimitry Andric       return {};
9940b57cec5SDimitry Andric     };
9950b57cec5SDimitry Andric 
9960b57cec5SDimitry Andric     Expected<std::vector<BitcodeModule>> BMsOrErr = getBitcodeModuleList(MBRef);
9970b57cec5SDimitry Andric     if (!BMsOrErr)
9980b57cec5SDimitry Andric       return DiagErrors(BMsOrErr.takeError());
999af732203SDimitry Andric     BitcodeModule *Bm = llvm::lto::findThinLTOModule(*BMsOrErr);
10000b57cec5SDimitry Andric     // We have nothing to do if the file contains no ThinLTO module. This is
10010b57cec5SDimitry Andric     // possible if ThinLTO compilation was not able to split module. Content of
10020b57cec5SDimitry Andric     // the file was already processed by indexing and will be passed to the
10030b57cec5SDimitry Andric     // linker using merged object file.
10040b57cec5SDimitry Andric     if (!Bm) {
1005a7dea167SDimitry Andric       auto M = std::make_unique<llvm::Module>("empty", *VMContext);
10060b57cec5SDimitry Andric       M->setTargetTriple(CI.getTargetOpts().Triple);
10070b57cec5SDimitry Andric       return M;
10080b57cec5SDimitry Andric     }
10090b57cec5SDimitry Andric     Expected<std::unique_ptr<llvm::Module>> MOrErr =
10100b57cec5SDimitry Andric         Bm->parseModule(*VMContext);
10110b57cec5SDimitry Andric     if (!MOrErr)
10120b57cec5SDimitry Andric       return DiagErrors(MOrErr.takeError());
10130b57cec5SDimitry Andric     return std::move(*MOrErr);
10140b57cec5SDimitry Andric   }
10150b57cec5SDimitry Andric 
10160b57cec5SDimitry Andric   llvm::SMDiagnostic Err;
10170b57cec5SDimitry Andric   if (std::unique_ptr<llvm::Module> M = parseIR(MBRef, Err, *VMContext))
10180b57cec5SDimitry Andric     return M;
10190b57cec5SDimitry Andric 
10200b57cec5SDimitry Andric   // Translate from the diagnostic info to the SourceManager location if
10210b57cec5SDimitry Andric   // available.
10220b57cec5SDimitry Andric   // TODO: Unify this with ConvertBackendLocation()
10230b57cec5SDimitry Andric   SourceLocation Loc;
10240b57cec5SDimitry Andric   if (Err.getLineNo() > 0) {
10250b57cec5SDimitry Andric     assert(Err.getColumnNo() >= 0);
10260b57cec5SDimitry Andric     Loc = SM.translateFileLineCol(SM.getFileEntryForID(SM.getMainFileID()),
10270b57cec5SDimitry Andric                                   Err.getLineNo(), Err.getColumnNo() + 1);
10280b57cec5SDimitry Andric   }
10290b57cec5SDimitry Andric 
10300b57cec5SDimitry Andric   // Strip off a leading diagnostic code if there is one.
10310b57cec5SDimitry Andric   StringRef Msg = Err.getMessage();
10320b57cec5SDimitry Andric   if (Msg.startswith("error: "))
10330b57cec5SDimitry Andric     Msg = Msg.substr(7);
10340b57cec5SDimitry Andric 
10350b57cec5SDimitry Andric   unsigned DiagID =
10360b57cec5SDimitry Andric       CI.getDiagnostics().getCustomDiagID(DiagnosticsEngine::Error, "%0");
10370b57cec5SDimitry Andric 
10380b57cec5SDimitry Andric   CI.getDiagnostics().Report(Loc, DiagID) << Msg;
10390b57cec5SDimitry Andric   return {};
10400b57cec5SDimitry Andric }
10410b57cec5SDimitry Andric 
ExecuteAction()10420b57cec5SDimitry Andric void CodeGenAction::ExecuteAction() {
1043af732203SDimitry Andric   if (getCurrentFileKind().getLanguage() != Language::LLVM_IR) {
1044af732203SDimitry Andric     this->ASTFrontendAction::ExecuteAction();
1045af732203SDimitry Andric     return;
1046af732203SDimitry Andric   }
1047af732203SDimitry Andric 
10480b57cec5SDimitry Andric   // If this is an IR file, we have to treat it specially.
10490b57cec5SDimitry Andric   BackendAction BA = static_cast<BackendAction>(Act);
10500b57cec5SDimitry Andric   CompilerInstance &CI = getCompilerInstance();
1051480093f4SDimitry Andric   auto &CodeGenOpts = CI.getCodeGenOpts();
1052480093f4SDimitry Andric   auto &Diagnostics = CI.getDiagnostics();
10530b57cec5SDimitry Andric   std::unique_ptr<raw_pwrite_stream> OS =
10540b57cec5SDimitry Andric       GetOutputStream(CI, getCurrentFile(), BA);
10550b57cec5SDimitry Andric   if (BA != Backend_EmitNothing && !OS)
10560b57cec5SDimitry Andric     return;
10570b57cec5SDimitry Andric 
10580b57cec5SDimitry Andric   SourceManager &SM = CI.getSourceManager();
10590b57cec5SDimitry Andric   FileID FID = SM.getMainFileID();
1060af732203SDimitry Andric   Optional<MemoryBufferRef> MainFile = SM.getBufferOrNone(FID);
1061af732203SDimitry Andric   if (!MainFile)
10620b57cec5SDimitry Andric     return;
10630b57cec5SDimitry Andric 
10640b57cec5SDimitry Andric   TheModule = loadModule(*MainFile);
10650b57cec5SDimitry Andric   if (!TheModule)
10660b57cec5SDimitry Andric     return;
10670b57cec5SDimitry Andric 
10680b57cec5SDimitry Andric   const TargetOptions &TargetOpts = CI.getTargetOpts();
10690b57cec5SDimitry Andric   if (TheModule->getTargetTriple() != TargetOpts.Triple) {
1070af732203SDimitry Andric     Diagnostics.Report(SourceLocation(), diag::warn_fe_override_module)
10710b57cec5SDimitry Andric         << TargetOpts.Triple;
10720b57cec5SDimitry Andric     TheModule->setTargetTriple(TargetOpts.Triple);
10730b57cec5SDimitry Andric   }
10740b57cec5SDimitry Andric 
1075af732203SDimitry Andric   EmbedBitcode(TheModule.get(), CodeGenOpts, *MainFile);
10760b57cec5SDimitry Andric 
10770b57cec5SDimitry Andric   LLVMContext &Ctx = TheModule->getContext();
1078*5f7ddb14SDimitry Andric 
1079*5f7ddb14SDimitry Andric   // Restore any diagnostic handler previously set before returning from this
1080*5f7ddb14SDimitry Andric   // function.
1081*5f7ddb14SDimitry Andric   struct RAII {
1082*5f7ddb14SDimitry Andric     LLVMContext &Ctx;
1083*5f7ddb14SDimitry Andric     std::unique_ptr<DiagnosticHandler> PrevHandler = Ctx.getDiagnosticHandler();
1084*5f7ddb14SDimitry Andric     ~RAII() { Ctx.setDiagnosticHandler(std::move(PrevHandler)); }
1085*5f7ddb14SDimitry Andric   } _{Ctx};
10860b57cec5SDimitry Andric 
1087480093f4SDimitry Andric   // Set clang diagnostic handler. To do this we need to create a fake
1088480093f4SDimitry Andric   // BackendConsumer.
1089480093f4SDimitry Andric   BackendConsumer Result(BA, CI.getDiagnostics(), CI.getHeaderSearchOpts(),
1090480093f4SDimitry Andric                          CI.getPreprocessorOpts(), CI.getCodeGenOpts(),
1091480093f4SDimitry Andric                          CI.getTargetOpts(), CI.getLangOpts(),
1092480093f4SDimitry Andric                          std::move(LinkModules), *VMContext, nullptr);
109347395794SDimitry Andric   // PR44896: Force DiscardValueNames as false. DiscardValueNames cannot be
109447395794SDimitry Andric   // true here because the valued names are needed for reading textual IR.
109547395794SDimitry Andric   Ctx.setDiscardValueNames(false);
1096480093f4SDimitry Andric   Ctx.setDiagnosticHandler(
1097480093f4SDimitry Andric       std::make_unique<ClangDiagnosticHandler>(CodeGenOpts, &Result));
1098480093f4SDimitry Andric 
1099480093f4SDimitry Andric   Expected<std::unique_ptr<llvm::ToolOutputFile>> OptRecordFileOrErr =
11005ffd83dbSDimitry Andric       setupLLVMOptimizationRemarks(
1101480093f4SDimitry Andric           Ctx, CodeGenOpts.OptRecordFile, CodeGenOpts.OptRecordPasses,
1102480093f4SDimitry Andric           CodeGenOpts.OptRecordFormat, CodeGenOpts.DiagnosticsWithHotness,
1103480093f4SDimitry Andric           CodeGenOpts.DiagnosticsHotnessThreshold);
1104480093f4SDimitry Andric 
1105480093f4SDimitry Andric   if (Error E = OptRecordFileOrErr.takeError()) {
1106480093f4SDimitry Andric     reportOptRecordError(std::move(E), Diagnostics, CodeGenOpts);
1107480093f4SDimitry Andric     return;
1108480093f4SDimitry Andric   }
1109480093f4SDimitry Andric   std::unique_ptr<llvm::ToolOutputFile> OptRecordFile =
1110480093f4SDimitry Andric       std::move(*OptRecordFileOrErr);
1111480093f4SDimitry Andric 
1112480093f4SDimitry Andric   EmitBackendOutput(Diagnostics, CI.getHeaderSearchOpts(), CodeGenOpts,
1113480093f4SDimitry Andric                     TargetOpts, CI.getLangOpts(),
1114*5f7ddb14SDimitry Andric                     CI.getTarget().getDataLayoutString(), TheModule.get(), BA,
11150b57cec5SDimitry Andric                     std::move(OS));
1116480093f4SDimitry Andric   if (OptRecordFile)
1117480093f4SDimitry Andric     OptRecordFile->keep();
11180b57cec5SDimitry Andric }
11190b57cec5SDimitry Andric 
11200b57cec5SDimitry Andric //
11210b57cec5SDimitry Andric 
anchor()11220b57cec5SDimitry Andric void EmitAssemblyAction::anchor() { }
EmitAssemblyAction(llvm::LLVMContext * _VMContext)11230b57cec5SDimitry Andric EmitAssemblyAction::EmitAssemblyAction(llvm::LLVMContext *_VMContext)
11240b57cec5SDimitry Andric   : CodeGenAction(Backend_EmitAssembly, _VMContext) {}
11250b57cec5SDimitry Andric 
anchor()11260b57cec5SDimitry Andric void EmitBCAction::anchor() { }
EmitBCAction(llvm::LLVMContext * _VMContext)11270b57cec5SDimitry Andric EmitBCAction::EmitBCAction(llvm::LLVMContext *_VMContext)
11280b57cec5SDimitry Andric   : CodeGenAction(Backend_EmitBC, _VMContext) {}
11290b57cec5SDimitry Andric 
anchor()11300b57cec5SDimitry Andric void EmitLLVMAction::anchor() { }
EmitLLVMAction(llvm::LLVMContext * _VMContext)11310b57cec5SDimitry Andric EmitLLVMAction::EmitLLVMAction(llvm::LLVMContext *_VMContext)
11320b57cec5SDimitry Andric   : CodeGenAction(Backend_EmitLL, _VMContext) {}
11330b57cec5SDimitry Andric 
anchor()11340b57cec5SDimitry Andric void EmitLLVMOnlyAction::anchor() { }
EmitLLVMOnlyAction(llvm::LLVMContext * _VMContext)11350b57cec5SDimitry Andric EmitLLVMOnlyAction::EmitLLVMOnlyAction(llvm::LLVMContext *_VMContext)
11360b57cec5SDimitry Andric   : CodeGenAction(Backend_EmitNothing, _VMContext) {}
11370b57cec5SDimitry Andric 
anchor()11380b57cec5SDimitry Andric void EmitCodeGenOnlyAction::anchor() { }
EmitCodeGenOnlyAction(llvm::LLVMContext * _VMContext)11390b57cec5SDimitry Andric EmitCodeGenOnlyAction::EmitCodeGenOnlyAction(llvm::LLVMContext *_VMContext)
11400b57cec5SDimitry Andric   : CodeGenAction(Backend_EmitMCNull, _VMContext) {}
11410b57cec5SDimitry Andric 
anchor()11420b57cec5SDimitry Andric void EmitObjAction::anchor() { }
EmitObjAction(llvm::LLVMContext * _VMContext)11430b57cec5SDimitry Andric EmitObjAction::EmitObjAction(llvm::LLVMContext *_VMContext)
11440b57cec5SDimitry Andric   : CodeGenAction(Backend_EmitObj, _VMContext) {}
1145