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
This commit is contained in:
parent
a124e9c4a5
commit
adf48e1bd2
@ -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 @@ public:
|
||||
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 @@ public:
|
||||
|
||||
/// 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 @@ public:
|
||||
|
||||
// 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 @@ public:
|
||||
|
||||
/// 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 @@ public:
|
||||
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;
|
||||
|
||||
@ -49,9 +49,8 @@ public:
|
||||
/// 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 @@ public:
|
||||
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 @@ private:
|
||||
|
||||
/// 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 @@ class OperationInst final
|
||||
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 @@ public:
|
||||
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 @@ public:
|
||||
}
|
||||
|
||||
protected:
|
||||
TerminatorInst(Kind kind, Attribute *location)
|
||||
: Instruction(kind, location) {}
|
||||
TerminatorInst(Kind kind, Location *location) : Instruction(kind, location) {}
|
||||
~TerminatorInst() {}
|
||||
};
|
||||
|
||||
@ -367,7 +366,7 @@ protected:
|
||||
/// 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 @@ public:
|
||||
}
|
||||
|
||||
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 @@ class CondBranchInst : public TerminatorInst {
|
||||
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 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
CondBranchInst(Attribute *location, CFGValue *condition, BasicBlock *trueDest,
|
||||
CondBranchInst(Location *location, CFGValue *condition, BasicBlock *trueDest,
|
||||
BasicBlock *falseDest);
|
||||
|
||||
CFGValue *condition;
|
||||
@ -581,7 +579,7 @@ class ReturnInst final
|
||||
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 @@ private:
|
||||
return numOperands;
|
||||
}
|
||||
|
||||
ReturnInst(Attribute *location, unsigned numOperands);
|
||||
ReturnInst(Location *location, unsigned numOperands);
|
||||
~ReturnInst();
|
||||
|
||||
unsigned numOperands;
|
||||
|
||||
137
mlir/include/mlir/IR/Location.h
Normal file
137
mlir/include/mlir/IR/Location.h
Normal file
@ -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
|
||||
@ -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 @@ public:
|
||||
// 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 @@ public:
|
||||
/// 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:
|
||||
|
||||
@ -27,6 +27,7 @@ namespace mlir {
|
||||
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 @@ typedef std::pair<Identifier, Attribute*> NamedAttribute;
|
||||
/// 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 @@ struct OperationState {
|
||||
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 @@ public:
|
||||
/// 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.
|
||||
|
||||
@ -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 @@ public:
|
||||
/// 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 @@ public:
|
||||
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 @@ private:
|
||||
|
||||
/// 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>;
|
||||
|
||||
@ -40,7 +40,7 @@ class OperationStmt final
|
||||
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 @@ public:
|
||||
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 @@ private:
|
||||
/// 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 @@ private:
|
||||
// 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 @@ private:
|
||||
/// 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; }
|
||||
|
||||
@ -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;
|
||||
@ -32,6 +33,21 @@ Identifier Builder::getIdentifier(StringRef str) {
|
||||
|
||||
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 @@ OperationStmt *MLFuncBuilder::createOperation(const OperationState &state) {
|
||||
return op;
|
||||
}
|
||||
|
||||
ForStmt *MLFuncBuilder::createFor(Attribute *location,
|
||||
ForStmt *MLFuncBuilder::createFor(Location *location,
|
||||
ArrayRef<MLValue *> lbOperands,
|
||||
AffineMap *lbMap,
|
||||
ArrayRef<MLValue *> ubOperands,
|
||||
@ -238,7 +254,7 @@ ForStmt *MLFuncBuilder::createFor(Attribute *location,
|
||||
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;
|
||||
|
||||
@ -146,8 +146,8 @@ void Instruction::emitError(const Twine &message) const {
|
||||
// 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 @@ OperationInst *OperationInst::clone() const {
|
||||
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 @@ MutableArrayRef<BasicBlockOperand> TerminatorInst::getBasicBlockOperands() {
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// 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 @@ ReturnInst *ReturnInst::create(Attribute *location,
|
||||
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 @@ ReturnInst::~ReturnInst() {
|
||||
// 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 @@ void BranchInst::addOperands(ArrayRef<CFGValue *> values) {
|
||||
// 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) {
|
||||
|
||||
@ -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 @@ namespace mlir {
|
||||
/// 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 @@ public:
|
||||
DenseMap<const Function *, FunctionAttr *> functionAttrs;
|
||||
|
||||
public:
|
||||
MLIRContextImpl() : identifiers(allocator) {
|
||||
MLIRContextImpl() : filenames(locationAllocator), identifiers(allocator) {
|
||||
registerStandardOperations(operationSet);
|
||||
}
|
||||
|
||||
@ -293,8 +308,7 @@ auto MLIRContext::getDiagnosticHandler() const -> DiagnosticHandlerTy {
|
||||
/// 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 @@ void MLIRContext::emitDiagnostic(Attribute *location,
|
||||
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();
|
||||
@ -337,6 +353,39 @@ Identifier Identifier::get(StringRef str, const MLIRContext *context) {
|
||||
return Identifier(it->getKeyData());
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// 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
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@ -46,7 +46,7 @@ MLIRContext *Operation::getContext() const {
|
||||
|
||||
/// 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();
|
||||
|
||||
@ -209,7 +209,7 @@ void Statement::eraseFromBlock() {
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
/// 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 @@ OperationStmt *OperationStmt::create(Attribute *location, Identifier name,
|
||||
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 @@ bool OperationStmt::isReturn() const { return is<ReturnOp>(); }
|
||||
// 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 @@ ForStmt *ForStmt::create(Attribute *location, ArrayRef<MLValue *> lbOperands,
|
||||
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 @@ void ForStmt::setConstantUpperBound(int64_t value) {
|
||||
// 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) {}
|
||||
|
||||
|
||||
@ -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 @@ using llvm::SourceMgr;
|
||||
/// 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 @@ public:
|
||||
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 @@ private:
|
||||
// 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 @@ public:
|
||||
|
||||
/// 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 @@ private:
|
||||
|
||||
/// 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 @@ SSAValue *FunctionParser::createForwardReferencePlaceholder(SMLoc loc,
|
||||
// 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 @@ Module *mlir::parseSourceFile(llvm::SourceMgr &sourceMgr, MLIRContext *context,
|
||||
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 @@ Module *mlir::parseSourceFile(llvm::SourceMgr &sourceMgr, MLIRContext *context,
|
||||
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.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user