24 #include "llvm/ADT/SmallString.h"
25 #include "llvm/Bitcode/ReaderWriter.h"
26 #include "llvm/IR/DebugInfo.h"
27 #include "llvm/IR/DiagnosticInfo.h"
28 #include "llvm/IR/DiagnosticPrinter.h"
29 #include "llvm/IR/LLVMContext.h"
30 #include "llvm/IR/Module.h"
31 #include "llvm/IRReader/IRReader.h"
32 #include "llvm/Linker/Linker.h"
33 #include "llvm/Pass.h"
34 #include "llvm/Support/MemoryBuffer.h"
35 #include "llvm/Support/SourceMgr.h"
36 #include "llvm/Support/Timer.h"
38 using namespace clang;
43 virtual void anchor();
49 raw_pwrite_stream *AsmOutStream;
52 Timer LLVMIRGeneration;
54 std::unique_ptr<CodeGenerator> Gen;
56 std::unique_ptr<llvm::Module> TheModule, LinkModule;
65 const std::string &InFile, llvm::Module *LinkModule,
66 raw_pwrite_stream *OS, LLVMContext &
C,
68 : Diags(Diags), Action(Action), CodeGenOpts(CodeGenOpts),
69 TargetOpts(TargetOpts), LangOpts(LangOpts), AsmOutStream(OS),
70 Context(nullptr), LLVMIRGeneration(
"LLVM IR Generation Time"),
72 CodeGenOpts, C, CoverageInfo)),
73 LinkModule(LinkModule) {
74 llvm::TimePassesIsEnabled = TimePasses;
77 std::unique_ptr<llvm::Module>
takeModule() {
return std::move(TheModule); }
81 Gen->HandleCXXStaticMemberVarInstantiation(VD);
92 if (llvm::TimePassesIsEnabled)
93 LLVMIRGeneration.startTimer();
97 TheModule.reset(Gen->GetModule());
99 if (llvm::TimePassesIsEnabled)
100 LLVMIRGeneration.stopTimer();
106 "LLVM IR generation of declaration");
108 if (llvm::TimePassesIsEnabled)
109 LLVMIRGeneration.startTimer();
111 Gen->HandleTopLevelDecl(D);
113 if (llvm::TimePassesIsEnabled)
114 LLVMIRGeneration.stopTimer();
122 "LLVM IR generation of inline method");
123 if (llvm::TimePassesIsEnabled)
124 LLVMIRGeneration.startTimer();
126 Gen->HandleInlineMethodDefinition(D);
128 if (llvm::TimePassesIsEnabled)
129 LLVMIRGeneration.stopTimer();
134 PrettyStackTraceString CrashInfo(
"Per-file LLVM IR generation");
135 if (llvm::TimePassesIsEnabled)
136 LLVMIRGeneration.startTimer();
138 Gen->HandleTranslationUnit(C);
140 if (llvm::TimePassesIsEnabled)
141 LLVMIRGeneration.stopTimer();
150 llvm::Module *M = Gen->ReleaseModule();
158 assert(TheModule.get() == M &&
159 "Unexpected module change during IR generation");
163 if (Linker::LinkModules(
165 [=](
const DiagnosticInfo &DI) { linkerDiagnosticHandler(DI); }))
171 LLVMContext &Ctx = TheModule->getContext();
172 LLVMContext::InlineAsmDiagHandlerTy OldHandler =
173 Ctx.getInlineAsmDiagnosticHandler();
174 void *OldContext = Ctx.getInlineAsmDiagnosticContext();
175 Ctx.setInlineAsmDiagnosticHandler(InlineAsmDiagHandler,
this);
177 LLVMContext::DiagnosticHandlerTy OldDiagnosticHandler =
178 Ctx.getDiagnosticHandler();
179 void *OldDiagnosticContext = Ctx.getDiagnosticContext();
180 Ctx.setDiagnosticHandler(DiagnosticHandler,
this);
184 TheModule.get(),
Action, AsmOutStream);
186 Ctx.setInlineAsmDiagnosticHandler(OldHandler, OldContext);
188 Ctx.setDiagnosticHandler(OldDiagnosticHandler, OldDiagnosticContext);
194 "LLVM IR generation of declaration");
195 Gen->HandleTagDeclDefinition(D);
199 Gen->HandleTagDeclRequiredDefinition(D);
203 Gen->CompleteTentativeDefinition(D);
207 Gen->HandleVTable(RD);
211 Gen->HandleLinkerOptionPragma(Opts);
215 llvm::StringRef
Value)
override {
216 Gen->HandleDetectMismatch(Name, Value);
220 Gen->HandleDependentLibrary(Opts);
224 unsigned LocCookie) {
229 void linkerDiagnosticHandler(
const llvm::DiagnosticInfo &DI);
236 void InlineAsmDiagHandler2(
const llvm::SMDiagnostic &,
239 void DiagnosticHandlerImpl(
const llvm::DiagnosticInfo &DI);
243 bool InlineAsmDiagHandler(
const llvm::DiagnosticInfoInlineAsm &D);
247 bool StackSizeDiagHandler(
const llvm::DiagnosticInfoStackSize &D);
251 void EmitOptimizationMessage(
const llvm::DiagnosticInfoOptimizationBase &D,
254 OptimizationRemarkHandler(
const llvm::DiagnosticInfoOptimizationRemark &D);
255 void OptimizationRemarkHandler(
256 const llvm::DiagnosticInfoOptimizationRemarkMissed &D);
257 void OptimizationRemarkHandler(
258 const llvm::DiagnosticInfoOptimizationRemarkAnalysis &D);
259 void OptimizationFailureHandler(
260 const llvm::DiagnosticInfoOptimizationFailure &D);
263 void BackendConsumer::anchor() {}
277 const MemoryBuffer *LBuf =
278 LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(D.getLoc()));
282 std::unique_ptr<llvm::MemoryBuffer> CBuf =
283 llvm::MemoryBuffer::getMemBufferCopy(LBuf->getBuffer(),
284 LBuf->getBufferIdentifier());
289 unsigned Offset = D.getLoc().getPointer() - LBuf->getBufferStart();
305 StringRef Message = D.getMessage();
306 if (Message.startswith(
"error: "))
307 Message = Message.substr(7);
311 if (D.getLoc() != SMLoc())
315 switch (D.getKind()) {
316 case llvm::SourceMgr::DK_Error:
317 DiagID = diag::err_fe_inline_asm;
319 case llvm::SourceMgr::DK_Warning:
320 DiagID = diag::warn_fe_inline_asm;
322 case llvm::SourceMgr::DK_Note:
323 DiagID = diag::note_fe_inline_asm;
330 Diags.Report(LocCookie, DiagID).AddString(Message);
332 if (D.getLoc().isValid()) {
336 for (
unsigned i = 0, e = D.getRanges().size(); i != e; ++i) {
337 std::pair<unsigned, unsigned> Range = D.getRanges()[i];
338 unsigned Column = D.getColumnNo();
349 Diags.Report(Loc, DiagID).AddString(Message);
352 #define ComputeDiagID(Severity, GroupName, DiagID) \
354 switch (Severity) { \
355 case llvm::DS_Error: \
356 DiagID = diag::err_fe_##GroupName; \
358 case llvm::DS_Warning: \
359 DiagID = diag::warn_fe_##GroupName; \
361 case llvm::DS_Remark: \
362 llvm_unreachable("'remark' severity not expected"); \
364 case llvm::DS_Note: \
365 DiagID = diag::note_fe_##GroupName; \
370 #define ComputeDiagRemarkID(Severity, GroupName, DiagID) \
372 switch (Severity) { \
373 case llvm::DS_Error: \
374 DiagID = diag::err_fe_##GroupName; \
376 case llvm::DS_Warning: \
377 DiagID = diag::warn_fe_##GroupName; \
379 case llvm::DS_Remark: \
380 DiagID = diag::remark_fe_##GroupName; \
382 case llvm::DS_Note: \
383 DiagID = diag::note_fe_##GroupName; \
392 std::string Message = D.getMsgStr().str();
400 Diags.Report(LocCookie, DiagID).AddString(Message);
407 Diags.Report(Loc, DiagID).AddString(Message);
415 if (D.getSeverity() != llvm::DS_Warning)
420 if (
const Decl *ND = Gen->GetDeclForMangledName(D.getFunction().getName())) {
421 Diags.Report(ND->getASTContext().getFullLoc(ND->getLocation()),
422 diag::warn_fe_frame_larger_than)
431 const llvm::DiagnosticInfoOptimizationBase &D,
unsigned DiagID) {
433 assert(D.getSeverity() == llvm::DS_Remark ||
434 D.getSeverity() == llvm::DS_Warning);
442 if (D.isLocationAvailable()) {
443 D.getLocation(&Filename, &Line, &Column);
445 if (FE && Line > 0) {
448 DILoc = SourceMgr.translateFileLineCol(FE, Line, Column ? Column : 1);
457 if (
const Decl *FD = Gen->GetDeclForMangledName(D.getFunction().getName()))
458 Loc = FD->getASTContext().getFullLoc(FD->getBodyRBrace());
460 Diags.Report(Loc, DiagID)
464 if (DILoc.
isInvalid() && D.isLocationAvailable())
469 Diags.Report(Loc, diag::note_fe_backend_optimization_remark_invalid_loc)
470 << Filename << Line <<
Column;
474 const llvm::DiagnosticInfoOptimizationRemark &D) {
477 if (CodeGenOpts.OptimizationRemarkPattern &&
478 CodeGenOpts.OptimizationRemarkPattern->match(D.getPassName()))
479 EmitOptimizationMessage(D, diag::remark_fe_backend_optimization_remark);
483 const llvm::DiagnosticInfoOptimizationRemarkMissed &D) {
487 if (CodeGenOpts.OptimizationRemarkMissedPattern &&
488 CodeGenOpts.OptimizationRemarkMissedPattern->match(D.getPassName()))
489 EmitOptimizationMessage(D,
490 diag::remark_fe_backend_optimization_remark_missed);
494 const llvm::DiagnosticInfoOptimizationRemarkAnalysis &D) {
498 if (CodeGenOpts.OptimizationRemarkAnalysisPattern &&
499 CodeGenOpts.OptimizationRemarkAnalysisPattern->match(D.getPassName()))
500 EmitOptimizationMessage(
501 D, diag::remark_fe_backend_optimization_remark_analysis);
505 const llvm::DiagnosticInfoOptimizationFailure &D) {
506 EmitOptimizationMessage(D, diag::warn_fe_backend_optimization_failure);
510 if (DI.getSeverity() != DS_Error)
513 std::string MsgStorage;
515 raw_string_ostream Stream(MsgStorage);
516 DiagnosticPrinterRawOStream DP(Stream);
520 Diags.Report(diag::err_fe_cannot_link_module)
521 << LinkModule->getModuleIdentifier() << MsgStorage;
527 unsigned DiagID = diag::err_fe_inline_asm;
528 llvm::DiagnosticSeverity
Severity = DI.getSeverity();
530 switch (DI.getKind()) {
531 case llvm::DK_InlineAsm:
532 if (InlineAsmDiagHandler(cast<DiagnosticInfoInlineAsm>(DI)))
536 case llvm::DK_StackSize:
537 if (StackSizeDiagHandler(cast<DiagnosticInfoStackSize>(DI)))
541 case llvm::DK_OptimizationRemark:
544 OptimizationRemarkHandler(cast<DiagnosticInfoOptimizationRemark>(DI));
546 case llvm::DK_OptimizationRemarkMissed:
549 OptimizationRemarkHandler(cast<DiagnosticInfoOptimizationRemarkMissed>(DI));
551 case llvm::DK_OptimizationRemarkAnalysis:
554 OptimizationRemarkHandler(
555 cast<DiagnosticInfoOptimizationRemarkAnalysis>(DI));
557 case llvm::DK_OptimizationFailure:
560 OptimizationFailureHandler(cast<DiagnosticInfoOptimizationFailure>(DI));
567 std::string MsgStorage;
569 raw_string_ostream Stream(MsgStorage);
570 DiagnosticPrinterRawOStream DP(Stream);
576 Diags.Report(Loc, DiagID).AddString(MsgStorage);
581 : Act(_Act), LinkModule(nullptr),
582 VMContext(_VMContext ? _VMContext : new LLVMContext),
583 OwnsVMContext(!_VMContext) {}
607 return std::move(TheModule);
611 OwnsVMContext =
false;
615 static raw_pwrite_stream *
632 llvm_unreachable(
"Invalid action!");
635 std::unique_ptr<ASTConsumer>
642 llvm::Module *LinkModuleToUse = LinkModule;
647 if (!LinkModuleToUse && !LinkBCFile.empty()) {
651 << LinkBCFile << BCBuf.getError().message();
655 ErrorOr<std::unique_ptr<llvm::Module>> ModuleOrErr =
656 getLazyBitcodeModule(std::move(*BCBuf), *VMContext);
657 if (std::error_code EC = ModuleOrErr.getError()) {
659 << LinkBCFile << EC.message();
662 LinkModuleToUse = ModuleOrErr.get().release();
670 std::unique_ptr<PPCallbacks>(CoverageInfo));
676 LinkModuleToUse, OS, *VMContext, CoverageInfo));
678 return std::move(Result);
683 unsigned LocCookie) {
684 SM.print(
nullptr, llvm::errs());
699 llvm::MemoryBuffer *MainFile = SM.
getBuffer(FID, &Invalid);
703 llvm::SMDiagnostic Err;
704 TheModule = parseIR(MainFile->getMemBufferRef(), Err, *VMContext);
710 if (Err.getLineNo() > 0) {
711 assert(Err.getColumnNo() >= 0);
713 Err.getLineNo(), Err.getColumnNo() + 1);
717 StringRef Msg = Err.getMessage();
718 if (Msg.startswith(
"error: "))
728 if (TheModule->getTargetTriple() != TargetOpts.
Triple) {
730 diag::warn_fe_override_module)
732 TheModule->setTargetTriple(TargetOpts.
Triple);
735 LLVMContext &Ctx = TheModule->getContext();
739 TheModule.get(), BA, OS);
749 void EmitAssemblyAction::anchor() { }
753 void EmitBCAction::anchor() { }
757 void EmitLLVMAction::anchor() { }
761 void EmitLLVMOnlyAction::anchor() { }
765 void EmitCodeGenOnlyAction::anchor() { }
769 void EmitObjAction::anchor() { }
void EmitOptimizationMessage(const llvm::DiagnosticInfoOptimizationBase &D, unsigned DiagID)
Specialized handlers for optimization remarks. Note that these handlers only accept remarks and they ...
Defines the clang::ASTContext interface.
LangOptions & getLangOpts()
void HandleInlineMethodDefinition(CXXMethodDecl *D) override
This callback is invoked each time an inline method definition is completed.
PreprocessorOptions & getPreprocessorOpts()
static void InlineAsmDiagHandler(const llvm::SMDiagnostic &SM, void *Context, unsigned LocCookie)
static DeclContext * castToDeclContext(const Decl *)
llvm::Module * takeLinkModule()
Implements support for file system lookup, file system caching, and directory search management...
bool hasIRSupport() const override
Does this action support use with IR files?
Defines the clang::FileManager interface and associated types.
Emit human-readable LLVM assembly.
Run CodeGen, but don't emit anything.
void EndSourceFileAction() override
Callback at the end of processing a single input.
void ExecuteAction() override
Implement the ExecuteAction interface by running Sema on the already-initialized AST consumer...
Defines the SourceManager interface.
CompilerInstance & getCompilerInstance() const
bool HandleTopLevelDecl(DeclGroupRef D) override
llvm::MemoryBuffer * getBuffer(FileID FID, SourceLocation Loc, bool *Invalid=nullptr) const
Return the buffer for the specified FileID.
Stores additional source code information like skipped ranges which is required by the coverage mappi...
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
void HandleTagDeclRequiredDefinition(const TagDecl *D) override
This callback is invoked the first time each TagDecl is required to be complete.
std::unique_ptr< llvm::Module > takeModule()
TargetInfo & getTarget() const
Don't emit anything (benchmarking mode)
SourceManager & getSourceManager() const
Return the current source manager.
Options for controlling the target.
void HandleTagDeclDefinition(TagDecl *D) override
InputKind getCurrentFileKind() const
static raw_pwrite_stream * GetOutputStream(CompilerInstance &CI, StringRef InFile, BackendAction Action)
bool StackSizeDiagHandler(const llvm::DiagnosticInfoStackSize &D)
Specialized handler for StackSize diagnostic.
#define ComputeDiagRemarkID(Severity, GroupName, DiagID)
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
static SourceLocation getFromRawEncoding(unsigned Encoding)
Turn a raw encoding of a SourceLocation object into a real SourceLocation.
void OptimizationFailureHandler(const llvm::DiagnosticInfoOptimizationFailure &D)
void CompleteTentativeDefinition(VarDecl *D) override
CodeGenOptions & getCodeGenOpts()
void ExecuteAction() override
Callback to run the program action, using the initialized compiler instance.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
void EmitBackendOutput(DiagnosticsEngine &Diags, const CodeGenOptions &CGOpts, const TargetOptions &TOpts, const LangOptions &LOpts, StringRef TDesc, llvm::Module *M, BackendAction Action, raw_pwrite_stream *OS)
const TargetInfo & getTargetInfo() const
SourceLocation getLocWithOffset(int Offset) const
Return a source location with the specified offset from this SourceLocation.
FrontendOptions & getFrontendOpts()
Concrete class used by the front-end to report problems and issues.
BackendConsumer(BackendAction Action, DiagnosticsEngine &Diags, const HeaderSearchOptions &HeaderSearchOpts, const PreprocessorOptions &PPOpts, const CodeGenOptions &CodeGenOpts, const TargetOptions &TargetOpts, const LangOptions &LangOpts, bool TimePasses, const std::string &InFile, llvm::Module *LinkModule, raw_pwrite_stream *OS, LLVMContext &C, CoverageSourceInfo *CoverageInfo=nullptr)
void DiagnosticHandlerImpl(const llvm::DiagnosticInfo &DI)
This function is invoked when the backend needs to report something to the user.
void OptimizationRemarkHandler(const llvm::DiagnosticInfoOptimizationRemark &D)
static void DiagnosticHandler(const llvm::DiagnosticInfo &DI, void *Context)
static void BitcodeInlineAsmDiagHandler(const llvm::SMDiagnostic &SM, void *Context, unsigned LocCookie)
HeaderSearchOptions & getHeaderSearchOpts()
SourceLocation translateFileLineCol(const FileEntry *SourceFile, unsigned Line, unsigned Col) const
Get the source location for the given file:line:col triplet.
Preprocessor & getPreprocessor() const
Return the current preprocessor.
const FileEntry * getFile(StringRef Filename, bool OpenFile=false, bool CacheFailure=true)
Lookup, cache, and verify the specified file (real or virtual).
A little helper class used to produce diagnostics.
BackendConsumer * BEConsumer
const FileEntry * getFileEntryForID(FileID FID) const
Returns the FileEntry record for the provided FileID.
EmitLLVMAction(llvm::LLVMContext *_VMContext=nullptr)
~CodeGenAction() override
CodeGenAction(unsigned _Act, llvm::LLVMContext *_VMContext=nullptr)
FileID createFileID(const FileEntry *SourceFile, SourceLocation IncludePos, SrcMgr::CharacteristicKind FileCharacter, int LoadedID=0, unsigned LoadedOffset=0)
Create a new FileID that represents the specified file being #included from the specified IncludePosi...
Defines the clang::Preprocessor interface.
Emit native object files.
EmitObjAction(llvm::LLVMContext *_VMContext=nullptr)
DiagnosticsEngine & getDiagnostics() const
Get the current diagnostics engine.
The result type of a method or function.
EmitBCAction(llvm::LLVMContext *_VMContext=nullptr)
static FullSourceLoc ConvertBackendLocation(const llvm::SMDiagnostic &D, SourceManager &CSM)
Emit native assembly files.
EmitCodeGenOnlyAction(llvm::LLVMContext *_VMContext=nullptr)
Encodes a location in the source. The SourceManager can decode this to get at the full include stack...
bool isValid() const
Return true if this is a valid SourceLocation object.
TagDecl - Represents the declaration of a struct/union/class/enum.
const StringRef getCurrentFile() const
Cached information about one file (either on disk or in the virtual file system). ...
Represents a static or instance method of a struct/union/class.
const char * getTargetDescription() const
void HandleLinkerOptionPragma(llvm::StringRef Opts) override
Handle a pragma that appends to Linker Options. Currently this only exists to support Microsoft's #pr...
std::string LinkBitcodeFile
The name of the bitcode file to link before optzns.
#define ComputeDiagID(Severity, GroupName, DiagID)
unsigned getCustomDiagID(Level L, const char(&FormatString)[N])
Return an ID for a diagnostic with the specified format string and level.
FileID getMainFileID() const
Returns the FileID of the main source file.
EmitLLVMOnlyAction(llvm::LLVMContext *_VMContext=nullptr)
std::unique_ptr< llvm::Module > takeModule()
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
llvm::raw_null_ostream * createNullOutputFile()
FileManager & getFileManager() const
Return the current file manager to the caller.
llvm::ErrorOr< std::unique_ptr< llvm::MemoryBuffer > > getBufferForFile(const FileEntry *Entry, bool isVolatile=false, bool ShouldCloseOpenFile=true)
Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful, otherwise returning null.
void HandleDependentLibrary(llvm::StringRef Opts) override
Handle a dependent library created by a pragma in the source. Currently this only exists to support M...
void InlineAsmDiagHandler2(const llvm::SMDiagnostic &, SourceLocation LocCookie)
void linkerDiagnosticHandler(const llvm::DiagnosticInfo &DI)
void HandleVTable(CXXRecordDecl *RD) override
Callback involved at the end of a translation unit to notify the consumer that a vtable for the given...
void Initialize(ASTContext &Ctx) override
std::unique_ptr< ASTConsumer > CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override
Create the AST consumer object for this action, if supported.
SourceManager & getSourceManager()
raw_pwrite_stream * createDefaultOutputFile(bool Binary=true, StringRef BaseInput="", StringRef Extension="")
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate.h) and friends (in DeclFriend.h).
EmitAssemblyAction(llvm::LLVMContext *_VMContext=nullptr)
Represents a C++ struct/union/class.
llvm::LLVMContext * takeLLVMContext()
Take the LLVM context used by this action.
CodeGenerator * CreateLLVMCodeGen(DiagnosticsEngine &Diags, const std::string &ModuleName, const HeaderSearchOptions &HeaderSearchOpts, const PreprocessorOptions &PreprocessorOpts, const CodeGenOptions &CGO, llvm::LLVMContext &C, CoverageSourceInfo *CoverageInfo=nullptr)
void HandleCXXStaticMemberVarInstantiation(VarDecl *VD) override
HandleCXXStaticMemberVarInstantiation - Tell the consumer that this.
Defines the clang::TargetInfo interface.
A SourceLocation and its associated SourceManager.
void HandleTranslationUnit(ASTContext &C) override
SourceLocation getLocForStartOfFile(FileID FID) const
Return the source location corresponding to the first byte of the specified file. ...
A trivial tuple used to represent a source range.
TargetOptions & getTargetOpts()
void HandleDetectMismatch(llvm::StringRef Name, llvm::StringRef Value) override
Handle a pragma that emits a mismatch identifier and value to the object file for the linker to work ...
void addPPCallbacks(std::unique_ptr< PPCallbacks > C)
This class handles loading and caching of source files into memory.