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/include/mlir/IR/Builders.h b/include/mlir/IR/Builders.h
index 3cc8227..a545fe1 100644
--- a/include/mlir/IR/Builders.h
+++ b/include/mlir/IR/Builders.h
@@ -18,7 +18,6 @@
#ifndef MLIR_IR_BUILDERS_H
#define MLIR_IR_BUILDERS_H
-#include "mlir/IR/Attributes.h"
#include "mlir/IR/CFGFunction.h"
#include "mlir/IR/MLFunction.h"
#include "mlir/IR/Statements.h"
@@ -26,6 +25,9 @@
namespace mlir {
class MLIRContext;
class Module;
+class UnknownLoc;
+class UniquedFilename;
+class FileLineColLoc;
class Type;
class PrimitiveType;
class IntegerType;
@@ -59,6 +61,12 @@
Identifier getIdentifier(StringRef str);
Module *createModule();
+ // Locations.
+ UnknownLoc *getUnknownLoc();
+ UniquedFilename getUniquedFilename(StringRef filename);
+ FileLineColLoc *getFileLineColLoc(UniquedFilename filename, unsigned line,
+ unsigned column);
+
// Types.
FloatType *getBF16Type();
FloatType *getF16Type();
@@ -185,7 +193,7 @@
/// Create operation of specific op type at the current insertion point.
template <typename OpTy, typename... Args>
- OpPointer<OpTy> create(Attribute *location, Args... args) {
+ OpPointer<OpTy> create(Location *location, Args... args) {
OperationState state(getContext(), location, OpTy::getOperationName());
OpTy::build(this, &state, args...);
auto *inst = createOperation(state);
@@ -202,16 +210,16 @@
// Terminators.
- ReturnInst *createReturn(Attribute *location, ArrayRef<CFGValue *> operands) {
+ ReturnInst *createReturn(Location *location, ArrayRef<CFGValue *> operands) {
return insertTerminator(ReturnInst::create(location, operands));
}
- BranchInst *createBranch(Attribute *location, BasicBlock *dest,
+ BranchInst *createBranch(Location *location, BasicBlock *dest,
ArrayRef<CFGValue *> operands = {}) {
return insertTerminator(BranchInst::create(location, dest, operands));
}
- CondBranchInst *createCondBranch(Attribute *location, CFGValue *condition,
+ CondBranchInst *createCondBranch(Location *location, CFGValue *condition,
BasicBlock *trueDest,
BasicBlock *falseDest) {
return insertTerminator(
@@ -290,7 +298,7 @@
/// Create operation of specific op type at the current insertion point.
template <typename OpTy, typename... Args>
- OpPointer<OpTy> create(Attribute *location, Args... args) {
+ OpPointer<OpTy> create(Location *location, Args... args) {
OperationState state(getContext(), location, OpTy::getOperationName());
OpTy::build(this, &state, args...);
auto *stmt = createOperation(state);
@@ -311,15 +319,12 @@
return cloneStmt;
}
- /// Create a 'for' statement with bounds that may involve MLValue operands.
- /// When step is not specified, it is set to 1.
- ForStmt *createFor(Attribute *location, ArrayRef<MLValue *> lbOperands,
+ // Creates for statement. When step is not specified, it is set to 1.
+ ForStmt *createFor(Location *location, ArrayRef<MLValue *> lbOperands,
AffineMap *lbMap, ArrayRef<MLValue *> ubOperands,
AffineMap *ubMap, int64_t step = 1);
- /// Create if statement.
- /// TODO: pass operands.
- IfStmt *createIf(Attribute *location, IntegerSet *condition);
+ IfStmt *createIf(Location *location, IntegerSet *condition);
private:
StmtBlock *block = nullptr;
diff --git a/include/mlir/IR/Instructions.h b/include/mlir/IR/Instructions.h
index ad0cb05..1f75241 100644
--- a/include/mlir/IR/Instructions.h
+++ b/include/mlir/IR/Instructions.h
@@ -49,9 +49,8 @@
/// Return the context this operation is associated with.
MLIRContext *getContext() const;
- /// The source location the operation was defined or derived from. Note that
- /// it is possible for this pointer to be null.
- Attribute *getLoc() const { return location; }
+ /// The source location the operation was defined or derived from.
+ Location *getLoc() const { return location; }
/// Return the BasicBlock containing this instruction.
BasicBlock *getBlock() const { return block; }
@@ -138,8 +137,9 @@
void emitNote(const Twine &message) const;
protected:
- Instruction(Kind kind, Attribute *location)
- : kind(kind), location(location) {}
+ Instruction(Kind kind, Location *location) : kind(kind), location(location) {
+ assert(location && "location can never be null");
+ }
// Instructions are deleted through the destroy() member because this class
// does not have a virtual destructor. A vtable would bloat the size of
@@ -153,7 +153,7 @@
/// This holds information about the source location the operation was defined
/// or derived from.
- Attribute *location;
+ Location *location;
friend struct llvm::ilist_traits<OperationInst>;
friend class BasicBlock;
@@ -172,8 +172,8 @@
public llvm::ilist_node_with_parent<OperationInst, BasicBlock>,
private llvm::TrailingObjects<OperationInst, InstOperand, InstResult> {
public:
- /// Create a new OperationInst with the specific fields.
- static OperationInst *create(Attribute *location, Identifier name,
+ /// Create a new OperationInst with the specified fields.
+ static OperationInst *create(Location *location, Identifier name,
ArrayRef<CFGValue *> operands,
ArrayRef<Type *> resultTypes,
ArrayRef<NamedAttribute> attributes,
@@ -312,7 +312,7 @@
private:
const unsigned numOperands, numResults;
- OperationInst(Attribute *location, Identifier name, unsigned numOperands,
+ OperationInst(Location *location, Identifier name, unsigned numOperands,
unsigned numResults, ArrayRef<NamedAttribute> attributes,
MLIRContext *context);
~OperationInst();
@@ -358,8 +358,7 @@
}
protected:
- TerminatorInst(Kind kind, Attribute *location)
- : Instruction(kind, location) {}
+ TerminatorInst(Kind kind, Location *location) : Instruction(kind, location) {}
~TerminatorInst() {}
};
@@ -367,7 +366,7 @@
/// and may pass basic block arguments to the successor.
class BranchInst : public TerminatorInst {
public:
- static BranchInst *create(Attribute *location, BasicBlock *dest,
+ static BranchInst *create(Location *location, BasicBlock *dest,
ArrayRef<CFGValue *> operands = {}) {
return new BranchInst(location, dest, operands);
}
@@ -400,9 +399,8 @@
}
private:
- explicit BranchInst(Attribute *location, BasicBlock *dest,
+ explicit BranchInst(Location *location, BasicBlock *dest,
ArrayRef<CFGValue *> operands);
-
BasicBlockOperand dest;
std::vector<InstOperand> operands;
};
@@ -415,7 +413,7 @@
enum { trueIndex = 0, falseIndex = 1 };
public:
- static CondBranchInst *create(Attribute *location, CFGValue *condition,
+ static CondBranchInst *create(Location *location, CFGValue *condition,
BasicBlock *trueDest, BasicBlock *falseDest) {
return new CondBranchInst(location, condition, trueDest, falseDest);
}
@@ -561,7 +559,7 @@
}
private:
- CondBranchInst(Attribute *location, CFGValue *condition, BasicBlock *trueDest,
+ CondBranchInst(Location *location, CFGValue *condition, BasicBlock *trueDest,
BasicBlock *falseDest);
CFGValue *condition;
@@ -581,7 +579,7 @@
private llvm::TrailingObjects<ReturnInst, InstOperand> {
public:
/// Create a new ReturnInst with the specific fields.
- static ReturnInst *create(Attribute *location, ArrayRef<CFGValue *> operands);
+ static ReturnInst *create(Location *location, ArrayRef<CFGValue *> operands);
unsigned getNumOperands() const { return numOperands; }
@@ -606,7 +604,7 @@
return numOperands;
}
- ReturnInst(Attribute *location, unsigned numOperands);
+ ReturnInst(Location *location, unsigned numOperands);
~ReturnInst();
unsigned numOperands;
diff --git a/include/mlir/IR/Location.h b/include/mlir/IR/Location.h
new file mode 100644
index 0000000..613d0b6
--- /dev/null
+++ b/include/mlir/IR/Location.h
@@ -0,0 +1,137 @@
+//===- Location.h - MLIR Location Classes -----------------------*- C++ -*-===//
+//
+// Copyright 2019 The MLIR Authors.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+// =============================================================================
+//
+// These classes provide the ability to relate MLIR objects back to source
+// location position information.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_IR_LOCATION_H
+#define MLIR_IR_LOCATION_H
+
+#include "mlir/Support/LLVM.h"
+#include "llvm/ADT/StringRef.h"
+
+namespace mlir {
+class MLIRContext;
+
+/// Location objects represent source locations information in MLIR.
+class Location {
+public:
+ enum class Kind {
+ /// This represents an unknown location.
+ Unknown,
+
+ /// This represents a file/line/column location.
+ FileLineCol,
+
+ // Represents a location as a 'void*' pointer to a front-end's opaque
+ // location information, which must live longer than the MLIR objects that
+ // refer to it. OpaqueLocation's are never serialized.
+ //
+ // TODO: OpaqueLocation,
+
+ // Represents a value inlined through a function call.
+ // TODO: InlinedLocation,
+
+ // Represents a value composed of multiple source constructs.
+ // TODO: FusedLocation,
+ };
+
+ /// Return the classification for this location.
+ Kind getKind() const { return kind; }
+
+ /// Print the location.
+ void print(raw_ostream &os) const;
+ void dump() const;
+
+protected:
+ explicit Location(Kind kind) : kind(kind) {}
+ ~Location() {}
+
+private:
+ /// Classification of the subclass, used for type checking.
+ Kind kind : 8;
+
+ Location(const Location &) = delete;
+ void operator=(const Location &) = delete;
+};
+
+inline raw_ostream &operator<<(raw_ostream &os, const Location &loc) {
+ loc.print(os);
+ return os;
+}
+
+/// Represents an unknown location. This is always a singleton for a given
+/// MLIRContext.
+class UnknownLoc : public Location {
+public:
+ static UnknownLoc *get(MLIRContext *context);
+
+private:
+ explicit UnknownLoc() : Location(Kind::Unknown) {}
+};
+
+/// This class is used to represent a uniqued filename in an MLIRContext. It is
+/// a simple wrapper around a const char* to uniqued string memory.
+class UniquedFilename {
+public:
+ /// Unique the specified filename and return a stable pointer owned by the
+ /// specified context. The filename is not allowed to contain embedded ASCII
+ /// nul (\0) characters.
+ static UniquedFilename get(StringRef filename, MLIRContext *context);
+
+ StringRef getRef() const { return string; }
+ const char *data() const { return string; }
+
+private:
+ explicit UniquedFilename(const char *string) : string(string) {}
+ const char *string;
+};
+
+/// Represents a location derived from a file/line/column location. The column
+/// and line may be zero to represent unknown column and/or unknown line/column
+/// information.
+class FileLineColLoc : public Location {
+public:
+ /// Return a uniqued FileLineCol location object.
+ static FileLineColLoc *get(UniquedFilename filename, unsigned line,
+ unsigned column, MLIRContext *context);
+
+ StringRef getFilename() const { return filename.getRef(); }
+
+ unsigned getLine() const { return line; }
+ unsigned getColumn() const { return column; }
+
+ /// Methods for support type inquiry through isa, cast, and dyn_cast.
+ static bool classof(const Location *loc) {
+ return loc->getKind() == Kind::FileLineCol;
+ }
+
+private:
+ FileLineColLoc(UniquedFilename filename, unsigned line, unsigned column)
+ : Location(Kind::FileLineCol), filename(filename), line(line),
+ column(column) {}
+ ~FileLineColLoc() = delete;
+
+ const UniquedFilename filename;
+ const unsigned line, column;
+};
+
+} // end namespace mlir
+
+#endif
diff --git a/include/mlir/IR/MLIRContext.h b/include/mlir/IR/MLIRContext.h
index d782be6..0ea78dd 100644
--- a/include/mlir/IR/MLIRContext.h
+++ b/include/mlir/IR/MLIRContext.h
@@ -24,7 +24,7 @@
namespace mlir {
class MLIRContextImpl;
-class Attribute;
+class Location;
/// MLIRContext is the top-level object for a collection of MLIR modules. It
/// holds immortal uniqued objects like types, and the tables used to unique
@@ -58,7 +58,7 @@
// notes will be dropped and errors will terminate the process with exit(1).
using DiagnosticHandlerTy = std::function<void(
- Attribute *location, StringRef message, DiagnosticKind kind)>;
+ Location *location, StringRef message, DiagnosticKind kind)>;
/// Register a diagnostic handler with this LLVM context. The handler is
/// passed location information if present (nullptr if not) along with a
@@ -71,7 +71,7 @@
/// This emits an 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 emitDiagnostic(Attribute *location, const Twine &message,
+ void emitDiagnostic(Location *location, const Twine &message,
DiagnosticKind kind) const;
private:
diff --git a/include/mlir/IR/Operation.h b/include/mlir/IR/Operation.h
index d5b2b25..f5e3b17 100644
--- a/include/mlir/IR/Operation.h
+++ b/include/mlir/IR/Operation.h
@@ -27,6 +27,7 @@
class Attribute;
class AttributeListStorage;
class AbstractOperation;
+class Location;
template <typename OpType> class ConstOpPointer;
template <typename OpType> class OpPointer;
template <typename ObjectType, typename ElementType> class OperandIterator;
@@ -46,7 +47,7 @@
/// this in a collection.
struct OperationState {
MLIRContext *const context;
- Attribute *location;
+ Location *location;
Identifier name;
SmallVector<SSAValue *, 4> operands;
/// Types of the results of this operation.
@@ -54,14 +55,14 @@
SmallVector<NamedAttribute, 4> attributes;
public:
- OperationState(MLIRContext *context, Attribute *location, StringRef name)
+ OperationState(MLIRContext *context, Location *location, StringRef name)
: context(context), location(location),
name(Identifier::get(name, context)) {}
- OperationState(MLIRContext *context, Attribute *location, Identifier name)
+ OperationState(MLIRContext *context, Location *location, Identifier name)
: context(context), location(location), name(name) {}
- OperationState(MLIRContext *context, Attribute *location, StringRef name,
+ OperationState(MLIRContext *context, Location *location, StringRef name,
ArrayRef<SSAValue *> operands, ArrayRef<Type *> types,
ArrayRef<NamedAttribute> attributes = {})
: context(context), location(location),
@@ -92,9 +93,8 @@
/// Return the context this operation is associated with.
MLIRContext *getContext() const;
- /// The source location the operation was defined or derived from. Note that
- /// it is possible for this pointer to be null.
- Attribute *getLoc() const;
+ /// The source location the operation was defined or derived from.
+ Location *getLoc() const;
/// Return the function this operation is defined in. This has a verbose
/// name to avoid name lookup ambiguities.
diff --git a/include/mlir/IR/Statement.h b/include/mlir/IR/Statement.h
index d6d16e3..55a0aec 100644
--- a/include/mlir/IR/Statement.h
+++ b/include/mlir/IR/Statement.h
@@ -29,7 +29,7 @@
#include "llvm/ADT/ilist_node.h"
namespace mlir {
-class Attribute;
+class Location;
class MLFunction;
class StmtBlock;
class ForStmt;
@@ -52,9 +52,8 @@
/// Return the context this operation is associated with.
MLIRContext *getContext() const;
- /// The source location the operation was defined or derived from. Note that
- /// it is possible for this pointer to be null.
- Attribute *getLoc() const { return location; }
+ /// The source location the operation was defined or derived from.
+ Location *getLoc() const { return location; }
/// Remove this statement from its block and delete it.
void eraseFromBlock();
@@ -156,7 +155,10 @@
void emitNote(const Twine &message) const;
protected:
- Statement(Kind kind, Attribute *location) : kind(kind), location(location) {}
+ Statement(Kind kind, Location *location) : kind(kind), location(location) {
+ assert(location && "location should never be null");
+ }
+
// Statements are deleted through the destroy() member because this class
// does not have a virtual destructor.
~Statement();
@@ -168,7 +170,7 @@
/// This holds information about the source location the operation was defined
/// or derived from.
- Attribute *location;
+ Location *location;
// allow ilist_traits access to 'block' field.
friend struct llvm::ilist_traits<Statement>;
diff --git a/include/mlir/IR/Statements.h b/include/mlir/IR/Statements.h
index 1aa6581..c5af5d5 100644
--- a/include/mlir/IR/Statements.h
+++ b/include/mlir/IR/Statements.h
@@ -40,7 +40,7 @@
private llvm::TrailingObjects<OperationStmt, StmtOperand, StmtResult> {
public:
/// Create a new OperationStmt with the specific fields.
- static OperationStmt *create(Attribute *location, Identifier name,
+ static OperationStmt *create(Location *location, Identifier name,
ArrayRef<MLValue *> operands,
ArrayRef<Type *> resultTypes,
ArrayRef<NamedAttribute> attributes,
@@ -180,7 +180,7 @@
private:
const unsigned numOperands, numResults;
- OperationStmt(Attribute *location, Identifier name, unsigned numOperands,
+ OperationStmt(Location *location, Identifier name, unsigned numOperands,
unsigned numResults, ArrayRef<NamedAttribute> attributes,
MLIRContext *context);
~OperationStmt();
@@ -198,7 +198,7 @@
/// For statement represents an affine loop nest.
class ForStmt : public Statement, public MLValue, public StmtBlock {
public:
- static ForStmt *create(Attribute *location, ArrayRef<MLValue *> lbOperands,
+ static ForStmt *create(Location *location, ArrayRef<MLValue *> lbOperands,
AffineMap *lbMap, ArrayRef<MLValue *> ubOperands,
AffineMap *ubMap, int64_t step, MLIRContext *context);
@@ -336,7 +336,7 @@
// Operands for the lower and upper bounds.
std::vector<StmtOperand> operands;
- explicit ForStmt(Attribute *location, unsigned numOperands, AffineMap *lbMap,
+ explicit ForStmt(Location *location, unsigned numOperands, AffineMap *lbMap,
AffineMap *ubMap, int64_t step, MLIRContext *context);
};
@@ -412,7 +412,7 @@
/// If statement restricts execution to a subset of the loop iteration space.
class IfStmt : public Statement {
public:
- explicit IfStmt(Attribute *location, IntegerSet *condition);
+ explicit IfStmt(Location *location, IntegerSet *condition);
~IfStmt();
IfClause *getThen() const { return thenClause; }