#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/IR/DebugInfo.h"
#include "llvm/IR/DiagnosticInfo.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;
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;
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 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.
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) {
EmitBackendOutput(Diags, CodeGenOpts, TargetOpts, LangOpts,
C.getTargetInfo().getDataLayout(),
- getModule(), Action, AsmOutStream);
+ getModule(), Action, std::move(AsmOutStream));
Ctx.setInlineAsmDiagnosticHandler(OldHandler, OldContext);
Ctx.setDiagnosticHandler(OldDiagnosticHandler, OldDiagnosticContext);
+
+ if (OptRecordFile)
+ OptRecordFile->keep();
}
void HandleTagDeclDefinition(TagDecl *D) override {
/// 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;
}
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);
}
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;
EmitBackendOutput(CI.getDiagnostics(), CI.getCodeGenOpts(), TargetOpts,
CI.getLangOpts(), CI.getTarget().getDataLayout(),
- TheModule.get(), BA, OS);
+ TheModule.get(), BA, std::move(OS));
return;
}