From ff6e7cf558135055f65202f73a0c06db7a53e77d Mon Sep 17 00:00:00 2001 From: River Riddle Date: Fri, 3 May 2019 10:01:01 -0700 Subject: [PATCH] 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 --- mlir/include/mlir/IR/Diagnostics.h | 230 ++++++++++++++++++++- mlir/include/mlir/IR/Function.h | 10 +- mlir/include/mlir/IR/MLIRContext.h | 7 +- mlir/include/mlir/IR/OpDefinition.h | 14 +- mlir/include/mlir/IR/Operation.h | 17 +- .../FxpMathOps/Transforms/LowerUniformRealMath.cpp | 15 +- mlir/lib/IR/Diagnostics.cpp | 146 ++++++++++--- mlir/lib/IR/Dialect.cpp | 1 + mlir/lib/IR/Function.cpp | 15 +- mlir/lib/IR/MLIRContext.cpp | 13 +- mlir/lib/IR/Operation.cpp | 47 ++--- mlir/lib/IR/StandardTypes.cpp | 1 + mlir/lib/IR/Types.cpp | 1 + mlir/lib/Parser/Lexer.cpp | 1 + mlir/lib/Pass/Pass.cpp | 2 +- mlir/lib/Target/LLVMIR/ModuleTranslation.cpp | 6 +- 16 files changed, 415 insertions(+), 111 deletions(-) diff --git a/mlir/include/mlir/IR/Diagnostics.h b/mlir/include/mlir/IR/Diagnostics.h index 45cb66a..ebb70ba 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 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(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(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 getArguments() { return arguments; } + ArrayRef getArguments() const { return arguments; } + + /// Stream operator for inserting new diagnostic arguments. + template + typename std::enable_if::value, + Diagnostic &>::type + operator<<(Arg &&val) { + arguments.push_back(DiagnosticArgument(std::forward(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 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, 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 InFlightDiagnostic &&operator<<(Arg &&arg) && { + appendArgument(std::forward(arg)); + return std::move(*this); + } + template InFlightDiagnostic &operator<<(Arg &&arg) & { + appendArgument(std::forward(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 void appendArgument(Arg &&arg) { + assert(isInFlight() && "diagnostic not inflight"); + *impl << std::forward(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 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; @@ -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 4c57ff6..30eca05 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 d90035b..cdbfcf3 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 4430e24..636122a 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 d9ab876..23e147a 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 3e8a47a..96db87c 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 0311fa1..b266183 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(val.getAsOpaquePointer())) {} + +/// Returns this argument as a Type. +Type DiagnosticArgument::getAsType() const { + assert(getKind() == DiagnosticArgumentKind::Type); + return Type::getFromOpaquePointer(reinterpret_cast(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 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 lock(impl->mutex); - impl->handler = handler; -} - -/// Return the current diagnostic handler, or null if none is present. -auto DiagnosticEngine::getHandler() -> HandlerTy { - llvm::sys::SmartScopedLock 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 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 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()) { 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 lock(impl->mutex); + impl->handler = handler; +} + +/// Return the current diagnostic handler, or null if none is present. +auto DiagnosticEngine::getHandler() -> HandlerTy { + llvm::sys::SmartScopedLock 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 e87358c..89ff1b5 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 e655e2e..66b296f 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 5161c27..6e3c7c9 100644 --- a/mlir/lib/IR/MLIRContext.cpp +++ b/mlir/lib/IR/MLIRContext.cpp @@ -422,14 +422,17 @@ static ArrayRef 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 1a0aaa5..da02c58 100644 --- a/mlir/lib/IR/Operation.cpp +++ b/mlir/lib/IR/Operation.cpp @@ -307,30 +307,29 @@ void Operation::walk(const std::function &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 &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 1427f1f..25a0233 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 7019354..dba33a9 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 8d3fa88..59a435e 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 b7d7ca7..2489115 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 58bbc9c..8a9c649 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(); - 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); } -- 2.7.4