summaryrefslogtreecommitdiffstats
path: root/mlir/lib/IR/Diagnostics.cpp
diff options
context:
space:
mode:
authorRiver Riddle <riverriddle@google.com>2019-05-03 10:01:01 -0700
committerMehdi Amini <joker.eph@gmail.com>2019-05-06 08:26:34 -0700
commitff6e7cf558135055f65202f73a0c06db7a53e77d (patch)
tree1bf545d82cbb014499443e3e3da002195486c771 /mlir/lib/IR/Diagnostics.cpp
parent8c9fbb7eb833cd0f51cb2f02f0500aec481e8c30 (diff)
downloadbcm5719-llvm-ff6e7cf558135055f65202f73a0c06db7a53e77d.tar.gz
bcm5719-llvm-ff6e7cf558135055f65202f73a0c06db7a53e77d.zip
Introduce a new API for emitting diagnostics with Diagnostic and InFlightDiagnostic.
The Diagnostic 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. A diagnostic is currently comprised of several different elements: * A severity level. * A source Location. * A list of DiagnosticArguments that help compose and comprise the output message. * A DiagnosticArgument represents any value that may be part of the diagnostic, e.g. string, integer, Type, Attribute, etc. * Arguments can be added to the diagnostic via the stream(<<) operator. * (In a future cl) A list of attached notes. * These are in the form of other diagnostics that provide supplemental information to the main diagnostic, but do not have context on their own. The InFlightDiagnostic class represents an RAII wrapper around a Diagnostic that is set to be reported with the diagnostic engine. This allows for the user to modify a diagnostic that is inflight. The internally wrapped diagnostic can be reported directly or automatically upon destruction. These classes allow for more natural composition of diagnostics by removing the restriction that the message of a diagnostic is comprised of a single Twine. They should also allow for nice incremental improvements to the diagnostics experience in the future, e.g. formatv style diagnostics. Simple Example: emitError(loc, "integer bitwidth is limited to " + Twine(IntegerType::kMaxWidth) + " bits"); emitError(loc) << "integer bitwidth is limited to " << IntegerType::kMaxWidth << " bits"; -- PiperOrigin-RevId: 246526439
Diffstat (limited to 'mlir/lib/IR/Diagnostics.cpp')
-rw-r--r--mlir/lib/IR/Diagnostics.cpp146
1 files changed, 114 insertions, 32 deletions
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());
+}
OpenPOWER on IntegriCloud