Push location information more tightly into the IR, providing space for every
operation and statement to have a location, and make it so a location is
required to be specified whenever you make one (though a null location is still
allowed). This is to encourage compiler authors to propagate loc info
properly, allowing our failability story to work well.
This is still a WIP - it isn't clear if we want to continue abusing Attribute
for location information, or whether we should introduce a new class heirarchy
to do so. This is good step along the way, and unblocks some of the tf/xla
work that builds upon it.
PiperOrigin-RevId: 210001406
diff --git a/lib/IR/Instructions.cpp b/lib/IR/Instructions.cpp
index 8f64066..7378b7a 100644
--- a/lib/IR/Instructions.cpp
+++ b/lib/IR/Instructions.cpp
@@ -17,6 +17,7 @@
#include "mlir/IR/Instructions.h"
#include "mlir/IR/CFGFunction.h"
+#include "mlir/IR/MLIRContext.h"
using namespace mlir;
/// Replace all uses of 'this' value with the new value, updating anything in
@@ -118,12 +119,35 @@
dest.drop();
}
+/// Emit a note about this instruction, reporting up to any diagnostic
+/// handlers that may be listening.
+void Instruction::emitNote(const Twine &message) const {
+ getContext()->emitDiagnostic(getLoc(), message,
+ MLIRContext::DiagnosticKind::Note);
+}
+
+/// Emit a warning about this operation, reporting up to any diagnostic
+/// handlers that may be listening.
+void Instruction::emitWarning(const Twine &message) const {
+ getContext()->emitDiagnostic(getLoc(), message,
+ MLIRContext::DiagnosticKind::Warning);
+}
+
+/// Emit an error about fatal conditions with this instruction, 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.
+void Instruction::emitError(const Twine &message) const {
+ getContext()->emitDiagnostic(getLoc(), message,
+ MLIRContext::DiagnosticKind::Error);
+}
+
//===----------------------------------------------------------------------===//
// OperationInst
//===----------------------------------------------------------------------===//
/// Create a new OperationInst with the specific fields.
-OperationInst *OperationInst::create(Identifier name,
+OperationInst *OperationInst::create(Attribute *location, Identifier name,
ArrayRef<CFGValue *> operands,
ArrayRef<Type *> resultTypes,
ArrayRef<NamedAttribute> attributes,
@@ -134,7 +158,7 @@
// Initialize the OperationInst part of the instruction.
auto inst = ::new (rawMem) OperationInst(
- name, operands.size(), resultTypes.size(), attributes, context);
+ location, name, operands.size(), resultTypes.size(), attributes, context);
// Initialize the operands and results.
auto instOperands = inst->getInstOperands();
@@ -151,23 +175,23 @@
SmallVector<CFGValue *, 8> operands;
SmallVector<Type *, 8> resultTypes;
- // TODO(clattner): switch to iterator logic.
// Put together the operands and results.
- for (unsigned i = 0, e = getNumOperands(); i != e; ++i)
- operands.push_back(getInstOperand(i).get());
+ for (auto *operand : getOperands())
+ operands.push_back(const_cast<CFGValue *>(operand));
- for (unsigned i = 0, e = getNumResults(); i != e; ++i)
- resultTypes.push_back(getInstResult(i).getType());
+ for (auto *result : getResults())
+ resultTypes.push_back(result->getType());
- return create(getName(), operands, resultTypes, getAttrs(), getContext());
+ return create(getLoc(), getName(), operands, resultTypes, getAttrs(),
+ getContext());
}
-OperationInst::OperationInst(Identifier name, unsigned numOperands,
- unsigned numResults,
+OperationInst::OperationInst(Attribute *location, Identifier name,
+ unsigned numOperands, unsigned numResults,
ArrayRef<NamedAttribute> attributes,
MLIRContext *context)
- : Operation(name, /*isInstruction=*/true, attributes, context),
- Instruction(Kind::Operation), numOperands(numOperands),
+ : Operation(/*isInstruction=*/true, name, attributes, context),
+ Instruction(Kind::Operation, location), numOperands(numOperands),
numResults(numResults) {}
OperationInst::~OperationInst() {
@@ -257,12 +281,13 @@
//===----------------------------------------------------------------------===//
/// Create a new OperationInst with the specific fields.
-ReturnInst *ReturnInst::create(ArrayRef<CFGValue *> operands) {
+ReturnInst *ReturnInst::create(Attribute *location,
+ ArrayRef<CFGValue *> operands) {
auto byteSize = totalSizeToAlloc<InstOperand>(operands.size());
void *rawMem = malloc(byteSize);
// Initialize the ReturnInst part of the instruction.
- auto inst = ::new (rawMem) ReturnInst(operands.size());
+ auto inst = ::new (rawMem) ReturnInst(location, operands.size());
// Initialize the operands and results.
auto instOperands = inst->getInstOperands();
@@ -271,6 +296,9 @@
return inst;
}
+ReturnInst::ReturnInst(Attribute *location, unsigned numOperands)
+ : TerminatorInst(Kind::Return, location), numOperands(numOperands) {}
+
void ReturnInst::destroy() {
this->~ReturnInst();
free(this);
@@ -286,8 +314,8 @@
// BranchInst
//===----------------------------------------------------------------------===//
-BranchInst::BranchInst(BasicBlock *dest)
- : TerminatorInst(Kind::Branch), dest(this, dest) {}
+BranchInst::BranchInst(Attribute *location, BasicBlock *dest)
+ : TerminatorInst(Kind::Branch, location), dest(this, dest) {}
void BranchInst::setDest(BasicBlock *block) { dest.set(block); }
@@ -307,9 +335,9 @@
// CondBranchInst
//===----------------------------------------------------------------------===//
-CondBranchInst::CondBranchInst(CFGValue *condition, BasicBlock *trueDest,
- BasicBlock *falseDest)
- : TerminatorInst(Kind::CondBranch),
+CondBranchInst::CondBranchInst(Attribute *location, CFGValue *condition,
+ BasicBlock *trueDest, BasicBlock *falseDest)
+ : TerminatorInst(Kind::CondBranch, location),
condition(condition), dests{{this}, {this}}, numTrueOperands(0) {
dests[falseIndex].set(falseDest);
dests[trueIndex].set(trueDest);