blob: 5323b352a898db23f331afcb36d5c84d044048e3 [file] [log] [blame]
//===- Function.h - MLIR Function Class -------------------------*- C++ -*-===//
//
// Part of the MLIR Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Functions are the basic unit of composition in MLIR.
//
//===----------------------------------------------------------------------===//
#ifndef MLIR_IR_FUNCTION_H
#define MLIR_IR_FUNCTION_H
#include "mlir/Analysis/CallInterfaces.h"
#include "mlir/IR/Block.h"
#include "mlir/IR/FunctionSupport.h"
#include "mlir/IR/OpDefinition.h"
#include "mlir/IR/SymbolTable.h"
namespace mlir {
//===--------------------------------------------------------------------===//
// Function Operation.
//===--------------------------------------------------------------------===//
/// FuncOp represents a function, or an operation containing one region that
/// forms a CFG(Control Flow Graph). The region of a function is not allowed to
/// implicitly capture global values, and all external references must use
/// Function arguments or attributes that establish a symbolic connection(e.g.
/// symbols referenced by name via a string attribute).
class FuncOp : public Op<FuncOp, OpTrait::ZeroOperands, OpTrait::ZeroResult,
OpTrait::IsIsolatedFromAbove, OpTrait::Symbol,
OpTrait::FunctionLike, CallableOpInterface::Trait> {
public:
using Op::Op;
using Op::print;
static StringRef getOperationName() { return "func"; }
static FuncOp create(Location location, StringRef name, FunctionType type,
ArrayRef<NamedAttribute> attrs = {});
static FuncOp create(Location location, StringRef name, FunctionType type,
iterator_range<dialect_attr_iterator> attrs);
static FuncOp create(Location location, StringRef name, FunctionType type,
ArrayRef<NamedAttribute> attrs,
ArrayRef<NamedAttributeList> argAttrs);
static void build(Builder *builder, OperationState &result, StringRef name,
FunctionType type, ArrayRef<NamedAttribute> attrs);
static void build(Builder *builder, OperationState &result, StringRef name,
FunctionType type, ArrayRef<NamedAttribute> attrs,
ArrayRef<NamedAttributeList> argAttrs);
/// Operation hooks.
static ParseResult parse(OpAsmParser &parser, OperationState &result);
void print(OpAsmPrinter &p);
LogicalResult verify();
/// Erase a single argument at `argIndex`.
void eraseArgument(unsigned argIndex) { eraseArguments({argIndex}); }
/// Erases the arguments listed in `argIndices`.
/// `argIndices` is allowed to have duplicates and can be in any order.
void eraseArguments(ArrayRef<unsigned> argIndices);
/// Returns the type of this function.
FunctionType getType() {
return getAttrOfType<TypeAttr>(getTypeAttrName())
.getValue()
.cast<FunctionType>();
}
/// 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(FunctionType newType) {
SmallVector<char, 16> nameBuf;
auto oldType = getType();
for (int i = newType.getNumInputs(), e = oldType.getNumInputs(); i < e;
i++) {
removeAttr(getArgAttrName(i, nameBuf));
}
for (int i = newType.getNumResults(), e = oldType.getNumResults(); i < e;
i++) {
removeAttr(getResultAttrName(i, nameBuf));
}
setAttr(getTypeAttrName(), TypeAttr::get(newType));
}
/// Create a deep copy of this function and all of its blocks, remapping
/// any operands that use values outside of the function using the map that is
/// provided (leaving them alone if no entry is present). If the mapper
/// contains entries for function arguments, these arguments are not included
/// in the new function. Replaces references to cloned sub-values with the
/// corresponding value that is copied, and adds those mappings to the mapper.
FuncOp clone(BlockAndValueMapping &mapper);
FuncOp clone();
/// Clone the internal blocks and attributes from this function into dest. Any
/// cloned blocks are appended to the back of dest. This function asserts that
/// the attributes of the current function and dest are compatible.
void cloneInto(FuncOp dest, BlockAndValueMapping &mapper);
//===--------------------------------------------------------------------===//
// Body Handling
//===--------------------------------------------------------------------===//
/// 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.
Block *addEntryBlock();
/// Add a normal block to the end of the function's block list. The function
/// should at least already have an entry block.
Block *addBlock();
//===--------------------------------------------------------------------===//
// CallableOpInterface
//===--------------------------------------------------------------------===//
/// 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.
Region *getCallableRegion() { return isExternal() ? nullptr : &getBody(); }
/// Returns the results types that the callable region produces when executed.
ArrayRef<Type> getCallableResults() { return getType().getResults(); }
private:
// This trait needs access to the hooks defined below.
friend class OpTrait::FunctionLike<FuncOp>;
/// Returns the number of arguments. This is a hook for OpTrait::FunctionLike.
unsigned getNumFuncArguments() { return getType().getInputs().size(); }
/// Returns the number of results. This is a hook for OpTrait::FunctionLike.
unsigned getNumFuncResults() { return getType().getResults().size(); }
/// Hook for OpTrait::FunctionLike, called after verifying that the 'type'
/// attribute is present and checks if it holds a function type. Ensures
/// getType, getNumFuncArguments, and getNumFuncResults can be called safely.
LogicalResult verifyType() {
auto type = getTypeAttr().getValue();
if (!type.isa<FunctionType>())
return emitOpError("requires '" + getTypeAttrName() +
"' attribute of function type");
return success();
}
};
} // end namespace mlir
namespace llvm {
// Functions hash just like pointers.
template <> struct DenseMapInfo<mlir::FuncOp> {
static mlir::FuncOp getEmptyKey() {
auto pointer = llvm::DenseMapInfo<void *>::getEmptyKey();
return mlir::FuncOp::getFromOpaquePointer(pointer);
}
static mlir::FuncOp getTombstoneKey() {
auto pointer = llvm::DenseMapInfo<void *>::getTombstoneKey();
return mlir::FuncOp::getFromOpaquePointer(pointer);
}
static unsigned getHashValue(mlir::FuncOp val) {
return hash_value(val.getAsOpaquePointer());
}
static bool isEqual(mlir::FuncOp LHS, mlir::FuncOp RHS) { return LHS == RHS; }
};
/// Allow stealing the low bits of FuncOp.
template <> struct PointerLikeTypeTraits<mlir::FuncOp> {
public:
static inline void *getAsVoidPointer(mlir::FuncOp I) {
return const_cast<void *>(I.getAsOpaquePointer());
}
static inline mlir::FuncOp getFromVoidPointer(void *P) {
return mlir::FuncOp::getFromOpaquePointer(P);
}
enum { NumLowBitsAvailable = 3 };
};
} // namespace llvm
#endif // MLIR_IR_FUNCTION_H