forked from OSchip/llvm-project
Add a utility diagnostic handler class, SourceMgrDiagnosticHandler, to interface with llvm::SourceMgr. This lowers the barrier of entry for tools to get rich diagnostic handling when using llvm::SourceMgr.
-- PiperOrigin-RevId: 247358610
This commit is contained in:
parent
334d57ef41
commit
4bc23a40f4
|
@ -29,10 +29,16 @@
|
||||||
#include "llvm/ADT/Twine.h"
|
#include "llvm/ADT/Twine.h"
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
|
namespace llvm {
|
||||||
|
class SMLoc;
|
||||||
|
class SourceMgr;
|
||||||
|
} // end namespace llvm
|
||||||
|
|
||||||
namespace mlir {
|
namespace mlir {
|
||||||
class DiagnosticEngine;
|
class DiagnosticEngine;
|
||||||
class Identifier;
|
class Identifier;
|
||||||
struct LogicalResult;
|
struct LogicalResult;
|
||||||
|
class MLIRContext;
|
||||||
class Type;
|
class Type;
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
@ -414,6 +420,26 @@ private:
|
||||||
/// The internal implementation of the DiagnosticEngine.
|
/// The internal implementation of the DiagnosticEngine.
|
||||||
std::unique_ptr<detail::DiagnosticEngineImpl> impl;
|
std::unique_ptr<detail::DiagnosticEngineImpl> impl;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// SourceMgrDiagnosticHandler
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
/// This class is a utility diagnostic handler for use with llvm::SourceMgr.
|
||||||
|
class SourceMgrDiagnosticHandler {
|
||||||
|
public:
|
||||||
|
SourceMgrDiagnosticHandler(llvm::SourceMgr &mgr, MLIRContext *ctx);
|
||||||
|
|
||||||
|
/// Emit the given diagnostic information with the held source manager.
|
||||||
|
void emitDiagnostic(Location loc, Twine message, DiagnosticSeverity kind);
|
||||||
|
|
||||||
|
private:
|
||||||
|
/// Convert a location into the given memory buffer into an SMLoc.
|
||||||
|
llvm::SMLoc convertLocToSMLoc(Location loc);
|
||||||
|
|
||||||
|
/// The source manager that we are wrapping.
|
||||||
|
llvm::SourceMgr &mgr;
|
||||||
|
};
|
||||||
} // namespace mlir
|
} // namespace mlir
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -18,9 +18,11 @@
|
||||||
#include "mlir/IR/Diagnostics.h"
|
#include "mlir/IR/Diagnostics.h"
|
||||||
#include "mlir/IR/Identifier.h"
|
#include "mlir/IR/Identifier.h"
|
||||||
#include "mlir/IR/Location.h"
|
#include "mlir/IR/Location.h"
|
||||||
|
#include "mlir/IR/MLIRContext.h"
|
||||||
#include "mlir/IR/Types.h"
|
#include "mlir/IR/Types.h"
|
||||||
#include "llvm/ADT/Twine.h"
|
#include "llvm/ADT/Twine.h"
|
||||||
#include "llvm/Support/Mutex.h"
|
#include "llvm/Support/Mutex.h"
|
||||||
|
#include "llvm/Support/SourceMgr.h"
|
||||||
#include "llvm/Support/raw_ostream.h"
|
#include "llvm/Support/raw_ostream.h"
|
||||||
|
|
||||||
using namespace mlir;
|
using namespace mlir;
|
||||||
|
@ -223,3 +225,86 @@ void DiagnosticEngine::emit(const Diagnostic &diag) {
|
||||||
for (auto ¬e : diag.getNotes())
|
for (auto ¬e : diag.getNotes())
|
||||||
impl->emit(note.getLocation(), note.str(), note.getSeverity());
|
impl->emit(note.getLocation(), note.str(), note.getSeverity());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// SourceMgrDiagnosticHandler
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
/// Given a diagnostic kind, returns the LLVM DiagKind.
|
||||||
|
static llvm::SourceMgr::DiagKind getDiagKind(DiagnosticSeverity kind) {
|
||||||
|
switch (kind) {
|
||||||
|
case DiagnosticSeverity::Note:
|
||||||
|
return llvm::SourceMgr::DK_Note;
|
||||||
|
case DiagnosticSeverity::Warning:
|
||||||
|
return llvm::SourceMgr::DK_Warning;
|
||||||
|
case DiagnosticSeverity::Error:
|
||||||
|
return llvm::SourceMgr::DK_Error;
|
||||||
|
case DiagnosticSeverity::Remark:
|
||||||
|
return llvm::SourceMgr::DK_Remark;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SourceMgrDiagnosticHandler::SourceMgrDiagnosticHandler(llvm::SourceMgr &mgr,
|
||||||
|
MLIRContext *ctx)
|
||||||
|
: mgr(mgr) {
|
||||||
|
// Register a simple diagnostic handler.
|
||||||
|
ctx->getDiagEngine().setHandler(
|
||||||
|
[this](Location loc, StringRef message, DiagnosticSeverity kind) {
|
||||||
|
emitDiagnostic(loc, message, kind);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void SourceMgrDiagnosticHandler::emitDiagnostic(Location loc, Twine message,
|
||||||
|
DiagnosticSeverity kind) {
|
||||||
|
mgr.PrintMessage(convertLocToSMLoc(loc), getDiagKind(kind), message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert a location into the given memory buffer into an SMLoc.
|
||||||
|
llvm::SMLoc SourceMgrDiagnosticHandler::convertLocToSMLoc(Location loc) {
|
||||||
|
auto fileLoc = loc.dyn_cast<FileLineColLoc>();
|
||||||
|
|
||||||
|
// We currently only support FileLineColLoc.
|
||||||
|
if (!fileLoc)
|
||||||
|
return llvm::SMLoc();
|
||||||
|
|
||||||
|
auto *membuf = mgr.getMemoryBuffer(mgr.getMainFileID());
|
||||||
|
|
||||||
|
// TODO: This should really be upstreamed to be a method on llvm::SourceMgr.
|
||||||
|
// Doing so would allow it to use the offset cache that is already maintained
|
||||||
|
// by SrcBuffer, making this more efficient.
|
||||||
|
unsigned lineNo = fileLoc->getLine();
|
||||||
|
unsigned columnNo = fileLoc->getColumn();
|
||||||
|
|
||||||
|
// Scan for the correct line number.
|
||||||
|
const char *position = membuf->getBufferStart();
|
||||||
|
const char *end = membuf->getBufferEnd();
|
||||||
|
|
||||||
|
// We start counting line and column numbers from 1.
|
||||||
|
--lineNo;
|
||||||
|
--columnNo;
|
||||||
|
|
||||||
|
while (position < end && lineNo) {
|
||||||
|
auto curChar = *position++;
|
||||||
|
|
||||||
|
// Scan for newlines. If this isn't one, ignore it.
|
||||||
|
if (curChar != '\r' && curChar != '\n')
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// We saw a line break, decrement our counter.
|
||||||
|
--lineNo;
|
||||||
|
|
||||||
|
// Check for \r\n and \n\r and treat it as a single escape. We know that
|
||||||
|
// looking past one character is safe because MemoryBuffer's are always nul
|
||||||
|
// terminated.
|
||||||
|
if (*position != curChar && (*position == '\r' || *position == '\n'))
|
||||||
|
++position;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the line/column counter was invalid, return a pointer to the start of
|
||||||
|
// the buffer.
|
||||||
|
if (lineNo || position + columnNo > end)
|
||||||
|
return llvm::SMLoc::getFromPointer(membuf->getBufferStart());
|
||||||
|
|
||||||
|
// Otherwise return the right pointer.
|
||||||
|
return llvm::SMLoc::getFromPointer(position + columnNo);
|
||||||
|
}
|
||||||
|
|
|
@ -73,48 +73,6 @@ static std::vector<const mlir::PassRegistryEntry *> *passList;
|
||||||
|
|
||||||
enum OptResult { OptSuccess, OptFailure };
|
enum OptResult { OptSuccess, OptFailure };
|
||||||
|
|
||||||
/// Given a MemoryBuffer along with a line and column within it, return the
|
|
||||||
/// location being referenced.
|
|
||||||
static SMLoc getLocFromLineAndCol(MemoryBuffer &membuf, unsigned lineNo,
|
|
||||||
unsigned columnNo) {
|
|
||||||
// TODO: This should really be upstreamed to be a method on llvm::SourceMgr.
|
|
||||||
// Doing so would allow it to use the offset cache that is already maintained
|
|
||||||
// by SrcBuffer, making this more efficient.
|
|
||||||
|
|
||||||
// Scan for the correct line number.
|
|
||||||
const char *position = membuf.getBufferStart();
|
|
||||||
const char *end = membuf.getBufferEnd();
|
|
||||||
|
|
||||||
// We start counting line and column numbers from 1.
|
|
||||||
--lineNo;
|
|
||||||
--columnNo;
|
|
||||||
|
|
||||||
while (position < end && lineNo) {
|
|
||||||
auto curChar = *position++;
|
|
||||||
|
|
||||||
// Scan for newlines. If this isn't one, ignore it.
|
|
||||||
if (curChar != '\r' && curChar != '\n')
|
|
||||||
continue;
|
|
||||||
|
|
||||||
// We saw a line break, decrement our counter.
|
|
||||||
--lineNo;
|
|
||||||
|
|
||||||
// Check for \r\n and \n\r and treat it as a single escape. We know that
|
|
||||||
// looking past one character is safe because MemoryBuffer's are always nul
|
|
||||||
// terminated.
|
|
||||||
if (*position != curChar && (*position == '\r' || *position == '\n'))
|
|
||||||
++position;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the line/column counter was invalid, return a pointer to the start of
|
|
||||||
// the buffer.
|
|
||||||
if (lineNo || position + columnNo > end)
|
|
||||||
return SMLoc::getFromPointer(membuf.getBufferStart());
|
|
||||||
|
|
||||||
// Otherwise return the right pointer.
|
|
||||||
return SMLoc::getFromPointer(position + columnNo);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Perform the actions on the input file indicated by the command line flags
|
/// Perform the actions on the input file indicated by the command line flags
|
||||||
/// within the specified context.
|
/// within the specified context.
|
||||||
///
|
///
|
||||||
|
@ -165,20 +123,6 @@ static StringRef getDiagnosticKindString(DiagnosticSeverity kind) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given a diagnostic kind, returns the LLVM DiagKind.
|
|
||||||
static llvm::SourceMgr::DiagKind getDiagKind(DiagnosticSeverity kind) {
|
|
||||||
switch (kind) {
|
|
||||||
case DiagnosticSeverity::Note:
|
|
||||||
return llvm::SourceMgr::DK_Note;
|
|
||||||
case DiagnosticSeverity::Warning:
|
|
||||||
return llvm::SourceMgr::DK_Warning;
|
|
||||||
case DiagnosticSeverity::Error:
|
|
||||||
return llvm::SourceMgr::DK_Error;
|
|
||||||
case DiagnosticSeverity::Remark:
|
|
||||||
return llvm::SourceMgr::DK_Remark;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Parses the memory buffer. If successfully, run a series of passes against
|
/// Parses the memory buffer. If successfully, run a series of passes against
|
||||||
/// it and print the result.
|
/// it and print the result.
|
||||||
static OptResult processFile(std::unique_ptr<MemoryBuffer> ownedBuffer) {
|
static OptResult processFile(std::unique_ptr<MemoryBuffer> ownedBuffer) {
|
||||||
|
@ -189,24 +133,11 @@ static OptResult processFile(std::unique_ptr<MemoryBuffer> ownedBuffer) {
|
||||||
|
|
||||||
// Parse the input file.
|
// Parse the input file.
|
||||||
MLIRContext context;
|
MLIRContext context;
|
||||||
|
SourceMgrDiagnosticHandler sourceMgrHandler(sourceMgr, &context);
|
||||||
|
|
||||||
// If we are in verify mode then we have a lot of work to do, otherwise just
|
// If we are in verify mode then we have a lot of work to do, otherwise just
|
||||||
// perform the actions without worrying about it.
|
// perform the actions without worrying about it.
|
||||||
if (!verifyDiagnostics) {
|
if (!verifyDiagnostics) {
|
||||||
// Register a simple diagnostic handler that prints out info with context.
|
|
||||||
context.getDiagEngine().setHandler(
|
|
||||||
[&](Location location, StringRef message, DiagnosticSeverity kind) {
|
|
||||||
unsigned line = 1, column = 1;
|
|
||||||
SMLoc loc;
|
|
||||||
if (auto fileLoc = location.dyn_cast<FileLineColLoc>()) {
|
|
||||||
line = fileLoc->getLine();
|
|
||||||
column = fileLoc->getColumn();
|
|
||||||
loc = getLocFromLineAndCol(buffer, line, column);
|
|
||||||
}
|
|
||||||
|
|
||||||
sourceMgr.PrintMessage(loc, getDiagKind(kind), message);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Run the test actions.
|
// Run the test actions.
|
||||||
return performActions(sourceMgr, &context);
|
return performActions(sourceMgr, &context);
|
||||||
}
|
}
|
||||||
|
@ -264,9 +195,8 @@ static OptResult processFile(std::unique_ptr<MemoryBuffer> ownedBuffer) {
|
||||||
|
|
||||||
// If this error wasn't expected, produce an error out of mlir-opt saying
|
// If this error wasn't expected, produce an error out of mlir-opt saying
|
||||||
// so.
|
// so.
|
||||||
auto unexpectedLoc = getLocFromLineAndCol(buffer, line, column);
|
sourceMgrHandler.emitDiagnostic(location, "unexpected error: " + message,
|
||||||
sourceMgr.PrintMessage(unexpectedLoc, SourceMgr::DK_Error,
|
DiagnosticSeverity::Error);
|
||||||
"unexpected error: " + Twine(message));
|
|
||||||
result = OptFailure;
|
result = OptFailure;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue