Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
It enables OptimizationRemarkEmitter::allowExtraAnalysis and MachineOptimizationRemarkEmitter::allowExtraAnalysis to return true not only for -fsave-optimization-record but when specific remarks are requested with
command line options.
The diagnostic handler used to be callback now this patch adds a class
DiagnosticHandler. It has virtual method to provide custom diagnostic handler
and methods to control which particular remarks are enabled. 
However LLVM-C API users can still provide callback function for diagnostic handler.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@313382 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
vivekvpandya committed Sep 15, 2017
1 parent d3108e5 commit bb8204f
Show file tree
Hide file tree
Showing 23 changed files with 417 additions and 248 deletions.
7 changes: 3 additions & 4 deletions include/llvm/Analysis/OptimizationDiagnosticInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,9 @@ class OptimizationRemarkEmitter {
/// 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 {
// For now, only allow this with -fsave-optimization-record since the -Rpass
// options are handled in the front-end.
return F->getContext().getDiagnosticsOutputFile();
bool allowExtraAnalysis(StringRef PassName) const {
return (F->getContext().getDiagnosticsOutputFile() ||
F->getContext().getDiagHandlerPtr()->isAnyRemarkEnabled(PassName));
}

private:
Expand Down
20 changes: 13 additions & 7 deletions include/llvm/CodeGen/MachineOptimizationRemarkEmitter.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,9 @@ class MachineOptimizationRemark : public DiagnosticInfoMIROptimization {

/// \see DiagnosticInfoOptimizationBase::isEnabled.
bool isEnabled() const override {
return OptimizationRemark::isEnabled(getPassName());
const Function &Fn = getFunction();
LLVMContext &Ctx = Fn.getContext();
return Ctx.getDiagHandlerPtr()->isPassedOptRemarkEnabled(getPassName());
}
};

Expand All @@ -97,7 +99,9 @@ class MachineOptimizationRemarkMissed : public DiagnosticInfoMIROptimization {

/// \see DiagnosticInfoOptimizationBase::isEnabled.
bool isEnabled() const override {
return OptimizationRemarkMissed::isEnabled(getPassName());
const Function &Fn = getFunction();
LLVMContext &Ctx = Fn.getContext();
return Ctx.getDiagHandlerPtr()->isMissedOptRemarkEnabled(getPassName());
}
};

Expand All @@ -121,7 +125,9 @@ class MachineOptimizationRemarkAnalysis : public DiagnosticInfoMIROptimization {

/// \see DiagnosticInfoOptimizationBase::isEnabled.
bool isEnabled() const override {
return OptimizationRemarkAnalysis::isEnabled(getPassName());
const Function &Fn = getFunction();
LLVMContext &Ctx = Fn.getContext();
return Ctx.getDiagHandlerPtr()->isAnalysisRemarkEnabled(getPassName());
}
};

Expand Down Expand Up @@ -152,10 +158,10 @@ class MachineOptimizationRemarkEmitter {
/// 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 {
// For now, only allow this with -fsave-optimization-record since the -Rpass
// options are handled in the front-end.
return MF.getFunction()->getContext().getDiagnosticsOutputFile();
bool allowExtraAnalysis(StringRef PassName) const {
return (MF.getFunction()->getContext().getDiagnosticsOutputFile() ||
MF.getFunction()->getContext()
.getDiagHandlerPtr()->isAnyRemarkEnabled(PassName));
}

private:
Expand Down
67 changes: 67 additions & 0 deletions include/llvm/IR/DiagnosticHandler.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
//===- DiagnosticHandler.h - 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/ADT/StringRef.h"

namespace llvm {
class DiagnosticInfo;

/// \brief This is the base class for diagnostic handling in LLVM.
/// The handleDiagnostics method must be overriden by the subclasses to handle
/// diagnostic. The *RemarkEnabled methods can be overriden to control
/// which remarks are enabled.
struct DiagnosticHandler {
void *DiagnosticContext = nullptr;
DiagnosticHandler(void *DiagContext = nullptr)
: DiagnosticContext(DiagContext) {}
virtual ~DiagnosticHandler() = default;

using DiagnosticHandlerTy = void (*)(const DiagnosticInfo &DI, void *Context);

/// DiagHandlerCallback is settable from the C API and base implementation
/// of DiagnosticHandler will call it from handleDiagnostics(). Any derived
/// class of DiagnosticHandler should not use callback but
/// implement handleDiagnostics().
DiagnosticHandlerTy DiagHandlerCallback = nullptr;

/// Override handleDiagnostics to provide custom implementation.
/// Return true if it handles diagnostics reporting properly otherwise
/// return false to make LLVMContext::diagnose() to print the message
/// with a prefix based on the severity.
virtual bool handleDiagnostics(const DiagnosticInfo &DI) {
if (DiagHandlerCallback) {
DiagHandlerCallback(DI, DiagnosticContext);
return true;
}
return false;
}

/// Return true if analysis remarks are enabled, override
/// to provide different implementation.
virtual bool isAnalysisRemarkEnabled(StringRef PassName) const;

/// Return true if missed optimization remarks are enabled, override
/// to provide different implementation.
virtual bool isMissedOptRemarkEnabled(StringRef PassName) const;

/// Return true if passed optimization remarks are enabled, override
/// to provide different implementation.
virtual bool isPassedOptRemarkEnabled(StringRef PassName) const;

/// Return true if any type of remarks are enabled.
bool isAnyRemarkEnabled(StringRef PassName) const {
return (isMissedOptRemarkEnabled(PassName) ||
isPassedOptRemarkEnabled(PassName) ||
isAnalysisRemarkEnabled(PassName));
}
};
}
14 changes: 3 additions & 11 deletions include/llvm/IR/DiagnosticInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -604,10 +604,8 @@ class OptimizationRemark : public DiagnosticInfoIROptimization {
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.
Expand Down Expand Up @@ -647,10 +645,8 @@ class OptimizationRemarkMissed : public DiagnosticInfoIROptimization {
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.
Expand Down Expand Up @@ -701,12 +697,8 @@ class OptimizationRemarkAnalysis : public DiagnosticInfoIROptimization {
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;

Expand Down
41 changes: 27 additions & 14 deletions include/llvm/IR/LLVMContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#define LLVM_IR_LLVMCONTEXT_H

#include "llvm-c/Types.h"
#include "llvm/IR/DiagnosticHandler.h"
#include "llvm/Support/CBindingWrapping.h"
#include "llvm/Support/Options.h"
#include <cstdint>
Expand Down Expand Up @@ -167,11 +168,6 @@ class LLVMContext {
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);
Expand All @@ -194,26 +190,43 @@ class LLVMContext {
/// 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
/// setDiagnosticHandlerCallBack - This method sets a handler call back
/// 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,
void *DiagContext = nullptr,
void setDiagnosticHandlerCallBack(
DiagnosticHandler::DiagnosticHandlerTy DiagHandler,
void *DiagContext = nullptr, bool RespectFilters = false);

/// setDiagnosticHandler - This method sets unique_ptr to object of DiagnosticHandler
/// to provide custom diagnostic handling. The first argument is unique_ptr of object
/// of type DiagnosticHandler or a derived of that. The third argument should be
/// set to true if the handler only expects enabled diagnostics.
///
/// Ownership of this pointer is moved to LLVMContextImpl.
void setDiagnosticHandler(std::unique_ptr<DiagnosticHandler> &&DH,
bool RespectFilters = false);

/// getDiagnosticHandler - Return the diagnostic handler set by
/// setDiagnosticHandler.
DiagnosticHandlerTy getDiagnosticHandler() const;
/// getDiagnosticHandlerCallBack - Return the diagnostic handler call back set by
/// setDiagnosticHandlerCallBack.
DiagnosticHandler::DiagnosticHandlerTy getDiagnosticHandlerCallBack() const;

/// getDiagnosticContext - Return the diagnostic context set by
/// setDiagnosticContext.
void *getDiagnosticContext() const;

/// getDiagHandlerPtr - Returns const raw pointer of DiagnosticHandler set by
/// setDiagnosticHandler.
const DiagnosticHandler *getDiagHandlerPtr() const;

/// getDiagnosticHandler - transfers owenership of DiagnosticHandler unique_ptr
/// to caller.
std::unique_ptr<DiagnosticHandler> getDiagnosticHandler();

/// \brief Return if a code hotness metric should be included in optimization
/// diagnostics.
bool getDiagnosticsHotnessRequested() const;
Expand Down
17 changes: 12 additions & 5 deletions include/llvm/LTO/Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,20 +171,27 @@ struct Config {
bool UseInputModulePath = false);
};

struct LTOLLVMDiagnosticHandler : public DiagnosticHandler {
DiagnosticHandlerFunction *Fn;
LTOLLVMDiagnosticHandler(DiagnosticHandlerFunction *DiagHandlerFn)
: Fn(DiagHandlerFn) {}
bool handleDiagnostics(const DiagnosticInfo &DI) override {
(*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<DiagnosticHandlerFunction *>(Context);
(*Fn)(DI);
}

LTOLLVMContext(const Config &C) : DiagHandler(C.DiagHandler) {
setDiscardValueNames(C.ShouldDiscardValueNames);
enableDebugTypeODRUniquing();
setDiagnosticHandler(funcDiagHandler, &DiagHandler, true);
setDiagnosticHandler(
llvm::make_unique<LTOLLVMDiagnosticHandler>(&DiagHandler), true);
}
DiagnosticHandlerFunction DiagHandler;
};
Expand Down
5 changes: 1 addition & 4 deletions include/llvm/LTO/legacy/LTOCodeGenerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ struct LTOCodeGenerator {
LLVMContext &getContext() { return Context; }

void resetMergedModule() { MergedModule.reset(); }
void DiagnosticHandler(const DiagnosticInfo &DI);

private:
void initializeLTOPasses();
Expand All @@ -204,10 +205,6 @@ struct LTOCodeGenerator {
bool determineTarget();
std::unique_ptr<TargetMachine> 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);

Expand Down
1 change: 1 addition & 0 deletions lib/IR/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ add_llvm_library(LLVMCore
DebugInfo.cpp
DebugInfoMetadata.cpp
DebugLoc.cpp
DiagnosticHandler.cpp
DiagnosticInfo.cpp
DiagnosticPrinter.cpp
Dominators.cpp
Expand Down
6 changes: 3 additions & 3 deletions lib/IR/Core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,15 +85,15 @@ LLVMContextRef LLVMGetGlobalContext() { return wrap(&*GlobalContext); }
void LLVMContextSetDiagnosticHandler(LLVMContextRef C,
LLVMDiagnosticHandler Handler,
void *DiagnosticContext) {
unwrap(C)->setDiagnosticHandler(
LLVM_EXTENSION reinterpret_cast<LLVMContext::DiagnosticHandlerTy>(
unwrap(C)->setDiagnosticHandlerCallBack(
LLVM_EXTENSION reinterpret_cast<DiagnosticHandler::DiagnosticHandlerTy>(
Handler),
DiagnosticContext);
}

LLVMDiagnosticHandler LLVMContextGetDiagnosticHandler(LLVMContextRef C) {
return LLVM_EXTENSION reinterpret_cast<LLVMDiagnosticHandler>(
unwrap(C)->getDiagnosticHandler());
unwrap(C)->getDiagnosticHandlerCallBack());
}

void *LLVMContextGetDiagnosticContext(LLVMContextRef C) {
Expand Down
Loading

0 comments on commit bb8204f

Please sign in to comment.