#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Lex/Preprocessor.h"
-#include "llvm/ADT/SmallString.h"
#include "llvm/Bitcode/ReaderWriter.h"
-#include "llvm/CodeGen/DiagnosticInfoCodeGen.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/DiagnosticPrinter.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/Timer.h"
+#include "llvm/Support/ToolOutputFile.h"
+#include "llvm/Support/YAMLTraits.h"
#include <memory>
using namespace clang;
using namespace llvm;
const CodeGenOptions &CodeGenOpts;
const TargetOptions &TargetOpts;
const LangOptions &LangOpts;
- raw_pwrite_stream *AsmOutStream;
+ std::unique_ptr<raw_pwrite_stream> AsmOutStream;
ASTContext *Context;
Timer LLVMIRGeneration;
+ unsigned LLVMIRGenerationRefCount;
std::unique_ptr<CodeGenerator> Gen;
- std::unique_ptr<llvm::Module> TheModule;
SmallVector<std::pair<unsigned, std::unique_ptr<llvm::Module>>, 4>
LinkModules;
const TargetOptions &TargetOpts, const LangOptions &LangOpts,
bool TimePasses, const std::string &InFile,
const SmallVectorImpl<std::pair<unsigned, llvm::Module *>> &LinkModules,
- raw_pwrite_stream *OS, LLVMContext &C,
+ std::unique_ptr<raw_pwrite_stream> OS, LLVMContext &C,
CoverageSourceInfo *CoverageInfo = nullptr)
: Diags(Diags), Action(Action), CodeGenOpts(CodeGenOpts),
- TargetOpts(TargetOpts), LangOpts(LangOpts), AsmOutStream(OS),
- Context(nullptr), LLVMIRGeneration("LLVM IR Generation Time"),
+ TargetOpts(TargetOpts), LangOpts(LangOpts),
+ AsmOutStream(std::move(OS)), Context(nullptr),
+ LLVMIRGeneration("LLVM IR Generation Time"),
+ LLVMIRGenerationRefCount(0),
Gen(CreateLLVMCodeGen(Diags, InFile, HeaderSearchOpts, PPOpts,
CodeGenOpts, C, CoverageInfo)) {
llvm::TimePassesIsEnabled = TimePasses;
this->LinkModules.push_back(
std::make_pair(I.first, std::unique_ptr<llvm::Module>(I.second)));
}
- std::unique_ptr<llvm::Module> takeModule() { return std::move(TheModule); }
+ llvm::Module *getModule() const { return Gen->GetModule(); }
+ std::unique_ptr<llvm::Module> takeModule() {
+ return std::unique_ptr<llvm::Module>(Gen->ReleaseModule());
+ }
void releaseLinkModules() {
for (auto &I : LinkModules)
I.second.release();
Gen->Initialize(Ctx);
- TheModule.reset(Gen->GetModule());
-
if (llvm::TimePassesIsEnabled)
LLVMIRGeneration.stopTimer();
}
Context->getSourceManager(),
"LLVM IR generation of declaration");
- if (llvm::TimePassesIsEnabled)
- LLVMIRGeneration.startTimer();
+ // Recurse.
+ if (llvm::TimePassesIsEnabled) {
+ LLVMIRGenerationRefCount += 1;
+ if (LLVMIRGenerationRefCount == 1)
+ LLVMIRGeneration.startTimer();
+ }
Gen->HandleTopLevelDecl(D);
- if (llvm::TimePassesIsEnabled)
- LLVMIRGeneration.stopTimer();
+ if (llvm::TimePassesIsEnabled) {
+ LLVMIRGenerationRefCount -= 1;
+ if (LLVMIRGenerationRefCount == 0)
+ LLVMIRGeneration.stopTimer();
+ }
return true;
}
- void HandleInlineMethodDefinition(CXXMethodDecl *D) override {
+ void HandleInlineFunctionDefinition(FunctionDecl *D) override {
PrettyStackTraceDecl CrashInfo(D, SourceLocation(),
Context->getSourceManager(),
- "LLVM IR generation of inline method");
+ "LLVM IR generation of inline function");
if (llvm::TimePassesIsEnabled)
LLVMIRGeneration.startTimer();
- Gen->HandleInlineMethodDefinition(D);
+ Gen->HandleInlineFunctionDefinition(D);
if (llvm::TimePassesIsEnabled)
LLVMIRGeneration.stopTimer();
void HandleTranslationUnit(ASTContext &C) override {
{
PrettyStackTraceString CrashInfo("Per-file LLVM IR generation");
- if (llvm::TimePassesIsEnabled)
- LLVMIRGeneration.startTimer();
+ if (llvm::TimePassesIsEnabled) {
+ LLVMIRGenerationRefCount += 1;
+ if (LLVMIRGenerationRefCount == 1)
+ LLVMIRGeneration.startTimer();
+ }
Gen->HandleTranslationUnit(C);
- if (llvm::TimePassesIsEnabled)
- LLVMIRGeneration.stopTimer();
+ if (llvm::TimePassesIsEnabled) {
+ LLVMIRGenerationRefCount -= 1;
+ if (LLVMIRGenerationRefCount == 0)
+ LLVMIRGeneration.stopTimer();
+ }
}
// Silently ignore if we weren't initialized for some reason.
- if (!TheModule)
+ if (!getModule())
return;
- // Make sure IR generation is happy with the module. This is released by
- // the module provider.
- llvm::Module *M = Gen->ReleaseModule();
- if (!M) {
- // The module has been released by IR gen on failures, do not double
- // free.
- TheModule.release();
- return;
- }
-
- assert(TheModule.get() == M &&
- "Unexpected module change during IR generation");
-
// Install an inline asm handler so that diagnostics get printed through
// our diagnostics hooks.
- LLVMContext &Ctx = TheModule->getContext();
+ LLVMContext &Ctx = getModule()->getContext();
LLVMContext::InlineAsmDiagHandlerTy OldHandler =
Ctx.getInlineAsmDiagnosticHandler();
void *OldContext = Ctx.getInlineAsmDiagnosticContext();
Ctx.getDiagnosticHandler();
void *OldDiagnosticContext = Ctx.getDiagnosticContext();
Ctx.setDiagnosticHandler(DiagnosticHandler, this);
+ Ctx.setDiagnosticHotnessRequested(CodeGenOpts.DiagnosticsWithHotness);
+
+ std::unique_ptr<llvm::tool_output_file> OptRecordFile;
+ if (!CodeGenOpts.OptRecordFile.empty()) {
+ std::error_code EC;
+ OptRecordFile =
+ llvm::make_unique<llvm::tool_output_file>(CodeGenOpts.OptRecordFile,
+ EC, sys::fs::F_None);
+ if (EC) {
+ Diags.Report(diag::err_cannot_open_file) <<
+ CodeGenOpts.OptRecordFile << EC.message();
+ return;
+ }
+
+ Ctx.setDiagnosticsOutputFile(new yaml::Output(OptRecordFile->os()));
+
+ if (CodeGenOpts.getProfileUse() != CodeGenOptions::ProfileNone)
+ Ctx.setDiagnosticHotnessRequested(true);
+ }
// Link LinkModule into this module if present, preserving its validity.
for (auto &I : LinkModules) {
unsigned LinkFlags = I.first;
CurLinkModule = I.second.get();
- if (Linker::linkModules(*M, std::move(I.second), LinkFlags))
+ if (Linker::linkModules(*getModule(), std::move(I.second), LinkFlags))
return;
}
+ EmbedBitcode(getModule(), CodeGenOpts, llvm::MemoryBufferRef());
+
EmitBackendOutput(Diags, CodeGenOpts, TargetOpts, LangOpts,
- C.getTargetInfo().getDataLayoutString(),
- TheModule.get(), Action, AsmOutStream);
+ C.getTargetInfo().getDataLayout(),
+ getModule(), Action, std::move(AsmOutStream));
Ctx.setInlineAsmDiagnosticHandler(OldHandler, OldContext);
Ctx.setDiagnosticHandler(OldDiagnosticHandler, OldDiagnosticContext);
+
+ if (OptRecordFile)
+ OptRecordFile->keep();
}
void HandleTagDeclDefinition(TagDecl *D) override {
Gen->HandleVTable(RD);
}
- void HandleLinkerOption(llvm::StringRef Opts) override {
- Gen->HandleLinkerOption(Opts);
- }
-
- void HandleDetectMismatch(llvm::StringRef Name,
- llvm::StringRef Value) override {
- Gen->HandleDetectMismatch(Name, Value);
- }
-
- void HandleDependentLibrary(llvm::StringRef Opts) override {
- Gen->HandleDependentLibrary(Opts);
- }
-
static void InlineAsmDiagHandler(const llvm::SMDiagnostic &SM,void *Context,
unsigned LocCookie) {
SourceLocation Loc = SourceLocation::getFromRawEncoding(LocCookie);
/// them.
void EmitOptimizationMessage(const llvm::DiagnosticInfoOptimizationBase &D,
unsigned DiagID);
- void
- OptimizationRemarkHandler(const llvm::DiagnosticInfoOptimizationRemark &D);
+ void OptimizationRemarkHandler(const llvm::OptimizationRemark &D);
+ void OptimizationRemarkHandler(const llvm::OptimizationRemarkMissed &D);
+ void OptimizationRemarkHandler(const llvm::OptimizationRemarkAnalysis &D);
void OptimizationRemarkHandler(
- const llvm::DiagnosticInfoOptimizationRemarkMissed &D);
+ const llvm::OptimizationRemarkAnalysisFPCommute &D);
void OptimizationRemarkHandler(
- const llvm::DiagnosticInfoOptimizationRemarkAnalysis &D);
- void OptimizationRemarkHandler(
- const llvm::DiagnosticInfoOptimizationRemarkAnalysisFPCommute &D);
- void OptimizationRemarkHandler(
- const llvm::DiagnosticInfoOptimizationRemarkAnalysisAliasing &D);
+ const llvm::OptimizationRemarkAnalysisAliasing &D);
void OptimizationFailureHandler(
const llvm::DiagnosticInfoOptimizationFailure &D);
};
return false;
if (const Decl *ND = Gen->GetDeclForMangledName(D.getFunction().getName())) {
+ // FIXME: Shouldn't need to truncate to uint32_t
Diags.Report(ND->getASTContext().getFullLoc(ND->getLocation()),
diag::warn_fe_frame_larger_than)
- << D.getStackSize() << Decl::castToDeclContext(ND);
+ << static_cast<uint32_t>(D.getStackSize()) << Decl::castToDeclContext(ND);
return true;
}
// we could not translate this location. This can happen in the
// case of #line directives.
Diags.Report(Loc, diag::note_fe_backend_invalid_loc)
- << Filename << Line;
+ << Filename << Line << Column;
return Loc;
}
FullSourceLoc Loc = getBestLocationFromDebugLoc(D, BadDebugInfo, Filename,
Line, Column);
+ std::string Msg;
+ raw_string_ostream MsgStream(Msg);
+ MsgStream << D.getMsg();
+
+ if (D.getHotness())
+ MsgStream << " (hotness: " << *D.getHotness() << ")";
+
Diags.Report(Loc, DiagID)
- << AddFlagValue(D.getPassName() ? D.getPassName() : "")
- << D.getMsg().str();
+ << AddFlagValue(D.getPassName())
+ << MsgStream.str();
if (BadDebugInfo)
// If we were not able to translate the file:line:col information
}
void BackendConsumer::OptimizationRemarkHandler(
- const llvm::DiagnosticInfoOptimizationRemark &D) {
+ const llvm::OptimizationRemark &D) {
// Optimization remarks are active only if the -Rpass flag has a regular
// expression that matches the name of the pass name in \p D.
if (CodeGenOpts.OptimizationRemarkPattern &&
}
void BackendConsumer::OptimizationRemarkHandler(
- const llvm::DiagnosticInfoOptimizationRemarkMissed &D) {
+ const llvm::OptimizationRemarkMissed &D) {
// Missed optimization remarks are active only if the -Rpass-missed
// flag has a regular expression that matches the name of the pass
// name in \p D.
}
void BackendConsumer::OptimizationRemarkHandler(
- const llvm::DiagnosticInfoOptimizationRemarkAnalysis &D) {
+ const llvm::OptimizationRemarkAnalysis &D) {
// Optimization analysis remarks are active if the pass name is set to
// llvm::DiagnosticInfo::AlwasyPrint or if the -Rpass-analysis flag has a
// regular expression that matches the name of the pass name in \p D.
- if (D.getPassName() == llvm::DiagnosticInfo::AlwaysPrint ||
+ if (D.shouldAlwaysPrint() ||
(CodeGenOpts.OptimizationRemarkAnalysisPattern &&
CodeGenOpts.OptimizationRemarkAnalysisPattern->match(D.getPassName())))
EmitOptimizationMessage(
}
void BackendConsumer::OptimizationRemarkHandler(
- const llvm::DiagnosticInfoOptimizationRemarkAnalysisFPCommute &D) {
+ const llvm::OptimizationRemarkAnalysisFPCommute &D) {
// Optimization analysis remarks are active if the pass name is set to
// llvm::DiagnosticInfo::AlwasyPrint or if the -Rpass-analysis flag has a
// regular expression that matches the name of the pass name in \p D.
- if (D.getPassName() == llvm::DiagnosticInfo::AlwaysPrint ||
+ if (D.shouldAlwaysPrint() ||
(CodeGenOpts.OptimizationRemarkAnalysisPattern &&
CodeGenOpts.OptimizationRemarkAnalysisPattern->match(D.getPassName())))
EmitOptimizationMessage(
}
void BackendConsumer::OptimizationRemarkHandler(
- const llvm::DiagnosticInfoOptimizationRemarkAnalysisAliasing &D) {
+ const llvm::OptimizationRemarkAnalysisAliasing &D) {
// Optimization analysis remarks are active if the pass name is set to
// llvm::DiagnosticInfo::AlwasyPrint or if the -Rpass-analysis flag has a
// regular expression that matches the name of the pass name in \p D.
- if (D.getPassName() == llvm::DiagnosticInfo::AlwaysPrint ||
+ if (D.shouldAlwaysPrint() ||
(CodeGenOpts.OptimizationRemarkAnalysisPattern &&
CodeGenOpts.OptimizationRemarkAnalysisPattern->match(D.getPassName())))
EmitOptimizationMessage(
case llvm::DK_OptimizationRemark:
// Optimization remarks are always handled completely by this
// handler. There is no generic way of emitting them.
- OptimizationRemarkHandler(cast<DiagnosticInfoOptimizationRemark>(DI));
+ OptimizationRemarkHandler(cast<OptimizationRemark>(DI));
return;
case llvm::DK_OptimizationRemarkMissed:
// Optimization remarks are always handled completely by this
// handler. There is no generic way of emitting them.
- OptimizationRemarkHandler(cast<DiagnosticInfoOptimizationRemarkMissed>(DI));
+ OptimizationRemarkHandler(cast<OptimizationRemarkMissed>(DI));
return;
case llvm::DK_OptimizationRemarkAnalysis:
// Optimization remarks are always handled completely by this
// handler. There is no generic way of emitting them.
- OptimizationRemarkHandler(
- cast<DiagnosticInfoOptimizationRemarkAnalysis>(DI));
+ OptimizationRemarkHandler(cast<OptimizationRemarkAnalysis>(DI));
return;
case llvm::DK_OptimizationRemarkAnalysisFPCommute:
// Optimization remarks are always handled completely by this
// handler. There is no generic way of emitting them.
- OptimizationRemarkHandler(
- cast<DiagnosticInfoOptimizationRemarkAnalysisFPCommute>(DI));
+ OptimizationRemarkHandler(cast<OptimizationRemarkAnalysisFPCommute>(DI));
return;
case llvm::DK_OptimizationRemarkAnalysisAliasing:
// Optimization remarks are always handled completely by this
// handler. There is no generic way of emitting them.
- OptimizationRemarkHandler(
- cast<DiagnosticInfoOptimizationRemarkAnalysisAliasing>(DI));
+ OptimizationRemarkHandler(cast<OptimizationRemarkAnalysisAliasing>(DI));
return;
case llvm::DK_OptimizationFailure:
// Optimization failures are always handled completely by this
return VMContext;
}
-static raw_pwrite_stream *
+static std::unique_ptr<raw_pwrite_stream>
GetOutputStream(CompilerInstance &CI, StringRef InFile, BackendAction Action) {
switch (Action) {
case Backend_EmitAssembly:
std::unique_ptr<ASTConsumer>
CodeGenAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
BackendAction BA = static_cast<BackendAction>(Act);
- raw_pwrite_stream *OS = GetOutputStream(CI, InFile, BA);
+ std::unique_ptr<raw_pwrite_stream> OS = GetOutputStream(CI, InFile, BA);
if (BA != Backend_EmitNothing && !OS)
return nullptr;
BA, CI.getDiagnostics(), CI.getHeaderSearchOpts(),
CI.getPreprocessorOpts(), CI.getCodeGenOpts(), CI.getTargetOpts(),
CI.getLangOpts(), CI.getFrontendOpts().ShowTimers, InFile, LinkModules,
- OS, *VMContext, CoverageInfo));
+ std::move(OS), *VMContext, CoverageInfo));
BEConsumer = Result.get();
return std::move(Result);
}
void *Context,
unsigned LocCookie) {
SM.print(nullptr, llvm::errs());
+
+ auto Diags = static_cast<DiagnosticsEngine *>(Context);
+ unsigned DiagID;
+ switch (SM.getKind()) {
+ case llvm::SourceMgr::DK_Error:
+ DiagID = diag::err_fe_inline_asm;
+ break;
+ case llvm::SourceMgr::DK_Warning:
+ DiagID = diag::warn_fe_inline_asm;
+ break;
+ case llvm::SourceMgr::DK_Note:
+ DiagID = diag::note_fe_inline_asm;
+ break;
+ }
+
+ Diags->Report(DiagID).AddString("cannot compile inline asm");
}
void CodeGenAction::ExecuteAction() {
if (getCurrentFileKind() == IK_LLVM_IR) {
BackendAction BA = static_cast<BackendAction>(Act);
CompilerInstance &CI = getCompilerInstance();
- raw_pwrite_stream *OS = GetOutputStream(CI, getCurrentFile(), BA);
+ std::unique_ptr<raw_pwrite_stream> OS =
+ GetOutputStream(CI, getCurrentFile(), BA);
if (BA != Backend_EmitNothing && !OS)
return;
if (Invalid)
return;
+ // For ThinLTO backend invocations, ensure that the context
+ // merges types based on ODR identifiers.
+ if (!CI.getCodeGenOpts().ThinLTOIndexFile.empty())
+ VMContext->enableDebugTypeODRUniquing();
+
llvm::SMDiagnostic Err;
TheModule = parseIR(MainFile->getMemBufferRef(), Err, *VMContext);
if (!TheModule) {
TheModule->setTargetTriple(TargetOpts.Triple);
}
+ EmbedBitcode(TheModule.get(), CI.getCodeGenOpts(),
+ MainFile->getMemBufferRef());
+
LLVMContext &Ctx = TheModule->getContext();
- Ctx.setInlineAsmDiagnosticHandler(BitcodeInlineAsmDiagHandler);
+ Ctx.setInlineAsmDiagnosticHandler(BitcodeInlineAsmDiagHandler,
+ &CI.getDiagnostics());
+
EmitBackendOutput(CI.getDiagnostics(), CI.getCodeGenOpts(), TargetOpts,
- CI.getLangOpts(), CI.getTarget().getDataLayoutString(),
- TheModule.get(), BA, OS);
+ CI.getLangOpts(), CI.getTarget().getDataLayout(),
+ TheModule.get(), BA, std::move(OS));
return;
}