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