1210008Srdivacky//===--- CodeGenAction.cpp - LLVM Code Generation Frontend Action ---------===// 2210008Srdivacky// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6210008Srdivacky// 7210008Srdivacky//===----------------------------------------------------------------------===// 8210008Srdivacky 9321369Sdim#include "clang/CodeGen/CodeGenAction.h" 10321369Sdim#include "CodeGenModule.h" 11280031Sdim#include "CoverageMappingGen.h" 12321369Sdim#include "MacroPPCallbacks.h" 13249423Sdim#include "clang/AST/ASTConsumer.h" 14249423Sdim#include "clang/AST/ASTContext.h" 15280031Sdim#include "clang/AST/DeclCXX.h" 16249423Sdim#include "clang/AST/DeclGroup.h" 17360784Sdim#include "clang/Basic/DiagnosticFrontend.h" 18234353Sdim#include "clang/Basic/FileManager.h" 19360784Sdim#include "clang/Basic/LangStandard.h" 20210008Srdivacky#include "clang/Basic/SourceManager.h" 21210008Srdivacky#include "clang/Basic/TargetInfo.h" 22210008Srdivacky#include "clang/CodeGen/BackendUtil.h" 23210008Srdivacky#include "clang/CodeGen/ModuleBuilder.h" 24353358Sdim#include "clang/Driver/DriverDiagnostic.h" 25210008Srdivacky#include "clang/Frontend/CompilerInstance.h" 26210008Srdivacky#include "clang/Frontend/FrontendDiagnostic.h" 27280031Sdim#include "clang/Lex/Preprocessor.h" 28314564Sdim#include "llvm/Bitcode/BitcodeReader.h" 29321369Sdim#include "llvm/CodeGen/MachineOptimizationRemarkEmitter.h" 30276479Sdim#include "llvm/IR/DebugInfo.h" 31276479Sdim#include "llvm/IR/DiagnosticInfo.h" 32276479Sdim#include "llvm/IR/DiagnosticPrinter.h" 33321369Sdim#include "llvm/IR/GlobalValue.h" 34249423Sdim#include "llvm/IR/LLVMContext.h" 35249423Sdim#include "llvm/IR/Module.h" 36353358Sdim#include "llvm/IR/RemarkStreamer.h" 37249423Sdim#include "llvm/IRReader/IRReader.h" 38276479Sdim#include "llvm/Linker/Linker.h" 39249423Sdim#include "llvm/Pass.h" 40210008Srdivacky#include "llvm/Support/MemoryBuffer.h" 41210008Srdivacky#include "llvm/Support/SourceMgr.h" 42360784Sdim#include "llvm/Support/TimeProfiler.h" 43210008Srdivacky#include "llvm/Support/Timer.h" 44314564Sdim#include "llvm/Support/ToolOutputFile.h" 45314564Sdim#include "llvm/Support/YAMLTraits.h" 46321369Sdim#include "llvm/Transforms/IPO/Internalize.h" 47321369Sdim 48276479Sdim#include <memory> 49210008Srdivackyusing namespace clang; 50210008Srdivackyusing namespace llvm; 51210008Srdivacky 52218893Sdimnamespace clang { 53327952Sdim class BackendConsumer; 54327952Sdim class ClangDiagnosticHandler final : public DiagnosticHandler { 55327952Sdim public: 56327952Sdim ClangDiagnosticHandler(const CodeGenOptions &CGOpts, BackendConsumer *BCon) 57327952Sdim : CodeGenOpts(CGOpts), BackendCon(BCon) {} 58341825Sdim 59327952Sdim bool handleDiagnostics(const DiagnosticInfo &DI) override; 60327952Sdim 61327952Sdim bool isAnalysisRemarkEnabled(StringRef PassName) const override { 62327952Sdim return (CodeGenOpts.OptimizationRemarkAnalysisPattern && 63327952Sdim CodeGenOpts.OptimizationRemarkAnalysisPattern->match(PassName)); 64327952Sdim } 65327952Sdim bool isMissedOptRemarkEnabled(StringRef PassName) const override { 66327952Sdim return (CodeGenOpts.OptimizationRemarkMissedPattern && 67327952Sdim CodeGenOpts.OptimizationRemarkMissedPattern->match(PassName)); 68327952Sdim } 69327952Sdim bool isPassedOptRemarkEnabled(StringRef PassName) const override { 70327952Sdim return (CodeGenOpts.OptimizationRemarkPattern && 71327952Sdim CodeGenOpts.OptimizationRemarkPattern->match(PassName)); 72327952Sdim } 73327952Sdim 74327952Sdim bool isAnyRemarkEnabled() const override { 75327952Sdim return (CodeGenOpts.OptimizationRemarkAnalysisPattern || 76327952Sdim CodeGenOpts.OptimizationRemarkMissedPattern || 77327952Sdim CodeGenOpts.OptimizationRemarkPattern); 78327952Sdim } 79327952Sdim 80327952Sdim private: 81327952Sdim const CodeGenOptions &CodeGenOpts; 82327952Sdim BackendConsumer *BackendCon; 83327952Sdim }; 84327952Sdim 85360784Sdim static void reportOptRecordError(Error E, DiagnosticsEngine &Diags, 86360784Sdim const CodeGenOptions CodeGenOpts) { 87360784Sdim handleAllErrors( 88360784Sdim std::move(E), 89360784Sdim [&](const RemarkSetupFileError &E) { 90360784Sdim Diags.Report(diag::err_cannot_open_file) 91360784Sdim << CodeGenOpts.OptRecordFile << E.message(); 92360784Sdim }, 93360784Sdim [&](const RemarkSetupPatternError &E) { 94360784Sdim Diags.Report(diag::err_drv_optimization_remark_pattern) 95360784Sdim << E.message() << CodeGenOpts.OptRecordPasses; 96360784Sdim }, 97360784Sdim [&](const RemarkSetupFormatError &E) { 98360784Sdim Diags.Report(diag::err_drv_optimization_remark_format) 99360784Sdim << CodeGenOpts.OptRecordFormat; 100360784Sdim }); 101360784Sdim } 102360784Sdim 103210008Srdivacky class BackendConsumer : public ASTConsumer { 104321369Sdim using LinkModule = CodeGenAction::LinkModule; 105321369Sdim 106234353Sdim virtual void anchor(); 107226633Sdim DiagnosticsEngine &Diags; 108210008Srdivacky BackendAction Action; 109314564Sdim const HeaderSearchOptions &HeaderSearchOpts; 110210008Srdivacky const CodeGenOptions &CodeGenOpts; 111210008Srdivacky const TargetOptions &TargetOpts; 112224145Sdim const LangOptions &LangOpts; 113309124Sdim std::unique_ptr<raw_pwrite_stream> AsmOutStream; 114210008Srdivacky ASTContext *Context; 115210008Srdivacky 116210008Srdivacky Timer LLVMIRGeneration; 117314564Sdim unsigned LLVMIRGenerationRefCount; 118210008Srdivacky 119314564Sdim /// True if we've finished generating IR. This prevents us from generating 120314564Sdim /// additional LLVM IR after emitting output in HandleTranslationUnit. This 121314564Sdim /// can happen when Clang plugins trigger additional AST deserialization. 122314564Sdim bool IRGenFinished = false; 123314564Sdim 124276479Sdim std::unique_ptr<CodeGenerator> Gen; 125210008Srdivacky 126321369Sdim SmallVector<LinkModule, 4> LinkModules; 127210008Srdivacky 128296417Sdim // This is here so that the diagnostic printer knows the module a diagnostic 129296417Sdim // refers to. 130296417Sdim llvm::Module *CurLinkModule = nullptr; 131296417Sdim 132210008Srdivacky public: 133321369Sdim BackendConsumer(BackendAction Action, DiagnosticsEngine &Diags, 134321369Sdim const HeaderSearchOptions &HeaderSearchOpts, 135321369Sdim const PreprocessorOptions &PPOpts, 136321369Sdim const CodeGenOptions &CodeGenOpts, 137321369Sdim const TargetOptions &TargetOpts, 138321369Sdim const LangOptions &LangOpts, bool TimePasses, 139321369Sdim const std::string &InFile, 140321369Sdim SmallVector<LinkModule, 4> LinkModules, 141321369Sdim std::unique_ptr<raw_pwrite_stream> OS, LLVMContext &C, 142321369Sdim CoverageSourceInfo *CoverageInfo = nullptr) 143314564Sdim : Diags(Diags), Action(Action), HeaderSearchOpts(HeaderSearchOpts), 144314564Sdim CodeGenOpts(CodeGenOpts), TargetOpts(TargetOpts), LangOpts(LangOpts), 145309124Sdim AsmOutStream(std::move(OS)), Context(nullptr), 146314564Sdim LLVMIRGeneration("irgen", "LLVM IR Generation Time"), 147314564Sdim LLVMIRGenerationRefCount(0), 148288943Sdim Gen(CreateLLVMCodeGen(Diags, InFile, HeaderSearchOpts, PPOpts, 149321369Sdim CodeGenOpts, C, CoverageInfo)), 150321369Sdim LinkModules(std::move(LinkModules)) { 151341825Sdim FrontendTimesIsEnabled = TimePasses; 152210008Srdivacky llvm::TimePassesIsEnabled = TimePasses; 153210008Srdivacky } 154360784Sdim 155360784Sdim // This constructor is used in installing an empty BackendConsumer 156360784Sdim // to use the clang diagnostic handler for IR input files. It avoids 157360784Sdim // initializing the OS field. 158360784Sdim BackendConsumer(BackendAction Action, DiagnosticsEngine &Diags, 159360784Sdim const HeaderSearchOptions &HeaderSearchOpts, 160360784Sdim const PreprocessorOptions &PPOpts, 161360784Sdim const CodeGenOptions &CodeGenOpts, 162360784Sdim const TargetOptions &TargetOpts, 163360784Sdim const LangOptions &LangOpts, bool TimePasses, 164360784Sdim SmallVector<LinkModule, 4> LinkModules, LLVMContext &C, 165360784Sdim CoverageSourceInfo *CoverageInfo = nullptr) 166360784Sdim : Diags(Diags), Action(Action), HeaderSearchOpts(HeaderSearchOpts), 167360784Sdim CodeGenOpts(CodeGenOpts), TargetOpts(TargetOpts), LangOpts(LangOpts), 168360784Sdim Context(nullptr), 169360784Sdim LLVMIRGeneration("irgen", "LLVM IR Generation Time"), 170360784Sdim LLVMIRGenerationRefCount(0), 171360784Sdim Gen(CreateLLVMCodeGen(Diags, "", HeaderSearchOpts, PPOpts, 172360784Sdim CodeGenOpts, C, CoverageInfo)), 173360784Sdim LinkModules(std::move(LinkModules)) { 174360784Sdim FrontendTimesIsEnabled = TimePasses; 175360784Sdim llvm::TimePassesIsEnabled = TimePasses; 176360784Sdim } 177309124Sdim llvm::Module *getModule() const { return Gen->GetModule(); } 178309124Sdim std::unique_ptr<llvm::Module> takeModule() { 179309124Sdim return std::unique_ptr<llvm::Module>(Gen->ReleaseModule()); 180309124Sdim } 181210008Srdivacky 182321369Sdim CodeGenerator *getCodeGenerator() { return Gen.get(); } 183321369Sdim 184276479Sdim void HandleCXXStaticMemberVarInstantiation(VarDecl *VD) override { 185234353Sdim Gen->HandleCXXStaticMemberVarInstantiation(VD); 186234353Sdim } 187234353Sdim 188276479Sdim void Initialize(ASTContext &Ctx) override { 189296417Sdim assert(!Context && "initialized multiple times"); 190296417Sdim 191210008Srdivacky Context = &Ctx; 192210008Srdivacky 193341825Sdim if (FrontendTimesIsEnabled) 194210008Srdivacky LLVMIRGeneration.startTimer(); 195210008Srdivacky 196210008Srdivacky Gen->Initialize(Ctx); 197210008Srdivacky 198341825Sdim if (FrontendTimesIsEnabled) 199210008Srdivacky LLVMIRGeneration.stopTimer(); 200210008Srdivacky } 201210008Srdivacky 202276479Sdim bool HandleTopLevelDecl(DeclGroupRef D) override { 203210008Srdivacky PrettyStackTraceDecl CrashInfo(*D.begin(), SourceLocation(), 204210008Srdivacky Context->getSourceManager(), 205210008Srdivacky "LLVM IR generation of declaration"); 206210008Srdivacky 207314564Sdim // Recurse. 208341825Sdim if (FrontendTimesIsEnabled) { 209314564Sdim LLVMIRGenerationRefCount += 1; 210314564Sdim if (LLVMIRGenerationRefCount == 1) 211314564Sdim LLVMIRGeneration.startTimer(); 212314564Sdim } 213210008Srdivacky 214210008Srdivacky Gen->HandleTopLevelDecl(D); 215210008Srdivacky 216341825Sdim if (FrontendTimesIsEnabled) { 217314564Sdim LLVMIRGenerationRefCount -= 1; 218314564Sdim if (LLVMIRGenerationRefCount == 0) 219314564Sdim LLVMIRGeneration.stopTimer(); 220314564Sdim } 221234353Sdim 222234353Sdim return true; 223210008Srdivacky } 224210008Srdivacky 225309124Sdim void HandleInlineFunctionDefinition(FunctionDecl *D) override { 226276479Sdim PrettyStackTraceDecl CrashInfo(D, SourceLocation(), 227276479Sdim Context->getSourceManager(), 228309124Sdim "LLVM IR generation of inline function"); 229341825Sdim if (FrontendTimesIsEnabled) 230276479Sdim LLVMIRGeneration.startTimer(); 231276479Sdim 232309124Sdim Gen->HandleInlineFunctionDefinition(D); 233276479Sdim 234341825Sdim if (FrontendTimesIsEnabled) 235276479Sdim LLVMIRGeneration.stopTimer(); 236276479Sdim } 237276479Sdim 238314564Sdim void HandleInterestingDecl(DeclGroupRef D) override { 239314564Sdim // Ignore interesting decls from the AST reader after IRGen is finished. 240314564Sdim if (!IRGenFinished) 241314564Sdim HandleTopLevelDecl(D); 242314564Sdim } 243314564Sdim 244321369Sdim // Links each entry in LinkModules into our module. Returns true on error. 245321369Sdim bool LinkInModules() { 246321369Sdim for (auto &LM : LinkModules) { 247321369Sdim if (LM.PropagateAttrs) 248321369Sdim for (Function &F : *LM.Module) 249321369Sdim Gen->CGM().AddDefaultFnAttrs(F); 250321369Sdim 251321369Sdim CurLinkModule = LM.Module.get(); 252321369Sdim 253321369Sdim bool Err; 254321369Sdim if (LM.Internalize) { 255321369Sdim Err = Linker::linkModules( 256321369Sdim *getModule(), std::move(LM.Module), LM.LinkFlags, 257321369Sdim [](llvm::Module &M, const llvm::StringSet<> &GVS) { 258321369Sdim internalizeModule(M, [&GVS](const llvm::GlobalValue &GV) { 259321369Sdim return !GV.hasName() || (GVS.count(GV.getName()) == 0); 260321369Sdim }); 261321369Sdim }); 262321369Sdim } else { 263321369Sdim Err = Linker::linkModules(*getModule(), std::move(LM.Module), 264321369Sdim LM.LinkFlags); 265321369Sdim } 266321369Sdim 267321369Sdim if (Err) 268321369Sdim return true; 269321369Sdim } 270321369Sdim return false; // success 271321369Sdim } 272321369Sdim 273276479Sdim void HandleTranslationUnit(ASTContext &C) override { 274210008Srdivacky { 275360784Sdim llvm::TimeTraceScope TimeScope("Frontend"); 276210008Srdivacky PrettyStackTraceString CrashInfo("Per-file LLVM IR generation"); 277341825Sdim if (FrontendTimesIsEnabled) { 278314564Sdim LLVMIRGenerationRefCount += 1; 279314564Sdim if (LLVMIRGenerationRefCount == 1) 280314564Sdim LLVMIRGeneration.startTimer(); 281314564Sdim } 282210008Srdivacky 283210008Srdivacky Gen->HandleTranslationUnit(C); 284210008Srdivacky 285341825Sdim if (FrontendTimesIsEnabled) { 286314564Sdim LLVMIRGenerationRefCount -= 1; 287314564Sdim if (LLVMIRGenerationRefCount == 0) 288314564Sdim LLVMIRGeneration.stopTimer(); 289314564Sdim } 290314564Sdim 291341825Sdim IRGenFinished = true; 292210008Srdivacky } 293210008Srdivacky 294210008Srdivacky // Silently ignore if we weren't initialized for some reason. 295309124Sdim if (!getModule()) 296210008Srdivacky return; 297210008Srdivacky 298210008Srdivacky // Install an inline asm handler so that diagnostics get printed through 299210008Srdivacky // our diagnostics hooks. 300309124Sdim LLVMContext &Ctx = getModule()->getContext(); 301218893Sdim LLVMContext::InlineAsmDiagHandlerTy OldHandler = 302218893Sdim Ctx.getInlineAsmDiagnosticHandler(); 303210008Srdivacky void *OldContext = Ctx.getInlineAsmDiagnosticContext(); 304218893Sdim Ctx.setInlineAsmDiagnosticHandler(InlineAsmDiagHandler, this); 305210008Srdivacky 306327952Sdim std::unique_ptr<DiagnosticHandler> OldDiagnosticHandler = 307276479Sdim Ctx.getDiagnosticHandler(); 308360784Sdim Ctx.setDiagnosticHandler(std::make_unique<ClangDiagnosticHandler>( 309327952Sdim CodeGenOpts, this)); 310276479Sdim 311353358Sdim Expected<std::unique_ptr<llvm::ToolOutputFile>> OptRecordFileOrErr = 312360784Sdim setupOptimizationRemarks( 313360784Sdim Ctx, CodeGenOpts.OptRecordFile, CodeGenOpts.OptRecordPasses, 314360784Sdim CodeGenOpts.OptRecordFormat, CodeGenOpts.DiagnosticsWithHotness, 315360784Sdim CodeGenOpts.DiagnosticsHotnessThreshold); 316314564Sdim 317353358Sdim if (Error E = OptRecordFileOrErr.takeError()) { 318360784Sdim reportOptRecordError(std::move(E), Diags, CodeGenOpts); 319353358Sdim return; 320314564Sdim } 321360784Sdim 322353358Sdim std::unique_ptr<llvm::ToolOutputFile> OptRecordFile = 323353358Sdim std::move(*OptRecordFileOrErr); 324314564Sdim 325353358Sdim if (OptRecordFile && 326353358Sdim CodeGenOpts.getProfileUse() != CodeGenOptions::ProfileNone) 327353358Sdim Ctx.setDiagnosticsHotnessRequested(true); 328353358Sdim 329321369Sdim // Link each LinkModule into our module. 330321369Sdim if (LinkInModules()) 331321369Sdim return; 332296417Sdim 333309124Sdim EmbedBitcode(getModule(), CodeGenOpts, llvm::MemoryBufferRef()); 334309124Sdim 335314564Sdim EmitBackendOutput(Diags, HeaderSearchOpts, CodeGenOpts, TargetOpts, 336314564Sdim LangOpts, C.getTargetInfo().getDataLayout(), 337309124Sdim getModule(), Action, std::move(AsmOutStream)); 338276479Sdim 339210008Srdivacky Ctx.setInlineAsmDiagnosticHandler(OldHandler, OldContext); 340276479Sdim 341327952Sdim Ctx.setDiagnosticHandler(std::move(OldDiagnosticHandler)); 342314564Sdim 343314564Sdim if (OptRecordFile) 344314564Sdim OptRecordFile->keep(); 345210008Srdivacky } 346210008Srdivacky 347276479Sdim void HandleTagDeclDefinition(TagDecl *D) override { 348210008Srdivacky PrettyStackTraceDecl CrashInfo(D, SourceLocation(), 349210008Srdivacky Context->getSourceManager(), 350210008Srdivacky "LLVM IR generation of declaration"); 351210008Srdivacky Gen->HandleTagDeclDefinition(D); 352210008Srdivacky } 353210008Srdivacky 354276479Sdim void HandleTagDeclRequiredDefinition(const TagDecl *D) override { 355261991Sdim Gen->HandleTagDeclRequiredDefinition(D); 356261991Sdim } 357261991Sdim 358276479Sdim void CompleteTentativeDefinition(VarDecl *D) override { 359210008Srdivacky Gen->CompleteTentativeDefinition(D); 360210008Srdivacky } 361210008Srdivacky 362360784Sdim void CompleteExternalDeclaration(VarDecl *D) override { 363360784Sdim Gen->CompleteExternalDeclaration(D); 364360784Sdim } 365360784Sdim 366309124Sdim void AssignInheritanceModel(CXXRecordDecl *RD) override { 367309124Sdim Gen->AssignInheritanceModel(RD); 368309124Sdim } 369309124Sdim 370288943Sdim void HandleVTable(CXXRecordDecl *RD) override { 371288943Sdim Gen->HandleVTable(RD); 372210008Srdivacky } 373210008Srdivacky 374210008Srdivacky static void InlineAsmDiagHandler(const llvm::SMDiagnostic &SM,void *Context, 375210008Srdivacky unsigned LocCookie) { 376210008Srdivacky SourceLocation Loc = SourceLocation::getFromRawEncoding(LocCookie); 377210008Srdivacky ((BackendConsumer*)Context)->InlineAsmDiagHandler2(SM, Loc); 378210008Srdivacky } 379210008Srdivacky 380309124Sdim /// Get the best possible source location to represent a diagnostic that 381309124Sdim /// may have associated debug info. 382309124Sdim const FullSourceLoc 383321369Sdim getBestLocationFromDebugLoc(const llvm::DiagnosticInfoWithLocationBase &D, 384309124Sdim bool &BadDebugInfo, StringRef &Filename, 385309124Sdim unsigned &Line, unsigned &Column) const; 386309124Sdim 387210008Srdivacky void InlineAsmDiagHandler2(const llvm::SMDiagnostic &, 388210008Srdivacky SourceLocation LocCookie); 389276479Sdim 390276479Sdim void DiagnosticHandlerImpl(const llvm::DiagnosticInfo &DI); 391341825Sdim /// Specialized handler for InlineAsm diagnostic. 392276479Sdim /// \return True if the diagnostic has been successfully reported, false 393276479Sdim /// otherwise. 394276479Sdim bool InlineAsmDiagHandler(const llvm::DiagnosticInfoInlineAsm &D); 395341825Sdim /// Specialized handler for StackSize diagnostic. 396276479Sdim /// \return True if the diagnostic has been successfully reported, false 397276479Sdim /// otherwise. 398276479Sdim bool StackSizeDiagHandler(const llvm::DiagnosticInfoStackSize &D); 399341825Sdim /// Specialized handler for unsupported backend feature diagnostic. 400309124Sdim void UnsupportedDiagHandler(const llvm::DiagnosticInfoUnsupported &D); 401360784Sdim /// Specialized handler for misexpect warnings. 402360784Sdim /// Note that misexpect remarks are emitted through ORE 403360784Sdim void MisExpectDiagHandler(const llvm::DiagnosticInfoMisExpect &D); 404341825Sdim /// Specialized handlers for optimization remarks. 405276479Sdim /// Note that these handlers only accept remarks and they always handle 406276479Sdim /// them. 407276479Sdim void EmitOptimizationMessage(const llvm::DiagnosticInfoOptimizationBase &D, 408276479Sdim unsigned DiagID); 409321369Sdim void 410321369Sdim OptimizationRemarkHandler(const llvm::DiagnosticInfoOptimizationBase &D); 411276479Sdim void OptimizationRemarkHandler( 412314564Sdim const llvm::OptimizationRemarkAnalysisFPCommute &D); 413276479Sdim void OptimizationRemarkHandler( 414314564Sdim const llvm::OptimizationRemarkAnalysisAliasing &D); 415276479Sdim void OptimizationFailureHandler( 416276479Sdim const llvm::DiagnosticInfoOptimizationFailure &D); 417210008Srdivacky }; 418321369Sdim 419234353Sdim void BackendConsumer::anchor() {} 420210008Srdivacky} 421210008Srdivacky 422327952Sdimbool ClangDiagnosticHandler::handleDiagnostics(const DiagnosticInfo &DI) { 423327952Sdim BackendCon->DiagnosticHandlerImpl(DI); 424327952Sdim return true; 425327952Sdim} 426327952Sdim 427210008Srdivacky/// ConvertBackendLocation - Convert a location in a temporary llvm::SourceMgr 428210008Srdivacky/// buffer to be a valid FullSourceLoc. 429210008Srdivackystatic FullSourceLoc ConvertBackendLocation(const llvm::SMDiagnostic &D, 430210008Srdivacky SourceManager &CSM) { 431210008Srdivacky // Get both the clang and llvm source managers. The location is relative to 432210008Srdivacky // a memory buffer that the LLVM Source Manager is handling, we need to add 433210008Srdivacky // a copy to the Clang source manager. 434210008Srdivacky const llvm::SourceMgr &LSM = *D.getSourceMgr(); 435210008Srdivacky 436210008Srdivacky // We need to copy the underlying LLVM memory buffer because llvm::SourceMgr 437210008Srdivacky // already owns its one and clang::SourceManager wants to own its one. 438210008Srdivacky const MemoryBuffer *LBuf = 439210008Srdivacky LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(D.getLoc())); 440210008Srdivacky 441210008Srdivacky // Create the copy and transfer ownership to clang::SourceManager. 442276479Sdim // TODO: Avoid copying files into memory. 443280031Sdim std::unique_ptr<llvm::MemoryBuffer> CBuf = 444280031Sdim llvm::MemoryBuffer::getMemBufferCopy(LBuf->getBuffer(), 445280031Sdim LBuf->getBufferIdentifier()); 446276479Sdim // FIXME: Keep a file ID map instead of creating new IDs for each location. 447280031Sdim FileID FID = CSM.createFileID(std::move(CBuf)); 448210008Srdivacky 449210008Srdivacky // Translate the offset into the file. 450276479Sdim unsigned Offset = D.getLoc().getPointer() - LBuf->getBufferStart(); 451210008Srdivacky SourceLocation NewLoc = 452226633Sdim CSM.getLocForStartOfFile(FID).getLocWithOffset(Offset); 453210008Srdivacky return FullSourceLoc(NewLoc, CSM); 454210008Srdivacky} 455210008Srdivacky 456210008Srdivacky 457210008Srdivacky/// InlineAsmDiagHandler2 - This function is invoked when the backend hits an 458210008Srdivacky/// error parsing inline asm. The SMDiagnostic indicates the error relative to 459210008Srdivacky/// the temporary memory buffer that the inline asm parser has set up. 460210008Srdivackyvoid BackendConsumer::InlineAsmDiagHandler2(const llvm::SMDiagnostic &D, 461210008Srdivacky SourceLocation LocCookie) { 462210008Srdivacky // There are a couple of different kinds of errors we could get here. First, 463210008Srdivacky // we re-format the SMDiagnostic in terms of a clang diagnostic. 464210008Srdivacky 465210008Srdivacky // Strip "error: " off the start of the message string. 466226633Sdim StringRef Message = D.getMessage(); 467210008Srdivacky if (Message.startswith("error: ")) 468210008Srdivacky Message = Message.substr(7); 469210008Srdivacky 470210008Srdivacky // If the SMDiagnostic has an inline asm source location, translate it. 471210008Srdivacky FullSourceLoc Loc; 472210008Srdivacky if (D.getLoc() != SMLoc()) 473210008Srdivacky Loc = ConvertBackendLocation(D, Context->getSourceManager()); 474210008Srdivacky 475276479Sdim unsigned DiagID; 476276479Sdim switch (D.getKind()) { 477276479Sdim case llvm::SourceMgr::DK_Error: 478276479Sdim DiagID = diag::err_fe_inline_asm; 479276479Sdim break; 480276479Sdim case llvm::SourceMgr::DK_Warning: 481276479Sdim DiagID = diag::warn_fe_inline_asm; 482276479Sdim break; 483276479Sdim case llvm::SourceMgr::DK_Note: 484276479Sdim DiagID = diag::note_fe_inline_asm; 485276479Sdim break; 486327952Sdim case llvm::SourceMgr::DK_Remark: 487327952Sdim llvm_unreachable("remarks unexpected"); 488276479Sdim } 489210008Srdivacky // If this problem has clang-level source location information, report the 490276479Sdim // issue in the source with a note showing the instantiated 491210008Srdivacky // code. 492210008Srdivacky if (LocCookie.isValid()) { 493276479Sdim Diags.Report(LocCookie, DiagID).AddString(Message); 494321369Sdim 495234353Sdim if (D.getLoc().isValid()) { 496234353Sdim DiagnosticBuilder B = Diags.Report(Loc, diag::note_fe_inline_asm_here); 497234353Sdim // Convert the SMDiagnostic ranges into SourceRange and attach them 498234353Sdim // to the diagnostic. 499296417Sdim for (const std::pair<unsigned, unsigned> &Range : D.getRanges()) { 500234353Sdim unsigned Column = D.getColumnNo(); 501234353Sdim B << SourceRange(Loc.getLocWithOffset(Range.first - Column), 502234353Sdim Loc.getLocWithOffset(Range.second - Column)); 503234353Sdim } 504234353Sdim } 505210008Srdivacky return; 506210008Srdivacky } 507321369Sdim 508276479Sdim // Otherwise, report the backend issue as occurring in the generated .s file. 509276479Sdim // If Loc is invalid, we still need to report the issue, it just gets no 510210008Srdivacky // location info. 511276479Sdim Diags.Report(Loc, DiagID).AddString(Message); 512210008Srdivacky} 513210008Srdivacky 514276479Sdim#define ComputeDiagID(Severity, GroupName, DiagID) \ 515276479Sdim do { \ 516276479Sdim switch (Severity) { \ 517276479Sdim case llvm::DS_Error: \ 518276479Sdim DiagID = diag::err_fe_##GroupName; \ 519276479Sdim break; \ 520276479Sdim case llvm::DS_Warning: \ 521276479Sdim DiagID = diag::warn_fe_##GroupName; \ 522276479Sdim break; \ 523276479Sdim case llvm::DS_Remark: \ 524276479Sdim llvm_unreachable("'remark' severity not expected"); \ 525276479Sdim break; \ 526276479Sdim case llvm::DS_Note: \ 527276479Sdim DiagID = diag::note_fe_##GroupName; \ 528276479Sdim break; \ 529276479Sdim } \ 530276479Sdim } while (false) 531210008Srdivacky 532276479Sdim#define ComputeDiagRemarkID(Severity, GroupName, DiagID) \ 533276479Sdim do { \ 534276479Sdim switch (Severity) { \ 535276479Sdim case llvm::DS_Error: \ 536276479Sdim DiagID = diag::err_fe_##GroupName; \ 537276479Sdim break; \ 538276479Sdim case llvm::DS_Warning: \ 539276479Sdim DiagID = diag::warn_fe_##GroupName; \ 540276479Sdim break; \ 541276479Sdim case llvm::DS_Remark: \ 542276479Sdim DiagID = diag::remark_fe_##GroupName; \ 543276479Sdim break; \ 544276479Sdim case llvm::DS_Note: \ 545276479Sdim DiagID = diag::note_fe_##GroupName; \ 546276479Sdim break; \ 547276479Sdim } \ 548276479Sdim } while (false) 549276479Sdim 550276479Sdimbool 551276479SdimBackendConsumer::InlineAsmDiagHandler(const llvm::DiagnosticInfoInlineAsm &D) { 552276479Sdim unsigned DiagID; 553276479Sdim ComputeDiagID(D.getSeverity(), inline_asm, DiagID); 554276479Sdim std::string Message = D.getMsgStr().str(); 555276479Sdim 556276479Sdim // If this problem has clang-level source location information, report the 557276479Sdim // issue as being a problem in the source with a note showing the instantiated 558276479Sdim // code. 559276479Sdim SourceLocation LocCookie = 560276479Sdim SourceLocation::getFromRawEncoding(D.getLocCookie()); 561276479Sdim if (LocCookie.isValid()) 562276479Sdim Diags.Report(LocCookie, DiagID).AddString(Message); 563276479Sdim else { 564276479Sdim // Otherwise, report the backend diagnostic as occurring in the generated 565276479Sdim // .s file. 566276479Sdim // If Loc is invalid, we still need to report the diagnostic, it just gets 567276479Sdim // no location info. 568276479Sdim FullSourceLoc Loc; 569276479Sdim Diags.Report(Loc, DiagID).AddString(Message); 570276479Sdim } 571276479Sdim // We handled all the possible severities. 572276479Sdim return true; 573276479Sdim} 574276479Sdim 575276479Sdimbool 576276479SdimBackendConsumer::StackSizeDiagHandler(const llvm::DiagnosticInfoStackSize &D) { 577276479Sdim if (D.getSeverity() != llvm::DS_Warning) 578276479Sdim // For now, the only support we have for StackSize diagnostic is warning. 579276479Sdim // We do not know how to format other severities. 580276479Sdim return false; 581276479Sdim 582276479Sdim if (const Decl *ND = Gen->GetDeclForMangledName(D.getFunction().getName())) { 583309124Sdim // FIXME: Shouldn't need to truncate to uint32_t 584276479Sdim Diags.Report(ND->getASTContext().getFullLoc(ND->getLocation()), 585276479Sdim diag::warn_fe_frame_larger_than) 586309124Sdim << static_cast<uint32_t>(D.getStackSize()) << Decl::castToDeclContext(ND); 587276479Sdim return true; 588276479Sdim } 589276479Sdim 590276479Sdim return false; 591276479Sdim} 592276479Sdim 593309124Sdimconst FullSourceLoc BackendConsumer::getBestLocationFromDebugLoc( 594321369Sdim const llvm::DiagnosticInfoWithLocationBase &D, bool &BadDebugInfo, 595321369Sdim StringRef &Filename, unsigned &Line, unsigned &Column) const { 596276479Sdim SourceManager &SourceMgr = Context->getSourceManager(); 597276479Sdim FileManager &FileMgr = SourceMgr.getFileManager(); 598276479Sdim SourceLocation DILoc; 599288943Sdim 600288943Sdim if (D.isLocationAvailable()) { 601344779Sdim D.getLocation(Filename, Line, Column); 602344779Sdim if (Line > 0) { 603360784Sdim auto FE = FileMgr.getFile(Filename); 604344779Sdim if (!FE) 605344779Sdim FE = FileMgr.getFile(D.getAbsolutePath()); 606344779Sdim if (FE) { 607344779Sdim // If -gcolumn-info was not used, Column will be 0. This upsets the 608344779Sdim // source manager, so pass 1 if Column is not set. 609360784Sdim DILoc = SourceMgr.translateFileLineCol(*FE, Line, Column ? Column : 1); 610344779Sdim } 611288943Sdim } 612309124Sdim BadDebugInfo = DILoc.isInvalid(); 613276479Sdim } 614276479Sdim 615276479Sdim // If a location isn't available, try to approximate it using the associated 616276479Sdim // function definition. We use the definition's right brace to differentiate 617276479Sdim // from diagnostics that genuinely relate to the function itself. 618276479Sdim FullSourceLoc Loc(DILoc, SourceMgr); 619276479Sdim if (Loc.isInvalid()) 620276479Sdim if (const Decl *FD = Gen->GetDeclForMangledName(D.getFunction().getName())) 621309124Sdim Loc = FD->getASTContext().getFullLoc(FD->getLocation()); 622276479Sdim 623309124Sdim if (DILoc.isInvalid() && D.isLocationAvailable()) 624309124Sdim // If we were not able to translate the file:line:col information 625309124Sdim // back to a SourceLocation, at least emit a note stating that 626309124Sdim // we could not translate this location. This can happen in the 627309124Sdim // case of #line directives. 628309124Sdim Diags.Report(Loc, diag::note_fe_backend_invalid_loc) 629309124Sdim << Filename << Line << Column; 630309124Sdim 631309124Sdim return Loc; 632309124Sdim} 633309124Sdim 634309124Sdimvoid BackendConsumer::UnsupportedDiagHandler( 635309124Sdim const llvm::DiagnosticInfoUnsupported &D) { 636309124Sdim // We only support errors. 637309124Sdim assert(D.getSeverity() == llvm::DS_Error); 638309124Sdim 639309124Sdim StringRef Filename; 640309124Sdim unsigned Line, Column; 641321369Sdim bool BadDebugInfo = false; 642360784Sdim FullSourceLoc Loc; 643360784Sdim std::string Msg; 644360784Sdim raw_string_ostream MsgStream(Msg); 645309124Sdim 646360784Sdim // Context will be nullptr for IR input files, we will construct the diag 647360784Sdim // message from llvm::DiagnosticInfoUnsupported. 648360784Sdim if (Context != nullptr) { 649360784Sdim Loc = getBestLocationFromDebugLoc(D, BadDebugInfo, Filename, Line, Column); 650360784Sdim MsgStream << D.getMessage(); 651360784Sdim } else { 652360784Sdim DiagnosticPrinterRawOStream DP(MsgStream); 653360784Sdim D.print(DP); 654360784Sdim } 655360784Sdim Diags.Report(Loc, diag::err_fe_backend_unsupported) << MsgStream.str(); 656309124Sdim 657309124Sdim if (BadDebugInfo) 658309124Sdim // If we were not able to translate the file:line:col information 659309124Sdim // back to a SourceLocation, at least emit a note stating that 660309124Sdim // we could not translate this location. This can happen in the 661309124Sdim // case of #line directives. 662309124Sdim Diags.Report(Loc, diag::note_fe_backend_invalid_loc) 663309124Sdim << Filename << Line << Column; 664309124Sdim} 665309124Sdim 666360784Sdimvoid BackendConsumer::MisExpectDiagHandler( 667360784Sdim const llvm::DiagnosticInfoMisExpect &D) { 668360784Sdim StringRef Filename; 669360784Sdim unsigned Line, Column; 670360784Sdim bool BadDebugInfo = false; 671360784Sdim FullSourceLoc Loc; 672360784Sdim std::string Msg; 673360784Sdim raw_string_ostream MsgStream(Msg); 674360784Sdim DiagnosticPrinterRawOStream DP(MsgStream); 675360784Sdim 676360784Sdim // Context will be nullptr for IR input files, we will construct the diag 677360784Sdim // message from llvm::DiagnosticInfoMisExpect. 678360784Sdim if (Context != nullptr) { 679360784Sdim Loc = getBestLocationFromDebugLoc(D, BadDebugInfo, Filename, Line, Column); 680360784Sdim MsgStream << D.getMsg(); 681360784Sdim } else { 682360784Sdim DiagnosticPrinterRawOStream DP(MsgStream); 683360784Sdim D.print(DP); 684360784Sdim } 685360784Sdim Diags.Report(Loc, diag::warn_profile_data_misexpect) << MsgStream.str(); 686360784Sdim 687360784Sdim if (BadDebugInfo) 688360784Sdim // If we were not able to translate the file:line:col information 689360784Sdim // back to a SourceLocation, at least emit a note stating that 690360784Sdim // we could not translate this location. This can happen in the 691360784Sdim // case of #line directives. 692360784Sdim Diags.Report(Loc, diag::note_fe_backend_invalid_loc) 693360784Sdim << Filename << Line << Column; 694360784Sdim} 695360784Sdim 696309124Sdimvoid BackendConsumer::EmitOptimizationMessage( 697309124Sdim const llvm::DiagnosticInfoOptimizationBase &D, unsigned DiagID) { 698309124Sdim // We only support warnings and remarks. 699309124Sdim assert(D.getSeverity() == llvm::DS_Remark || 700309124Sdim D.getSeverity() == llvm::DS_Warning); 701309124Sdim 702309124Sdim StringRef Filename; 703309124Sdim unsigned Line, Column; 704309124Sdim bool BadDebugInfo = false; 705360784Sdim FullSourceLoc Loc; 706314564Sdim std::string Msg; 707314564Sdim raw_string_ostream MsgStream(Msg); 708314564Sdim 709360784Sdim // Context will be nullptr for IR input files, we will construct the remark 710360784Sdim // message from llvm::DiagnosticInfoOptimizationBase. 711360784Sdim if (Context != nullptr) { 712360784Sdim Loc = getBestLocationFromDebugLoc(D, BadDebugInfo, Filename, Line, Column); 713360784Sdim MsgStream << D.getMsg(); 714360784Sdim } else { 715360784Sdim DiagnosticPrinterRawOStream DP(MsgStream); 716360784Sdim D.print(DP); 717360784Sdim } 718360784Sdim 719314564Sdim if (D.getHotness()) 720314564Sdim MsgStream << " (hotness: " << *D.getHotness() << ")"; 721314564Sdim 722276479Sdim Diags.Report(Loc, DiagID) 723314564Sdim << AddFlagValue(D.getPassName()) 724314564Sdim << MsgStream.str(); 725276479Sdim 726309124Sdim if (BadDebugInfo) 727276479Sdim // If we were not able to translate the file:line:col information 728276479Sdim // back to a SourceLocation, at least emit a note stating that 729276479Sdim // we could not translate this location. This can happen in the 730276479Sdim // case of #line directives. 731309124Sdim Diags.Report(Loc, diag::note_fe_backend_invalid_loc) 732276479Sdim << Filename << Line << Column; 733276479Sdim} 734276479Sdim 735276479Sdimvoid BackendConsumer::OptimizationRemarkHandler( 736321369Sdim const llvm::DiagnosticInfoOptimizationBase &D) { 737327952Sdim // Without hotness information, don't show noisy remarks. 738327952Sdim if (D.isVerbose() && !D.getHotness()) 739327952Sdim return; 740327952Sdim 741321369Sdim if (D.isPassed()) { 742321369Sdim // Optimization remarks are active only if the -Rpass flag has a regular 743321369Sdim // expression that matches the name of the pass name in \p D. 744321369Sdim if (CodeGenOpts.OptimizationRemarkPattern && 745321369Sdim CodeGenOpts.OptimizationRemarkPattern->match(D.getPassName())) 746321369Sdim EmitOptimizationMessage(D, diag::remark_fe_backend_optimization_remark); 747321369Sdim } else if (D.isMissed()) { 748321369Sdim // Missed optimization remarks are active only if the -Rpass-missed 749321369Sdim // flag has a regular expression that matches the name of the pass 750321369Sdim // name in \p D. 751321369Sdim if (CodeGenOpts.OptimizationRemarkMissedPattern && 752321369Sdim CodeGenOpts.OptimizationRemarkMissedPattern->match(D.getPassName())) 753321369Sdim EmitOptimizationMessage( 754321369Sdim D, diag::remark_fe_backend_optimization_remark_missed); 755321369Sdim } else { 756321369Sdim assert(D.isAnalysis() && "Unknown remark type"); 757276479Sdim 758321369Sdim bool ShouldAlwaysPrint = false; 759321369Sdim if (auto *ORA = dyn_cast<llvm::OptimizationRemarkAnalysis>(&D)) 760321369Sdim ShouldAlwaysPrint = ORA->shouldAlwaysPrint(); 761276479Sdim 762321369Sdim if (ShouldAlwaysPrint || 763321369Sdim (CodeGenOpts.OptimizationRemarkAnalysisPattern && 764321369Sdim CodeGenOpts.OptimizationRemarkAnalysisPattern->match(D.getPassName()))) 765321369Sdim EmitOptimizationMessage( 766321369Sdim D, diag::remark_fe_backend_optimization_remark_analysis); 767321369Sdim } 768276479Sdim} 769276479Sdim 770296417Sdimvoid BackendConsumer::OptimizationRemarkHandler( 771314564Sdim const llvm::OptimizationRemarkAnalysisFPCommute &D) { 772296417Sdim // Optimization analysis remarks are active if the pass name is set to 773296417Sdim // llvm::DiagnosticInfo::AlwasyPrint or if the -Rpass-analysis flag has a 774296417Sdim // regular expression that matches the name of the pass name in \p D. 775296417Sdim 776309124Sdim if (D.shouldAlwaysPrint() || 777296417Sdim (CodeGenOpts.OptimizationRemarkAnalysisPattern && 778296417Sdim CodeGenOpts.OptimizationRemarkAnalysisPattern->match(D.getPassName()))) 779296417Sdim EmitOptimizationMessage( 780296417Sdim D, diag::remark_fe_backend_optimization_remark_analysis_fpcommute); 781276479Sdim} 782276479Sdim 783296417Sdimvoid BackendConsumer::OptimizationRemarkHandler( 784314564Sdim const llvm::OptimizationRemarkAnalysisAliasing &D) { 785296417Sdim // Optimization analysis remarks are active if the pass name is set to 786296417Sdim // llvm::DiagnosticInfo::AlwasyPrint or if the -Rpass-analysis flag has a 787296417Sdim // regular expression that matches the name of the pass name in \p D. 788280031Sdim 789309124Sdim if (D.shouldAlwaysPrint() || 790296417Sdim (CodeGenOpts.OptimizationRemarkAnalysisPattern && 791296417Sdim CodeGenOpts.OptimizationRemarkAnalysisPattern->match(D.getPassName()))) 792296417Sdim EmitOptimizationMessage( 793296417Sdim D, diag::remark_fe_backend_optimization_remark_analysis_aliasing); 794296417Sdim} 795280031Sdim 796296417Sdimvoid BackendConsumer::OptimizationFailureHandler( 797296417Sdim const llvm::DiagnosticInfoOptimizationFailure &D) { 798296417Sdim EmitOptimizationMessage(D, diag::warn_fe_backend_optimization_failure); 799280031Sdim} 800280031Sdim 801341825Sdim/// This function is invoked when the backend needs 802276479Sdim/// to report something to the user. 803276479Sdimvoid BackendConsumer::DiagnosticHandlerImpl(const DiagnosticInfo &DI) { 804276479Sdim unsigned DiagID = diag::err_fe_inline_asm; 805276479Sdim llvm::DiagnosticSeverity Severity = DI.getSeverity(); 806276479Sdim // Get the diagnostic ID based. 807276479Sdim switch (DI.getKind()) { 808276479Sdim case llvm::DK_InlineAsm: 809276479Sdim if (InlineAsmDiagHandler(cast<DiagnosticInfoInlineAsm>(DI))) 810276479Sdim return; 811276479Sdim ComputeDiagID(Severity, inline_asm, DiagID); 812276479Sdim break; 813276479Sdim case llvm::DK_StackSize: 814276479Sdim if (StackSizeDiagHandler(cast<DiagnosticInfoStackSize>(DI))) 815276479Sdim return; 816276479Sdim ComputeDiagID(Severity, backend_frame_larger_than, DiagID); 817276479Sdim break; 818296417Sdim case DK_Linker: 819296417Sdim assert(CurLinkModule); 820296417Sdim // FIXME: stop eating the warnings and notes. 821296417Sdim if (Severity != DS_Error) 822296417Sdim return; 823296417Sdim DiagID = diag::err_fe_cannot_link_module; 824296417Sdim break; 825276479Sdim case llvm::DK_OptimizationRemark: 826276479Sdim // Optimization remarks are always handled completely by this 827276479Sdim // handler. There is no generic way of emitting them. 828314564Sdim OptimizationRemarkHandler(cast<OptimizationRemark>(DI)); 829276479Sdim return; 830276479Sdim case llvm::DK_OptimizationRemarkMissed: 831276479Sdim // Optimization remarks are always handled completely by this 832276479Sdim // handler. There is no generic way of emitting them. 833314564Sdim OptimizationRemarkHandler(cast<OptimizationRemarkMissed>(DI)); 834276479Sdim return; 835276479Sdim case llvm::DK_OptimizationRemarkAnalysis: 836276479Sdim // Optimization remarks are always handled completely by this 837276479Sdim // handler. There is no generic way of emitting them. 838314564Sdim OptimizationRemarkHandler(cast<OptimizationRemarkAnalysis>(DI)); 839276479Sdim return; 840296417Sdim case llvm::DK_OptimizationRemarkAnalysisFPCommute: 841296417Sdim // Optimization remarks are always handled completely by this 842296417Sdim // handler. There is no generic way of emitting them. 843314564Sdim OptimizationRemarkHandler(cast<OptimizationRemarkAnalysisFPCommute>(DI)); 844296417Sdim return; 845296417Sdim case llvm::DK_OptimizationRemarkAnalysisAliasing: 846296417Sdim // Optimization remarks are always handled completely by this 847296417Sdim // handler. There is no generic way of emitting them. 848314564Sdim OptimizationRemarkHandler(cast<OptimizationRemarkAnalysisAliasing>(DI)); 849296417Sdim return; 850321369Sdim case llvm::DK_MachineOptimizationRemark: 851321369Sdim // Optimization remarks are always handled completely by this 852321369Sdim // handler. There is no generic way of emitting them. 853321369Sdim OptimizationRemarkHandler(cast<MachineOptimizationRemark>(DI)); 854321369Sdim return; 855321369Sdim case llvm::DK_MachineOptimizationRemarkMissed: 856321369Sdim // Optimization remarks are always handled completely by this 857321369Sdim // handler. There is no generic way of emitting them. 858321369Sdim OptimizationRemarkHandler(cast<MachineOptimizationRemarkMissed>(DI)); 859321369Sdim return; 860321369Sdim case llvm::DK_MachineOptimizationRemarkAnalysis: 861321369Sdim // Optimization remarks are always handled completely by this 862321369Sdim // handler. There is no generic way of emitting them. 863321369Sdim OptimizationRemarkHandler(cast<MachineOptimizationRemarkAnalysis>(DI)); 864321369Sdim return; 865276479Sdim case llvm::DK_OptimizationFailure: 866276479Sdim // Optimization failures are always handled completely by this 867276479Sdim // handler. 868276479Sdim OptimizationFailureHandler(cast<DiagnosticInfoOptimizationFailure>(DI)); 869276479Sdim return; 870309124Sdim case llvm::DK_Unsupported: 871309124Sdim UnsupportedDiagHandler(cast<DiagnosticInfoUnsupported>(DI)); 872309124Sdim return; 873360784Sdim case llvm::DK_MisExpect: 874360784Sdim MisExpectDiagHandler(cast<DiagnosticInfoMisExpect>(DI)); 875360784Sdim return; 876276479Sdim default: 877276479Sdim // Plugin IDs are not bound to any value as they are set dynamically. 878276479Sdim ComputeDiagRemarkID(Severity, backend_plugin, DiagID); 879276479Sdim break; 880276479Sdim } 881276479Sdim std::string MsgStorage; 882276479Sdim { 883276479Sdim raw_string_ostream Stream(MsgStorage); 884276479Sdim DiagnosticPrinterRawOStream DP(Stream); 885276479Sdim DI.print(DP); 886276479Sdim } 887276479Sdim 888296417Sdim if (DiagID == diag::err_fe_cannot_link_module) { 889296417Sdim Diags.Report(diag::err_fe_cannot_link_module) 890296417Sdim << CurLinkModule->getModuleIdentifier() << MsgStorage; 891296417Sdim return; 892296417Sdim } 893296417Sdim 894276479Sdim // Report the backend message using the usual diagnostic mechanism. 895276479Sdim FullSourceLoc Loc; 896276479Sdim Diags.Report(Loc, DiagID).AddString(MsgStorage); 897276479Sdim} 898276479Sdim#undef ComputeDiagID 899276479Sdim 900218893SdimCodeGenAction::CodeGenAction(unsigned _Act, LLVMContext *_VMContext) 901296417Sdim : Act(_Act), VMContext(_VMContext ? _VMContext : new LLVMContext), 902296417Sdim OwnsVMContext(!_VMContext) {} 903210008Srdivacky 904218893SdimCodeGenAction::~CodeGenAction() { 905218893Sdim TheModule.reset(); 906218893Sdim if (OwnsVMContext) 907218893Sdim delete VMContext; 908218893Sdim} 909210008Srdivacky 910210008Srdivackybool CodeGenAction::hasIRSupport() const { return true; } 911210008Srdivacky 912210008Srdivackyvoid CodeGenAction::EndSourceFileAction() { 913210008Srdivacky // If the consumer creation failed, do nothing. 914210008Srdivacky if (!getCompilerInstance().hasASTConsumer()) 915210008Srdivacky return; 916210008Srdivacky 917210008Srdivacky // Steal the module from the consumer. 918280031Sdim TheModule = BEConsumer->takeModule(); 919210008Srdivacky} 920210008Srdivacky 921280031Sdimstd::unique_ptr<llvm::Module> CodeGenAction::takeModule() { 922280031Sdim return std::move(TheModule); 923280031Sdim} 924210008Srdivacky 925218893Sdimllvm::LLVMContext *CodeGenAction::takeLLVMContext() { 926218893Sdim OwnsVMContext = false; 927218893Sdim return VMContext; 928218893Sdim} 929218893Sdim 930309124Sdimstatic std::unique_ptr<raw_pwrite_stream> 931288943SdimGetOutputStream(CompilerInstance &CI, StringRef InFile, BackendAction Action) { 932210008Srdivacky switch (Action) { 933210008Srdivacky case Backend_EmitAssembly: 934210008Srdivacky return CI.createDefaultOutputFile(false, InFile, "s"); 935210008Srdivacky case Backend_EmitLL: 936210008Srdivacky return CI.createDefaultOutputFile(false, InFile, "ll"); 937210008Srdivacky case Backend_EmitBC: 938210008Srdivacky return CI.createDefaultOutputFile(true, InFile, "bc"); 939210008Srdivacky case Backend_EmitNothing: 940276479Sdim return nullptr; 941210008Srdivacky case Backend_EmitMCNull: 942276479Sdim return CI.createNullOutputFile(); 943210008Srdivacky case Backend_EmitObj: 944210008Srdivacky return CI.createDefaultOutputFile(true, InFile, "o"); 945210008Srdivacky } 946210008Srdivacky 947226633Sdim llvm_unreachable("Invalid action!"); 948210008Srdivacky} 949210008Srdivacky 950280031Sdimstd::unique_ptr<ASTConsumer> 951280031SdimCodeGenAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { 952210008Srdivacky BackendAction BA = static_cast<BackendAction>(Act); 953341825Sdim std::unique_ptr<raw_pwrite_stream> OS = CI.takeOutputStream(); 954341825Sdim if (!OS) 955341825Sdim OS = GetOutputStream(CI, InFile, BA); 956341825Sdim 957210008Srdivacky if (BA != Backend_EmitNothing && !OS) 958276479Sdim return nullptr; 959210008Srdivacky 960296417Sdim // Load bitcode modules to link with, if we need to. 961296417Sdim if (LinkModules.empty()) 962321369Sdim for (const CodeGenOptions::BitcodeFileToLink &F : 963321369Sdim CI.getCodeGenOpts().LinkBitcodeFiles) { 964321369Sdim auto BCBuf = CI.getFileManager().getBufferForFile(F.Filename); 965296417Sdim if (!BCBuf) { 966296417Sdim CI.getDiagnostics().Report(diag::err_cannot_open_file) 967321369Sdim << F.Filename << BCBuf.getError().message(); 968296417Sdim LinkModules.clear(); 969296417Sdim return nullptr; 970296417Sdim } 971234353Sdim 972314564Sdim Expected<std::unique_ptr<llvm::Module>> ModuleOrErr = 973314564Sdim getOwningLazyBitcodeModule(std::move(*BCBuf), *VMContext); 974314564Sdim if (!ModuleOrErr) { 975314564Sdim handleAllErrors(ModuleOrErr.takeError(), [&](ErrorInfoBase &EIB) { 976314564Sdim CI.getDiagnostics().Report(diag::err_cannot_open_file) 977321369Sdim << F.Filename << EIB.message(); 978314564Sdim }); 979296417Sdim LinkModules.clear(); 980296417Sdim return nullptr; 981296417Sdim } 982321369Sdim LinkModules.push_back({std::move(ModuleOrErr.get()), F.PropagateAttrs, 983321369Sdim F.Internalize, F.LinkFlags}); 984234353Sdim } 985234353Sdim 986280031Sdim CoverageSourceInfo *CoverageInfo = nullptr; 987280031Sdim // Add the preprocessor callback only when the coverage mapping is generated. 988280031Sdim if (CI.getCodeGenOpts().CoverageMapping) { 989280031Sdim CoverageInfo = new CoverageSourceInfo; 990280031Sdim CI.getPreprocessor().addPPCallbacks( 991280031Sdim std::unique_ptr<PPCallbacks>(CoverageInfo)); 992280031Sdim } 993296417Sdim 994280031Sdim std::unique_ptr<BackendConsumer> Result(new BackendConsumer( 995288943Sdim BA, CI.getDiagnostics(), CI.getHeaderSearchOpts(), 996288943Sdim CI.getPreprocessorOpts(), CI.getCodeGenOpts(), CI.getTargetOpts(), 997321369Sdim CI.getLangOpts(), CI.getFrontendOpts().ShowTimers, InFile, 998321369Sdim std::move(LinkModules), std::move(OS), *VMContext, CoverageInfo)); 999280031Sdim BEConsumer = Result.get(); 1000321369Sdim 1001321369Sdim // Enable generating macro debug info only when debug info is not disabled and 1002321369Sdim // also macro debug info is enabled. 1003321369Sdim if (CI.getCodeGenOpts().getDebugInfo() != codegenoptions::NoDebugInfo && 1004321369Sdim CI.getCodeGenOpts().MacroDebugInfo) { 1005321369Sdim std::unique_ptr<PPCallbacks> Callbacks = 1006360784Sdim std::make_unique<MacroPPCallbacks>(BEConsumer->getCodeGenerator(), 1007321369Sdim CI.getPreprocessor()); 1008321369Sdim CI.getPreprocessor().addPPCallbacks(std::move(Callbacks)); 1009321369Sdim } 1010321369Sdim 1011280031Sdim return std::move(Result); 1012210008Srdivacky} 1013210008Srdivacky 1014288943Sdimstatic void BitcodeInlineAsmDiagHandler(const llvm::SMDiagnostic &SM, 1015288943Sdim void *Context, 1016288943Sdim unsigned LocCookie) { 1017288943Sdim SM.print(nullptr, llvm::errs()); 1018309124Sdim 1019309124Sdim auto Diags = static_cast<DiagnosticsEngine *>(Context); 1020309124Sdim unsigned DiagID; 1021309124Sdim switch (SM.getKind()) { 1022309124Sdim case llvm::SourceMgr::DK_Error: 1023309124Sdim DiagID = diag::err_fe_inline_asm; 1024309124Sdim break; 1025309124Sdim case llvm::SourceMgr::DK_Warning: 1026309124Sdim DiagID = diag::warn_fe_inline_asm; 1027309124Sdim break; 1028309124Sdim case llvm::SourceMgr::DK_Note: 1029309124Sdim DiagID = diag::note_fe_inline_asm; 1030309124Sdim break; 1031327952Sdim case llvm::SourceMgr::DK_Remark: 1032327952Sdim llvm_unreachable("remarks unexpected"); 1033309124Sdim } 1034309124Sdim 1035309124Sdim Diags->Report(DiagID).AddString("cannot compile inline asm"); 1036288943Sdim} 1037288943Sdim 1038353358Sdimstd::unique_ptr<llvm::Module> 1039353358SdimCodeGenAction::loadModule(MemoryBufferRef MBRef) { 1040321369Sdim CompilerInstance &CI = getCompilerInstance(); 1041321369Sdim SourceManager &SM = CI.getSourceManager(); 1042321369Sdim 1043321369Sdim // For ThinLTO backend invocations, ensure that the context 1044321369Sdim // merges types based on ODR identifiers. We also need to read 1045321369Sdim // the correct module out of a multi-module bitcode file. 1046321369Sdim if (!CI.getCodeGenOpts().ThinLTOIndexFile.empty()) { 1047321369Sdim VMContext->enableDebugTypeODRUniquing(); 1048321369Sdim 1049321369Sdim auto DiagErrors = [&](Error E) -> std::unique_ptr<llvm::Module> { 1050321369Sdim unsigned DiagID = 1051321369Sdim CI.getDiagnostics().getCustomDiagID(DiagnosticsEngine::Error, "%0"); 1052321369Sdim handleAllErrors(std::move(E), [&](ErrorInfoBase &EIB) { 1053321369Sdim CI.getDiagnostics().Report(DiagID) << EIB.message(); 1054321369Sdim }); 1055321369Sdim return {}; 1056321369Sdim }; 1057321369Sdim 1058341825Sdim Expected<std::vector<BitcodeModule>> BMsOrErr = getBitcodeModuleList(MBRef); 1059341825Sdim if (!BMsOrErr) 1060341825Sdim return DiagErrors(BMsOrErr.takeError()); 1061341825Sdim BitcodeModule *Bm = FindThinLTOModule(*BMsOrErr); 1062341825Sdim // We have nothing to do if the file contains no ThinLTO module. This is 1063341825Sdim // possible if ThinLTO compilation was not able to split module. Content of 1064341825Sdim // the file was already processed by indexing and will be passed to the 1065341825Sdim // linker using merged object file. 1066341825Sdim if (!Bm) { 1067360784Sdim auto M = std::make_unique<llvm::Module>("empty", *VMContext); 1068341825Sdim M->setTargetTriple(CI.getTargetOpts().Triple); 1069341825Sdim return M; 1070341825Sdim } 1071321369Sdim Expected<std::unique_ptr<llvm::Module>> MOrErr = 1072341825Sdim Bm->parseModule(*VMContext); 1073321369Sdim if (!MOrErr) 1074321369Sdim return DiagErrors(MOrErr.takeError()); 1075321369Sdim return std::move(*MOrErr); 1076321369Sdim } 1077321369Sdim 1078321369Sdim llvm::SMDiagnostic Err; 1079321369Sdim if (std::unique_ptr<llvm::Module> M = parseIR(MBRef, Err, *VMContext)) 1080321369Sdim return M; 1081321369Sdim 1082321369Sdim // Translate from the diagnostic info to the SourceManager location if 1083321369Sdim // available. 1084321369Sdim // TODO: Unify this with ConvertBackendLocation() 1085321369Sdim SourceLocation Loc; 1086321369Sdim if (Err.getLineNo() > 0) { 1087321369Sdim assert(Err.getColumnNo() >= 0); 1088321369Sdim Loc = SM.translateFileLineCol(SM.getFileEntryForID(SM.getMainFileID()), 1089321369Sdim Err.getLineNo(), Err.getColumnNo() + 1); 1090321369Sdim } 1091321369Sdim 1092321369Sdim // Strip off a leading diagnostic code if there is one. 1093321369Sdim StringRef Msg = Err.getMessage(); 1094321369Sdim if (Msg.startswith("error: ")) 1095321369Sdim Msg = Msg.substr(7); 1096321369Sdim 1097321369Sdim unsigned DiagID = 1098321369Sdim CI.getDiagnostics().getCustomDiagID(DiagnosticsEngine::Error, "%0"); 1099321369Sdim 1100321369Sdim CI.getDiagnostics().Report(Loc, DiagID) << Msg; 1101321369Sdim return {}; 1102321369Sdim} 1103321369Sdim 1104210008Srdivackyvoid CodeGenAction::ExecuteAction() { 1105210008Srdivacky // If this is an IR file, we have to treat it specially. 1106360784Sdim if (getCurrentFileKind().getLanguage() == Language::LLVM_IR) { 1107210008Srdivacky BackendAction BA = static_cast<BackendAction>(Act); 1108210008Srdivacky CompilerInstance &CI = getCompilerInstance(); 1109360784Sdim auto &CodeGenOpts = CI.getCodeGenOpts(); 1110360784Sdim auto &Diagnostics = CI.getDiagnostics(); 1111309124Sdim std::unique_ptr<raw_pwrite_stream> OS = 1112309124Sdim GetOutputStream(CI, getCurrentFile(), BA); 1113210008Srdivacky if (BA != Backend_EmitNothing && !OS) 1114210008Srdivacky return; 1115210008Srdivacky 1116210008Srdivacky bool Invalid; 1117210008Srdivacky SourceManager &SM = CI.getSourceManager(); 1118276479Sdim FileID FID = SM.getMainFileID(); 1119353358Sdim const llvm::MemoryBuffer *MainFile = SM.getBuffer(FID, &Invalid); 1120210008Srdivacky if (Invalid) 1121210008Srdivacky return; 1122210008Srdivacky 1123321369Sdim TheModule = loadModule(*MainFile); 1124321369Sdim if (!TheModule) 1125321369Sdim return; 1126309124Sdim 1127276479Sdim const TargetOptions &TargetOpts = CI.getTargetOpts(); 1128276479Sdim if (TheModule->getTargetTriple() != TargetOpts.Triple) { 1129360784Sdim Diagnostics.Report(SourceLocation(), 1130360784Sdim diag::warn_fe_override_module) 1131288943Sdim << TargetOpts.Triple; 1132276479Sdim TheModule->setTargetTriple(TargetOpts.Triple); 1133210008Srdivacky } 1134210008Srdivacky 1135360784Sdim EmbedBitcode(TheModule.get(), CodeGenOpts, 1136309124Sdim MainFile->getMemBufferRef()); 1137309124Sdim 1138288943Sdim LLVMContext &Ctx = TheModule->getContext(); 1139309124Sdim Ctx.setInlineAsmDiagnosticHandler(BitcodeInlineAsmDiagHandler, 1140360784Sdim &Diagnostics); 1141309124Sdim 1142360784Sdim // Set clang diagnostic handler. To do this we need to create a fake 1143360784Sdim // BackendConsumer. 1144360784Sdim BackendConsumer Result(BA, CI.getDiagnostics(), CI.getHeaderSearchOpts(), 1145360784Sdim CI.getPreprocessorOpts(), CI.getCodeGenOpts(), 1146360784Sdim CI.getTargetOpts(), CI.getLangOpts(), 1147360784Sdim CI.getFrontendOpts().ShowTimers, 1148360784Sdim std::move(LinkModules), *VMContext, nullptr); 1149360784Sdim // PR44896: Force DiscardValueNames as false. DiscardValueNames cannot be 1150360784Sdim // true here because the valued names are needed for reading textual IR. 1151360784Sdim Ctx.setDiscardValueNames(false); 1152360784Sdim Ctx.setDiagnosticHandler( 1153360784Sdim std::make_unique<ClangDiagnosticHandler>(CodeGenOpts, &Result)); 1154360784Sdim 1155360784Sdim Expected<std::unique_ptr<llvm::ToolOutputFile>> OptRecordFileOrErr = 1156360784Sdim setupOptimizationRemarks( 1157360784Sdim Ctx, CodeGenOpts.OptRecordFile, CodeGenOpts.OptRecordPasses, 1158360784Sdim CodeGenOpts.OptRecordFormat, CodeGenOpts.DiagnosticsWithHotness, 1159360784Sdim CodeGenOpts.DiagnosticsHotnessThreshold); 1160360784Sdim 1161360784Sdim if (Error E = OptRecordFileOrErr.takeError()) { 1162360784Sdim reportOptRecordError(std::move(E), Diagnostics, CodeGenOpts); 1163360784Sdim return; 1164360784Sdim } 1165360784Sdim std::unique_ptr<llvm::ToolOutputFile> OptRecordFile = 1166360784Sdim std::move(*OptRecordFileOrErr); 1167360784Sdim 1168360784Sdim EmitBackendOutput(Diagnostics, CI.getHeaderSearchOpts(), CodeGenOpts, 1169360784Sdim TargetOpts, CI.getLangOpts(), 1170314564Sdim CI.getTarget().getDataLayout(), TheModule.get(), BA, 1171314564Sdim std::move(OS)); 1172360784Sdim 1173360784Sdim if (OptRecordFile) 1174360784Sdim OptRecordFile->keep(); 1175210008Srdivacky return; 1176210008Srdivacky } 1177210008Srdivacky 1178210008Srdivacky // Otherwise follow the normal AST path. 1179210008Srdivacky this->ASTFrontendAction::ExecuteAction(); 1180210008Srdivacky} 1181210008Srdivacky 1182210008Srdivacky// 1183210008Srdivacky 1184234353Sdimvoid EmitAssemblyAction::anchor() { } 1185218893SdimEmitAssemblyAction::EmitAssemblyAction(llvm::LLVMContext *_VMContext) 1186218893Sdim : CodeGenAction(Backend_EmitAssembly, _VMContext) {} 1187210008Srdivacky 1188234353Sdimvoid EmitBCAction::anchor() { } 1189218893SdimEmitBCAction::EmitBCAction(llvm::LLVMContext *_VMContext) 1190218893Sdim : CodeGenAction(Backend_EmitBC, _VMContext) {} 1191210008Srdivacky 1192234353Sdimvoid EmitLLVMAction::anchor() { } 1193218893SdimEmitLLVMAction::EmitLLVMAction(llvm::LLVMContext *_VMContext) 1194218893Sdim : CodeGenAction(Backend_EmitLL, _VMContext) {} 1195210008Srdivacky 1196234353Sdimvoid EmitLLVMOnlyAction::anchor() { } 1197218893SdimEmitLLVMOnlyAction::EmitLLVMOnlyAction(llvm::LLVMContext *_VMContext) 1198218893Sdim : CodeGenAction(Backend_EmitNothing, _VMContext) {} 1199210008Srdivacky 1200234353Sdimvoid EmitCodeGenOnlyAction::anchor() { } 1201218893SdimEmitCodeGenOnlyAction::EmitCodeGenOnlyAction(llvm::LLVMContext *_VMContext) 1202218893Sdim : CodeGenAction(Backend_EmitMCNull, _VMContext) {} 1203210008Srdivacky 1204234353Sdimvoid EmitObjAction::anchor() { } 1205218893SdimEmitObjAction::EmitObjAction(llvm::LLVMContext *_VMContext) 1206218893Sdim : CodeGenAction(Backend_EmitObj, _VMContext) {} 1207