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