summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--mlir/include/mlir/IR/Diagnostics.h230
-rw-r--r--mlir/include/mlir/IR/Function.h10
-rw-r--r--mlir/include/mlir/IR/MLIRContext.h7
-rw-r--r--mlir/include/mlir/IR/OpDefinition.h14
-rw-r--r--mlir/include/mlir/IR/Operation.h17
-rw-r--r--mlir/lib/FxpMathOps/Transforms/LowerUniformRealMath.cpp15
-rw-r--r--mlir/lib/IR/Diagnostics.cpp146
-rw-r--r--mlir/lib/IR/Dialect.cpp1
-rw-r--r--mlir/lib/IR/Function.cpp15
-rw-r--r--mlir/lib/IR/MLIRContext.cpp13
-rw-r--r--mlir/lib/IR/Operation.cpp47
-rw-r--r--mlir/lib/IR/StandardTypes.cpp1
-rw-r--r--mlir/lib/IR/Types.cpp1
-rw-r--r--mlir/lib/Parser/Lexer.cpp1
-rw-r--r--mlir/lib/Pass/Pass.cpp2
-rw-r--r--mlir/lib/Target/LLVMIR/ModuleTranslation.cpp6
16 files changed, 415 insertions, 111 deletions
diff --git a/mlir/include/mlir/IR/Diagnostics.h b/mlir/include/mlir/IR/Diagnostics.h
index 45cb66a7126..ebb70bab287 100644
--- a/mlir/include/mlir/IR/Diagnostics.h
+++ b/mlir/include/mlir/IR/Diagnostics.h
@@ -22,11 +22,16 @@
#ifndef MLIR_IR_DIAGNOSTICS_H
#define MLIR_IR_DIAGNOSTICS_H
+#include "mlir/IR/Location.h"
#include "mlir/Support/LLVM.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/Twine.h"
#include <functional>
namespace mlir {
-class Location;
+class DiagnosticEngine;
+class LogicalResult;
+class Type;
namespace detail {
struct DiagnosticEngineImpl;
@@ -41,6 +46,217 @@ enum class DiagnosticSeverity {
};
//===----------------------------------------------------------------------===//
+// DiagnosticArgument
+//===----------------------------------------------------------------------===//
+
+/// A variant type that holds a single argument for a diagnostic.
+class DiagnosticArgument {
+public:
+ /// Enum that represents the different kinds of diagnostic arguments
+ /// supported.
+ enum class DiagnosticArgumentKind {
+ Integer,
+ String,
+ Type,
+ Unsigned,
+ };
+
+ /// Outputs this argument to a stream.
+ void print(raw_ostream &os) const;
+
+ /// Returns the kind of this argument.
+ DiagnosticArgumentKind getKind() const { return kind; }
+
+ /// Returns this argument as a string.
+ StringRef getAsString() const {
+ assert(getKind() == DiagnosticArgumentKind::String);
+ return stringVal;
+ }
+
+ /// Returns this argument as a signed integer.
+ int64_t getAsInteger() const {
+ assert(getKind() == DiagnosticArgumentKind::Integer);
+ return static_cast<int64_t>(opaqueVal);
+ }
+
+ /// Returns this argument as a Type.
+ Type getAsType() const;
+
+ /// Returns this argument as an unsigned integer.
+ uint64_t getAsUnsigned() const {
+ assert(getKind() == DiagnosticArgumentKind::Unsigned);
+ return static_cast<uint64_t>(opaqueVal);
+ }
+
+private:
+ friend class Diagnostic;
+
+ // Construct from an int64_t.
+ explicit DiagnosticArgument(int64_t val)
+ : kind(DiagnosticArgumentKind::Integer), opaqueVal(val) {}
+
+ // Construct from an uint64_t.
+ explicit DiagnosticArgument(uint64_t val)
+ : kind(DiagnosticArgumentKind::Unsigned), opaqueVal(val) {}
+
+ // Construct from a string reference.
+ explicit DiagnosticArgument(StringRef val)
+ : kind(DiagnosticArgumentKind::String), stringVal(val) {}
+
+ // Construct from a Type.
+ explicit DiagnosticArgument(Type val);
+
+ /// The kind of this argument.
+ DiagnosticArgumentKind kind;
+
+ /// The value of this argument.
+ union {
+ intptr_t opaqueVal;
+ StringRef stringVal;
+ };
+};
+
+inline raw_ostream &operator<<(raw_ostream &os, const DiagnosticArgument &arg) {
+ arg.print(os);
+ return os;
+}
+
+//===----------------------------------------------------------------------===//
+// Diagnostic
+//===----------------------------------------------------------------------===//
+
+/// This class contains all of the information necessary to report a diagnostic
+/// to the DiagnosticEngine. It should generally not be constructed directly,
+/// and instead used transitively via InFlightDiagnostic.
+class Diagnostic {
+public:
+ Diagnostic(Location loc, DiagnosticSeverity severity)
+ : loc(loc), severity(severity) {}
+ Diagnostic(Diagnostic &&) = default;
+ Diagnostic &operator=(Diagnostic &&) = default;
+
+ /// Returns the severity of this diagnostic.
+ DiagnosticSeverity getSeverity() const { return severity; }
+
+ /// Returns the source location for this diagnostic.
+ Location getLocation() const { return loc; }
+
+ /// Returns the current list of diagnostic arguments.
+ MutableArrayRef<DiagnosticArgument> getArguments() { return arguments; }
+ ArrayRef<DiagnosticArgument> getArguments() const { return arguments; }
+
+ /// Stream operator for inserting new diagnostic arguments.
+ template <typename Arg>
+ typename std::enable_if<!std::is_convertible<Arg, StringRef>::value,
+ Diagnostic &>::type
+ operator<<(Arg &&val) {
+ arguments.push_back(DiagnosticArgument(std::forward<Arg>(val)));
+ return *this;
+ }
+ Diagnostic &operator<<(const char *val) {
+ arguments.push_back(DiagnosticArgument(val));
+ return *this;
+ }
+ Diagnostic &operator<<(const Twine &val) {
+ llvm::SmallString<0> str;
+ arguments.push_back(DiagnosticArgument(val.toStringRef(str)));
+ stringArguments.emplace_back(std::move(str), arguments.size());
+ return *this;
+ }
+
+ /// Outputs this diagnostic to a stream.
+ void print(raw_ostream &os) const;
+
+ /// Converts the diagnostic to a string.
+ std::string str() const;
+
+private:
+ Diagnostic(const Diagnostic &rhs) = delete;
+ Diagnostic &operator=(const Diagnostic &rhs) = delete;
+
+ /// The source location.
+ Location loc;
+
+ /// The severity of this diagnostic.
+ DiagnosticSeverity severity;
+
+ /// The current list of arguments.
+ SmallVector<DiagnosticArgument, 4> arguments;
+
+ /// A list of string values used as arguments and the corresponding index of
+ /// those arguments. This is used to guarantee the liveness of non-constant
+ /// strings used in diagnostics.
+ std::vector<std::pair<llvm::SmallString<0>, unsigned>> stringArguments;
+};
+
+inline raw_ostream &operator<<(raw_ostream &os, const Diagnostic &diag) {
+ diag.print(os);
+ return os;
+}
+
+//===----------------------------------------------------------------------===//
+// InFlightDiagnostic
+//===----------------------------------------------------------------------===//
+
+/// This class represents a diagnostic that is inflight and set to be reported.
+/// This allows for last minute modifications of the diagnostic before it is
+/// emitted by a DiagnosticEngine.
+class InFlightDiagnostic {
+public:
+ InFlightDiagnostic() = default;
+ InFlightDiagnostic(InFlightDiagnostic &&rhs)
+ : owner(rhs.owner), impl(std::move(rhs.impl)) {
+ // Reset the rhs diagnostic.
+ rhs.impl.reset();
+ }
+ ~InFlightDiagnostic() {
+ if (isInFlight())
+ report();
+ }
+
+ /// Stream operator for new diagnostic arguments.
+ template <typename Arg> InFlightDiagnostic &&operator<<(Arg &&arg) && {
+ appendArgument(std::forward<Arg>(arg));
+ return std::move(*this);
+ }
+ template <typename Arg> InFlightDiagnostic &operator<<(Arg &&arg) & {
+ appendArgument(std::forward<Arg>(arg));
+ return *this;
+ }
+
+ /// Reports the diagnostic to the engine.
+ void report();
+
+ /// Allow an inflight diagnostic to be converted to 'failure', otherwise
+ /// 'success' if this is an empty diagnostic.
+ operator LogicalResult() const;
+
+ /// Returns if the diagnostic is still in flight.
+ bool isInFlight() const { return impl.hasValue(); }
+
+private:
+ InFlightDiagnostic &operator=(const InFlightDiagnostic &) = delete;
+ InFlightDiagnostic &operator=(InFlightDiagnostic &&) = delete;
+ InFlightDiagnostic(DiagnosticEngine *owner, Diagnostic &&rhs)
+ : owner(owner), impl(std::move(rhs)) {}
+
+ /// Add an argument to the internal diagnostic.
+ template <typename Arg> void appendArgument(Arg &&arg) {
+ assert(isInFlight() && "diagnostic not inflight");
+ *impl << std::forward<Arg>(arg);
+ }
+
+ // Allow access to the constructor.
+ friend DiagnosticEngine;
+
+ /// The engine that this diagnostic is to report to.
+ DiagnosticEngine *owner;
+
+ /// The raw diagnostic that is inflight to be reported.
+ llvm::Optional<Diagnostic> impl;
+};
+
+//===----------------------------------------------------------------------===//
// DiagnosticEngine
//===----------------------------------------------------------------------===//
@@ -60,7 +276,7 @@ public:
//
// Tools using MLIR are encouraged to register error handlers and define a
// schema for their location information. If they don't, then warnings and
- // notes will be dropped and errors will terminate the process with exit(1).
+ // notes will be dropped and errors will be emitted to errs.
using HandlerTy =
std::function<void(Location, StringRef, DiagnosticSeverity)>;
@@ -74,10 +290,14 @@ public:
/// Return the current diagnostic handler, or null if none is present.
HandlerTy getHandler();
+ /// Create a new inflight diagnostic with the given location and severity.
+ InFlightDiagnostic emit(Location loc, DiagnosticSeverity severity) {
+ return InFlightDiagnostic(this, Diagnostic(loc, severity));
+ }
+
/// Emit a diagnostic using the registered issue handle if present, or with
- /// the default behavior if not. The MLIR compiler should not generally
- /// interact with this, it should use methods on Operation instead.
- void emit(Location loc, const Twine &msg, DiagnosticSeverity severity);
+ /// the default behavior if not.
+ void emit(const Diagnostic &diag);
private:
friend class MLIRContextImpl;
diff --git a/mlir/include/mlir/IR/Function.h b/mlir/include/mlir/IR/Function.h
index 4c57ff6b3fc..30eca05d6f3 100644
--- a/mlir/include/mlir/IR/Function.h
+++ b/mlir/include/mlir/IR/Function.h
@@ -250,18 +250,16 @@ public:
void dump();
/// Emit an error about fatal conditions with this function, reporting up to
- /// any diagnostic handlers that may be listening. This function always
- /// returns failure. NOTE: This may terminate the containing application,
- /// only use when the IR is in an inconsistent state.
- LogicalResult emitError(const Twine &message);
+ /// any diagnostic handlers that may be listening.
+ InFlightDiagnostic emitError(const Twine &message);
/// Emit a warning about this function, reporting up to any diagnostic
/// handlers that may be listening.
- void emitWarning(const Twine &message);
+ InFlightDiagnostic emitWarning(const Twine &message);
/// Emit a remark about this function, reporting up to any diagnostic
/// handlers that may be listening.
- void emitRemark(const Twine &message);
+ InFlightDiagnostic emitRemark(const Twine &message);
/// Displays the CFG in a window. This is for use from the debugger and
/// depends on Graphviz to generate the graph.
diff --git a/mlir/include/mlir/IR/MLIRContext.h b/mlir/include/mlir/IR/MLIRContext.h
index d90035bc823..cdbfcf35470 100644
--- a/mlir/include/mlir/IR/MLIRContext.h
+++ b/mlir/include/mlir/IR/MLIRContext.h
@@ -27,6 +27,7 @@ namespace mlir {
class AbstractOperation;
class DiagnosticEngine;
class Dialect;
+class InFlightDiagnostic;
class Location;
class MLIRContextImpl;
class StorageUniquer;
@@ -60,11 +61,11 @@ public:
// MLIRContextImpl type.
MLIRContextImpl &getImpl() { return *impl.get(); }
- /// Emit an error message using the diagnostic engine and return true.
- bool emitError(Location location, const Twine &message);
+ /// Emit an error message using the diagnostic engine.
+ InFlightDiagnostic emitError(Location location, const Twine &message);
/// Emit a remark message using the diagnostic engine.
- void emitRemark(Location location, const Twine &message);
+ InFlightDiagnostic emitRemark(Location location, const Twine &message);
/// Returns the diagnostic engine for this context.
DiagnosticEngine &getDiagEngine();
diff --git a/mlir/include/mlir/IR/OpDefinition.h b/mlir/include/mlir/IR/OpDefinition.h
index 4430e242e76..636122aea71 100644
--- a/mlir/include/mlir/IR/OpDefinition.h
+++ b/mlir/include/mlir/IR/OpDefinition.h
@@ -104,26 +104,24 @@ public:
void erase() { state->erase(); }
/// Emit an error about fatal conditions with this operation, reporting up to
- /// any diagnostic handlers that may be listening. This function always
- /// returns failure. NOTE: This may terminate the containing application,
- /// only use when the IR is in an inconsistent state.
- LogicalResult emitError(const Twine &message);
+ /// any diagnostic handlers that may be listening.
+ InFlightDiagnostic emitError(const Twine &message);
/// Emit an error with the op name prefixed, like "'dim' op " which is
/// convenient for verifiers. This always returns failure.
- LogicalResult emitOpError(const Twine &message);
+ InFlightDiagnostic emitOpError(const Twine &message);
/// Emit a warning about this operation, reporting up to any diagnostic
/// handlers that may be listening.
- void emitWarning(const Twine &message);
+ InFlightDiagnostic emitWarning(const Twine &message);
/// Emit a note about this operation, reporting up to any diagnostic
/// handlers that may be listening.
- void emitNote(const Twine &message);
+ InFlightDiagnostic emitNote(const Twine &message);
/// Emit a remark about this operation, reporting up to any diagnostic
/// handlers that may be listening.
- void emitRemark(const Twine &message);
+ InFlightDiagnostic emitRemark(const Twine &message);
// These are default implementations of customization hooks.
public:
diff --git a/mlir/include/mlir/IR/Operation.h b/mlir/include/mlir/IR/Operation.h
index d9ab87670b6..23e147a3ae7 100644
--- a/mlir/include/mlir/IR/Operation.h
+++ b/mlir/include/mlir/IR/Operation.h
@@ -24,6 +24,7 @@
#include "mlir/IR/AffineMap.h"
#include "mlir/IR/Block.h"
+#include "mlir/IR/Diagnostics.h"
#include "mlir/IR/OperationSupport.h"
#include "llvm/ADT/Twine.h"
#include "llvm/ADT/ilist.h"
@@ -429,26 +430,24 @@ public:
//===--------------------------------------------------------------------===//
/// Emit an error with the op name prefixed, like "'dim' op " which is
- /// convenient for verifiers. This function always returns failure.
- LogicalResult emitOpError(const Twine &message);
+ /// convenient for verifiers.
+ InFlightDiagnostic emitOpError(const Twine &message);
/// Emit an error about fatal conditions with this operation, reporting up to
- /// any diagnostic handlers that may be listening. This function always
- /// returns failure. NOTE: This may terminate the containing application,
- /// only use when the IR is in an inconsistent state.
- LogicalResult emitError(const Twine &message);
+ /// any diagnostic handlers that may be listening.
+ InFlightDiagnostic emitError(const Twine &message);
/// Emit a warning about this operation, reporting up to any diagnostic
/// handlers that may be listening.
- void emitWarning(const Twine &message);
+ InFlightDiagnostic emitWarning(const Twine &message);
/// Emit a note about this operation, reporting up to any diagnostic
/// handlers that may be listening.
- void emitNote(const Twine &message);
+ InFlightDiagnostic emitNote(const Twine &message);
/// Emit a remark about this operation, reporting up to any diagnostic
/// handlers that may be listening.
- void emitRemark(const Twine &message);
+ InFlightDiagnostic emitRemark(const Twine &message);
private:
Operation(Location location, OperationName name, unsigned numResults,
diff --git a/mlir/lib/FxpMathOps/Transforms/LowerUniformRealMath.cpp b/mlir/lib/FxpMathOps/Transforms/LowerUniformRealMath.cpp
index 3e8a47a474b..96db87ca375 100644
--- a/mlir/lib/FxpMathOps/Transforms/LowerUniformRealMath.cpp
+++ b/mlir/lib/FxpMathOps/Transforms/LowerUniformRealMath.cpp
@@ -52,10 +52,10 @@ static Value *emitUniformPerLayerDequantize(Location loc, Value *input,
// Pre-conditions.
if (!elementType.isSigned()) {
// TODO: Support unsigned storage type.
- return rewriter.getContext()->getDiagEngine().emit(
- loc, "unimplemented: dequantize signed uniform",
- DiagnosticSeverity::Warning),
- nullptr;
+ rewriter.getContext()->getDiagEngine().emit(loc,
+ DiagnosticSeverity::Warning)
+ << "unimplemented: dequantize signed uniform";
+ return nullptr;
}
Type storageType = elementType.castToStorageType(input->getType());
@@ -94,10 +94,9 @@ emitUniformPerAxisDequantize(Location loc, Value *input,
UniformQuantizedPerAxisType elementType,
PatternRewriter &rewriter) {
// TODO: Support per-axis dequantize.
- return rewriter.getContext()->getDiagEngine().emit(
- loc, "unimplemented: per-axis uniform dequantization",
- DiagnosticSeverity::Warning),
- nullptr;
+ rewriter.getContext()->getDiagEngine().emit(loc, DiagnosticSeverity::Warning)
+ << "unimplemented: per-axis uniform dequantization";
+ return nullptr;
}
static Value *emitDequantize(Location loc, Value *input,
diff --git a/mlir/lib/IR/Diagnostics.cpp b/mlir/lib/IR/Diagnostics.cpp
index 0311fa16420..b266183bb8d 100644
--- a/mlir/lib/IR/Diagnostics.cpp
+++ b/mlir/lib/IR/Diagnostics.cpp
@@ -17,6 +17,7 @@
#include "mlir/IR/Diagnostics.h"
#include "mlir/IR/Location.h"
+#include "mlir/IR/Types.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/Mutex.h"
#include "llvm/Support/raw_ostream.h"
@@ -24,9 +25,86 @@
using namespace mlir;
using namespace mlir::detail;
+//===----------------------------------------------------------------------===//
+// DiagnosticArgument
+//===----------------------------------------------------------------------===//
+
+// Construct from a Type.
+DiagnosticArgument::DiagnosticArgument(Type val)
+ : kind(DiagnosticArgumentKind::Type),
+ opaqueVal(reinterpret_cast<intptr_t>(val.getAsOpaquePointer())) {}
+
+/// Returns this argument as a Type.
+Type DiagnosticArgument::getAsType() const {
+ assert(getKind() == DiagnosticArgumentKind::Type);
+ return Type::getFromOpaquePointer(reinterpret_cast<const void *>(opaqueVal));
+}
+
+/// Outputs this argument to a stream.
+void DiagnosticArgument::print(raw_ostream &os) const {
+ switch (kind) {
+ case DiagnosticArgumentKind::Integer:
+ os << getAsInteger();
+ break;
+ case DiagnosticArgumentKind::String:
+ os << getAsString();
+ break;
+ case DiagnosticArgumentKind::Type:
+ os << getAsType();
+ break;
+ case DiagnosticArgumentKind::Unsigned:
+ os << getAsUnsigned();
+ break;
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Diagnostic
+//===----------------------------------------------------------------------===//
+
+/// Outputs this diagnostic to a stream.
+void Diagnostic::print(raw_ostream &os) const {
+ for (auto &arg : getArguments())
+ arg.print(os);
+}
+
+/// Convert the diagnostic to a string.
+std::string Diagnostic::str() const {
+ std::string str;
+ llvm::raw_string_ostream os(str);
+ print(os);
+ return os.str();
+}
+
+//===----------------------------------------------------------------------===//
+// InFlightDiagnostic
+//===----------------------------------------------------------------------===//
+
+/// Allow an inflight diagnostic to be converted to 'failure', otherwise
+/// 'success' if this is an empty diagnostic.
+InFlightDiagnostic::operator LogicalResult() const {
+ return failure(isInFlight());
+}
+
+/// Reports the diagnostic to the engine.
+void InFlightDiagnostic::report() {
+ if (isInFlight()) {
+ owner->emit(*impl);
+ impl.reset();
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// DiagnosticEngineImpl
+//===----------------------------------------------------------------------===//
+
namespace mlir {
namespace detail {
struct DiagnosticEngineImpl {
+ /// Emit a diagnostic using the registered issue handle if present, or with
+ /// the default behavior if not.
+ void emit(Location loc, StringRef msg, DiagnosticSeverity severity);
+
/// A mutex to ensure that diagnostics emission is thread-safe.
llvm::sys::SmartMutex<true> mutex;
@@ -37,42 +115,18 @@ struct DiagnosticEngineImpl {
} // namespace detail
} // namespace mlir
-//===----------------------------------------------------------------------===//
-// DiagnosticEngine
-//===----------------------------------------------------------------------===//
-
-DiagnosticEngine::DiagnosticEngine() : impl(new DiagnosticEngineImpl()) {}
-DiagnosticEngine::~DiagnosticEngine() {}
-
-/// Register a diagnostic handler with this engine. The handler is
-/// passed location information if present (nullptr if not) along with a
-/// message and a severity that indicates whether this is an error, warning,
-/// etc.
-void DiagnosticEngine::setHandler(const HandlerTy &handler) {
- llvm::sys::SmartScopedLock<true> lock(impl->mutex);
- impl->handler = handler;
-}
-
-/// Return the current diagnostic handler, or null if none is present.
-auto DiagnosticEngine::getHandler() -> HandlerTy {
- llvm::sys::SmartScopedLock<true> lock(impl->mutex);
- return impl->handler;
-}
-
/// Emit a diagnostic using the registered issue handle if present, or with
-/// the default behavior if not. The MLIR compiler should not generally
-/// interact with this, it should use methods on Operation instead.
-void DiagnosticEngine::emit(Location loc, const Twine &msg,
- DiagnosticSeverity severity) {
- /// Lock access to the diagnostic engine.
- llvm::sys::SmartScopedLock<true> lock(impl->mutex);
+/// the default behavior if not.
+void DiagnosticEngineImpl::emit(Location loc, StringRef msg,
+ DiagnosticSeverity severity) {
+ // Lock access to the handler.
+ llvm::sys::SmartScopedLock<true> lock(mutex);
// If we had a handler registered, emit the diagnostic using it.
- if (impl->handler) {
+ if (handler) {
// TODO(b/131756158) FusedLoc should be handled by the diagnostic handler
// instead of here.
- // Check to see if we are emitting a diagnostic on a fused
- // location.
+ // Check to see if we are emitting a diagnostic on a fused location.
if (auto fusedLoc = loc.dyn_cast<FusedLoc>()) {
auto fusedLocs = fusedLoc->getLocations();
@@ -85,7 +139,7 @@ void DiagnosticEngine::emit(Location loc, const Twine &msg,
return;
}
- return impl->handler(loc, msg.str(), severity);
+ return handler(loc, msg, severity);
}
// Otherwise, if this is an error we emit it to stderr.
@@ -101,3 +155,31 @@ void DiagnosticEngine::emit(Location loc, const Twine &msg,
os << msg << '\n';
os.flush();
}
+
+//===----------------------------------------------------------------------===//
+// DiagnosticEngine
+//===----------------------------------------------------------------------===//
+
+DiagnosticEngine::DiagnosticEngine() : impl(new DiagnosticEngineImpl()) {}
+DiagnosticEngine::~DiagnosticEngine() {}
+
+/// Set the diagnostic handler for this engine. The handler is passed
+/// location information if present (nullptr if not) along with a message and
+/// a severity that indicates whether this is an error, warning, etc. Note
+/// that this replaces any existing handler.
+void DiagnosticEngine::setHandler(const HandlerTy &handler) {
+ llvm::sys::SmartScopedLock<true> lock(impl->mutex);
+ impl->handler = handler;
+}
+
+/// Return the current diagnostic handler, or null if none is present.
+auto DiagnosticEngine::getHandler() -> HandlerTy {
+ llvm::sys::SmartScopedLock<true> lock(impl->mutex);
+ return impl->handler;
+}
+
+/// Emit a diagnostic using the registered issue handler if present, or with
+/// the default behavior if not.
+void DiagnosticEngine::emit(const Diagnostic &diag) {
+ impl->emit(diag.getLocation(), diag.str(), diag.getSeverity());
+}
diff --git a/mlir/lib/IR/Dialect.cpp b/mlir/lib/IR/Dialect.cpp
index e87358c4bd4..89ff1b50ed4 100644
--- a/mlir/lib/IR/Dialect.cpp
+++ b/mlir/lib/IR/Dialect.cpp
@@ -16,6 +16,7 @@
// =============================================================================
#include "mlir/IR/Dialect.h"
+#include "mlir/IR/Diagnostics.h"
#include "mlir/IR/DialectHooks.h"
#include "mlir/IR/MLIRContext.h"
#include "llvm/ADT/Twine.h"
diff --git a/mlir/lib/IR/Function.cpp b/mlir/lib/IR/Function.cpp
index e655e2ed774..66b296f2454 100644
--- a/mlir/lib/IR/Function.cpp
+++ b/mlir/lib/IR/Function.cpp
@@ -118,23 +118,24 @@ void Function::erase() {
/// Emit a remark about this function, reporting up to any diagnostic
/// handlers that may be listening.
-void Function::emitRemark(const Twine &message) {
- getContext()->emitRemark(getLoc(), message);
+InFlightDiagnostic Function::emitRemark(const Twine &message) {
+ return getContext()->emitRemark(getLoc(), message);
}
/// Emit a warning about this function, reporting up to any diagnostic
/// handlers that may be listening.
-void Function::emitWarning(const Twine &message) {
- getContext()->getDiagEngine().emit(getLoc(), message,
- DiagnosticSeverity::Warning);
+InFlightDiagnostic Function::emitWarning(const Twine &message) {
+ return getContext()->getDiagEngine().emit(getLoc(),
+ DiagnosticSeverity::Warning)
+ << message;
}
/// Emit an error about fatal conditions with this function, reporting up to
/// any diagnostic handlers that may be listening. This function always
/// returns failure. NOTE: This may terminate the containing application, only
/// use when the IR is in an inconsistent state.
-LogicalResult Function::emitError(const Twine &message) {
- return getContext()->emitError(getLoc(), message), failure();
+InFlightDiagnostic Function::emitError(const Twine &message) {
+ return getContext()->emitError(getLoc(), message);
}
/// Clone the internal blocks from this function into dest and all attributes
diff --git a/mlir/lib/IR/MLIRContext.cpp b/mlir/lib/IR/MLIRContext.cpp
index 5161c27368c..6e3c7c9da5a 100644
--- a/mlir/lib/IR/MLIRContext.cpp
+++ b/mlir/lib/IR/MLIRContext.cpp
@@ -422,14 +422,17 @@ static ArrayRef<T> copyArrayRefInto(llvm::BumpPtrAllocator &allocator,
// Diagnostic Handlers
//===----------------------------------------------------------------------===//
-bool MLIRContext::emitError(Location location, const llvm::Twine &message) {
- getImpl().diagEngine.emit(location, message, DiagnosticSeverity::Error);
- return true;
+InFlightDiagnostic MLIRContext::emitError(Location location,
+ const llvm::Twine &message) {
+ return getImpl().diagEngine.emit(location, DiagnosticSeverity::Error)
+ << message;
}
/// Emit a remark message using the diagnostic engine.
-void MLIRContext::emitRemark(Location location, const Twine &message) {
- getImpl().diagEngine.emit(location, message, DiagnosticSeverity::Remark);
+InFlightDiagnostic MLIRContext::emitRemark(Location location,
+ const Twine &message) {
+ return getImpl().diagEngine.emit(location, DiagnosticSeverity::Remark)
+ << message;
}
/// Returns the diagnostic engine for this context.
diff --git a/mlir/lib/IR/Operation.cpp b/mlir/lib/IR/Operation.cpp
index 1a0aaa526c1..da02c58d366 100644
--- a/mlir/lib/IR/Operation.cpp
+++ b/mlir/lib/IR/Operation.cpp
@@ -307,30 +307,29 @@ void Operation::walk(const std::function<void(Operation *)> &callback) {
/// Emit a remark about this operation, reporting up to any diagnostic
/// handlers that may be listening.
-void Operation::emitRemark(const Twine &message) {
- getContext()->emitRemark(getLoc(), message);
+InFlightDiagnostic Operation::emitRemark(const Twine &message) {
+ return getContext()->emitRemark(getLoc(), message);
}
/// Emit a note about this operation, reporting up to any diagnostic
/// handlers that may be listening.
-void Operation::emitNote(const Twine &message) {
- getContext()->getDiagEngine().emit(getLoc(), message,
- DiagnosticSeverity::Note);
+InFlightDiagnostic Operation::emitNote(const Twine &message) {
+ return getContext()->getDiagEngine().emit(getLoc(), DiagnosticSeverity::Note)
+ << message;
}
/// Emit a warning about this operation, reporting up to any diagnostic
/// handlers that may be listening.
-void Operation::emitWarning(const Twine &message) {
- getContext()->getDiagEngine().emit(getLoc(), message,
- DiagnosticSeverity::Warning);
+InFlightDiagnostic Operation::emitWarning(const Twine &message) {
+ return getContext()->getDiagEngine().emit(getLoc(),
+ DiagnosticSeverity::Warning)
+ << message;
}
/// Emit an error about fatal conditions with this operation, reporting up to
-/// any diagnostic handlers that may be listening. This function always
-/// returns failure. NOTE: This may terminate the containing application, only
-/// use when the IR is in an inconsistent state.
-LogicalResult Operation::emitError(const Twine &message) {
- return getContext()->emitError(getLoc(), message), failure();
+/// any diagnostic handlers that may be listening.
+InFlightDiagnostic Operation::emitError(const Twine &message) {
+ return getContext()->emitError(getLoc(), message);
}
/// Given an operation 'other' that is within the same parent block, return
@@ -551,7 +550,7 @@ LogicalResult Operation::fold(SmallVectorImpl<Value *> &results) {
/// Emit an error with the op name prefixed, like "'dim' op " which is
/// convenient for verifiers.
-LogicalResult Operation::emitOpError(const Twine &message) {
+InFlightDiagnostic Operation::emitOpError(const Twine &message) {
return emitError(Twine('\'') + getName().getStringRef() + "' op " + message);
}
@@ -652,35 +651,33 @@ bool OpState::parse(OpAsmParser *parser, OperationState *result) {
void OpState::print(OpAsmPrinter *p) { p->printGenericOp(getOperation()); }
/// Emit an error about fatal conditions with this operation, reporting up to
-/// any diagnostic handlers that may be listening. NOTE: This may terminate
-/// the containing application, only use when the IR is in an inconsistent
-/// state.
-LogicalResult OpState::emitError(const Twine &message) {
+/// any diagnostic handlers that may be listening.
+InFlightDiagnostic OpState::emitError(const Twine &message) {
return getOperation()->emitError(message);
}
/// Emit an error with the op name prefixed, like "'dim' op " which is
/// convenient for verifiers.
-LogicalResult OpState::emitOpError(const Twine &message) {
+InFlightDiagnostic OpState::emitOpError(const Twine &message) {
return getOperation()->emitOpError(message);
}
/// Emit a warning about this operation, reporting up to any diagnostic
/// handlers that may be listening.
-void OpState::emitWarning(const Twine &message) {
- getOperation()->emitWarning(message);
+InFlightDiagnostic OpState::emitWarning(const Twine &message) {
+ return getOperation()->emitWarning(message);
}
/// Emit a note about this operation, reporting up to any diagnostic
/// handlers that may be listening.
-void OpState::emitNote(const Twine &message) {
- getOperation()->emitNote(message);
+InFlightDiagnostic OpState::emitNote(const Twine &message) {
+ return getOperation()->emitNote(message);
}
/// Emit a remark about this operation, reporting up to any diagnostic
/// handlers that may be listening.
-void OpState::emitRemark(const Twine &message) {
- getOperation()->emitRemark(message);
+InFlightDiagnostic OpState::emitRemark(const Twine &message) {
+ return getOperation()->emitRemark(message);
}
//===----------------------------------------------------------------------===//
diff --git a/mlir/lib/IR/StandardTypes.cpp b/mlir/lib/IR/StandardTypes.cpp
index 1427f1f03c0..25a02332516 100644
--- a/mlir/lib/IR/StandardTypes.cpp
+++ b/mlir/lib/IR/StandardTypes.cpp
@@ -18,6 +18,7 @@
#include "mlir/IR/StandardTypes.h"
#include "TypeDetail.h"
#include "mlir/IR/AffineMap.h"
+#include "mlir/IR/Diagnostics.h"
#include "mlir/Support/STLExtras.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/Twine.h"
diff --git a/mlir/lib/IR/Types.cpp b/mlir/lib/IR/Types.cpp
index 701935439f6..dba33a97886 100644
--- a/mlir/lib/IR/Types.cpp
+++ b/mlir/lib/IR/Types.cpp
@@ -17,6 +17,7 @@
#include "mlir/IR/Types.h"
#include "TypeDetail.h"
+#include "mlir/IR/Diagnostics.h"
#include "mlir/IR/Dialect.h"
#include "llvm/ADT/Twine.h"
diff --git a/mlir/lib/Parser/Lexer.cpp b/mlir/lib/Parser/Lexer.cpp
index 8d3fa88419d..59a435e2266 100644
--- a/mlir/lib/Parser/Lexer.cpp
+++ b/mlir/lib/Parser/Lexer.cpp
@@ -20,6 +20,7 @@
//===----------------------------------------------------------------------===//
#include "Lexer.h"
+#include "mlir/IR/Diagnostics.h"
#include "mlir/IR/Location.h"
#include "mlir/IR/MLIRContext.h"
#include "llvm/Support/SourceMgr.h"
diff --git a/mlir/lib/Pass/Pass.cpp b/mlir/lib/Pass/Pass.cpp
index b7d7ca74dba..2489115877d 100644
--- a/mlir/lib/Pass/Pass.cpp
+++ b/mlir/lib/Pass/Pass.cpp
@@ -222,7 +222,7 @@ struct ParallelDiagnosticHandler {
// Emit the diagnostics back to the context.
emitDiagnostics(
[&](Location loc, StringRef message, DiagnosticSeverity kind) {
- return context.getDiagEngine().emit(loc, message, kind);
+ return context.getDiagEngine().emit(loc, kind) << message;
});
}
diff --git a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
index 58bbc9c873b..8a9c649feb3 100644
--- a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
@@ -339,10 +339,12 @@ bool ModuleTranslation::convertOneFunction(Function &func) {
// NB: Attribute already verified to be boolean, so check if we can indeed
// attach the attribute to this argument, based on its type.
auto argTy = mlirArg->getType().dyn_cast<LLVM::LLVMType>();
- if (!argTy.getUnderlyingType()->isPointerTy())
- return argTy.getContext()->emitError(
+ if (!argTy.getUnderlyingType()->isPointerTy()) {
+ argTy.getContext()->emitError(
func.getLoc(),
"llvm.noalias attribute attached to LLVM non-pointer argument");
+ return true;
+ }
if (attr.getValue())
llvmArg.addAttr(llvm::Attribute::AttrKind::NoAlias);
}
OpenPOWER on IntegriCloud