Index: include/llvm/Analysis/OptimizationDiagnosticInfo.h =================================================================== --- include/llvm/Analysis/OptimizationDiagnosticInfo.h +++ include/llvm/Analysis/OptimizationDiagnosticInfo.h @@ -78,10 +78,13 @@ /// use the extra analysis (1) to filter trivial false positives or (2) to /// provide more context so that non-trivial false positives can be quickly /// detected by the user. - bool allowExtraAnalysis() const { + bool allowExtraAnalysis(const StringRef &PassName) const { // For now, only allow this with -fsave-optimization-record since the -Rpass // options are handled in the front-end. - return F->getContext().getDiagnosticsOutputFile(); + if ( F->getContext().getDiagnosticsOutputFile() || + F->getContext().getDiagHandler()->isRemarkEnable(PassName)) + return true; + return false; } private: Index: include/llvm/CodeGen/MachineOptimizationRemarkEmitter.h =================================================================== --- include/llvm/CodeGen/MachineOptimizationRemarkEmitter.h +++ include/llvm/CodeGen/MachineOptimizationRemarkEmitter.h @@ -73,7 +73,9 @@ /// \see DiagnosticInfoOptimizationBase::isEnabled. bool isEnabled() const override { - return OptimizationRemark::isEnabled(getPassName()); + const Function &Fn = getFunction(); + LLVMContext &Ctx = Fn.getContext(); + return Ctx.getDiagHandler()->isPassedOptRemarkEnable(getPassName()); } }; @@ -97,7 +99,9 @@ /// \see DiagnosticInfoOptimizationBase::isEnabled. bool isEnabled() const override { - return OptimizationRemarkMissed::isEnabled(getPassName()); + const Function &Fn = getFunction(); + LLVMContext &Ctx = Fn.getContext(); + return Ctx.getDiagHandler()->isMissedOptRemarkEnable(getPassName()); } }; @@ -121,7 +125,9 @@ /// \see DiagnosticInfoOptimizationBase::isEnabled. bool isEnabled() const override { - return OptimizationRemarkAnalysis::isEnabled(getPassName()); + const Function &Fn = getFunction(); + LLVMContext &Ctx = Fn.getContext(); + return Ctx.getDiagHandler()->isAnalysisRemarkEnable(getPassName()); } }; @@ -152,10 +158,13 @@ /// that are normally too noisy. In this mode, we can use the extra analysis /// (1) to filter trivial false positives or (2) to provide more context so /// that non-trivial false positives can be quickly detected by the user. - bool allowExtraAnalysis() const { + bool allowExtraAnalysis(const StringRef &PassName) const { // For now, only allow this with -fsave-optimization-record since the -Rpass // options are handled in the front-end. - return MF.getFunction()->getContext().getDiagnosticsOutputFile(); + if ( MF.getFunction()->getContext().getDiagnosticsOutputFile() || + MF.getFunction()->getContext().getDiagHandler()->isRemarkEnable(PassName)) + return true; + return false; } private: Index: include/llvm/IR/DiagnosticHandler.h =================================================================== --- /dev/null +++ include/llvm/IR/DiagnosticHandler.h @@ -0,0 +1,35 @@ +//===- DiagnosticHandler.cpp - DiagnosticHandler class for LLVM -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// Base DiagnosticHandler class declaration. Derive from this class to provide +// custom diagnostic reporting. +//===----------------------------------------------------------------------===// + +#include "llvm/Support/Regex.h" + +namespace llvm { +class DiagnosticInfo; +struct DiagnosticHandler { +public: + void *DiagnosticContext = nullptr; + DiagnosticHandler (void *DiagContext); + DiagnosticHandler() = default; + virtual ~DiagnosticHandler() = default; + using DiagnosticHandlerTy = void (*)(const DiagnosticInfo &DI, void *Context); + // DiagHandlerCallback is settable from the C API and base implimentation + // of DiagnosticHandler will call it from handleDiagnostics(). Any derived + // class of DiagnosticHandler should not use callback but + // implement handleDiagnostics(). + DiagnosticHandlerTy DiagHandlerCallback = nullptr; + bool isRemarkEnable(const StringRef &PassName); + virtual bool handleDiagnostics(const DiagnosticInfo &DI); + virtual bool isAnalysisRemarkEnable(const StringRef &PassName); + virtual bool isMissedOptRemarkEnable(const StringRef &PassName); + virtual bool isPassedOptRemarkEnable(const StringRef &PassName); +}; +} Index: include/llvm/IR/DiagnosticInfo.h =================================================================== --- include/llvm/IR/DiagnosticInfo.h +++ include/llvm/IR/DiagnosticInfo.h @@ -33,7 +33,6 @@ // Forward declarations. class DiagnosticPrinter; -class Function; class Instruction; class LLVMContext; class Module; @@ -610,10 +609,8 @@ return DI->getKind() == DK_OptimizationRemark; } - static bool isEnabled(StringRef PassName); - /// \see DiagnosticInfoOptimizationBase::isEnabled. - bool isEnabled() const override { return isEnabled(getPassName()); } + bool isEnabled() const override; private: /// This is deprecated now and only used by the function API below. @@ -653,10 +650,8 @@ return DI->getKind() == DK_OptimizationRemarkMissed; } - static bool isEnabled(StringRef PassName); - /// \see DiagnosticInfoOptimizationBase::isEnabled. - bool isEnabled() const override { return isEnabled(getPassName()); } + bool isEnabled() const override; private: /// This is deprecated now and only used by the function API below. @@ -707,12 +702,8 @@ return DI->getKind() == DK_OptimizationRemarkAnalysis; } - static bool isEnabled(StringRef PassName); - /// \see DiagnosticInfoOptimizationBase::isEnabled. - bool isEnabled() const override { - return shouldAlwaysPrint() || isEnabled(getPassName()); - } + bool isEnabled() const override; static const char *AlwaysPrint; Index: include/llvm/IR/LLVMContext.h =================================================================== --- include/llvm/IR/LLVMContext.h +++ include/llvm/IR/LLVMContext.h @@ -15,6 +15,7 @@ #ifndef LLVM_IR_LLVMCONTEXT_H #define LLVM_IR_LLVMCONTEXT_H +#include "DiagnosticHandler.h" #include "llvm-c/Types.h" #include "llvm/Support/CBindingWrapping.h" #include "llvm/Support/Options.h" @@ -167,11 +168,6 @@ using InlineAsmDiagHandlerTy = void (*)(const SMDiagnostic&, void *Context, unsigned LocCookie); - /// Defines the type of a diagnostic handler. - /// \see LLVMContext::setDiagnosticHandler. - /// \see LLVMContext::diagnose. - using DiagnosticHandlerTy = void (*)(const DiagnosticInfo &DI, void *Context); - /// Defines the type of a yield callback. /// \see LLVMContext::setYieldCallback. using YieldCallbackTy = void (*)(LLVMContext *Context, void *OpaqueHandle); @@ -194,26 +190,30 @@ /// setInlineAsmDiagnosticHandler. void *getInlineAsmDiagnosticContext() const; - /// setDiagnosticHandler - This method sets a handler that is invoked - /// when the backend needs to report anything to the user. The first - /// argument is a function pointer and the second is a context pointer that - /// gets passed into the DiagHandler. The third argument should be set to - /// true if the handler only expects enabled diagnostics. - /// - /// LLVMContext doesn't take ownership or interpret either of these - /// pointers. - void setDiagnosticHandler(DiagnosticHandlerTy DiagHandler, + // /// setDiagnosticHandler - This method sets a handler that is invoked + // /// when the backend needs to report anything to the user. The first + // /// argument is a function pointer and the second is a context pointer that + // /// gets passed into the DiagHandler. The third argument should be set to + // /// true if the handler only expects enabled diagnostics. + // /// + // /// LLVMContext doesn't take ownership or interpret either of these + // /// pointers. + void setDiagnosticHandlerCallBack(DiagnosticHandler::DiagnosticHandlerTy DiagHandler, void *DiagContext = nullptr, bool RespectFilters = false); + void setDiagnosticHandler(std::unique_ptr &&DH, + bool RespectFilters = false); /// getDiagnosticHandler - Return the diagnostic handler set by /// setDiagnosticHandler. - DiagnosticHandlerTy getDiagnosticHandler() const; + DiagnosticHandler::DiagnosticHandlerTy getDiagnosticHandlerCallBack() const; /// getDiagnosticContext - Return the diagnostic context set by /// setDiagnosticContext. void *getDiagnosticContext() const; + DiagnosticHandler *getDiagHandler() const; + /// \brief Return if a code hotness metric should be included in optimization /// diagnostics. bool getDiagnosticsHotnessRequested() const; Index: include/llvm/LTO/Config.h =================================================================== --- include/llvm/LTO/Config.h +++ include/llvm/LTO/Config.h @@ -171,20 +171,26 @@ bool UseInputModulePath = false); }; +struct LTOLLVMDiagnosticHandler : public DiagnosticHandler { + LTOLLVMDiagnosticHandler(void *Context) : DiagnosticHandler(Context) {} + bool handleDiagnostics(const DiagnosticInfo &DI) override { + auto *Fn = static_cast(DiagnosticContext); + (*Fn)(DI); + return true; + } +}; /// A derived class of LLVMContext that initializes itself according to a given /// Config object. The purpose of this class is to tie ownership of the /// diagnostic handler to the context, as opposed to the Config object (which /// may be ephemeral). +// FIXME: This should not be required as diagnostic handler is not callback. struct LTOLLVMContext : LLVMContext { - static void funcDiagHandler(const DiagnosticInfo &DI, void *Context) { - auto *Fn = static_cast(Context); - (*Fn)(DI); - } LTOLLVMContext(const Config &C) : DiagHandler(C.DiagHandler) { setDiscardValueNames(C.ShouldDiscardValueNames); enableDebugTypeODRUniquing(); - setDiagnosticHandler(funcDiagHandler, &DiagHandler, true); + setDiagnosticHandler( + llvm::make_unique(&DiagHandler), true); } DiagnosticHandlerFunction DiagHandler; }; Index: include/llvm/LTO/legacy/LTOCodeGenerator.h =================================================================== --- include/llvm/LTO/legacy/LTOCodeGenerator.h +++ include/llvm/LTO/legacy/LTOCodeGenerator.h @@ -184,6 +184,7 @@ LLVMContext &getContext() { return Context; } void resetMergedModule() { MergedModule.reset(); } + void DiagnosticHandler(const DiagnosticInfo &DI); private: void initializeLTOPasses(); @@ -204,10 +205,6 @@ bool determineTarget(); std::unique_ptr createTargetMachine(); - static void DiagnosticHandler(const DiagnosticInfo &DI, void *Context); - - void DiagnosticHandler2(const DiagnosticInfo &DI); - void emitError(const std::string &ErrMsg); void emitWarning(const std::string &ErrMsg); Index: lib/IR/CMakeLists.txt =================================================================== --- lib/IR/CMakeLists.txt +++ lib/IR/CMakeLists.txt @@ -17,6 +17,7 @@ DebugInfo.cpp DebugInfoMetadata.cpp DebugLoc.cpp + DiagnosticHandler.cpp DiagnosticInfo.cpp DiagnosticPrinter.cpp Dominators.cpp Index: lib/IR/Core.cpp =================================================================== --- lib/IR/Core.cpp +++ lib/IR/Core.cpp @@ -85,15 +85,15 @@ void LLVMContextSetDiagnosticHandler(LLVMContextRef C, LLVMDiagnosticHandler Handler, void *DiagnosticContext) { - unwrap(C)->setDiagnosticHandler( - LLVM_EXTENSION reinterpret_cast( + unwrap(C)->setDiagnosticHandlerCallBack( + LLVM_EXTENSION reinterpret_cast( Handler), DiagnosticContext); } LLVMDiagnosticHandler LLVMContextGetDiagnosticHandler(LLVMContextRef C) { return LLVM_EXTENSION reinterpret_cast( - unwrap(C)->getDiagnosticHandler()); + unwrap(C)->getDiagnosticHandlerCallBack()); } void *LLVMContextGetDiagnosticContext(LLVMContextRef C) { Index: lib/IR/DiagnosticHandler.cpp =================================================================== --- /dev/null +++ lib/IR/DiagnosticHandler.cpp @@ -0,0 +1,110 @@ +//===- DiagnosticHandler.h - DiagnosticHandler class for LLVM -------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// +//===----------------------------------------------------------------------===// +#include "llvm/IR/DiagnosticHandler.h" +#include "llvm/Support/CommandLine.h" +#include +#include +using namespace llvm; + +namespace { + +/// \brief Regular expression corresponding to the value given in one of the +/// -pass-remarks* command line flags. Passes whose name matches this regexp +/// will emit a diagnostic when calling the associated diagnostic function +/// (emitOptimizationRemark, emitOptimizationRemarkMissed or +/// emitOptimizationRemarkAnalysis). +struct PassRemarksOpt { + std::shared_ptr Pattern; + + void operator=(const std::string &Val) { + // Create a regexp object to match pass names for emitOptimizationRemark. + if (!Val.empty()) { + Pattern = std::make_shared(Val); + std::string RegexError; + if (!Pattern->isValid(RegexError)) + report_fatal_error("Invalid regular expression '" + Val + + "' in -pass-remarks: " + RegexError, + false); + } + } +}; + +static PassRemarksOpt PassRemarksPassedOptLoc; +static PassRemarksOpt PassRemarksMissedOptLoc; +static PassRemarksOpt PassRemarksAnalysisOptLoc; + +// -pass-remarks +// Command line flag to enable emitOptimizationRemark() +static cl::opt> +PassRemarks("pass-remarks", cl::value_desc("pattern"), + cl::desc("Enable optimization remarks from passes whose name match " + "the given regular expression"), + cl::Hidden, cl::location(PassRemarksPassedOptLoc), cl::ValueRequired, + cl::ZeroOrMore); + +// -pass-remarks-missed +// Command line flag to enable emitOptimizationRemarkMissed() +static cl::opt> PassRemarksMissed( + "pass-remarks-missed", cl::value_desc("pattern"), + cl::desc("Enable missed optimization remarks from passes whose name match " + "the given regular expression"), + cl::Hidden, cl::location(PassRemarksMissedOptLoc), cl::ValueRequired, + cl::ZeroOrMore); + +// -pass-remarks-analysis +// Command line flag to enable emitOptimizationRemarkAnalysis() +static cl::opt> +PassRemarksAnalysis( + "pass-remarks-analysis", cl::value_desc("pattern"), + cl::desc( + "Enable optimization analysis remarks from passes whose name match " + "the given regular expression"), + cl::Hidden, cl::location(PassRemarksAnalysisOptLoc), cl::ValueRequired, + cl::ZeroOrMore); +} + +DiagnosticHandler::DiagnosticHandler (void *DiagContext) : + DiagnosticContext(DiagContext) {} + +bool DiagnosticHandler::isRemarkEnable(const StringRef &PassName) { + if (isMissedOptRemarkEnable(PassName) || isPassedOptRemarkEnable(PassName) + || isAnalysisRemarkEnable(PassName)) + return true; + return false; +} + +bool DiagnosticHandler::isAnalysisRemarkEnable(const StringRef &PassName) { + if (PassRemarksAnalysisOptLoc.Pattern && + PassRemarksAnalysisOptLoc.Pattern->match(PassName)) + return true; + return false; +} +bool DiagnosticHandler::isMissedOptRemarkEnable(const StringRef &PassName) { + if (PassRemarksMissedOptLoc.Pattern && + PassRemarksMissedOptLoc.Pattern->match(PassName)) + return true; + return false; +} +bool DiagnosticHandler::isPassedOptRemarkEnable(const StringRef &PassName) { + if (PassRemarksPassedOptLoc.Pattern && + PassRemarksPassedOptLoc.Pattern->match(PassName)) + return true; + return false; +} + +bool DiagnosticHandler::handleDiagnostics(const DiagnosticInfo &DI) { + if(DiagHandlerCallback) { + DiagHandlerCallback(DI, DiagnosticContext); + return true; + } + return false; +} Index: lib/IR/DiagnosticInfo.cpp =================================================================== --- lib/IR/DiagnosticInfo.cpp +++ lib/IR/DiagnosticInfo.cpp @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// #include "llvm/IR/DiagnosticInfo.h" +#include "LLVMContextImpl.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/Twine.h" #include "llvm/ADT/iterator_range.h" @@ -63,39 +64,6 @@ } // end anonymous namespace -static PassRemarksOpt PassRemarksOptLoc; -static PassRemarksOpt PassRemarksMissedOptLoc; -static PassRemarksOpt PassRemarksAnalysisOptLoc; - -// -pass-remarks -// Command line flag to enable optimization remarks -static cl::opt> -PassRemarks("pass-remarks", cl::value_desc("pattern"), - cl::desc("Enable optimization remarks from passes whose name match " - "the given regular expression"), - cl::Hidden, cl::location(PassRemarksOptLoc), cl::ValueRequired, - cl::ZeroOrMore); - -// -pass-remarks-missed -// Command line flag to enable missed optimization remarks -static cl::opt> PassRemarksMissed( - "pass-remarks-missed", cl::value_desc("pattern"), - cl::desc("Enable missed optimization remarks from passes whose name match " - "the given regular expression"), - cl::Hidden, cl::location(PassRemarksMissedOptLoc), cl::ValueRequired, - cl::ZeroOrMore); - -// -pass-remarks-analysis -// Command line flag to enable optimization analysis remarks -static cl::opt> -PassRemarksAnalysis( - "pass-remarks-analysis", cl::value_desc("pattern"), - cl::desc( - "Enable optimization analysis remarks from passes whose name match " - "the given regular expression"), - cl::Hidden, cl::location(PassRemarksAnalysisOptLoc), cl::ValueRequired, - cl::ZeroOrMore); - int llvm::getNextAvailablePluginDiagnosticKind() { static std::atomic PluginKindID(DK_FirstPluginKind); return ++PluginKindID; @@ -283,9 +251,10 @@ RemarkName, *Func, Func->getSubprogram(), &getFirstFunctionBlock(Func)) {} -bool OptimizationRemark::isEnabled(StringRef PassName) { - return PassRemarksOptLoc.Pattern && - PassRemarksOptLoc.Pattern->match(PassName); +bool OptimizationRemark::isEnabled() const { + const Function &Fn = getFunction(); + LLVMContext &Ctx = Fn.getContext(); + return Ctx.getDiagHandler()->isPassedOptRemarkEnable(getPassName().str()); } OptimizationRemarkMissed::OptimizationRemarkMissed( @@ -303,9 +272,10 @@ *Inst->getParent()->getParent(), Inst->getDebugLoc(), Inst->getParent()) {} -bool OptimizationRemarkMissed::isEnabled(StringRef PassName) { - return PassRemarksMissedOptLoc.Pattern && - PassRemarksMissedOptLoc.Pattern->match(PassName); +bool OptimizationRemarkMissed::isEnabled() const { + const Function &Fn = getFunction(); + LLVMContext &Ctx = Fn.getContext(); + return Ctx.getDiagHandler()->isMissedOptRemarkEnable(getPassName().str()); } OptimizationRemarkAnalysis::OptimizationRemarkAnalysis( @@ -330,9 +300,10 @@ *cast(CodeRegion)->getParent(), Loc, CodeRegion) {} -bool OptimizationRemarkAnalysis::isEnabled(StringRef PassName) { - return PassRemarksAnalysisOptLoc.Pattern && - PassRemarksAnalysisOptLoc.Pattern->match(PassName); +bool OptimizationRemarkAnalysis::isEnabled() const { + const Function &Fn = getFunction(); + LLVMContext &Ctx = Fn.getContext(); + return Ctx.getDiagHandler()->isAnalysisRemarkEnable(getPassName().str()) || shouldAlwaysPrint(); } void DiagnosticInfoMIRParser::print(DiagnosticPrinter &DP) const { Index: lib/IR/LLVMContext.cpp =================================================================== --- lib/IR/LLVMContext.cpp +++ lib/IR/LLVMContext.cpp @@ -129,11 +129,18 @@ return pImpl->InlineAsmDiagContext; } -void LLVMContext::setDiagnosticHandler(DiagnosticHandlerTy DiagnosticHandler, - void *DiagnosticContext, - bool RespectFilters) { - pImpl->DiagnosticHandler = DiagnosticHandler; - pImpl->DiagnosticContext = DiagnosticContext; +void LLVMContext::setDiagnosticHandlerCallBack( + DiagnosticHandler::DiagnosticHandlerTy DiagnosticHandler, + void *DiagnosticContext, + bool RespectFilters) { + pImpl->DiagHandler->DiagHandlerCallback = DiagnosticHandler; + pImpl->DiagHandler->DiagnosticContext = DiagnosticContext; + pImpl->RespectDiagnosticFilters = RespectFilters; +} + +void LLVMContext::setDiagnosticHandler(std::unique_ptr &&DH, + bool RespectFilters) { + pImpl->DiagHandler = std::move(DH); pImpl->RespectDiagnosticFilters = RespectFilters; } @@ -159,12 +166,12 @@ pImpl->DiagnosticsOutputFile = std::move(F); } -LLVMContext::DiagnosticHandlerTy LLVMContext::getDiagnosticHandler() const { - return pImpl->DiagnosticHandler; +DiagnosticHandler::DiagnosticHandlerTy LLVMContext::getDiagnosticHandlerCallBack() const { + return pImpl->DiagHandler->DiagHandlerCallback; } void *LLVMContext::getDiagnosticContext() const { - return pImpl->DiagnosticContext; + return pImpl->DiagHandler->DiagnosticContext; } void LLVMContext::setYieldCallback(YieldCallbackTy Callback, void *OpaqueHandle) @@ -194,7 +201,6 @@ // diagnostic and return. if (auto *Remark = dyn_cast(&DI)) return Remark->isEnabled(); - return true; } @@ -215,15 +221,13 @@ void LLVMContext::diagnose(const DiagnosticInfo &DI) { // If there is a report handler, use it. - if (pImpl->DiagnosticHandler) { + if (pImpl->DiagHandler) { if (!pImpl->RespectDiagnosticFilters || isDiagnosticEnabled(DI)) - pImpl->DiagnosticHandler(DI, pImpl->DiagnosticContext); - return; + if(pImpl->DiagHandler->handleDiagnostics(DI)) + return; } - if (!isDiagnosticEnabled(DI)) return; - // Otherwise, print the message with a prefix based on the severity. DiagnosticPrinterRawOStream DP(errs()); errs() << getDiagnosticMessagePrefix(DI.getSeverity()) << ": "; @@ -315,3 +319,7 @@ OptBisect &LLVMContext::getOptBisect() { return pImpl->getOptBisect(); } + +DiagnosticHandler *LLVMContext::getDiagHandler() const { + return pImpl->DiagHandler.get(); +} Index: lib/IR/LLVMContextImpl.h =================================================================== --- lib/IR/LLVMContextImpl.h +++ lib/IR/LLVMContextImpl.h @@ -1168,8 +1168,7 @@ LLVMContext::InlineAsmDiagHandlerTy InlineAsmDiagHandler = nullptr; void *InlineAsmDiagContext = nullptr; - LLVMContext::DiagnosticHandlerTy DiagnosticHandler = nullptr; - void *DiagnosticContext = nullptr; + std::unique_ptr DiagHandler; bool RespectDiagnosticFilters = false; bool DiagnosticsHotnessRequested = false; uint64_t DiagnosticsHotnessThreshold = 0; Index: lib/IR/LLVMContextImpl.cpp =================================================================== --- lib/IR/LLVMContextImpl.cpp +++ lib/IR/LLVMContextImpl.cpp @@ -22,7 +22,8 @@ using namespace llvm; LLVMContextImpl::LLVMContextImpl(LLVMContext &C) - : VoidTy(C, Type::VoidTyID), + : DiagHandler(llvm::make_unique(nullptr)), + VoidTy(C, Type::VoidTyID), LabelTy(C, Type::LabelTyID), HalfTy(C, Type::HalfTyID), FloatTy(C, Type::FloatTyID), Index: lib/LTO/LTOCodeGenerator.cpp =================================================================== --- lib/LTO/LTOCodeGenerator.cpp +++ lib/LTO/LTOCodeGenerator.cpp @@ -622,12 +622,8 @@ } } -void LTOCodeGenerator::DiagnosticHandler(const DiagnosticInfo &DI, - void *Context) { - ((LTOCodeGenerator *)Context)->DiagnosticHandler2(DI); -} -void LTOCodeGenerator::DiagnosticHandler2(const DiagnosticInfo &DI) { +void LTOCodeGenerator::DiagnosticHandler(const DiagnosticInfo &DI) { // Map the LLVM internal diagnostic severity to the LTO diagnostic severity. lto_codegen_diagnostic_severity_t Severity; switch (DI.getSeverity()) { @@ -657,17 +653,25 @@ (*DiagHandler)(Severity, MsgStorage.c_str(), DiagContext); } +namespace { +struct LTODiagnosticHandler : public DiagnosticHandler { + LTODiagnosticHandler(void *Context) : DiagnosticHandler(Context) {} + bool handleDiagnostics(const DiagnosticInfo &DI) override { + ((LTOCodeGenerator *)DiagnosticContext)->DiagnosticHandler(DI); + return true; + } +}; +} + void LTOCodeGenerator::setDiagnosticHandler(lto_diagnostic_handler_t DiagHandler, void *Ctxt) { this->DiagHandler = DiagHandler; this->DiagContext = Ctxt; if (!DiagHandler) - return Context.setDiagnosticHandler(nullptr, nullptr); - // Register the LTOCodeGenerator stub in the LLVMContext to forward the - // diagnostic to the external DiagHandler. - Context.setDiagnosticHandler(LTOCodeGenerator::DiagnosticHandler, this, - /* RespectFilters */ true); + return Context.setDiagnosticHandler(nullptr); + Context.setDiagnosticHandler( + llvm::make_unique(this), true); } namespace { Index: lib/Transforms/Scalar/GVN.cpp =================================================================== --- lib/Transforms/Scalar/GVN.cpp +++ lib/Transforms/Scalar/GVN.cpp @@ -896,8 +896,7 @@ Instruction *I = DepInfo.getInst(); dbgs() << " is clobbered by " << *I << '\n'; ); - - if (ORE->allowExtraAnalysis()) + if (ORE->allowExtraAnalysis(DEBUG_TYPE)) reportMayClobberedLoad(LI, DepInfo, DT, ORE); return false; Index: lib/Transforms/Vectorize/LoopVectorize.cpp =================================================================== --- lib/Transforms/Vectorize/LoopVectorize.cpp +++ lib/Transforms/Vectorize/LoopVectorize.cpp @@ -4929,12 +4929,15 @@ // Store the result and return it at the end instead of exiting early, in case // allowExtraAnalysis is used to report multiple reasons for not vectorizing. bool Result = true; + + bool DoExtraAnalysis = ORE->allowExtraAnalysis(DEBUG_TYPE); + if (DoExtraAnalysis) // We must have a loop in canonical form. Loops with indirectbr in them cannot // be canonicalized. if (!TheLoop->getLoopPreheader()) { ORE->emit(createMissedAnalysis("CFGNotUnderstood") << "loop control flow is not understood by vectorizer"); - if (ORE->allowExtraAnalysis()) + if (DoExtraAnalysis) Result = false; else return false; @@ -4947,7 +4950,7 @@ if (!TheLoop->empty()) { ORE->emit(createMissedAnalysis("NotInnermostLoop") << "loop is not the innermost loop"); - if (ORE->allowExtraAnalysis()) + if (DoExtraAnalysis) Result = false; else return false; @@ -4957,7 +4960,7 @@ if (TheLoop->getNumBackEdges() != 1) { ORE->emit(createMissedAnalysis("CFGNotUnderstood") << "loop control flow is not understood by vectorizer"); - if (ORE->allowExtraAnalysis()) + if (DoExtraAnalysis) Result = false; else return false; @@ -4967,7 +4970,7 @@ if (!TheLoop->getExitingBlock()) { ORE->emit(createMissedAnalysis("CFGNotUnderstood") << "loop control flow is not understood by vectorizer"); - if (ORE->allowExtraAnalysis()) + if (DoExtraAnalysis) Result = false; else return false; @@ -4979,7 +4982,7 @@ if (TheLoop->getExitingBlock() != TheLoop->getLoopLatch()) { ORE->emit(createMissedAnalysis("CFGNotUnderstood") << "loop control flow is not understood by vectorizer"); - if (ORE->allowExtraAnalysis()) + if (DoExtraAnalysis) Result = false; else return false; @@ -4993,7 +4996,7 @@ unsigned NumBlocks = TheLoop->getNumBlocks(); if (NumBlocks != 1 && !canVectorizeWithIfConvert()) { DEBUG(dbgs() << "LV: Can't if-convert the loop.\n"); - if (ORE->allowExtraAnalysis()) + if (DoExtraAnalysis) Result = false; else return false; @@ -5002,7 +5005,7 @@ // Check if we can vectorize the instructions and CFG in this loop. if (!canVectorizeInstrs()) { DEBUG(dbgs() << "LV: Can't vectorize the instructions or CFG\n"); - if (ORE->allowExtraAnalysis()) + if (DoExtraAnalysis) Result = false; else return false; @@ -5011,7 +5014,7 @@ // Go over each instruction and look at memory deps. if (!canVectorizeMemory()) { DEBUG(dbgs() << "LV: Can't vectorize due to memory conflicts\n"); - if (ORE->allowExtraAnalysis()) + if (DoExtraAnalysis) Result = false; else return false; @@ -5042,7 +5045,7 @@ << "Too many SCEV assumptions need to be made and checked " << "at runtime"); DEBUG(dbgs() << "LV: Too many SCEV checks needed.\n"); - if (ORE->allowExtraAnalysis()) + if (DoExtraAnalysis) Result = false; else return false; Index: tools/llc/llc.cpp =================================================================== --- tools/llc/llc.cpp +++ tools/llc/llc.cpp @@ -156,6 +156,25 @@ RunPassNames->push_back(PassName); } }; + +struct LLCDiagnosticHandler : public DiagnosticHandler { + LLCDiagnosticHandler(void *Context) : DiagnosticHandler(Context) {} + bool handleDiagnostics(const DiagnosticInfo &DI) override { + bool *HasError = static_cast(DiagnosticContext); + if (DI.getSeverity() == DS_Error) + *HasError = true; + + if (auto *Remark = dyn_cast(&DI)) + if (!Remark->isEnabled()) + return true; + + DiagnosticPrinterRawOStream DP(errs()); + errs() << LLVMContext::getDiagnosticMessagePrefix(DI.getSeverity()) << ": "; + DI.print(DP); + errs() << "\n"; + return true; + } +}; } static RunPassOption RunPassOpt; @@ -235,7 +254,7 @@ return FDOut; } -static void DiagnosticHandler(const DiagnosticInfo &DI, void *Context) { +static void DiagnosticHandlerImpl(const DiagnosticInfo &DI, void *Context) { bool *HasError = static_cast(Context); if (DI.getSeverity() == DS_Error) *HasError = true; @@ -308,7 +327,8 @@ // Set a diagnostic handler that doesn't exit on the first error bool HasError = false; - Context.setDiagnosticHandler(DiagnosticHandler, &HasError); + Context.setDiagnosticHandler( + llvm::make_unique(&HasError)); Context.setInlineAsmDiagnosticHandler(InlineAsmDiagHandler, &HasError); if (PassRemarksWithHotness) Index: tools/llvm-dis/llvm-dis.cpp =================================================================== --- tools/llvm-dis/llvm-dis.cpp +++ tools/llvm-dis/llvm-dis.cpp @@ -122,6 +122,27 @@ } }; +struct LLVMDisDiagnosticHandler : public DiagnosticHandler { + LLVMDisDiagnosticHandler(void *Context) : DiagnosticHandler(Context) {} + bool handleDiagnostics(const DiagnosticInfo &DI) override { + raw_ostream &OS = errs(); + OS << (char *)DiagnosticContext << ": "; + switch (DI.getSeverity()) { + case DS_Error: OS << "error: "; break; + case DS_Warning: OS << "warning: "; break; + case DS_Remark: OS << "remark: "; break; + case DS_Note: OS << "note: "; break; + } + + DiagnosticPrinterRawOStream DP(OS); + DI.print(DP); + OS << '\n'; + + if (DI.getSeverity() == DS_Error) + exit(1); + return true; + } +}; } // end anon namespace static void diagnosticHandler(const DiagnosticInfo &DI, void *Context) { @@ -166,9 +187,8 @@ LLVMContext Context; llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. - - Context.setDiagnosticHandler(diagnosticHandler, argv[0]); - + Context.setDiagnosticHandler( + llvm::make_unique(argv[0])); cl::ParseCommandLineOptions(argc, argv, "llvm .bc -> .ll disassembler\n"); std::unique_ptr M = openInputFile(Context); Index: tools/llvm-link/llvm-link.cpp =================================================================== --- tools/llvm-link/llvm-link.cpp +++ tools/llvm-link/llvm-link.cpp @@ -182,6 +182,31 @@ } } // anonymous namespace +namespace { + struct LLVMLinkDiagnosticHandler : public DiagnosticHandler { + bool handleDiagnostics(const DiagnosticInfo &DI) override { + unsigned Severity = DI.getSeverity(); + switch (Severity) { + case DS_Error: + errs() << "ERROR: "; + break; + case DS_Warning: + if (SuppressWarnings) + return true; + errs() << "WARNING: "; + break; + case DS_Remark: + case DS_Note: + llvm_unreachable("Only expecting warnings and errors"); + } + + DiagnosticPrinterRawOStream DP(errs()); + DI.print(DP); + errs() << '\n'; + return true; + } +}; +} static void diagnosticHandler(const DiagnosticInfo &DI, void *C) { unsigned Severity = DI.getSeverity(); switch (Severity) { @@ -347,8 +372,8 @@ ExitOnErr.setBanner(std::string(argv[0]) + ": "); LLVMContext Context; - Context.setDiagnosticHandler(diagnosticHandler, nullptr, true); - + Context.setDiagnosticHandler( + llvm::make_unique(), true); llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. cl::ParseCommandLineOptions(argc, argv, "llvm linker\n"); Index: tools/llvm-lto/llvm-lto.cpp =================================================================== --- tools/llvm-lto/llvm-lto.cpp +++ tools/llvm-lto/llvm-lto.cpp @@ -36,7 +36,40 @@ #include using namespace llvm; +static std::string CurrentActivity; +namespace { +struct LLVMLTODiagnosticHandler : public DiagnosticHandler { + bool handleDiagnostics(const DiagnosticInfo &DI) override { + raw_ostream &OS = errs(); + OS << "llvm-lto: "; + switch (DI.getSeverity()) { + case DS_Error: + OS << "error"; + break; + case DS_Warning: + OS << "warning"; + break; + case DS_Remark: + OS << "remark"; + break; + case DS_Note: + OS << "note"; + break; + } + if (!CurrentActivity.empty()) + OS << ' ' << CurrentActivity; + OS << ": "; + DiagnosticPrinterRawOStream DP(OS); + DI.print(DP); + OS << '\n'; + + if (DI.getSeverity() == DS_Error) + exit(1); + return true; + } +}; +} static cl::opt OptLevel("O", cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] " "(default = '-O2')"), @@ -204,7 +237,6 @@ errs() << Msg << "\n"; } -static std::string CurrentActivity; static void diagnosticHandler(const DiagnosticInfo &DI, void *Context) { raw_ostream &OS = errs(); OS << "llvm-lto: "; @@ -263,7 +295,8 @@ Buffer = std::move(BufferOrErr.get()); CurrentActivity = ("loading file '" + Path + "'").str(); std::unique_ptr Context = llvm::make_unique(); - Context->setDiagnosticHandler(diagnosticHandler, nullptr, true); + Context->setDiagnosticHandler( + llvm::make_unique(), true); ErrorOr> Ret = LTOModule::createInLocalContext( std::move(Context), Buffer->getBufferStart(), Buffer->getBufferSize(), Options, Path); @@ -808,7 +841,8 @@ unsigned BaseArg = 0; LLVMContext Context; - Context.setDiagnosticHandler(diagnosticHandler, nullptr, true); + Context.setDiagnosticHandler( + llvm::make_unique(), true); LTOCodeGenerator CodeGen(Context); @@ -834,7 +868,6 @@ LTOModule::createFromFile(Context, InputFilenames[i], Options); std::unique_ptr &Module = *ModuleOrErr; CurrentActivity = ""; - unsigned NumSyms = Module->getSymbolCount(); for (unsigned I = 0; I < NumSyms; ++I) { StringRef Name = Module->getSymbolName(I); Index: tools/lto/lto.cpp =================================================================== --- tools/lto/lto.cpp +++ tools/lto/lto.cpp @@ -75,20 +75,23 @@ static LLVMContext *LTOContext = nullptr; -static void diagnosticHandler(const DiagnosticInfo &DI, void *Context) { - if (DI.getSeverity() != DS_Error) { - DiagnosticPrinterRawOStream DP(errs()); - DI.print(DP); - errs() << '\n'; - return; - } - sLastErrorString = ""; - { - raw_string_ostream Stream(sLastErrorString); - DiagnosticPrinterRawOStream DP(Stream); - DI.print(DP); +struct LTOToolDiagnosticHandler : public DiagnosticHandler { + bool handleDiagnostics(const DiagnosticInfo &DI) override { + if (DI.getSeverity() != DS_Error) { + DiagnosticPrinterRawOStream DP(errs()); + DI.print(DP); + errs() << '\n'; + return true; + } + sLastErrorString = ""; + { + raw_string_ostream Stream(sLastErrorString); + DiagnosticPrinterRawOStream DP(Stream); + DI.print(DP); + } + return true; } -} +}; // Initialize the configured targets if they have not been initialized. static void lto_initialize() { @@ -108,7 +111,8 @@ static LLVMContext Context; LTOContext = &Context; - LTOContext->setDiagnosticHandler(diagnosticHandler, nullptr, true); + LTOContext->setDiagnosticHandler( + llvm::make_unique(), true); initialized = true; } } @@ -274,7 +278,8 @@ // Create a local context. Ownership will be transferred to LTOModule. std::unique_ptr Context = llvm::make_unique(); - Context->setDiagnosticHandler(diagnosticHandler, nullptr, true); + Context->setDiagnosticHandler( + llvm::make_unique(), true); ErrorOr> M = LTOModule::createInLocalContext( std::move(Context), mem, length, Options, StringRef(path));