24#include "llvm/ADT/APFloat.h"
25#include "llvm/ADT/MapVector.h"
26#include "llvm/ADT/STLExtras.h"
27#include "llvm/ADT/SmallVectorExtras.h"
29#include "mlir/Dialect/Func/IR/FuncOpsDialect.cpp.inc"
35struct FuncDialectBytecodeInterface : BytecodeDialectInterface {
36 using BytecodeDialectInterface::BytecodeDialectInterface;
38 void writeVersion(DialectBytecodeWriter &writer)
const override {
42 std::unique_ptr<DialectVersion>
43 readVersion(DialectBytecodeReader &reader)
const override {
48 reader.
emitError(
"unsupported func dialect bytecode version");
51 return std::make_unique<DialectVersion>();
60void FuncDialect::initialize() {
61 addInterfaces<FuncDialectBytecodeInterface>();
64#include "mlir/Dialect/Func/IR/FuncOps.cpp.inc"
66 declarePromisedInterface<ConvertToEmitCPatternInterface, FuncDialect>();
67 declarePromisedInterface<DialectInlinerInterface, FuncDialect>();
68 declarePromisedInterface<ConvertToLLVMPatternInterface, FuncDialect>();
69 declarePromisedInterfaces<bufferization::BufferizableOpInterface, CallOp,
77 if (ConstantOp::isBuildableWith(value, type))
78 return ConstantOp::create(builder, loc, type,
79 llvm::cast<FlatSymbolRefAttr>(value));
89 auto fnAttr = getCalleeAttr();
91 return emitOpError(
"requires a 'callee' symbol reference attribute");
94 return emitOpError() <<
"'" << fnAttr.getValue()
95 <<
"' does not reference a valid function";
101FunctionType CallOp::getCalleeType() {
102 return FunctionType::get(
getContext(), getOperandTypes(), getResultTypes());
110LogicalResult CallIndirectOp::canonicalize(CallIndirectOp indirectCall,
118 auto directCall = CallOp::create(
119 rewriter, indirectCall.getLoc(), indirectCall.getResultTypes(), calledFn,
120 indirectCall.getArgOperands(), indirectCall.getArgAttrsAttr(),
121 indirectCall.getResAttrsAttr());
122 directCall->setDiscardableAttrs(indirectCall->getDiscardableAttrDictionary());
123 rewriter.
replaceOp(indirectCall, directCall.getResults());
132 StringRef fnName = getValue();
137 this->getOperation(), StringAttr::get(
getContext(), fnName));
139 return emitOpError() <<
"reference to undefined function '" << fnName
143 if (fn.getFunctionType() != type)
144 return emitOpError(
"reference to function with mismatched type");
150 return getValueAttr();
153void ConstantOp::getAsmResultNames(
155 setNameFn(getResult(),
"f");
158bool ConstantOp::isBuildableWith(
Attribute value,
Type type) {
159 return llvm::isa<FlatSymbolRefAttr>(value) && llvm::isa<FunctionType>(type);
184 Properties &properties = getProperties();
195FuncOp FuncOp::create(
Location location, StringRef name, FunctionType type,
199 FuncOp::build(builder, state, name, type, attrs);
202FuncOp FuncOp::create(
Location location, StringRef name, FunctionType type,
207FuncOp FuncOp::create(
Location location, StringRef name, FunctionType type,
210 FuncOp
func = create(location, name, type, attrs);
211 func.setAllArgAttrs(argAttrs);
219 state.
addAttribute(getFunctionTypeAttrName(state.
name), TypeAttr::get(type));
223 if (argAttrs.empty())
225 assert(type.getNumInputs() == argAttrs.size());
227 builder, state, argAttrs, {},
228 getArgAttrsAttrName(state.
name), getResAttrsAttrName(state.
name));
239 getFunctionTypeAttrName(
result.name), buildFuncType,
240 getArgAttrsAttrName(
result.name), getResAttrsAttrName(
result.name));
245 p, *
this,
false, getFunctionTypeAttrName(),
246 getArgAttrsAttrName(), getResAttrsAttrName());
251void FuncOp::cloneInto(FuncOp dest,
IRMapping &mapper) {
254 for (
const auto &attr : dest->getDiscardableAttrDictionary().getValue())
255 newAttrMap.insert({attr.getName(), attr.getValue()});
256 for (
const auto &attr : (*this)->getDiscardableAttrDictionary().getValue())
257 newAttrMap.insert({attr.getName(), attr.getValue()});
259 auto newAttrs = llvm::map_to_vector(
260 newAttrMap, [](std::pair<StringAttr, Attribute> attrPair) {
263 dest->setDiscardableAttrs(DictionaryAttr::get(
getContext(), newAttrs));
266 getBody().cloneInto(&dest.getBody(), mapper);
282 FunctionType oldType = getFunctionType();
284 unsigned oldNumArgs = oldType.getNumInputs();
286 newInputs.reserve(oldNumArgs);
287 for (
unsigned i = 0; i != oldNumArgs; ++i)
288 if (!mapper.
contains(getArgument(i)))
289 newInputs.push_back(oldType.getInput(i));
293 if (newInputs.size() != oldNumArgs) {
294 newFunc.setType(FunctionType::get(oldType.getContext(), newInputs,
295 oldType.getResults()));
297 if (
ArrayAttr argAttrs = getAllArgAttrs()) {
299 newArgAttrs.reserve(newInputs.size());
300 for (
unsigned i = 0; i != oldNumArgs; ++i)
301 if (!mapper.
contains(getArgument(i)))
302 newArgAttrs.push_back(argAttrs[i]);
303 newFunc.setAllArgAttrs(newArgAttrs);
309 cloneInto(newFunc, mapper);
312FuncOp FuncOp::clone() {
314 return clone(mapper);
321LogicalResult FuncOp::verifyRegions() {
326 auto resultTypes = getFunctionType().getResults();
327 for (
Block &block : getBody()) {
332 auto returnOp = dyn_cast<RegionBranchTerminatorOpInterface>(&block.back());
337 if (operands.size() != resultTypes.size())
338 return returnOp->emitOpError(
"has ")
339 << operands.size() <<
" operands, but enclosing function (@"
340 << getName() <<
") returns " << resultTypes.size();
342 for (
auto [i, opType] : llvm::enumerate(llvm::zip(operands, resultTypes))) {
343 auto [operand, resTy] = opType;
344 if (operand.get().getType() != resTy)
345 return returnOp->emitError() <<
"type of return operand " << i <<
" ("
346 << operand.get().getType()
347 <<
") doesn't match function result type ("
348 << resTy <<
") in function @" << getName();
359#define GET_OP_CLASSES
360#include "mlir/Dialect/Func/IR/FuncOps.cpp.inc"
Attributes are known-constant values of operations.
MLIRContext * getContext() const
Return the context this attribute belongs to.
Block represents an ordered list of Operations.
This class is a general helper class for creating context-global objects like types,...
FunctionType getFunctionType(TypeRange inputs, TypeRange results)
StringAttr getStringAttr(const Twine &bytes)
This class defines a virtual interface for reading a bytecode stream, providing hooks into the byteco...
virtual LogicalResult readVarInt(uint64_t &result)=0
Read a variable width integer.
virtual FailureOr< const DialectVersion * > getDialectVersion(StringRef dialectName) const =0
Retrieve the dialect version by name if available.
virtual LogicalResult readOptionalAttribute(Attribute &attr)=0
Read an optional reference to the given attribute.
virtual InFlightDiagnostic emitError(const Twine &msg={}) const =0
Emit an error to the reader.
virtual LogicalResult readAttribute(Attribute &result)=0
Read a reference to the given attribute.
This class defines a virtual interface for writing to a bytecode stream, providing hooks into the byt...
virtual void writeOptionalAttribute(Attribute attr)=0
virtual void writeVarInt(uint64_t value)=0
Write a variable width integer to the output stream.
virtual void writeAttribute(Attribute attr)=0
Write a reference to the given attribute.
virtual int64_t getBytecodeVersion() const =0
Return the bytecode version being emitted for.
A symbol reference with a reference path containing a single element.
This is a utility class for mapping one set of IR entities to another.
bool contains(T from) const
Checks to see if a mapping for 'from' exists.
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
void append(StringRef name, Attribute attr)
Add an attribute with the specified name.
NamedAttribute represents a combination of a name and an Attribute value.
The OpAsmParser has methods for interacting with the asm parser: parsing things from it,...
This is a pure-virtual base class that exposes the asmprinter hooks necessary to implement a custom p...
This class helps build Operations.
This class represents a single result from folding an operation.
Operation is the basic unit of execution within MLIR.
iterator_range< dialect_attr_iterator > dialect_attr_range
static Operation * create(Location location, OperationName name, TypeRange resultTypes, ValueRange operands, NamedAttrList &&attributes, PropertyRef properties, BlockRange successors, unsigned numRegions)
Create a new Operation with the specific fields.
A special type of RewriterBase that coordinates the application of a rewrite pattern on the current I...
This class represents a successor of a region.
virtual void replaceOp(Operation *op, ValueRange newValues)
Replace the results of the given (original) operation with the specified list of values (replacements...
This class represents a collection of SymbolTables.
virtual Operation * lookupNearestSymbolFrom(Operation *from, StringAttr symbol)
Returns the operation registered with the given symbol name within the closest parent operation of,...
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
A named class for passing around the variadic flag.
@ kDialectVersioning
Dialects versioning was added in version 1.
LogicalResult verifyCallOpInterface(CallOpInterface call, TypeRange argumentTypes, TypeRange resultTypes)
Verify that the forwarded operands and results of call are in a 1:1 relationship with the given argum...
void addArgAndResultAttrs(Builder &builder, OperationState &result, ArrayRef< DictionaryAttr > argAttrs, ArrayRef< DictionaryAttr > resultAttrs, StringAttr argAttrsName, StringAttr resAttrsName)
Adds argument and result attributes, provided as argAttrs and resultAttrs arguments,...
void printFunctionOp(OpAsmPrinter &p, FunctionOpInterface op, bool isVariadic, StringRef typeAttrName, StringAttr argAttrsName, StringAttr resAttrsName)
Printer implementation for function-like operations.
ParseResult parseFunctionOp(OpAsmParser &parser, OperationState &result, bool allowVariadic, StringAttr typeAttrName, FuncTypeBuilder funcTypeBuilder, StringAttr argAttrsName, StringAttr resAttrsName)
Parser implementation for function-like operations.
Include the generated interface declarations.
bool matchPattern(Value value, const Pattern &pattern)
Entry point for matching a pattern over a Value.
Type getType(OpFoldResult ofr)
Returns the int type of the integer in ofr.
Operation * cloneWithoutRegions(OpBuilder &b, Operation *op, TypeRange newResultTypes, ValueRange newOperands)
Operation * clone(OpBuilder &b, Operation *op, TypeRange newResultTypes, ValueRange newOperands)
detail::constant_op_matcher m_Constant()
Matches a constant foldable operation.
llvm::function_ref< Fn > function_ref
This represents an operation in an abstracted form, suitable for use with the builder APIs.
T & getOrAddProperties()
Get (or create) the properties of the provided type to be set on the operation on creation.
void addAttribute(StringRef name, Attribute attr)
Add an attribute with the specified name.
Region * addRegion()
Create a region that should be attached to the operation.