1345 lines
65 KiB
C++
1345 lines
65 KiB
C++
/*===- TableGen'erated file -------------------------------------*- C++ -*-===*\
|
|
|* *|
|
|
|* Interface Declarations *|
|
|
|* *|
|
|
|* Automatically generated file, do not edit! *|
|
|
|* *|
|
|
\*===----------------------------------------------------------------------===*/
|
|
|
|
namespace mlir {
|
|
|
|
/// This interfaces provides support for interacting with operations that
|
|
/// behave like functions. In particular, these operations:
|
|
///
|
|
/// - must be symbols, i.e. have the `Symbol` trait.
|
|
/// - must have a single region, that may be comprised with multiple blocks,
|
|
/// that corresponds to the function body.
|
|
/// * when this region is empty, the operation corresponds to an external
|
|
/// function.
|
|
/// * leading arguments of the first block of the region are treated as
|
|
/// function arguments.
|
|
///
|
|
/// The function, aside from implementing the various interface methods,
|
|
/// should have the following ODS arguments:
|
|
///
|
|
/// - `function_type` (required)
|
|
/// * A TypeAttr that holds the signature type of the function.
|
|
///
|
|
/// - `arg_attrs` (optional)
|
|
/// * An ArrayAttr of DictionaryAttr that contains attribute dictionaries
|
|
/// for each of the function arguments.
|
|
///
|
|
/// - `res_attrs` (optional)
|
|
/// * An ArrayAttr of DictionaryAttr that contains attribute dictionaries
|
|
/// for each of the function results.
|
|
class FunctionOpInterface;
|
|
|
|
} // namespace mlir
|
|
namespace mlir {
|
|
|
|
/// This interfaces provides support for interacting with operations that
|
|
/// behave like functions. In particular, these operations:
|
|
///
|
|
/// - must be symbols, i.e. have the `Symbol` trait.
|
|
/// - must have a single region, that may be comprised with multiple blocks,
|
|
/// that corresponds to the function body.
|
|
/// * when this region is empty, the operation corresponds to an external
|
|
/// function.
|
|
/// * leading arguments of the first block of the region are treated as
|
|
/// function arguments.
|
|
///
|
|
/// The function, aside from implementing the various interface methods,
|
|
/// should have the following ODS arguments:
|
|
///
|
|
/// - `function_type` (required)
|
|
/// * A TypeAttr that holds the signature type of the function.
|
|
///
|
|
/// - `arg_attrs` (optional)
|
|
/// * An ArrayAttr of DictionaryAttr that contains attribute dictionaries
|
|
/// for each of the function arguments.
|
|
///
|
|
/// - `res_attrs` (optional)
|
|
/// * An ArrayAttr of DictionaryAttr that contains attribute dictionaries
|
|
/// for each of the function results.
|
|
namespace detail {
|
|
struct FunctionOpInterfaceInterfaceTraits {
|
|
struct Concept {
|
|
/// The methods defined by the interface.
|
|
::mlir::Type (*getFunctionType)(const Concept *impl, ::mlir::Operation *);
|
|
void (*setFunctionTypeAttr)(const Concept *impl, ::mlir::Operation *, ::mlir::TypeAttr);
|
|
::mlir::Type (*cloneTypeWith)(const Concept *impl, ::mlir::Operation *, ::mlir::TypeRange, ::mlir::TypeRange);
|
|
::llvm::LogicalResult (*verifyBody)(const Concept *impl, ::mlir::Operation *);
|
|
::llvm::LogicalResult (*verifyType)(const Concept *impl, ::mlir::Operation *);
|
|
/// The base classes of this interface.
|
|
const ::mlir::SymbolOpInterface::Concept *implSymbolOpInterface = nullptr;
|
|
const ::mlir::ArgAndResultAttrsOpInterface::Concept *implArgAndResultAttrsOpInterface = nullptr;
|
|
const ::mlir::CallableOpInterface::Concept *implCallableOpInterface = nullptr;
|
|
|
|
void initializeInterfaceConcept(::mlir::detail::InterfaceMap &interfaceMap) {
|
|
implSymbolOpInterface = interfaceMap.lookup<::mlir::SymbolOpInterface>();
|
|
assert(implSymbolOpInterface && "`::mlir::FunctionOpInterface` expected its base interface `::mlir::SymbolOpInterface` to be registered");
|
|
implArgAndResultAttrsOpInterface = interfaceMap.lookup<::mlir::ArgAndResultAttrsOpInterface>();
|
|
assert(implArgAndResultAttrsOpInterface && "`::mlir::FunctionOpInterface` expected its base interface `::mlir::ArgAndResultAttrsOpInterface` to be registered");
|
|
implCallableOpInterface = interfaceMap.lookup<::mlir::CallableOpInterface>();
|
|
assert(implCallableOpInterface && "`::mlir::FunctionOpInterface` expected its base interface `::mlir::CallableOpInterface` to be registered");
|
|
}
|
|
};
|
|
template<typename ConcreteOp>
|
|
class Model : public Concept {
|
|
public:
|
|
using Interface = ::mlir::FunctionOpInterface;
|
|
Model() : Concept{getFunctionType, setFunctionTypeAttr, cloneTypeWith, verifyBody, verifyType} {}
|
|
|
|
static inline ::mlir::Type getFunctionType(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
|
|
static inline void setFunctionTypeAttr(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::TypeAttr type);
|
|
static inline ::mlir::Type cloneTypeWith(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::TypeRange inputs, ::mlir::TypeRange results);
|
|
static inline ::llvm::LogicalResult verifyBody(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
|
|
static inline ::llvm::LogicalResult verifyType(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
|
|
};
|
|
template<typename ConcreteOp>
|
|
class FallbackModel : public Concept {
|
|
public:
|
|
using Interface = ::mlir::FunctionOpInterface;
|
|
FallbackModel() : Concept{getFunctionType, setFunctionTypeAttr, cloneTypeWith, verifyBody, verifyType} {}
|
|
|
|
static inline ::mlir::Type getFunctionType(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
|
|
static inline void setFunctionTypeAttr(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::TypeAttr type);
|
|
static inline ::mlir::Type cloneTypeWith(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::TypeRange inputs, ::mlir::TypeRange results);
|
|
static inline ::llvm::LogicalResult verifyBody(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
|
|
static inline ::llvm::LogicalResult verifyType(const Concept *impl, ::mlir::Operation *tablegen_opaque_val);
|
|
};
|
|
template<typename ConcreteModel, typename ConcreteOp>
|
|
class ExternalModel : public FallbackModel<ConcreteModel> {
|
|
public:
|
|
using ConcreteEntity = ConcreteOp;
|
|
::mlir::Type cloneTypeWith(::mlir::Operation *tablegen_opaque_val, ::mlir::TypeRange inputs, ::mlir::TypeRange results) const;
|
|
::llvm::LogicalResult verifyBody(::mlir::Operation *tablegen_opaque_val) const;
|
|
::llvm::LogicalResult verifyType(::mlir::Operation *tablegen_opaque_val) const;
|
|
};
|
|
};
|
|
template <typename ConcreteOp>
|
|
struct FunctionOpInterfaceTrait;
|
|
|
|
} // namespace detail
|
|
class FunctionOpInterface : public ::mlir::OpInterface<FunctionOpInterface, detail::FunctionOpInterfaceInterfaceTraits> {
|
|
public:
|
|
using ::mlir::OpInterface<FunctionOpInterface, detail::FunctionOpInterfaceInterfaceTraits>::OpInterface;
|
|
template <typename ConcreteOp>
|
|
struct Trait : public detail::FunctionOpInterfaceTrait<ConcreteOp> {};
|
|
|
|
/// Returns the type of the function.
|
|
::mlir::Type getFunctionType();
|
|
|
|
/// Set the type of the function. This method should perform an unsafe
|
|
/// modification to the function type; it should not update argument or
|
|
/// result attributes.
|
|
void setFunctionTypeAttr(::mlir::TypeAttr type);
|
|
|
|
/// Returns a clone of the function type with the given argument and
|
|
/// result types.
|
|
///
|
|
/// Note: The default implementation assumes the function type has
|
|
/// an appropriate clone method:
|
|
/// `Type clone(ArrayRef<Type> inputs, ArrayRef<Type> results)`
|
|
::mlir::Type cloneTypeWith(::mlir::TypeRange inputs, ::mlir::TypeRange results);
|
|
|
|
/// Verify the contents of the body of this function.
|
|
///
|
|
/// Note: The default implementation merely checks that if the entry block
|
|
/// exists, it has the same number and type of arguments as the function type.
|
|
::llvm::LogicalResult verifyBody();
|
|
|
|
/// Verify the type attribute of the function for derived op-specific
|
|
/// invariants.
|
|
::llvm::LogicalResult verifyType();
|
|
|
|
/// Block list iterator types.
|
|
using BlockListType = ::mlir::Region::BlockListType;
|
|
using iterator = BlockListType::iterator;
|
|
using reverse_iterator = BlockListType::reverse_iterator;
|
|
|
|
/// Block argument iterator types.
|
|
using BlockArgListType = ::mlir::Region::BlockArgListType;
|
|
using args_iterator = BlockArgListType::iterator;
|
|
|
|
//===------------------------------------------------------------------===//
|
|
// Body Handling
|
|
//===------------------------------------------------------------------===//
|
|
|
|
/// Returns true if this function is external, i.e. it has no body.
|
|
bool isExternal() { return empty(); }
|
|
|
|
/// Return the region containing the body of this function.
|
|
::mlir::Region &getFunctionBody() { return (*this)->getRegion(0); }
|
|
|
|
/// Delete all blocks from this function.
|
|
void eraseBody() {
|
|
getFunctionBody().dropAllReferences();
|
|
getFunctionBody().getBlocks().clear();
|
|
}
|
|
|
|
/// Return the list of blocks within the function body.
|
|
BlockListType &getBlocks() { return getFunctionBody().getBlocks(); }
|
|
|
|
iterator begin() { return getFunctionBody().begin(); }
|
|
iterator end() { return getFunctionBody().end(); }
|
|
reverse_iterator rbegin() { return getFunctionBody().rbegin(); }
|
|
reverse_iterator rend() { return getFunctionBody().rend(); }
|
|
|
|
/// Returns true if this function has no blocks within the body.
|
|
bool empty() { return getFunctionBody().empty(); }
|
|
|
|
/// Push a new block to the back of the body region.
|
|
void push_back(::mlir::Block *block) { getFunctionBody().push_back(block); }
|
|
|
|
/// Push a new block to the front of the body region.
|
|
void push_front(::mlir::Block *block) { getFunctionBody().push_front(block); }
|
|
|
|
/// Return the last block in the body region.
|
|
::mlir::Block &back() { return getFunctionBody().back(); }
|
|
|
|
/// Return the first block in the body region.
|
|
::mlir::Block &front() { return getFunctionBody().front(); }
|
|
|
|
/// Add an entry block to an empty function, and set up the block arguments
|
|
/// to match the signature of the function. The newly inserted entry block
|
|
/// is returned.
|
|
::mlir::Block *addEntryBlock() {
|
|
assert(empty() && "function already has an entry block");
|
|
::mlir::Block *entry = new ::mlir::Block();
|
|
push_back(entry);
|
|
|
|
// FIXME: Allow for passing in locations for these arguments instead of using
|
|
// the operations location.
|
|
::llvm::ArrayRef<::mlir::Type> inputTypes = (*this).getArgumentTypes();
|
|
::llvm::SmallVector<::mlir::Location> locations(inputTypes.size(),
|
|
(*this).getOperation()->getLoc());
|
|
entry->addArguments(inputTypes, locations);
|
|
return entry;
|
|
}
|
|
|
|
/// Add a normal block to the end of the function's block list. The function
|
|
/// should at least already have an entry block.
|
|
::mlir::Block *addBlock() {
|
|
assert(!empty() && "function should at least have an entry block");
|
|
push_back(new ::mlir::Block());
|
|
return &back();
|
|
}
|
|
|
|
//===------------------------------------------------------------------===//
|
|
// Type Attribute Handling
|
|
//===------------------------------------------------------------------===//
|
|
|
|
/// Change the type of this function in place. This is an extremely dangerous
|
|
/// operation and it is up to the caller to ensure that this is legal for
|
|
/// this function, and to restore invariants:
|
|
/// - the entry block args must be updated to match the function params.
|
|
/// - the argument/result attributes may need an update: if the new type
|
|
/// has less parameters we drop the extra attributes, if there are more
|
|
/// parameters they won't have any attributes.
|
|
void setType(::mlir::Type newType) {
|
|
::mlir::function_interface_impl::setFunctionType((*this), newType);
|
|
}
|
|
|
|
//===------------------------------------------------------------------===//
|
|
// Argument and Result Handling
|
|
//===------------------------------------------------------------------===//
|
|
|
|
/// Returns the number of function arguments.
|
|
unsigned getNumArguments() { return (*this).getArgumentTypes().size(); }
|
|
|
|
/// Returns the number of function results.
|
|
unsigned getNumResults() { return (*this).getResultTypes().size(); }
|
|
|
|
/// Returns the entry block function argument at the given index.
|
|
::mlir::BlockArgument getArgument(unsigned idx) {
|
|
return getFunctionBody().getArgument(idx);
|
|
}
|
|
|
|
/// Support argument iteration.
|
|
args_iterator args_begin() { return getFunctionBody().args_begin(); }
|
|
args_iterator args_end() { return getFunctionBody().args_end(); }
|
|
BlockArgListType getArguments() { return getFunctionBody().getArguments(); }
|
|
|
|
/// Insert a single argument of type `argType` with attributes `argAttrs` and
|
|
/// location `argLoc` at `argIndex`. Returns failure if the function cannot be
|
|
/// updated to have the new signature.
|
|
::llvm::LogicalResult insertArgument(
|
|
unsigned argIndex, ::mlir::Type argType, ::mlir::DictionaryAttr argAttrs,
|
|
::mlir::Location argLoc) {
|
|
return insertArguments({argIndex}, {argType}, {argAttrs}, {argLoc});
|
|
}
|
|
|
|
/// Inserts arguments with the listed types, attributes, and locations at the
|
|
/// listed indices. `argIndices` must be sorted. Arguments are inserted in the
|
|
/// order they are listed, such that arguments with identical index will
|
|
/// appear in the same order that they were listed here. Returns failure if
|
|
/// the function cannot be updated to have the new signature.
|
|
::llvm::LogicalResult insertArguments(
|
|
::llvm::ArrayRef<unsigned> argIndices, ::mlir::TypeRange argTypes,
|
|
::llvm::ArrayRef<::mlir::DictionaryAttr> argAttrs,
|
|
::llvm::ArrayRef<::mlir::Location> argLocs) {
|
|
unsigned originalNumArgs = (*this).getNumArguments();
|
|
::mlir::Type newType = (*this).getTypeWithArgsAndResults(
|
|
argIndices, argTypes, /*resultIndices=*/{}, /*resultTypes=*/{});
|
|
if (!newType)
|
|
return ::llvm::failure();
|
|
::mlir::function_interface_impl::insertFunctionArguments(
|
|
(*this), argIndices, argTypes, argAttrs, argLocs,
|
|
originalNumArgs, newType);
|
|
return ::llvm::success();
|
|
}
|
|
|
|
/// Insert a single result of type `resultType` at `resultIndex`.Returns
|
|
/// failure if the function cannot be updated to have the new signature.
|
|
::llvm::LogicalResult insertResult(
|
|
unsigned resultIndex, ::mlir::Type resultType,
|
|
::mlir::DictionaryAttr resultAttrs) {
|
|
return insertResults({resultIndex}, {resultType}, {resultAttrs});
|
|
}
|
|
|
|
/// Inserts results with the listed types at the listed indices.
|
|
/// `resultIndices` must be sorted. Results are inserted in the order they are
|
|
/// listed, such that results with identical index will appear in the same
|
|
/// order that they were listed here. Returns failure if the function
|
|
/// cannot be updated to have the new signature.
|
|
::llvm::LogicalResult insertResults(
|
|
::llvm::ArrayRef<unsigned> resultIndices,
|
|
::mlir::TypeRange resultTypes,
|
|
::llvm::ArrayRef<::mlir::DictionaryAttr> resultAttrs) {
|
|
unsigned originalNumResults = (*this).getNumResults();
|
|
::mlir::Type newType = (*this).getTypeWithArgsAndResults(
|
|
/*argIndices=*/{}, /*argTypes=*/{}, resultIndices, resultTypes);
|
|
if (!newType)
|
|
return ::llvm::failure();
|
|
::mlir::function_interface_impl::insertFunctionResults(
|
|
(*this), resultIndices, resultTypes, resultAttrs,
|
|
originalNumResults, newType);
|
|
return ::llvm::success();
|
|
}
|
|
|
|
/// Erase a single argument at `argIndex`. Returns failure if the function
|
|
/// cannot be updated to have the new signature.
|
|
::llvm::LogicalResult eraseArgument(unsigned argIndex) {
|
|
::llvm::BitVector argsToErase((*this).getNumArguments());
|
|
argsToErase.set(argIndex);
|
|
return eraseArguments(argsToErase);
|
|
}
|
|
|
|
/// Erases the arguments listed in `argIndices`. Returns failure if the
|
|
/// function cannot be updated to have the new signature.
|
|
::llvm::LogicalResult eraseArguments(const ::llvm::BitVector &argIndices) {
|
|
::mlir::Type newType = (*this).getTypeWithoutArgs(argIndices);
|
|
if (!newType)
|
|
return ::llvm::failure();
|
|
::mlir::function_interface_impl::eraseFunctionArguments(
|
|
(*this), argIndices, newType);
|
|
return ::llvm::success();
|
|
}
|
|
|
|
/// Erase a single result at `resultIndex`. Returns failure if the function
|
|
/// cannot be updated to have the new signature.
|
|
::llvm::LogicalResult eraseResult(unsigned resultIndex) {
|
|
::llvm::BitVector resultsToErase((*this).getNumResults());
|
|
resultsToErase.set(resultIndex);
|
|
return eraseResults(resultsToErase);
|
|
}
|
|
|
|
/// Erases the results listed in `resultIndices`. Returns failure if the
|
|
/// function cannot be updated to have the new signature.
|
|
::llvm::LogicalResult eraseResults(const ::llvm::BitVector &resultIndices) {
|
|
::mlir::Type newType = (*this).getTypeWithoutResults(resultIndices);
|
|
if (!newType)
|
|
return ::llvm::failure();
|
|
::mlir::function_interface_impl::eraseFunctionResults(
|
|
(*this), resultIndices, newType);
|
|
return ::llvm::success();
|
|
}
|
|
|
|
/// Return the type of this function with the specified arguments and
|
|
/// results inserted. This is used to update the function's signature in
|
|
/// the `insertArguments` and `insertResults` methods. The arrays must be
|
|
/// sorted by increasing index. Return nullptr if the updated type would
|
|
/// not be valid.
|
|
::mlir::Type getTypeWithArgsAndResults(
|
|
::llvm::ArrayRef<unsigned> argIndices, ::mlir::TypeRange argTypes,
|
|
::llvm::ArrayRef<unsigned> resultIndices, ::mlir::TypeRange resultTypes) {
|
|
::llvm::SmallVector<::mlir::Type> argStorage, resultStorage;
|
|
::mlir::TypeRange newArgTypes = insertTypesInto(
|
|
(*this).getArgumentTypes(), argIndices, argTypes, argStorage);
|
|
::mlir::TypeRange newResultTypes = insertTypesInto(
|
|
(*this).getResultTypes(), resultIndices, resultTypes, resultStorage);
|
|
return (*this).cloneTypeWith(newArgTypes, newResultTypes);
|
|
}
|
|
|
|
/// Return the type of this function without the specified arguments and
|
|
/// results. This is used to update the function's signature in the
|
|
/// `eraseArguments` and `eraseResults` methods. Return nullptr if the
|
|
/// updated type would not be valid.
|
|
::mlir::Type getTypeWithoutArgsAndResults(
|
|
const ::llvm::BitVector &argIndices, const ::llvm::BitVector &resultIndices) {
|
|
::llvm::SmallVector<::mlir::Type> argStorage, resultStorage;
|
|
::mlir::TypeRange newArgTypes = filterTypesOut(
|
|
(*this).getArgumentTypes(), argIndices, argStorage);
|
|
::mlir::TypeRange newResultTypes = filterTypesOut(
|
|
(*this).getResultTypes(), resultIndices, resultStorage);
|
|
return (*this).cloneTypeWith(newArgTypes, newResultTypes);
|
|
}
|
|
::mlir::Type getTypeWithoutArgs(const ::llvm::BitVector &argIndices) {
|
|
::llvm::SmallVector<::mlir::Type> argStorage;
|
|
::mlir::TypeRange newArgTypes = filterTypesOut(
|
|
(*this).getArgumentTypes(), argIndices, argStorage);
|
|
return (*this).cloneTypeWith(newArgTypes, (*this).getResultTypes());
|
|
}
|
|
::mlir::Type getTypeWithoutResults(const ::llvm::BitVector &resultIndices) {
|
|
::llvm::SmallVector<::mlir::Type> resultStorage;
|
|
::mlir::TypeRange newResultTypes = filterTypesOut(
|
|
(*this).getResultTypes(), resultIndices, resultStorage);
|
|
return (*this).cloneTypeWith((*this).getArgumentTypes(), newResultTypes);
|
|
}
|
|
|
|
//===------------------------------------------------------------------===//
|
|
// Argument Attributes
|
|
//===------------------------------------------------------------------===//
|
|
|
|
/// Return all of the attributes for the argument at 'index'.
|
|
::llvm::ArrayRef<::mlir::NamedAttribute> getArgAttrs(unsigned index) {
|
|
return ::mlir::function_interface_impl::getArgAttrs((*this), index);
|
|
}
|
|
|
|
/// Return an ArrayAttr containing all argument attribute dictionaries of
|
|
/// this function, or nullptr if no arguments have attributes.
|
|
::mlir::ArrayAttr getAllArgAttrs() { return (*this).getArgAttrsAttr(); }
|
|
|
|
/// Return all argument attributes of this function.
|
|
void getAllArgAttrs(::llvm::SmallVectorImpl<::mlir::DictionaryAttr> &result) {
|
|
if (::mlir::ArrayAttr argAttrs = getAllArgAttrs()) {
|
|
auto argAttrRange = argAttrs.template getAsRange<::mlir::DictionaryAttr>();
|
|
result.append(argAttrRange.begin(), argAttrRange.end());
|
|
} else {
|
|
result.append((*this).getNumArguments(),
|
|
::mlir::DictionaryAttr::get(this->getOperation()->getContext()));
|
|
}
|
|
}
|
|
|
|
/// Return the specified attribute, if present, for the argument at 'index',
|
|
/// null otherwise.
|
|
::mlir::Attribute getArgAttr(unsigned index, ::mlir::StringAttr name) {
|
|
auto argDict = getArgAttrDict(index);
|
|
return argDict ? argDict.get(name) : nullptr;
|
|
}
|
|
::mlir::Attribute getArgAttr(unsigned index, ::llvm::StringRef name) {
|
|
auto argDict = getArgAttrDict(index);
|
|
return argDict ? argDict.get(name) : nullptr;
|
|
}
|
|
|
|
template <typename AttrClass>
|
|
AttrClass getArgAttrOfType(unsigned index, ::mlir::StringAttr name) {
|
|
return ::llvm::dyn_cast_or_null<AttrClass>(getArgAttr(index, name));
|
|
}
|
|
template <typename AttrClass>
|
|
AttrClass getArgAttrOfType(unsigned index, ::llvm::StringRef name) {
|
|
return ::llvm::dyn_cast_or_null<AttrClass>(getArgAttr(index, name));
|
|
}
|
|
|
|
/// Set the attributes held by the argument at 'index'.
|
|
void setArgAttrs(unsigned index, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes) {
|
|
::mlir::function_interface_impl::setArgAttrs((*this), index, attributes);
|
|
}
|
|
|
|
/// Set the attributes held by the argument at 'index'. `attributes` may be
|
|
/// null, in which case any existing argument attributes are removed.
|
|
void setArgAttrs(unsigned index, ::mlir::DictionaryAttr attributes) {
|
|
::mlir::function_interface_impl::setArgAttrs((*this), index, attributes);
|
|
}
|
|
void setAllArgAttrs(::llvm::ArrayRef<::mlir::DictionaryAttr> attributes) {
|
|
assert(attributes.size() == (*this).getNumArguments());
|
|
::mlir::function_interface_impl::setAllArgAttrDicts((*this), attributes);
|
|
}
|
|
void setAllArgAttrs(::llvm::ArrayRef<::mlir::Attribute> attributes) {
|
|
assert(attributes.size() == (*this).getNumArguments());
|
|
::mlir::function_interface_impl::setAllArgAttrDicts((*this), attributes);
|
|
}
|
|
void setAllArgAttrs(::mlir::ArrayAttr attributes) {
|
|
assert(attributes.size() == (*this).getNumArguments());
|
|
(*this).setArgAttrsAttr(attributes);
|
|
}
|
|
|
|
/// If the an attribute exists with the specified name, change it to the new
|
|
/// value. Otherwise, add a new attribute with the specified name/value.
|
|
void setArgAttr(unsigned index, ::mlir::StringAttr name, ::mlir::Attribute value) {
|
|
::mlir::function_interface_impl::setArgAttr((*this), index, name, value);
|
|
}
|
|
void setArgAttr(unsigned index, ::llvm::StringRef name, ::mlir::Attribute value) {
|
|
setArgAttr(index,
|
|
::mlir::StringAttr::get(this->getOperation()->getContext(), name),
|
|
value);
|
|
}
|
|
|
|
/// Remove the attribute 'name' from the argument at 'index'. Return the
|
|
/// attribute that was erased, or nullptr if there was no attribute with
|
|
/// such name.
|
|
::mlir::Attribute removeArgAttr(unsigned index, ::mlir::StringAttr name) {
|
|
return ::mlir::function_interface_impl::removeArgAttr((*this), index, name);
|
|
}
|
|
::mlir::Attribute removeArgAttr(unsigned index, ::llvm::StringRef name) {
|
|
return removeArgAttr(
|
|
index, ::mlir::StringAttr::get(this->getOperation()->getContext(), name));
|
|
}
|
|
|
|
//===------------------------------------------------------------------===//
|
|
// Result Attributes
|
|
//===------------------------------------------------------------------===//
|
|
|
|
/// Return all of the attributes for the result at 'index'.
|
|
::llvm::ArrayRef<::mlir::NamedAttribute> getResultAttrs(unsigned index) {
|
|
return ::mlir::function_interface_impl::getResultAttrs((*this), index);
|
|
}
|
|
|
|
/// Return an ArrayAttr containing all result attribute dictionaries of this
|
|
/// function, or nullptr if no results have attributes.
|
|
::mlir::ArrayAttr getAllResultAttrs() {
|
|
auto attrs = (*this).getResAttrsAttr();
|
|
return attrs && !attrs.empty() ? attrs : nullptr;
|
|
}
|
|
|
|
/// Return all result attributes of this function.
|
|
void getAllResultAttrs(::llvm::SmallVectorImpl<::mlir::DictionaryAttr> &result) {
|
|
if (::mlir::ArrayAttr argAttrs = getAllResultAttrs()) {
|
|
auto argAttrRange = argAttrs.template getAsRange<::mlir::DictionaryAttr>();
|
|
result.append(argAttrRange.begin(), argAttrRange.end());
|
|
} else {
|
|
result.append((*this).getNumResults(),
|
|
::mlir::DictionaryAttr::get(this->getOperation()->getContext()));
|
|
}
|
|
}
|
|
|
|
/// Return the specified attribute, if present, for the result at 'index',
|
|
/// null otherwise.
|
|
::mlir::Attribute getResultAttr(unsigned index, ::mlir::StringAttr name) {
|
|
auto argDict = getResultAttrDict(index);
|
|
return argDict ? argDict.get(name) : nullptr;
|
|
}
|
|
::mlir::Attribute getResultAttr(unsigned index, ::llvm::StringRef name) {
|
|
auto argDict = getResultAttrDict(index);
|
|
return argDict ? argDict.get(name) : nullptr;
|
|
}
|
|
|
|
template <typename AttrClass>
|
|
AttrClass getResultAttrOfType(unsigned index, ::mlir::StringAttr name) {
|
|
return ::llvm::dyn_cast_or_null<AttrClass>(getResultAttr(index, name));
|
|
}
|
|
template <typename AttrClass>
|
|
AttrClass getResultAttrOfType(unsigned index, ::llvm::StringRef name) {
|
|
return ::llvm::dyn_cast_or_null<AttrClass>(getResultAttr(index, name));
|
|
}
|
|
|
|
/// Set the attributes held by the result at 'index'.
|
|
void setResultAttrs(unsigned index, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes) {
|
|
::mlir::function_interface_impl::setResultAttrs((*this), index, attributes);
|
|
}
|
|
|
|
/// Set the attributes held by the result at 'index'. `attributes` may be
|
|
/// null, in which case any existing argument attributes are removed.
|
|
void setResultAttrs(unsigned index, ::mlir::DictionaryAttr attributes) {
|
|
::mlir::function_interface_impl::setResultAttrs((*this), index, attributes);
|
|
}
|
|
void setAllResultAttrs(::llvm::ArrayRef<::mlir::DictionaryAttr> attributes) {
|
|
assert(attributes.size() == (*this).getNumResults());
|
|
::mlir::function_interface_impl::setAllResultAttrDicts(
|
|
(*this), attributes);
|
|
}
|
|
void setAllResultAttrs(::llvm::ArrayRef<::mlir::Attribute> attributes) {
|
|
assert(attributes.size() == (*this).getNumResults());
|
|
::mlir::function_interface_impl::setAllResultAttrDicts(
|
|
(*this), attributes);
|
|
}
|
|
void setAllResultAttrs(::mlir::ArrayAttr attributes) {
|
|
assert(attributes.size() == (*this).getNumResults());
|
|
(*this).setResAttrsAttr(attributes);
|
|
}
|
|
|
|
/// If the an attribute exists with the specified name, change it to the new
|
|
/// value. Otherwise, add a new attribute with the specified name/value.
|
|
void setResultAttr(unsigned index, ::mlir::StringAttr name, ::mlir::Attribute value) {
|
|
::mlir::function_interface_impl::setResultAttr((*this), index, name, value);
|
|
}
|
|
void setResultAttr(unsigned index, ::llvm::StringRef name, ::mlir::Attribute value) {
|
|
setResultAttr(index,
|
|
::mlir::StringAttr::get(this->getOperation()->getContext(), name),
|
|
value);
|
|
}
|
|
|
|
/// Remove the attribute 'name' from the result at 'index'. Return the
|
|
/// attribute that was erased, or nullptr if there was no attribute with
|
|
/// such name.
|
|
::mlir::Attribute removeResultAttr(unsigned index, ::mlir::StringAttr name) {
|
|
return ::mlir::function_interface_impl::removeResultAttr((*this), index, name);
|
|
}
|
|
::mlir::Attribute removeResultAttr(unsigned index, ::llvm::StringRef name) {
|
|
return removeResultAttr(
|
|
index, ::mlir::StringAttr::get(this->getOperation()->getContext(), name));
|
|
}
|
|
|
|
/// Returns the dictionary attribute corresponding to the argument at
|
|
/// 'index'. If there are no argument attributes at 'index', a null
|
|
/// attribute is returned.
|
|
::mlir::DictionaryAttr getArgAttrDict(unsigned index) {
|
|
assert(index < (*this).getNumArguments() && "invalid argument number");
|
|
return ::mlir::function_interface_impl::getArgAttrDict((*this), index);
|
|
}
|
|
|
|
/// Returns the dictionary attribute corresponding to the result at 'index'.
|
|
/// If there are no result attributes at 'index', a null attribute is
|
|
/// returned.
|
|
::mlir::DictionaryAttr getResultAttrDict(unsigned index) {
|
|
assert(index < (*this).getNumResults() && "invalid result number");
|
|
return ::mlir::function_interface_impl::getResultAttrDict((*this), index);
|
|
}
|
|
//===----------------------------------------------------------------===//
|
|
// Inherited from ::mlir::SymbolOpInterface
|
|
//===----------------------------------------------------------------===//
|
|
|
|
operator ::mlir::SymbolOpInterface () const {
|
|
if (!*this) return nullptr;
|
|
return ::mlir::SymbolOpInterface(*this, getImpl()->implSymbolOpInterface);
|
|
}
|
|
|
|
|
|
/// Returns the name of this symbol.
|
|
::mlir::StringAttr getNameAttr();
|
|
|
|
/// Sets the name of this symbol.
|
|
void setName(::mlir::StringAttr name);
|
|
|
|
/// Gets the visibility of this symbol.
|
|
mlir::SymbolTable::Visibility getVisibility();
|
|
|
|
/// Returns true if this symbol has nested visibility.
|
|
bool isNested();
|
|
|
|
/// Returns true if this symbol has private visibility.
|
|
bool isPrivate();
|
|
|
|
/// Returns true if this symbol has public visibility.
|
|
bool isPublic();
|
|
|
|
/// Sets the visibility of this symbol.
|
|
void setVisibility(mlir::SymbolTable::Visibility vis);
|
|
|
|
/// Sets the visibility of this symbol to be nested.
|
|
void setNested();
|
|
|
|
/// Sets the visibility of this symbol to be private.
|
|
void setPrivate();
|
|
|
|
/// Sets the visibility of this symbol to be public.
|
|
void setPublic();
|
|
|
|
/// Get all of the uses of the current symbol that are nested within the
|
|
/// given operation 'from'.
|
|
/// Note: See mlir::SymbolTable::getSymbolUses for more details.
|
|
::std::optional<::mlir::SymbolTable::UseRange> getSymbolUses(::mlir::Operation * from);
|
|
|
|
/// Return if the current symbol is known to have no uses that are nested
|
|
/// within the given operation 'from'.
|
|
/// Note: See mlir::SymbolTable::symbolKnownUseEmpty for more details.
|
|
bool symbolKnownUseEmpty(::mlir::Operation * from);
|
|
|
|
/// Attempt to replace all uses of the current symbol with the provided
|
|
/// symbol 'newSymbol' that are nested within the given operation 'from'.
|
|
/// Note: See mlir::SymbolTable::replaceAllSymbolUses for more details.
|
|
::llvm::LogicalResult replaceAllSymbolUses(::mlir::StringAttr newSymbol, ::mlir::Operation * from);
|
|
|
|
/// Returns true if this operation optionally defines a symbol based on the
|
|
/// presence of the symbol name.
|
|
bool isOptionalSymbol();
|
|
|
|
/// Returns true if this operation can be discarded if it has no remaining
|
|
/// symbol uses.
|
|
bool canDiscardOnUseEmpty();
|
|
|
|
/// Returns true if this operation is a declaration of a symbol (as opposed
|
|
/// to a definition).
|
|
bool isDeclaration();
|
|
|
|
using Visibility = mlir::SymbolTable::Visibility;
|
|
|
|
/// Convenience version of `getNameAttr` that returns a StringRef.
|
|
::mlir::StringRef getName() {
|
|
return getNameAttr().getValue();
|
|
}
|
|
|
|
/// Convenience version of `setName` that take a StringRef.
|
|
void setName(::mlir::StringRef name) {
|
|
setName(::mlir::StringAttr::get((*this)->getContext(), name));
|
|
}
|
|
//===----------------------------------------------------------------===//
|
|
// Inherited from ::mlir::ArgAndResultAttrsOpInterface
|
|
//===----------------------------------------------------------------===//
|
|
|
|
operator ::mlir::ArgAndResultAttrsOpInterface () const {
|
|
if (!*this) return nullptr;
|
|
return ::mlir::ArgAndResultAttrsOpInterface(*this, getImpl()->implArgAndResultAttrsOpInterface);
|
|
}
|
|
|
|
|
|
/// Get the array of argument attribute dictionaries. The method should
|
|
/// return an array attribute containing only dictionary attributes equal in
|
|
/// number to the number of arguments. Alternatively, the method can
|
|
/// return null to indicate that there are no argument attributes.
|
|
::mlir::ArrayAttr getArgAttrsAttr();
|
|
|
|
/// Get the array of result attribute dictionaries. The method should return
|
|
/// an array attribute containing only dictionary attributes equal in number
|
|
/// to the number of results. Alternatively, the method can return
|
|
/// null to indicate that there are no result attributes.
|
|
::mlir::ArrayAttr getResAttrsAttr();
|
|
|
|
/// Set the array of argument attribute dictionaries.
|
|
void setArgAttrsAttr(::mlir::ArrayAttr attrs);
|
|
|
|
/// Set the array of result attribute dictionaries.
|
|
void setResAttrsAttr(::mlir::ArrayAttr attrs);
|
|
|
|
/// Remove the array of argument attribute dictionaries. This is the same as
|
|
/// setting all argument attributes to an empty dictionary. The method should
|
|
/// return the removed attribute.
|
|
::mlir::Attribute removeArgAttrsAttr();
|
|
|
|
/// Remove the array of result attribute dictionaries. This is the same as
|
|
/// setting all result attributes to an empty dictionary. The method should
|
|
/// return the removed attribute.
|
|
::mlir::Attribute removeResAttrsAttr();
|
|
//===----------------------------------------------------------------===//
|
|
// Inherited from ::mlir::CallableOpInterface
|
|
//===----------------------------------------------------------------===//
|
|
|
|
operator ::mlir::CallableOpInterface () const {
|
|
if (!*this) return nullptr;
|
|
return ::mlir::CallableOpInterface(*this, getImpl()->implCallableOpInterface);
|
|
}
|
|
|
|
|
|
/// Returns the region on the current operation that is callable. This may
|
|
/// return null in the case of an external callable object, e.g. an external
|
|
/// function.
|
|
::mlir::Region *getCallableRegion();
|
|
|
|
/// Returns the callable's argument types based exclusively on the type (to
|
|
/// allow for this method may be called on function declarations).
|
|
::llvm::ArrayRef<::mlir::Type> getArgumentTypes();
|
|
|
|
/// Returns the callable's result types based exclusively on the type (to
|
|
/// allow for this method may be called on function declarations).
|
|
::llvm::ArrayRef<::mlir::Type> getResultTypes();
|
|
};
|
|
|
|
} // namespace mlir
|
|
namespace mlir::detail {
|
|
|
|
template <typename ConcreteOp>
|
|
struct FunctionOpInterfaceTrait : public ::mlir::OpInterface<FunctionOpInterface, detail::FunctionOpInterfaceInterfaceTraits>::Trait<ConcreteOp> {
|
|
|
|
/// Returns a clone of the function type with the given argument and
|
|
/// result types.
|
|
///
|
|
/// Note: The default implementation assumes the function type has
|
|
/// an appropriate clone method:
|
|
/// `Type clone(ArrayRef<Type> inputs, ArrayRef<Type> results)`
|
|
::mlir::Type cloneTypeWith(::mlir::TypeRange inputs, ::mlir::TypeRange results) {
|
|
return (*static_cast<ConcreteOp *>(this)).getFunctionType().clone(inputs, results);
|
|
}
|
|
|
|
/// Verify the contents of the body of this function.
|
|
///
|
|
/// Note: The default implementation merely checks that if the entry block
|
|
/// exists, it has the same number and type of arguments as the function type.
|
|
::llvm::LogicalResult verifyBody() {
|
|
if ((*static_cast<ConcreteOp *>(this)).isExternal())
|
|
return success();
|
|
ArrayRef<Type> fnInputTypes = (*static_cast<ConcreteOp *>(this)).getArgumentTypes();
|
|
// NOTE: This should just be (*static_cast<ConcreteOp *>(this)).front() but access generically
|
|
// because the interface methods defined here may be shadowed in
|
|
// arbitrary ways. https://github.com/llvm/llvm-project/issues/54807
|
|
Block &entryBlock = (*static_cast<ConcreteOp *>(this))->getRegion(0).front();
|
|
|
|
unsigned numArguments = fnInputTypes.size();
|
|
if (entryBlock.getNumArguments() != numArguments)
|
|
return (*static_cast<ConcreteOp *>(this)).emitOpError("entry block must have ")
|
|
<< numArguments << " arguments to match function signature";
|
|
|
|
for (unsigned i = 0, e = fnInputTypes.size(); i != e; ++i) {
|
|
Type argType = entryBlock.getArgument(i).getType();
|
|
if (fnInputTypes[i] != argType) {
|
|
return (*static_cast<ConcreteOp *>(this)).emitOpError("type of entry block argument #")
|
|
<< i << '(' << argType
|
|
<< ") must match the type of the corresponding argument in "
|
|
<< "function signature(" << fnInputTypes[i] << ')';
|
|
}
|
|
}
|
|
|
|
return success();
|
|
}
|
|
|
|
/// Verify the type attribute of the function for derived op-specific
|
|
/// invariants.
|
|
::llvm::LogicalResult verifyType() {
|
|
return success();
|
|
}
|
|
static ::llvm::LogicalResult verifyTrait(::mlir::Operation *op) {
|
|
return function_interface_impl::verifyTrait(cast<ConcreteOp>(op));
|
|
}
|
|
|
|
//===------------------------------------------------------------------===//
|
|
// Builders
|
|
//===------------------------------------------------------------------===//
|
|
|
|
/// Build the function with the given name, attributes, and type. This
|
|
/// builder also inserts an entry block into the function body with the
|
|
/// given argument types.
|
|
static void buildWithEntryBlock(
|
|
OpBuilder &builder, OperationState &state, StringRef name, Type type,
|
|
ArrayRef<NamedAttribute> attrs, TypeRange inputTypes) {
|
|
OpBuilder::InsertionGuard g(builder);
|
|
state.addAttribute(SymbolTable::getSymbolAttrName(),
|
|
builder.getStringAttr(name));
|
|
state.addAttribute(ConcreteOp::getFunctionTypeAttrName(state.name),
|
|
TypeAttr::get(type));
|
|
state.attributes.append(attrs.begin(), attrs.end());
|
|
|
|
// Add the function body.
|
|
Region *bodyRegion = state.addRegion();
|
|
Block *body = builder.createBlock(bodyRegion);
|
|
for (Type input : inputTypes)
|
|
body->addArgument(input, state.location);
|
|
}
|
|
|
|
|
|
/// Block list iterator types.
|
|
using BlockListType = ::mlir::Region::BlockListType;
|
|
using iterator = BlockListType::iterator;
|
|
using reverse_iterator = BlockListType::reverse_iterator;
|
|
|
|
/// Block argument iterator types.
|
|
using BlockArgListType = ::mlir::Region::BlockArgListType;
|
|
using args_iterator = BlockArgListType::iterator;
|
|
|
|
//===------------------------------------------------------------------===//
|
|
// Body Handling
|
|
//===------------------------------------------------------------------===//
|
|
|
|
/// Returns true if this function is external, i.e. it has no body.
|
|
bool isExternal() { return empty(); }
|
|
|
|
/// Return the region containing the body of this function.
|
|
::mlir::Region &getFunctionBody() { return (*static_cast<ConcreteOp *>(this))->getRegion(0); }
|
|
|
|
/// Delete all blocks from this function.
|
|
void eraseBody() {
|
|
getFunctionBody().dropAllReferences();
|
|
getFunctionBody().getBlocks().clear();
|
|
}
|
|
|
|
/// Return the list of blocks within the function body.
|
|
BlockListType &getBlocks() { return getFunctionBody().getBlocks(); }
|
|
|
|
iterator begin() { return getFunctionBody().begin(); }
|
|
iterator end() { return getFunctionBody().end(); }
|
|
reverse_iterator rbegin() { return getFunctionBody().rbegin(); }
|
|
reverse_iterator rend() { return getFunctionBody().rend(); }
|
|
|
|
/// Returns true if this function has no blocks within the body.
|
|
bool empty() { return getFunctionBody().empty(); }
|
|
|
|
/// Push a new block to the back of the body region.
|
|
void push_back(::mlir::Block *block) { getFunctionBody().push_back(block); }
|
|
|
|
/// Push a new block to the front of the body region.
|
|
void push_front(::mlir::Block *block) { getFunctionBody().push_front(block); }
|
|
|
|
/// Return the last block in the body region.
|
|
::mlir::Block &back() { return getFunctionBody().back(); }
|
|
|
|
/// Return the first block in the body region.
|
|
::mlir::Block &front() { return getFunctionBody().front(); }
|
|
|
|
/// Add an entry block to an empty function, and set up the block arguments
|
|
/// to match the signature of the function. The newly inserted entry block
|
|
/// is returned.
|
|
::mlir::Block *addEntryBlock() {
|
|
assert(empty() && "function already has an entry block");
|
|
::mlir::Block *entry = new ::mlir::Block();
|
|
push_back(entry);
|
|
|
|
// FIXME: Allow for passing in locations for these arguments instead of using
|
|
// the operations location.
|
|
::llvm::ArrayRef<::mlir::Type> inputTypes = (*static_cast<ConcreteOp *>(this)).getArgumentTypes();
|
|
::llvm::SmallVector<::mlir::Location> locations(inputTypes.size(),
|
|
(*static_cast<ConcreteOp *>(this)).getOperation()->getLoc());
|
|
entry->addArguments(inputTypes, locations);
|
|
return entry;
|
|
}
|
|
|
|
/// Add a normal block to the end of the function's block list. The function
|
|
/// should at least already have an entry block.
|
|
::mlir::Block *addBlock() {
|
|
assert(!empty() && "function should at least have an entry block");
|
|
push_back(new ::mlir::Block());
|
|
return &back();
|
|
}
|
|
|
|
//===------------------------------------------------------------------===//
|
|
// Type Attribute Handling
|
|
//===------------------------------------------------------------------===//
|
|
|
|
/// Change the type of this function in place. This is an extremely dangerous
|
|
/// operation and it is up to the caller to ensure that this is legal for
|
|
/// this function, and to restore invariants:
|
|
/// - the entry block args must be updated to match the function params.
|
|
/// - the argument/result attributes may need an update: if the new type
|
|
/// has less parameters we drop the extra attributes, if there are more
|
|
/// parameters they won't have any attributes.
|
|
void setType(::mlir::Type newType) {
|
|
::mlir::function_interface_impl::setFunctionType((*static_cast<ConcreteOp *>(this)), newType);
|
|
}
|
|
|
|
//===------------------------------------------------------------------===//
|
|
// Argument and Result Handling
|
|
//===------------------------------------------------------------------===//
|
|
|
|
/// Returns the number of function arguments.
|
|
unsigned getNumArguments() { return (*static_cast<ConcreteOp *>(this)).getArgumentTypes().size(); }
|
|
|
|
/// Returns the number of function results.
|
|
unsigned getNumResults() { return (*static_cast<ConcreteOp *>(this)).getResultTypes().size(); }
|
|
|
|
/// Returns the entry block function argument at the given index.
|
|
::mlir::BlockArgument getArgument(unsigned idx) {
|
|
return getFunctionBody().getArgument(idx);
|
|
}
|
|
|
|
/// Support argument iteration.
|
|
args_iterator args_begin() { return getFunctionBody().args_begin(); }
|
|
args_iterator args_end() { return getFunctionBody().args_end(); }
|
|
BlockArgListType getArguments() { return getFunctionBody().getArguments(); }
|
|
|
|
/// Insert a single argument of type `argType` with attributes `argAttrs` and
|
|
/// location `argLoc` at `argIndex`. Returns failure if the function cannot be
|
|
/// updated to have the new signature.
|
|
::llvm::LogicalResult insertArgument(
|
|
unsigned argIndex, ::mlir::Type argType, ::mlir::DictionaryAttr argAttrs,
|
|
::mlir::Location argLoc) {
|
|
return insertArguments({argIndex}, {argType}, {argAttrs}, {argLoc});
|
|
}
|
|
|
|
/// Inserts arguments with the listed types, attributes, and locations at the
|
|
/// listed indices. `argIndices` must be sorted. Arguments are inserted in the
|
|
/// order they are listed, such that arguments with identical index will
|
|
/// appear in the same order that they were listed here. Returns failure if
|
|
/// the function cannot be updated to have the new signature.
|
|
::llvm::LogicalResult insertArguments(
|
|
::llvm::ArrayRef<unsigned> argIndices, ::mlir::TypeRange argTypes,
|
|
::llvm::ArrayRef<::mlir::DictionaryAttr> argAttrs,
|
|
::llvm::ArrayRef<::mlir::Location> argLocs) {
|
|
unsigned originalNumArgs = (*static_cast<ConcreteOp *>(this)).getNumArguments();
|
|
::mlir::Type newType = (*static_cast<ConcreteOp *>(this)).getTypeWithArgsAndResults(
|
|
argIndices, argTypes, /*resultIndices=*/{}, /*resultTypes=*/{});
|
|
if (!newType)
|
|
return ::llvm::failure();
|
|
::mlir::function_interface_impl::insertFunctionArguments(
|
|
(*static_cast<ConcreteOp *>(this)), argIndices, argTypes, argAttrs, argLocs,
|
|
originalNumArgs, newType);
|
|
return ::llvm::success();
|
|
}
|
|
|
|
/// Insert a single result of type `resultType` at `resultIndex`.Returns
|
|
/// failure if the function cannot be updated to have the new signature.
|
|
::llvm::LogicalResult insertResult(
|
|
unsigned resultIndex, ::mlir::Type resultType,
|
|
::mlir::DictionaryAttr resultAttrs) {
|
|
return insertResults({resultIndex}, {resultType}, {resultAttrs});
|
|
}
|
|
|
|
/// Inserts results with the listed types at the listed indices.
|
|
/// `resultIndices` must be sorted. Results are inserted in the order they are
|
|
/// listed, such that results with identical index will appear in the same
|
|
/// order that they were listed here. Returns failure if the function
|
|
/// cannot be updated to have the new signature.
|
|
::llvm::LogicalResult insertResults(
|
|
::llvm::ArrayRef<unsigned> resultIndices,
|
|
::mlir::TypeRange resultTypes,
|
|
::llvm::ArrayRef<::mlir::DictionaryAttr> resultAttrs) {
|
|
unsigned originalNumResults = (*static_cast<ConcreteOp *>(this)).getNumResults();
|
|
::mlir::Type newType = (*static_cast<ConcreteOp *>(this)).getTypeWithArgsAndResults(
|
|
/*argIndices=*/{}, /*argTypes=*/{}, resultIndices, resultTypes);
|
|
if (!newType)
|
|
return ::llvm::failure();
|
|
::mlir::function_interface_impl::insertFunctionResults(
|
|
(*static_cast<ConcreteOp *>(this)), resultIndices, resultTypes, resultAttrs,
|
|
originalNumResults, newType);
|
|
return ::llvm::success();
|
|
}
|
|
|
|
/// Erase a single argument at `argIndex`. Returns failure if the function
|
|
/// cannot be updated to have the new signature.
|
|
::llvm::LogicalResult eraseArgument(unsigned argIndex) {
|
|
::llvm::BitVector argsToErase((*static_cast<ConcreteOp *>(this)).getNumArguments());
|
|
argsToErase.set(argIndex);
|
|
return eraseArguments(argsToErase);
|
|
}
|
|
|
|
/// Erases the arguments listed in `argIndices`. Returns failure if the
|
|
/// function cannot be updated to have the new signature.
|
|
::llvm::LogicalResult eraseArguments(const ::llvm::BitVector &argIndices) {
|
|
::mlir::Type newType = (*static_cast<ConcreteOp *>(this)).getTypeWithoutArgs(argIndices);
|
|
if (!newType)
|
|
return ::llvm::failure();
|
|
::mlir::function_interface_impl::eraseFunctionArguments(
|
|
(*static_cast<ConcreteOp *>(this)), argIndices, newType);
|
|
return ::llvm::success();
|
|
}
|
|
|
|
/// Erase a single result at `resultIndex`. Returns failure if the function
|
|
/// cannot be updated to have the new signature.
|
|
::llvm::LogicalResult eraseResult(unsigned resultIndex) {
|
|
::llvm::BitVector resultsToErase((*static_cast<ConcreteOp *>(this)).getNumResults());
|
|
resultsToErase.set(resultIndex);
|
|
return eraseResults(resultsToErase);
|
|
}
|
|
|
|
/// Erases the results listed in `resultIndices`. Returns failure if the
|
|
/// function cannot be updated to have the new signature.
|
|
::llvm::LogicalResult eraseResults(const ::llvm::BitVector &resultIndices) {
|
|
::mlir::Type newType = (*static_cast<ConcreteOp *>(this)).getTypeWithoutResults(resultIndices);
|
|
if (!newType)
|
|
return ::llvm::failure();
|
|
::mlir::function_interface_impl::eraseFunctionResults(
|
|
(*static_cast<ConcreteOp *>(this)), resultIndices, newType);
|
|
return ::llvm::success();
|
|
}
|
|
|
|
/// Return the type of this function with the specified arguments and
|
|
/// results inserted. This is used to update the function's signature in
|
|
/// the `insertArguments` and `insertResults` methods. The arrays must be
|
|
/// sorted by increasing index. Return nullptr if the updated type would
|
|
/// not be valid.
|
|
::mlir::Type getTypeWithArgsAndResults(
|
|
::llvm::ArrayRef<unsigned> argIndices, ::mlir::TypeRange argTypes,
|
|
::llvm::ArrayRef<unsigned> resultIndices, ::mlir::TypeRange resultTypes) {
|
|
::llvm::SmallVector<::mlir::Type> argStorage, resultStorage;
|
|
::mlir::TypeRange newArgTypes = insertTypesInto(
|
|
(*static_cast<ConcreteOp *>(this)).getArgumentTypes(), argIndices, argTypes, argStorage);
|
|
::mlir::TypeRange newResultTypes = insertTypesInto(
|
|
(*static_cast<ConcreteOp *>(this)).getResultTypes(), resultIndices, resultTypes, resultStorage);
|
|
return (*static_cast<ConcreteOp *>(this)).cloneTypeWith(newArgTypes, newResultTypes);
|
|
}
|
|
|
|
/// Return the type of this function without the specified arguments and
|
|
/// results. This is used to update the function's signature in the
|
|
/// `eraseArguments` and `eraseResults` methods. Return nullptr if the
|
|
/// updated type would not be valid.
|
|
::mlir::Type getTypeWithoutArgsAndResults(
|
|
const ::llvm::BitVector &argIndices, const ::llvm::BitVector &resultIndices) {
|
|
::llvm::SmallVector<::mlir::Type> argStorage, resultStorage;
|
|
::mlir::TypeRange newArgTypes = filterTypesOut(
|
|
(*static_cast<ConcreteOp *>(this)).getArgumentTypes(), argIndices, argStorage);
|
|
::mlir::TypeRange newResultTypes = filterTypesOut(
|
|
(*static_cast<ConcreteOp *>(this)).getResultTypes(), resultIndices, resultStorage);
|
|
return (*static_cast<ConcreteOp *>(this)).cloneTypeWith(newArgTypes, newResultTypes);
|
|
}
|
|
::mlir::Type getTypeWithoutArgs(const ::llvm::BitVector &argIndices) {
|
|
::llvm::SmallVector<::mlir::Type> argStorage;
|
|
::mlir::TypeRange newArgTypes = filterTypesOut(
|
|
(*static_cast<ConcreteOp *>(this)).getArgumentTypes(), argIndices, argStorage);
|
|
return (*static_cast<ConcreteOp *>(this)).cloneTypeWith(newArgTypes, (*static_cast<ConcreteOp *>(this)).getResultTypes());
|
|
}
|
|
::mlir::Type getTypeWithoutResults(const ::llvm::BitVector &resultIndices) {
|
|
::llvm::SmallVector<::mlir::Type> resultStorage;
|
|
::mlir::TypeRange newResultTypes = filterTypesOut(
|
|
(*static_cast<ConcreteOp *>(this)).getResultTypes(), resultIndices, resultStorage);
|
|
return (*static_cast<ConcreteOp *>(this)).cloneTypeWith((*static_cast<ConcreteOp *>(this)).getArgumentTypes(), newResultTypes);
|
|
}
|
|
|
|
//===------------------------------------------------------------------===//
|
|
// Argument Attributes
|
|
//===------------------------------------------------------------------===//
|
|
|
|
/// Return all of the attributes for the argument at 'index'.
|
|
::llvm::ArrayRef<::mlir::NamedAttribute> getArgAttrs(unsigned index) {
|
|
return ::mlir::function_interface_impl::getArgAttrs((*static_cast<ConcreteOp *>(this)), index);
|
|
}
|
|
|
|
/// Return an ArrayAttr containing all argument attribute dictionaries of
|
|
/// this function, or nullptr if no arguments have attributes.
|
|
::mlir::ArrayAttr getAllArgAttrs() { return (*static_cast<ConcreteOp *>(this)).getArgAttrsAttr(); }
|
|
|
|
/// Return all argument attributes of this function.
|
|
void getAllArgAttrs(::llvm::SmallVectorImpl<::mlir::DictionaryAttr> &result) {
|
|
if (::mlir::ArrayAttr argAttrs = getAllArgAttrs()) {
|
|
auto argAttrRange = argAttrs.template getAsRange<::mlir::DictionaryAttr>();
|
|
result.append(argAttrRange.begin(), argAttrRange.end());
|
|
} else {
|
|
result.append((*static_cast<ConcreteOp *>(this)).getNumArguments(),
|
|
::mlir::DictionaryAttr::get(this->getOperation()->getContext()));
|
|
}
|
|
}
|
|
|
|
/// Return the specified attribute, if present, for the argument at 'index',
|
|
/// null otherwise.
|
|
::mlir::Attribute getArgAttr(unsigned index, ::mlir::StringAttr name) {
|
|
auto argDict = getArgAttrDict(index);
|
|
return argDict ? argDict.get(name) : nullptr;
|
|
}
|
|
::mlir::Attribute getArgAttr(unsigned index, ::llvm::StringRef name) {
|
|
auto argDict = getArgAttrDict(index);
|
|
return argDict ? argDict.get(name) : nullptr;
|
|
}
|
|
|
|
template <typename AttrClass>
|
|
AttrClass getArgAttrOfType(unsigned index, ::mlir::StringAttr name) {
|
|
return ::llvm::dyn_cast_or_null<AttrClass>(getArgAttr(index, name));
|
|
}
|
|
template <typename AttrClass>
|
|
AttrClass getArgAttrOfType(unsigned index, ::llvm::StringRef name) {
|
|
return ::llvm::dyn_cast_or_null<AttrClass>(getArgAttr(index, name));
|
|
}
|
|
|
|
/// Set the attributes held by the argument at 'index'.
|
|
void setArgAttrs(unsigned index, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes) {
|
|
::mlir::function_interface_impl::setArgAttrs((*static_cast<ConcreteOp *>(this)), index, attributes);
|
|
}
|
|
|
|
/// Set the attributes held by the argument at 'index'. `attributes` may be
|
|
/// null, in which case any existing argument attributes are removed.
|
|
void setArgAttrs(unsigned index, ::mlir::DictionaryAttr attributes) {
|
|
::mlir::function_interface_impl::setArgAttrs((*static_cast<ConcreteOp *>(this)), index, attributes);
|
|
}
|
|
void setAllArgAttrs(::llvm::ArrayRef<::mlir::DictionaryAttr> attributes) {
|
|
assert(attributes.size() == (*static_cast<ConcreteOp *>(this)).getNumArguments());
|
|
::mlir::function_interface_impl::setAllArgAttrDicts((*static_cast<ConcreteOp *>(this)), attributes);
|
|
}
|
|
void setAllArgAttrs(::llvm::ArrayRef<::mlir::Attribute> attributes) {
|
|
assert(attributes.size() == (*static_cast<ConcreteOp *>(this)).getNumArguments());
|
|
::mlir::function_interface_impl::setAllArgAttrDicts((*static_cast<ConcreteOp *>(this)), attributes);
|
|
}
|
|
void setAllArgAttrs(::mlir::ArrayAttr attributes) {
|
|
assert(attributes.size() == (*static_cast<ConcreteOp *>(this)).getNumArguments());
|
|
(*static_cast<ConcreteOp *>(this)).setArgAttrsAttr(attributes);
|
|
}
|
|
|
|
/// If the an attribute exists with the specified name, change it to the new
|
|
/// value. Otherwise, add a new attribute with the specified name/value.
|
|
void setArgAttr(unsigned index, ::mlir::StringAttr name, ::mlir::Attribute value) {
|
|
::mlir::function_interface_impl::setArgAttr((*static_cast<ConcreteOp *>(this)), index, name, value);
|
|
}
|
|
void setArgAttr(unsigned index, ::llvm::StringRef name, ::mlir::Attribute value) {
|
|
setArgAttr(index,
|
|
::mlir::StringAttr::get(this->getOperation()->getContext(), name),
|
|
value);
|
|
}
|
|
|
|
/// Remove the attribute 'name' from the argument at 'index'. Return the
|
|
/// attribute that was erased, or nullptr if there was no attribute with
|
|
/// such name.
|
|
::mlir::Attribute removeArgAttr(unsigned index, ::mlir::StringAttr name) {
|
|
return ::mlir::function_interface_impl::removeArgAttr((*static_cast<ConcreteOp *>(this)), index, name);
|
|
}
|
|
::mlir::Attribute removeArgAttr(unsigned index, ::llvm::StringRef name) {
|
|
return removeArgAttr(
|
|
index, ::mlir::StringAttr::get(this->getOperation()->getContext(), name));
|
|
}
|
|
|
|
//===------------------------------------------------------------------===//
|
|
// Result Attributes
|
|
//===------------------------------------------------------------------===//
|
|
|
|
/// Return all of the attributes for the result at 'index'.
|
|
::llvm::ArrayRef<::mlir::NamedAttribute> getResultAttrs(unsigned index) {
|
|
return ::mlir::function_interface_impl::getResultAttrs((*static_cast<ConcreteOp *>(this)), index);
|
|
}
|
|
|
|
/// Return an ArrayAttr containing all result attribute dictionaries of this
|
|
/// function, or nullptr if no results have attributes.
|
|
::mlir::ArrayAttr getAllResultAttrs() {
|
|
auto attrs = (*static_cast<ConcreteOp *>(this)).getResAttrsAttr();
|
|
return attrs && !attrs.empty() ? attrs : nullptr;
|
|
}
|
|
|
|
/// Return all result attributes of this function.
|
|
void getAllResultAttrs(::llvm::SmallVectorImpl<::mlir::DictionaryAttr> &result) {
|
|
if (::mlir::ArrayAttr argAttrs = getAllResultAttrs()) {
|
|
auto argAttrRange = argAttrs.template getAsRange<::mlir::DictionaryAttr>();
|
|
result.append(argAttrRange.begin(), argAttrRange.end());
|
|
} else {
|
|
result.append((*static_cast<ConcreteOp *>(this)).getNumResults(),
|
|
::mlir::DictionaryAttr::get(this->getOperation()->getContext()));
|
|
}
|
|
}
|
|
|
|
/// Return the specified attribute, if present, for the result at 'index',
|
|
/// null otherwise.
|
|
::mlir::Attribute getResultAttr(unsigned index, ::mlir::StringAttr name) {
|
|
auto argDict = getResultAttrDict(index);
|
|
return argDict ? argDict.get(name) : nullptr;
|
|
}
|
|
::mlir::Attribute getResultAttr(unsigned index, ::llvm::StringRef name) {
|
|
auto argDict = getResultAttrDict(index);
|
|
return argDict ? argDict.get(name) : nullptr;
|
|
}
|
|
|
|
template <typename AttrClass>
|
|
AttrClass getResultAttrOfType(unsigned index, ::mlir::StringAttr name) {
|
|
return ::llvm::dyn_cast_or_null<AttrClass>(getResultAttr(index, name));
|
|
}
|
|
template <typename AttrClass>
|
|
AttrClass getResultAttrOfType(unsigned index, ::llvm::StringRef name) {
|
|
return ::llvm::dyn_cast_or_null<AttrClass>(getResultAttr(index, name));
|
|
}
|
|
|
|
/// Set the attributes held by the result at 'index'.
|
|
void setResultAttrs(unsigned index, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes) {
|
|
::mlir::function_interface_impl::setResultAttrs((*static_cast<ConcreteOp *>(this)), index, attributes);
|
|
}
|
|
|
|
/// Set the attributes held by the result at 'index'. `attributes` may be
|
|
/// null, in which case any existing argument attributes are removed.
|
|
void setResultAttrs(unsigned index, ::mlir::DictionaryAttr attributes) {
|
|
::mlir::function_interface_impl::setResultAttrs((*static_cast<ConcreteOp *>(this)), index, attributes);
|
|
}
|
|
void setAllResultAttrs(::llvm::ArrayRef<::mlir::DictionaryAttr> attributes) {
|
|
assert(attributes.size() == (*static_cast<ConcreteOp *>(this)).getNumResults());
|
|
::mlir::function_interface_impl::setAllResultAttrDicts(
|
|
(*static_cast<ConcreteOp *>(this)), attributes);
|
|
}
|
|
void setAllResultAttrs(::llvm::ArrayRef<::mlir::Attribute> attributes) {
|
|
assert(attributes.size() == (*static_cast<ConcreteOp *>(this)).getNumResults());
|
|
::mlir::function_interface_impl::setAllResultAttrDicts(
|
|
(*static_cast<ConcreteOp *>(this)), attributes);
|
|
}
|
|
void setAllResultAttrs(::mlir::ArrayAttr attributes) {
|
|
assert(attributes.size() == (*static_cast<ConcreteOp *>(this)).getNumResults());
|
|
(*static_cast<ConcreteOp *>(this)).setResAttrsAttr(attributes);
|
|
}
|
|
|
|
/// If the an attribute exists with the specified name, change it to the new
|
|
/// value. Otherwise, add a new attribute with the specified name/value.
|
|
void setResultAttr(unsigned index, ::mlir::StringAttr name, ::mlir::Attribute value) {
|
|
::mlir::function_interface_impl::setResultAttr((*static_cast<ConcreteOp *>(this)), index, name, value);
|
|
}
|
|
void setResultAttr(unsigned index, ::llvm::StringRef name, ::mlir::Attribute value) {
|
|
setResultAttr(index,
|
|
::mlir::StringAttr::get(this->getOperation()->getContext(), name),
|
|
value);
|
|
}
|
|
|
|
/// Remove the attribute 'name' from the result at 'index'. Return the
|
|
/// attribute that was erased, or nullptr if there was no attribute with
|
|
/// such name.
|
|
::mlir::Attribute removeResultAttr(unsigned index, ::mlir::StringAttr name) {
|
|
return ::mlir::function_interface_impl::removeResultAttr((*static_cast<ConcreteOp *>(this)), index, name);
|
|
}
|
|
::mlir::Attribute removeResultAttr(unsigned index, ::llvm::StringRef name) {
|
|
return removeResultAttr(
|
|
index, ::mlir::StringAttr::get(this->getOperation()->getContext(), name));
|
|
}
|
|
|
|
/// Returns the dictionary attribute corresponding to the argument at
|
|
/// 'index'. If there are no argument attributes at 'index', a null
|
|
/// attribute is returned.
|
|
::mlir::DictionaryAttr getArgAttrDict(unsigned index) {
|
|
assert(index < (*static_cast<ConcreteOp *>(this)).getNumArguments() && "invalid argument number");
|
|
return ::mlir::function_interface_impl::getArgAttrDict((*static_cast<ConcreteOp *>(this)), index);
|
|
}
|
|
|
|
/// Returns the dictionary attribute corresponding to the result at 'index'.
|
|
/// If there are no result attributes at 'index', a null attribute is
|
|
/// returned.
|
|
::mlir::DictionaryAttr getResultAttrDict(unsigned index) {
|
|
assert(index < (*static_cast<ConcreteOp *>(this)).getNumResults() && "invalid result number");
|
|
return ::mlir::function_interface_impl::getResultAttrDict((*static_cast<ConcreteOp *>(this)), index);
|
|
}
|
|
|
|
};
|
|
|
|
} // namespace mlir::detail
|
|
namespace mlir {
|
|
|
|
template<typename ConcreteOp>
|
|
::mlir::Type detail::FunctionOpInterfaceInterfaceTraits::Model<ConcreteOp>::getFunctionType(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
|
|
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).getFunctionType();
|
|
}
|
|
template<typename ConcreteOp>
|
|
void detail::FunctionOpInterfaceInterfaceTraits::Model<ConcreteOp>::setFunctionTypeAttr(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::TypeAttr type) {
|
|
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).setFunctionTypeAttr(type);
|
|
}
|
|
template<typename ConcreteOp>
|
|
::mlir::Type detail::FunctionOpInterfaceInterfaceTraits::Model<ConcreteOp>::cloneTypeWith(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::TypeRange inputs, ::mlir::TypeRange results) {
|
|
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).cloneTypeWith(inputs, results);
|
|
}
|
|
template<typename ConcreteOp>
|
|
::llvm::LogicalResult detail::FunctionOpInterfaceInterfaceTraits::Model<ConcreteOp>::verifyBody(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
|
|
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).verifyBody();
|
|
}
|
|
template<typename ConcreteOp>
|
|
::llvm::LogicalResult detail::FunctionOpInterfaceInterfaceTraits::Model<ConcreteOp>::verifyType(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
|
|
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).verifyType();
|
|
}
|
|
template<typename ConcreteOp>
|
|
::mlir::Type detail::FunctionOpInterfaceInterfaceTraits::FallbackModel<ConcreteOp>::getFunctionType(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
|
|
return static_cast<const ConcreteOp *>(impl)->getFunctionType(tablegen_opaque_val);
|
|
}
|
|
template<typename ConcreteOp>
|
|
void detail::FunctionOpInterfaceInterfaceTraits::FallbackModel<ConcreteOp>::setFunctionTypeAttr(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::TypeAttr type) {
|
|
return static_cast<const ConcreteOp *>(impl)->setFunctionTypeAttr(tablegen_opaque_val, type);
|
|
}
|
|
template<typename ConcreteOp>
|
|
::mlir::Type detail::FunctionOpInterfaceInterfaceTraits::FallbackModel<ConcreteOp>::cloneTypeWith(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, ::mlir::TypeRange inputs, ::mlir::TypeRange results) {
|
|
return static_cast<const ConcreteOp *>(impl)->cloneTypeWith(tablegen_opaque_val, inputs, results);
|
|
}
|
|
template<typename ConcreteOp>
|
|
::llvm::LogicalResult detail::FunctionOpInterfaceInterfaceTraits::FallbackModel<ConcreteOp>::verifyBody(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
|
|
return static_cast<const ConcreteOp *>(impl)->verifyBody(tablegen_opaque_val);
|
|
}
|
|
template<typename ConcreteOp>
|
|
::llvm::LogicalResult detail::FunctionOpInterfaceInterfaceTraits::FallbackModel<ConcreteOp>::verifyType(const Concept *impl, ::mlir::Operation *tablegen_opaque_val) {
|
|
return static_cast<const ConcreteOp *>(impl)->verifyType(tablegen_opaque_val);
|
|
}
|
|
template<typename ConcreteModel, typename ConcreteOp>
|
|
::mlir::Type detail::FunctionOpInterfaceInterfaceTraits::ExternalModel<ConcreteModel, ConcreteOp>::cloneTypeWith(::mlir::Operation *tablegen_opaque_val, ::mlir::TypeRange inputs, ::mlir::TypeRange results) const {
|
|
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).getFunctionType().clone(inputs, results);
|
|
}
|
|
template<typename ConcreteModel, typename ConcreteOp>
|
|
::llvm::LogicalResult detail::FunctionOpInterfaceInterfaceTraits::ExternalModel<ConcreteModel, ConcreteOp>::verifyBody(::mlir::Operation *tablegen_opaque_val) const {
|
|
if ((llvm::cast<ConcreteOp>(tablegen_opaque_val)).isExternal())
|
|
return success();
|
|
ArrayRef<Type> fnInputTypes = (llvm::cast<ConcreteOp>(tablegen_opaque_val)).getArgumentTypes();
|
|
// NOTE: This should just be (llvm::cast<ConcreteOp>(tablegen_opaque_val)).front() but access generically
|
|
// because the interface methods defined here may be shadowed in
|
|
// arbitrary ways. https://github.com/llvm/llvm-project/issues/54807
|
|
Block &entryBlock = (llvm::cast<ConcreteOp>(tablegen_opaque_val))->getRegion(0).front();
|
|
|
|
unsigned numArguments = fnInputTypes.size();
|
|
if (entryBlock.getNumArguments() != numArguments)
|
|
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).emitOpError("entry block must have ")
|
|
<< numArguments << " arguments to match function signature";
|
|
|
|
for (unsigned i = 0, e = fnInputTypes.size(); i != e; ++i) {
|
|
Type argType = entryBlock.getArgument(i).getType();
|
|
if (fnInputTypes[i] != argType) {
|
|
return (llvm::cast<ConcreteOp>(tablegen_opaque_val)).emitOpError("type of entry block argument #")
|
|
<< i << '(' << argType
|
|
<< ") must match the type of the corresponding argument in "
|
|
<< "function signature(" << fnInputTypes[i] << ')';
|
|
}
|
|
}
|
|
|
|
return success();
|
|
}
|
|
template<typename ConcreteModel, typename ConcreteOp>
|
|
::llvm::LogicalResult detail::FunctionOpInterfaceInterfaceTraits::ExternalModel<ConcreteModel, ConcreteOp>::verifyType(::mlir::Operation *tablegen_opaque_val) const {
|
|
return success();
|
|
}
|
|
|
|
} // namespace mlir
|