Introduce a new Location abstraction to represent location data in a structured
(and more useful) way rather than hacking up a pile of attributes for it. In
the future this will grow to represent inlined locations, fusion cases etc, but
for now we start with simple Unknown and File/Line/Col locations. NFC.
PiperOrigin-RevId: 210485775
diff --git a/lib/IR/Builders.cpp b/lib/IR/Builders.cpp
index 376d54e..8d0f223 100644
--- a/lib/IR/Builders.cpp
+++ b/lib/IR/Builders.cpp
@@ -20,6 +20,7 @@
#include "mlir/IR/AffineMap.h"
#include "mlir/IR/Attributes.h"
#include "mlir/IR/IntegerSet.h"
+#include "mlir/IR/Location.h"
#include "mlir/IR/Module.h"
#include "mlir/IR/Types.h"
using namespace mlir;
@@ -33,6 +34,21 @@
Module *Builder::createModule() { return new Module(context); }
//===----------------------------------------------------------------------===//
+// Locations.
+//===----------------------------------------------------------------------===//
+
+UnknownLoc *Builder::getUnknownLoc() { return UnknownLoc::get(context); }
+
+UniquedFilename Builder::getUniquedFilename(StringRef filename) {
+ return UniquedFilename::get(filename, context);
+}
+
+FileLineColLoc *Builder::getFileLineColLoc(UniquedFilename filename,
+ unsigned line, unsigned column) {
+ return FileLineColLoc::get(filename, line, column, context);
+}
+
+//===----------------------------------------------------------------------===//
// Types.
//===----------------------------------------------------------------------===//
@@ -227,7 +243,7 @@
return op;
}
-ForStmt *MLFuncBuilder::createFor(Attribute *location,
+ForStmt *MLFuncBuilder::createFor(Location *location,
ArrayRef<MLValue *> lbOperands,
AffineMap *lbMap,
ArrayRef<MLValue *> ubOperands,
@@ -238,7 +254,7 @@
return stmt;
}
-IfStmt *MLFuncBuilder::createIf(Attribute *location, IntegerSet *condition) {
+IfStmt *MLFuncBuilder::createIf(Location *location, IntegerSet *condition) {
auto *stmt = new IfStmt(location, condition);
block->getStatements().insert(insertPoint, stmt);
return stmt;
diff --git a/lib/IR/Instructions.cpp b/lib/IR/Instructions.cpp
index bd48783..90a5016 100644
--- a/lib/IR/Instructions.cpp
+++ b/lib/IR/Instructions.cpp
@@ -146,8 +146,8 @@
// OperationInst
//===----------------------------------------------------------------------===//
-/// Create a new OperationInst with the specific fields.
-OperationInst *OperationInst::create(Attribute *location, Identifier name,
+/// Create a new OperationInst with the specified fields.
+OperationInst *OperationInst::create(Location *location, Identifier name,
ArrayRef<CFGValue *> operands,
ArrayRef<Type *> resultTypes,
ArrayRef<NamedAttribute> attributes,
@@ -186,7 +186,7 @@
getContext());
}
-OperationInst::OperationInst(Attribute *location, Identifier name,
+OperationInst::OperationInst(Location *location, Identifier name,
unsigned numOperands, unsigned numResults,
ArrayRef<NamedAttribute> attributes,
MLIRContext *context)
@@ -281,7 +281,7 @@
//===----------------------------------------------------------------------===//
/// Create a new OperationInst with the specific fields.
-ReturnInst *ReturnInst::create(Attribute *location,
+ReturnInst *ReturnInst::create(Location *location,
ArrayRef<CFGValue *> operands) {
auto byteSize = totalSizeToAlloc<InstOperand>(operands.size());
void *rawMem = malloc(byteSize);
@@ -296,7 +296,7 @@
return inst;
}
-ReturnInst::ReturnInst(Attribute *location, unsigned numOperands)
+ReturnInst::ReturnInst(Location *location, unsigned numOperands)
: TerminatorInst(Kind::Return, location), numOperands(numOperands) {}
void ReturnInst::destroy() {
@@ -314,7 +314,7 @@
// BranchInst
//===----------------------------------------------------------------------===//
-BranchInst::BranchInst(Attribute *location, BasicBlock *dest,
+BranchInst::BranchInst(Location *location, BasicBlock *dest,
ArrayRef<CFGValue *> operands)
: TerminatorInst(Kind::Branch, location), dest(this, dest) {
addOperands(operands);
@@ -338,7 +338,7 @@
// CondBranchInst
//===----------------------------------------------------------------------===//
-CondBranchInst::CondBranchInst(Attribute *location, CFGValue *condition,
+CondBranchInst::CondBranchInst(Location *location, CFGValue *condition,
BasicBlock *trueDest, BasicBlock *falseDest)
: TerminatorInst(Kind::CondBranch, location),
condition(condition), dests{{this}, {this}}, numTrueOperands(0) {
diff --git a/lib/IR/MLIRContext.cpp b/lib/IR/MLIRContext.cpp
index 024e1b6..46d0103 100644
--- a/lib/IR/MLIRContext.cpp
+++ b/lib/IR/MLIRContext.cpp
@@ -23,6 +23,7 @@
#include "mlir/IR/Function.h"
#include "mlir/IR/Identifier.h"
#include "mlir/IR/IntegerSet.h"
+#include "mlir/IR/Location.h"
#include "mlir/IR/OperationSet.h"
#include "mlir/IR/StandardOps.h"
#include "mlir/IR/Types.h"
@@ -182,12 +183,26 @@
/// This class is completely private to this file, so everything is public.
class MLIRContextImpl {
public:
- /// We put immortal objects into this allocator.
- llvm::BumpPtrAllocator allocator;
-
/// This is the set of all operations that are registered with the system.
OperationSet operationSet;
+ /// We put location info into this allocator, since it is generally not
+ /// touched by compiler passes.
+ llvm::BumpPtrAllocator locationAllocator;
+
+ /// The singleton for UnknownLoc.
+ UnknownLoc *theUnknownLoc = nullptr;
+
+ /// These are filename locations uniqued into this MLIRContext.
+ llvm::StringMap<char, llvm::BumpPtrAllocator &> filenames;
+
+ /// FileLineColLoc uniquing.
+ DenseMap<std::tuple<const char *, unsigned, unsigned>, FileLineColLoc *>
+ fileLineColLocs;
+
+ /// We put immortal objects into this allocator.
+ llvm::BumpPtrAllocator allocator;
+
/// This is the handler to use to report diagnostics, or null if not
/// registered.
MLIRContext::DiagnosticHandlerTy diagnosticHandler;
@@ -258,7 +273,7 @@
DenseMap<const Function *, FunctionAttr *> functionAttrs;
public:
- MLIRContextImpl() : identifiers(allocator) {
+ MLIRContextImpl() : filenames(locationAllocator), identifiers(allocator) {
registerStandardOperations(operationSet);
}
@@ -293,8 +308,7 @@
/// This emits 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 MLIRContext::emitDiagnostic(Attribute *location,
- const llvm::Twine &message,
+void MLIRContext::emitDiagnostic(Location *location, const llvm::Twine &message,
DiagnosticKind kind) const {
// If we had a handler registered, emit the diagnostic using it.
auto handler = getImpl().diagnosticHandler;
@@ -305,6 +319,8 @@
if (kind != DiagnosticKind::Error)
return;
+ // TODO(clattner): can improve this now!
+
// The default behavior for errors is to emit them to stderr and exit.
llvm::errs() << message.str() << "\n";
llvm::errs().flush();
@@ -338,6 +354,39 @@
}
//===----------------------------------------------------------------------===//
+// Location uniquing
+//===----------------------------------------------------------------------===//
+
+UnknownLoc *UnknownLoc::get(MLIRContext *context) {
+ auto &impl = context->getImpl();
+ if (auto *result = impl.theUnknownLoc)
+ return result;
+
+ impl.theUnknownLoc = impl.allocator.Allocate<UnknownLoc>();
+ new (impl.theUnknownLoc) UnknownLoc();
+ return impl.theUnknownLoc;
+}
+
+UniquedFilename UniquedFilename::get(StringRef filename, MLIRContext *context) {
+ auto &impl = context->getImpl();
+ auto it = impl.filenames.insert({filename, char()}).first;
+ return UniquedFilename(it->getKeyData());
+}
+
+FileLineColLoc *FileLineColLoc::get(UniquedFilename filename, unsigned line,
+ unsigned column, MLIRContext *context) {
+ auto &impl = context->getImpl();
+ auto &entry =
+ impl.fileLineColLocs[std::make_tuple(filename.data(), line, column)];
+ if (!entry) {
+ entry = impl.allocator.Allocate<FileLineColLoc>();
+ new (entry) FileLineColLoc(filename, line, column);
+ }
+
+ return entry;
+}
+
+//===----------------------------------------------------------------------===//
// Type uniquing
//===----------------------------------------------------------------------===//
diff --git a/lib/IR/Operation.cpp b/lib/IR/Operation.cpp
index 71167bd..f5d07d5 100644
--- a/lib/IR/Operation.cpp
+++ b/lib/IR/Operation.cpp
@@ -46,7 +46,7 @@
/// The source location the operation was defined or derived from. Note that
/// it is possible for this pointer to be null.
-Attribute *Operation::getLoc() const {
+Location *Operation::getLoc() const {
if (auto *inst = dyn_cast<OperationInst>(this))
return inst->getLoc();
return cast<OperationStmt>(this)->getLoc();
diff --git a/lib/IR/Statement.cpp b/lib/IR/Statement.cpp
index 3746f71..3f95a94 100644
--- a/lib/IR/Statement.cpp
+++ b/lib/IR/Statement.cpp
@@ -209,7 +209,7 @@
//===----------------------------------------------------------------------===//
/// Create a new OperationStmt with the specific fields.
-OperationStmt *OperationStmt::create(Attribute *location, Identifier name,
+OperationStmt *OperationStmt::create(Location *location, Identifier name,
ArrayRef<MLValue *> operands,
ArrayRef<Type *> resultTypes,
ArrayRef<NamedAttribute> attributes,
@@ -233,7 +233,7 @@
return stmt;
}
-OperationStmt::OperationStmt(Attribute *location, Identifier name,
+OperationStmt::OperationStmt(Location *location, Identifier name,
unsigned numOperands, unsigned numResults,
ArrayRef<NamedAttribute> attributes,
MLIRContext *context)
@@ -275,7 +275,7 @@
// ForStmt
//===----------------------------------------------------------------------===//
-ForStmt *ForStmt::create(Attribute *location, ArrayRef<MLValue *> lbOperands,
+ForStmt *ForStmt::create(Location *location, ArrayRef<MLValue *> lbOperands,
AffineMap *lbMap, ArrayRef<MLValue *> ubOperands,
AffineMap *ubMap, int64_t step, MLIRContext *context) {
assert(lbOperands.size() == lbMap->getNumOperands() &&
@@ -297,7 +297,7 @@
return stmt;
}
-ForStmt::ForStmt(Attribute *location, unsigned numOperands, AffineMap *lbMap,
+ForStmt::ForStmt(Location *location, unsigned numOperands, AffineMap *lbMap,
AffineMap *ubMap, int64_t step, MLIRContext *context)
: Statement(Kind::For, location),
MLValue(MLValueKind::ForStmt, Type::getAffineInt(context)),
@@ -357,7 +357,7 @@
// IfStmt
//===----------------------------------------------------------------------===//
-IfStmt::IfStmt(Attribute *location, IntegerSet *condition)
+IfStmt::IfStmt(Location *location, IntegerSet *condition)
: Statement(Kind::If, location), thenClause(new IfClause(this)),
elseClause(nullptr), condition(condition) {}
diff --git a/lib/Parser/Parser.cpp b/lib/Parser/Parser.cpp
index 756f25d..ebeb196 100644
--- a/lib/Parser/Parser.cpp
+++ b/lib/Parser/Parser.cpp
@@ -25,6 +25,7 @@
#include "mlir/IR/AffineMap.h"
#include "mlir/IR/Attributes.h"
#include "mlir/IR/Builders.h"
+#include "mlir/IR/Location.h"
#include "mlir/IR/MLFunction.h"
#include "mlir/IR/MLIRContext.h"
#include "mlir/IR/Module.h"
@@ -43,6 +44,14 @@
/// bool value. Failure is "true" in a boolean context.
enum ParseResult { ParseSuccess, ParseFailure };
+/// Return a uniqued filename for the main file the specified SourceMgr is
+/// looking at.
+static UniquedFilename getUniquedFilename(llvm::SourceMgr &sourceMgr,
+ MLIRContext *context) {
+ auto *buffer = sourceMgr.getMemoryBuffer(sourceMgr.getMainFileID());
+ return UniquedFilename::get(buffer->getBufferIdentifier(), context);
+}
+
namespace {
class Parser;
@@ -54,6 +63,7 @@
ParserState(llvm::SourceMgr &sourceMgr, Module *module,
SMDiagnosticHandlerTy errorReporter)
: context(module->getContext()), module(module),
+ filename(getUniquedFilename(sourceMgr, context)),
lex(sourceMgr, errorReporter), curToken(lex.lexToken()),
errorReporter(errorReporter), operationSet(OperationSet::get(context)) {
}
@@ -81,6 +91,9 @@
// This is the module we are parsing into.
Module *const module;
+ /// The filename to use for location generation.
+ UniquedFilename filename;
+
// The lexer for the source file we're parsing.
Lexer lex;
@@ -122,7 +135,7 @@
/// Encode the specified source location information into an attribute for
/// attachment to the IR.
- Attribute *getEncodedSourceLocation(llvm::SMLoc loc);
+ Location *getEncodedSourceLocation(llvm::SMLoc loc);
/// Emit an error and return failure.
ParseResult emitError(const Twine &message) {
@@ -209,16 +222,13 @@
/// Encode the specified source location information into an attribute for
/// attachment to the IR.
-Attribute *Parser::getEncodedSourceLocation(llvm::SMLoc loc) {
- // TODO(clattner): Switch to an more structured form that includes
- // file/line/column instead of just byte offset in the file. This will
- // eliminate this block of low level code poking at the SourceMgr directly.
+Location *Parser::getEncodedSourceLocation(llvm::SMLoc loc) {
auto &sourceMgr = getSourceMgr();
- auto fileID = sourceMgr.FindBufferContainingLoc(loc);
+ auto lineAndColumn =
+ sourceMgr.getLineAndColumn(loc, sourceMgr.getMainFileID());
- auto *srcBuffer = sourceMgr.getMemoryBuffer(fileID);
- unsigned locationEncoding = loc.getPointer() - srcBuffer->getBufferStart();
- return builder.getIntegerAttr(locationEncoding);
+ return FileLineColLoc::get(state.filename, lineAndColumn.first,
+ lineAndColumn.second, getContext());
}
ParseResult Parser::emitError(SMLoc loc, const Twine &message) {
@@ -1389,11 +1399,9 @@
// We create these placeholders as having an empty name, which we know cannot
// be created through normal user input, allowing us to distinguish them.
auto name = Identifier::get("placeholder", getContext());
- auto *inst =
- // FIXME(clattner): encode the location into the placeholder instead of
- // into the forwardReferencePlaceholders map!
- OperationInst::create(/*location=*/nullptr, name, /*operands=*/{}, type,
- /*attrs=*/{}, getContext());
+ auto *inst = OperationInst::create(getEncodedSourceLocation(loc), name,
+ /*operands=*/{}, type,
+ /*attributes=*/{}, getContext());
forwardReferencePlaceholders[inst->getResult(0)] = loc;
return inst->getResult(0);
}
@@ -3038,11 +3046,8 @@
auto existingContextHandler = context->getDiagnosticHandler();
// Install a new handler that uses the error reporter.
- context->registerDiagnosticHandler([&](Attribute *location, StringRef message,
+ context->registerDiagnosticHandler([&](Location *location, StringRef message,
MLIRContext::DiagnosticKind kind) {
- auto offset = cast<IntegerAttr>(location)->getValue();
- auto *mainBuffer = sourceMgr.getMemoryBuffer(sourceMgr.getMainFileID());
- auto ptr = mainBuffer->getBufferStart() + offset;
SourceMgr::DiagKind diagKind;
switch (kind) {
case MLIRContext::DiagnosticKind::Error:
@@ -3055,8 +3060,20 @@
diagKind = SourceMgr::DK_Note;
break;
}
- errorReporter(
- sourceMgr.GetMessage(SMLoc::getFromPointer(ptr), diagKind, message));
+
+ StringRef filename;
+ unsigned line = 0, column = 0;
+ if (auto fileLoc = dyn_cast<FileLineColLoc>(location)) {
+ filename = fileLoc->getFilename();
+ line = fileLoc->getLine();
+ column = fileLoc->getColumn();
+ }
+
+ auto diag = llvm::SMDiagnostic(sourceMgr, SMLoc(), filename, line, column,
+ diagKind, message, /*LineStr=*/StringRef(),
+ /*Ranges=*/{}, /*FixIts=*/{});
+
+ errorReporter(diag);
});
// This is the result module we are parsing into.