Index: include/llvm/CodeGen/MachineOptimizationRemarkEmitter.h =================================================================== --- include/llvm/CodeGen/MachineOptimizationRemarkEmitter.h +++ include/llvm/CodeGen/MachineOptimizationRemarkEmitter.h @@ -73,7 +73,12 @@ /// \see DiagnosticInfoOptimizationBase::isEnabled. bool isEnabled() const override { - return OptimizationRemark::isEnabled(getPassName()); + const Function &Fn = getFunction(); + LLVMContext &Ctx = Fn.getContext(); + RemarkInfo RemarkInfoVal = Ctx.getDiagHandler()->isRemarkEnable(getPassName().str()); + if (RemarkInfoVal == RemarkInfo::PassedOptRemarkEnable) + return true; + return false; } }; @@ -97,7 +102,12 @@ /// \see DiagnosticInfoOptimizationBase::isEnabled. bool isEnabled() const override { - return OptimizationRemarkMissed::isEnabled(getPassName()); + const Function &Fn = getFunction(); + LLVMContext &Ctx = Fn.getContext(); + RemarkInfo RemarkInfoVal = Ctx.getDiagHandler()->isRemarkEnable(getPassName().str()); + if (RemarkInfoVal == RemarkInfo::MissedOptRemarkEnable) + return true; + return false; } }; @@ -121,7 +131,12 @@ /// \see DiagnosticInfoOptimizationBase::isEnabled. bool isEnabled() const override { - return OptimizationRemarkAnalysis::isEnabled(getPassName()); + const Function &Fn = getFunction(); + LLVMContext &Ctx = Fn.getContext(); + RemarkInfo RemarkInfoVal = Ctx.getDiagHandler()->isRemarkEnable(getPassName().str()); + if (RemarkInfoVal == RemarkInfo::AnalysisRemarkEnable) + return true; + return false; } }; Index: include/llvm/IR/DiagnosticHandler.h =================================================================== --- /dev/null +++ include/llvm/IR/DiagnosticHandler.h @@ -0,0 +1,37 @@ +//===- 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. +// +//===----------------------------------------------------------------------===// +// +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/Regex.h" + +namespace llvm { +enum class RemarkInfo { + RemarkNotEnabled, + AnalysisRemarkEnable, + MissedOptRemarkEnable, + PassedOptRemarkEnable +}; +class DiagnosticInfo; +class DiagnosticHandler { +public: + virtual ~DiagnosticHandler() = default; + using DiagnosticHandlerTy = void (*)(const DiagnosticInfo &DI, void *Context); + DiagnosticHandlerTy DiagHandlerCallback; + RemarkInfo isRemarkEnable(const std::string &PassName); + void setAnalysisRemarkPassNamePattern(std::shared_ptr AnalysisRemark); + void setPassedRemarkPassNamePattern(std::shared_ptr PassedOptRemark); + void setMissedRemarkPassNamePattern(std::shared_ptr MissedOptRemark); + virtual void HandleDiagnostics(const DiagnosticInfo &DI, void *Context); + static bool isAnalysisRemarkEnable(const std::string &PassName); + static bool isMissedOptRemarkEnable(const std::string &PassName); + static bool isPassedOptRemarkEnable(const std::string &PassName); +}; +} Index: include/llvm/IR/DiagnosticInfo.h =================================================================== --- include/llvm/IR/DiagnosticInfo.h +++ include/llvm/IR/DiagnosticInfo.h @@ -15,17 +15,20 @@ #ifndef LLVM_IR_DIAGNOSTICINFO_H #define LLVM_IR_DIAGNOSTICINFO_H -#include "llvm-c/Types.h" +#include "llvm/ADT/None.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/Twine.h" #include "llvm/IR/DebugLoc.h" +#include "llvm/IR/Function.h" #include "llvm/Support/CBindingWrapping.h" +#include "llvm/Support/Debug.h" #include "llvm/Support/YAMLTraits.h" +#include "llvm-c/Types.h" +#include #include #include -#include #include #include @@ -33,7 +36,6 @@ // Forward declarations. class DiagnosticPrinter; -class Function; class Instruction; class LLVMContext; class Module; @@ -119,7 +121,7 @@ virtual void print(DiagnosticPrinter &DP) const = 0; }; -using DiagnosticHandlerFunction = std::function; +typedef std::function DiagnosticHandlerFunction; /// Diagnostic information for inline asm reporting. /// This is basically a message and an optional location. @@ -604,10 +606,10 @@ return DI->getKind() == DK_OptimizationRemark; } - static bool isEnabled(StringRef PassName); - /// \see DiagnosticInfoOptimizationBase::isEnabled. - bool isEnabled() const override { return isEnabled(getPassName()); } + bool isEnabled() const override { + return DiagnosticHandler::isPassedOptRemarkEnable(getPassName().str()); +} private: /// This is deprecated now and only used by the function API below. @@ -652,10 +654,10 @@ return DI->getKind() == DK_OptimizationRemarkMissed; } - static bool isEnabled(StringRef PassName); - /// \see DiagnosticInfoOptimizationBase::isEnabled. - bool isEnabled() const override { return isEnabled(getPassName()); } + bool isEnabled() const override { + return DiagnosticHandler::isMissedOptRemarkEnable(getPassName().str()); + } private: /// This is deprecated now and only used by the function API below. @@ -712,11 +714,10 @@ return DI->getKind() == DK_OptimizationRemarkAnalysis; } - static bool isEnabled(StringRef PassName); - /// \see DiagnosticInfoOptimizationBase::isEnabled. bool isEnabled() const override { - return shouldAlwaysPrint() || isEnabled(getPassName()); + return DiagnosticHandler::isAnalysisRemarkEnable(getPassName().str()) || + shouldAlwaysPrint(); } 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,31 @@ /// 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, + void *DiagContext = nullptr, + 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 @@ -168,20 +168,23 @@ bool UseInputModulePath = false); }; +class LTOLLVMDiagnosticHandler : public DiagnosticHandler { + void HandleDiagnostics(const DiagnosticInfo &DI, void *Context) { + auto *Fn = static_cast(Context); + (*Fn)(DI); + } +}; /// 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). 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(std::unique_ptr(new LTOLLVMDiagnosticHandler()), + &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,9 +205,8 @@ 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,119 @@ +//===- 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); +} + +void DiagnosticHandler::setAnalysisRemarkPassNamePattern(std::shared_ptr AnalysisRemark) { + PassRemarksAnalysisOptLoc.Pattern = AnalysisRemark; +} + +void DiagnosticHandler::setPassedRemarkPassNamePattern(std::shared_ptr PassedOptRemark) { + PassRemarksPassedOptLoc.Pattern = PassedOptRemark; +} + +void DiagnosticHandler::setMissedRemarkPassNamePattern(std::shared_ptr MissedOptRemark) { + PassRemarksMissedOptLoc.Pattern = MissedOptRemark; +} + +RemarkInfo DiagnosticHandler::isRemarkEnable(const std::string &PassName) { + if (PassRemarksMissedOptLoc.Pattern && PassRemarksMissedOptLoc.Pattern->match(PassName)) + return RemarkInfo::MissedOptRemarkEnable; + + if (PassRemarksPassedOptLoc.Pattern && PassRemarksPassedOptLoc.Pattern->match(PassName)) + return RemarkInfo::PassedOptRemarkEnable; + + if (PassRemarksAnalysisOptLoc.Pattern && PassRemarksAnalysisOptLoc.Pattern->match(PassName)) + return RemarkInfo::AnalysisRemarkEnable; + + return RemarkInfo::RemarkNotEnabled; +} + +bool DiagnosticHandler::isAnalysisRemarkEnable(const std::string &PassName) { + if (PassRemarksAnalysisOptLoc.Pattern && PassRemarksAnalysisOptLoc.Pattern->match(PassName)) + return true; + return false; +} +bool DiagnosticHandler::isMissedOptRemarkEnable(const std::string &PassName) { + if (PassRemarksMissedOptLoc.Pattern && PassRemarksMissedOptLoc.Pattern->match(PassName)) + return true; + return false; +} +bool DiagnosticHandler::isPassedOptRemarkEnable(const std::string &PassName) { + if (PassRemarksPassedOptLoc.Pattern && PassRemarksPassedOptLoc.Pattern->match(PassName)) + return true; + return false; +} + +void DiagnosticHandler::HandleDiagnostics(const DiagnosticInfo &DI, void *Context) { + if(DiagHandlerCallback) + DiagHandlerCallback(DI, Context); +} \ No newline at end of file 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" @@ -41,64 +42,6 @@ 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); - } - } -}; - -} // end anonymous namespace - -static PassRemarksOpt PassRemarksOptLoc; -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(PassRemarksOptLoc), 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); - int llvm::getNextAvailablePluginDiagnosticKind() { static std::atomic PluginKindID(DK_FirstPluginKind); return ++PluginKindID; @@ -259,10 +202,14 @@ RemarkName, *Func, Func->getSubprogram(), &getFirstFunctionBlock(Func)) {} -bool OptimizationRemark::isEnabled(StringRef PassName) { - return PassRemarksOptLoc.Pattern && - PassRemarksOptLoc.Pattern->match(PassName); -} +// bool OptimizationRemark::isEnabled(StringRef PassName) { +// //const Function &Fn = getFunction(); +// LLVMContext &Ctx = Fn.getContext(); +// RemarkInfo RemarkInfoVal = Ctx.getDiagHandler().isRemarkEnable(PassName.str()); +// if (RemarkInfoVal == RemarkInfo::OptRemarkEnable) +// return true; +// return false; +// } OptimizationRemarkMissed::OptimizationRemarkMissed( const char *PassName, StringRef RemarkName, const DiagnosticLocation &Loc, @@ -279,10 +226,14 @@ *Inst->getParent()->getParent(), Inst->getDebugLoc(), Inst->getParent()) {} -bool OptimizationRemarkMissed::isEnabled(StringRef PassName) { - return PassRemarksMissedOptLoc.Pattern && - PassRemarksMissedOptLoc.Pattern->match(PassName); -} +// bool OptimizationRemarkMissed::isEnabled(StringRef PassName) { +// const Function &Fn = getFunction(); +// LLVMContext &Ctx = Fn.getContext(); +// RemarkInfo RemarkInfoVal = Ctx.getDiagHandler().isRemarkEnable(PassName.str()); +// if (RemarkInfoVal == RemarkInfo::MissedOptRemarkEnable) +// return true; +// return false; +// } OptimizationRemarkAnalysis::OptimizationRemarkAnalysis( const char *PassName, StringRef RemarkName, const DiagnosticLocation &Loc, @@ -306,10 +257,14 @@ *cast(CodeRegion)->getParent(), Loc, CodeRegion) {} -bool OptimizationRemarkAnalysis::isEnabled(StringRef PassName) { - return PassRemarksAnalysisOptLoc.Pattern && - PassRemarksAnalysisOptLoc.Pattern->match(PassName); -} +// bool OptimizationRemarkAnalysis::isEnabled(StringRef PassName) { +// const Function &Fn = getFunction(); +// LLVMContext &Ctx = Fn.getContext(); +// RemarkInfo RemarkInfoVal = Ctx.getDiagHandler().isRemarkEnable(PassName.str()); +// if (RemarkInfoVal == RemarkInfo::AnalysisRemarkEnable) +// return true; +// return false; +// } void DiagnosticInfoMIRParser::print(DiagnosticPrinter &DP) const { DP << Diagnostic; Index: lib/IR/LLVMContext.cpp =================================================================== --- lib/IR/LLVMContext.cpp +++ lib/IR/LLVMContext.cpp @@ -29,6 +29,7 @@ #include #include #include +#include using namespace llvm; @@ -129,10 +130,20 @@ return pImpl->InlineAsmDiagContext; } -void LLVMContext::setDiagnosticHandler(DiagnosticHandlerTy DiagnosticHandler, +void LLVMContext::setDiagnosticHandlerCallBack(DiagnosticHandler::DiagnosticHandlerTy DiagnosticHandler, void *DiagnosticContext, bool RespectFilters) { - pImpl->DiagnosticHandler = DiagnosticHandler; + if (!pImpl->DiagHandler) + pImpl->DiagHandler = std::unique_ptr(new class DiagnosticHandler()); + pImpl->DiagHandler->DiagHandlerCallback = DiagnosticHandler; + pImpl->DiagnosticContext = DiagnosticContext; + pImpl->RespectDiagnosticFilters = RespectFilters; +} + +void LLVMContext::setDiagnosticHandler(std::unique_ptr &&DH, + void *DiagnosticContext, + bool RespectFilters) { + pImpl->DiagHandler = std::move(DH); pImpl->DiagnosticContext = DiagnosticContext; pImpl->RespectDiagnosticFilters = RespectFilters; } @@ -159,8 +170,8 @@ 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 { @@ -215,15 +226,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); + pImpl->DiagHandler->HandleDiagnostics(DI, pImpl->DiagnosticContext); 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 +324,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,7 +1168,7 @@ LLVMContext::InlineAsmDiagHandlerTy InlineAsmDiagHandler = nullptr; void *InlineAsmDiagContext = nullptr; - LLVMContext::DiagnosticHandlerTy DiagnosticHandler = nullptr; + std::unique_ptr DiagHandler = nullptr; void *DiagnosticContext = nullptr; bool RespectDiagnosticFilters = false; bool DiagnosticsHotnessRequested = false; Index: lib/LTO/LTOCodeGenerator.cpp =================================================================== --- lib/LTO/LTOCodeGenerator.cpp +++ lib/LTO/LTOCodeGenerator.cpp @@ -62,6 +62,7 @@ #include "llvm/Transforms/ObjCARC.h" #include "llvm/Transforms/Utils/ModuleUtils.h" #include +#include using namespace llvm; const char* LTOCodeGenerator::getVersionString() { @@ -623,12 +624,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()) { @@ -658,17 +655,22 @@ (*DiagHandler)(Severity, MsgStorage.c_str(), DiagContext); } +namespace { +class LTODiagnosticHandler : public DiagnosticHandler { + void HandleDiagnostics(const DiagnosticInfo &DI, void *Context) { + ((LTOCodeGenerator *)Context)->DiagnosticHandler(DI); + } +}; +} + 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(std::unique_ptr(new LTODiagnosticHandler()), this, true); } namespace { Index: tools/llc/llc.cpp =================================================================== --- tools/llc/llc.cpp +++ tools/llc/llc.cpp @@ -13,7 +13,6 @@ // //===----------------------------------------------------------------------===// - #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/Triple.h" #include "llvm/Analysis/TargetLibraryInfo.h" @@ -59,22 +58,22 @@ // and back-end code generation options are specified with the target machine. // static cl::opt -InputFilename(cl::Positional, cl::desc(""), cl::init("-")); + InputFilename(cl::Positional, cl::desc(""), cl::init("-")); static cl::opt -InputLanguage("x", cl::desc("Input language ('ir' or 'mir')")); + InputLanguage("x", cl::desc("Input language ('ir' or 'mir')")); -static cl::opt -OutputFilename("o", cl::desc("Output filename"), cl::value_desc("filename")); +static cl::opt OutputFilename("o", cl::desc("Output filename"), + cl::value_desc("filename")); static cl::opt -TimeCompilations("time-compilations", cl::Hidden, cl::init(1u), - cl::value_desc("N"), - cl::desc("Repeat compilation N times for timing")); + TimeCompilations("time-compilations", cl::Hidden, cl::init(1u), + cl::value_desc("N"), + cl::desc("Repeat compilation N times for timing")); static cl::opt -NoIntegratedAssembler("no-integrated-as", cl::Hidden, - cl::desc("Disable integrated assembler")); + NoIntegratedAssembler("no-integrated-as", cl::Hidden, + cl::desc("Disable integrated assembler")); static cl::opt PreserveComments("preserve-as-comments", cl::Hidden, @@ -83,15 +82,12 @@ // Determine optimization level. static cl::opt -OptLevel("O", - cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] " - "(default = '-O2')"), - cl::Prefix, - cl::ZeroOrMore, - cl::init(' ')); + OptLevel("O", cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] " + "(default = '-O2')"), + cl::Prefix, cl::ZeroOrMore, cl::init(' ')); static cl::opt -TargetTriple("mtriple", cl::desc("Override target triple for module")); + TargetTriple("mtriple", cl::desc("Override target triple for module")); static cl::opt SplitDwarfFile( "split-dwarf-file", @@ -101,8 +97,9 @@ static cl::opt NoVerify("disable-verify", cl::Hidden, cl::desc("Do not verify input module")); -static cl::opt DisableSimplifyLibCalls("disable-simplify-libcalls", - cl::desc("Disable simplify-libcalls")); +static cl::opt + DisableSimplifyLibCalls("disable-simplify-libcalls", + cl::desc("Disable simplify-libcalls")); static cl::opt ShowMCEncoding("show-mc-encoding", cl::Hidden, cl::desc("Show encoding in .s output")); @@ -126,21 +123,24 @@ cl::desc("Discard names from Value (other than GlobalValue)."), cl::init(false), cl::Hidden); -static cl::opt StopBefore("stop-before", - cl::desc("Stop compilation before a specific pass"), - cl::value_desc("pass-name"), cl::init("")); +static cl::opt + StopBefore("stop-before", + cl::desc("Stop compilation before a specific pass"), + cl::value_desc("pass-name"), cl::init("")); -static cl::opt StopAfter("stop-after", - cl::desc("Stop compilation after a specific pass"), - cl::value_desc("pass-name"), cl::init("")); +static cl::opt + StopAfter("stop-after", cl::desc("Stop compilation after a specific pass"), + cl::value_desc("pass-name"), cl::init("")); -static cl::opt StartBefore("start-before", - cl::desc("Resume compilation before a specific pass"), - cl::value_desc("pass-name"), cl::init("")); +static cl::opt + StartBefore("start-before", + cl::desc("Resume compilation before a specific pass"), + cl::value_desc("pass-name"), cl::init("")); -static cl::opt StartAfter("start-after", - cl::desc("Resume compilation after a specific pass"), - cl::value_desc("pass-name"), cl::init("")); +static cl::opt + StartAfter("start-after", + cl::desc("Resume compilation after a specific pass"), + cl::value_desc("pass-name"), cl::init("")); static cl::list IncludeDirs("I", cl::desc("include search path")); @@ -172,6 +172,23 @@ RunPassNames->push_back(PassName); } }; + +class LLCDiagnosticHandler : public DiagnosticHandler { + void HandleDiagnostics(const DiagnosticInfo &DI, void *Context) { + bool *HasError = static_cast(Context); + if (DI.getSeverity() == DS_Error) + *HasError = true; + + if (auto *Remark = dyn_cast(&DI)) + if (!Remark->isEnabled()) + return; + + DiagnosticPrinterRawOStream DP(errs()); + errs() << LLVMContext::getDiagnosticMessagePrefix(DI.getSeverity()) << ": "; + DI.print(DP); + errs() << "\n"; + } +}; } static RunPassOption RunPassOpt; @@ -183,9 +200,9 @@ static int compileModule(char **, LLVMContext &); -static std::unique_ptr -GetOutputStream(const char *TargetName, Triple::OSType OS, - const char *ProgName) { +static std::unique_ptr GetOutputStream(const char *TargetName, + Triple::OSType OS, + const char *ProgName) { // If we don't yet have an output filename, make one. if (OutputFilename.empty()) { if (InputFilename == "-") @@ -241,8 +258,8 @@ sys::fs::OpenFlags OpenFlags = sys::fs::F_None; if (!Binary) OpenFlags |= sys::fs::F_Text; - auto FDOut = llvm::make_unique(OutputFilename, EC, - OpenFlags); + auto FDOut = + llvm::make_unique(OutputFilename, EC, OpenFlags); if (EC) { errs() << EC.message() << '\n'; return nullptr; @@ -251,7 +268,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; @@ -289,7 +306,7 @@ EnableDebugBuffering = true; LLVMContext Context; - llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. + llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. // Initialize targets first, so that --version shows registered targets. InitializeAllTargets(); @@ -324,7 +341,9 @@ // Set a diagnostic handler that doesn't exit on the first error bool HasError = false; - Context.setDiagnosticHandler(DiagnosticHandler, &HasError); + Context.setDiagnosticHandler( + std::unique_ptr(new LLCDiagnosticHandler()), + &HasError); Context.setInlineAsmDiagnosticHandler(InlineAsmDiagHandler, &HasError); if (PassRemarksWithHotness) @@ -346,8 +365,7 @@ llvm::make_unique(YamlFile->os())); } - if (InputLanguage != "" && InputLanguage != "ir" && - InputLanguage != "mir") { + if (InputLanguage != "" && InputLanguage != "ir" && InputLanguage != "mir") { errs() << argv[0] << "Input language must be '', 'IR' or 'MIR'\n"; return 1; } @@ -363,8 +381,8 @@ return 0; } -static bool addPass(PassManagerBase &PM, const char *argv0, - StringRef PassName, TargetPassConfig &TPC) { +static bool addPass(PassManagerBase &PM, const char *argv0, StringRef PassName, + TargetPassConfig &TPC) { if (PassName == "none") return false; @@ -410,8 +428,8 @@ std::unique_ptr MIR; Triple TheTriple; - bool SkipModule = MCPU == "help" || - (!MAttrs.empty() && MAttrs.front() == "help"); + bool SkipModule = + MCPU == "help" || (!MAttrs.empty() && MAttrs.front() == "help"); // If user just wants to list available options, skip module loading if (!SkipModule) { @@ -448,8 +466,8 @@ // Get the target specific parser. std::string Error; - const Target *TheTarget = TargetRegistry::lookupTarget(MArch, TheTriple, - Error); + const Target *TheTarget = + TargetRegistry::lookupTarget(MArch, TheTriple, Error); if (!TheTarget) { errs() << argv[0] << ": " << Error; return 1; @@ -462,11 +480,20 @@ default: errs() << argv[0] << ": invalid optimization level.\n"; return 1; - case ' ': break; - case '0': OLvl = CodeGenOpt::None; break; - case '1': OLvl = CodeGenOpt::Less; break; - case '2': OLvl = CodeGenOpt::Default; break; - case '3': OLvl = CodeGenOpt::Aggressive; break; + case ' ': + break; + case '0': + OLvl = CodeGenOpt::None; + break; + case '1': + OLvl = CodeGenOpt::Less; + break; + case '2': + OLvl = CodeGenOpt::Default; + break; + case '3': + OLvl = CodeGenOpt::Aggressive; + break; } TargetOptions Options = InitTargetOptionsFromCodeGenFlags(); @@ -497,7 +524,8 @@ // Figure out where we are going to send the output. std::unique_ptr Out = GetOutputStream(TheTarget->getName(), TheTriple.getOS(), argv[0]); - if (!Out) return 1; + if (!Out) + return 1; // Build up all of the passes that we want to do to the module. legacy::PassManager PM; @@ -520,7 +548,7 @@ if (RelaxAll.getNumOccurrences() > 0 && FileType != TargetMachine::CGFT_ObjectFile) errs() << argv[0] - << ": warning: ignoring -mc-relax-all because filetype != obj"; + << ": warning: ignoring -mc-relax-all because filetype != obj"; { raw_pwrite_stream *OS = &Out->os(); @@ -553,7 +581,7 @@ if (MIR) { // Construct a custom pass pipeline that starts after instruction // selection. - LLVMTargetMachine &LLVMTM = static_cast(*Target); + LLVMTargetMachine &LLVMTM = static_cast(*Target); TargetPassConfig &TPC = *LLVMTM.createPassConfig(PM); TPC.setDisableVerify(NoVerify); PM.add(&TPC); @@ -567,7 +595,7 @@ if (!StartAfter.empty() || !StopAfter.empty() || !StartBefore.empty() || !StopBefore.empty()) { errs() << argv0 << ": start-after and/or stop-after passes are " - "redundant when run-pass is specified.\n"; + "redundant when run-pass is specified.\n"; return 1; } @@ -595,7 +623,7 @@ StartBeforeID, StartAfterID, StopBeforeID, StopAfterID)) { errs() << argv0 << ": target does not support generation of this" - << " file type!\n"; + << " file type!\n"; return 1; } Index: tools/llvm-dis/llvm-dis.cpp =================================================================== --- tools/llvm-dis/llvm-dis.cpp +++ tools/llvm-dis/llvm-dis.cpp @@ -117,6 +117,25 @@ } }; +class LLVMDisDiagnosticHandler : public DiagnosticHandler { + void HandleDiagnostics(const DiagnosticInfo &DI, void *Context) { + raw_ostream &OS = errs(); + OS << (char *)Context << ": "; + 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); + } +}; } // end anon namespace static void diagnosticHandler(const DiagnosticInfo &DI, void *Context) { @@ -161,9 +180,7 @@ LLVMContext Context; llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. - - Context.setDiagnosticHandler(diagnosticHandler, argv[0]); - + Context.setDiagnosticHandler(std::unique_ptr(new LLVMDisDiagnosticHandler()), 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,30 @@ } } // anonymous namespace +namespace { + class LLVMLinkDiagnosticHandler : public DiagnosticHandler { + void HandleDiagnostics(const DiagnosticInfo &DI, void *Context) override { + unsigned Severity = DI.getSeverity(); + switch (Severity) { + case DS_Error: + errs() << "ERROR: "; + break; + case DS_Warning: + if (SuppressWarnings) + return; + errs() << "WARNING: "; + break; + case DS_Remark: + case DS_Note: + llvm_unreachable("Only expecting warnings and errors"); + } + + DiagnosticPrinterRawOStream DP(errs()); + DI.print(DP); + errs() << '\n'; + } +}; +} static void diagnosticHandler(const DiagnosticInfo &DI, void *C) { unsigned Severity = DI.getSeverity(); switch (Severity) { @@ -347,8 +371,7 @@ ExitOnErr.setBanner(std::string(argv[0]) + ": "); LLVMContext Context; - Context.setDiagnosticHandler(diagnosticHandler, nullptr, true); - + Context.setDiagnosticHandler(std::unique_ptr(new LLVMLinkDiagnosticHandler()), nullptr, 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,39 @@ #include using namespace llvm; +static std::string CurrentActivity; +namespace { + class LLVMLTODiagnosticHandler : public DiagnosticHandler { + void HandleDiagnostics(const DiagnosticInfo &DI, void *Context) { + 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); + } +}; +} static cl::opt OptLevel("O", cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] " "(default = '-O2')"), @@ -204,7 +236,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 +294,7 @@ Buffer = std::move(BufferOrErr.get()); CurrentActivity = ("loading file '" + Path + "'").str(); std::unique_ptr Context = llvm::make_unique(); - Context->setDiagnosticHandler(diagnosticHandler, nullptr, true); + Context->setDiagnosticHandler(std::unique_ptr(new LLVMLTODiagnosticHandler()), nullptr, true); ErrorOr> Ret = LTOModule::createInLocalContext( std::move(Context), Buffer->getBufferStart(), Buffer->getBufferSize(), Options, Path); @@ -808,7 +839,7 @@ unsigned BaseArg = 0; LLVMContext Context; - Context.setDiagnosticHandler(diagnosticHandler, nullptr, true); + Context.setDiagnosticHandler(std::unique_ptr(new LLVMLTODiagnosticHandler()), nullptr, true); LTOCodeGenerator CodeGen(Context); @@ -834,7 +865,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,22 @@ 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); +class LTOToolDiagnosticHandler : public DiagnosticHandler { + void HandleDiagnostics(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); + } } -} +}; // Initialize the configured targets if they have not been initialized. static void lto_initialize() { @@ -108,7 +110,7 @@ static LLVMContext Context; LTOContext = &Context; - LTOContext->setDiagnosticHandler(diagnosticHandler, nullptr, true); + LTOContext->setDiagnosticHandler(std::unique_ptr(new LTOToolDiagnosticHandler())); initialized = true; } } @@ -274,7 +276,7 @@ // Create a local context. Ownership will be transferred to LTOModule. std::unique_ptr Context = llvm::make_unique(); - Context->setDiagnosticHandler(diagnosticHandler, nullptr, true); + Context->setDiagnosticHandler(std::unique_ptr(new LTOToolDiagnosticHandler())); ErrorOr> M = LTOModule::createInLocalContext( std::move(Context), mem, length, Options, StringRef(path));