24 #include "llvm/ADT/APFloat.h"
25 #include "llvm/ADT/MapVector.h"
26 #include "llvm/ADT/STLExtras.h"
27 #include "llvm/Support/FormatVariadic.h"
28 #include "llvm/Support/raw_ostream.h"
31 #include "mlir/Dialect/Func/IR/FuncOpsDialect.cpp.inc"
40 void FuncDialect::initialize() {
43 #include "mlir/Dialect/Func/IR/FuncOps.cpp.inc"
45 declarePromisedInterface<ConvertToEmitCPatternInterface, FuncDialect>();
46 declarePromisedInterface<DialectInlinerInterface, FuncDialect>();
47 declarePromisedInterface<ConvertToLLVMPatternInterface, FuncDialect>();
48 declarePromisedInterfaces<bufferization::BufferizableOpInterface, CallOp,
56 if (ConstantOp::isBuildableWith(value, type))
57 return builder.
create<ConstantOp>(loc, type,
58 llvm::cast<FlatSymbolRefAttr>(value));
70 return emitOpError(
"requires a 'callee' symbol reference attribute");
73 return emitOpError() <<
"'" << fnAttr.getValue()
74 <<
"' does not reference a valid function";
77 auto fnType = fn.getFunctionType();
78 if (fnType.getNumInputs() != getNumOperands())
79 return emitOpError(
"incorrect number of operands for callee");
81 for (
unsigned i = 0, e = fnType.getNumInputs(); i != e; ++i)
82 if (getOperand(i).
getType() != fnType.getInput(i))
83 return emitOpError(
"operand type mismatch: expected operand type ")
84 << fnType.getInput(i) <<
", but provided "
85 << getOperand(i).getType() <<
" for operand number " << i;
87 if (fnType.getNumResults() != getNumResults())
88 return emitOpError(
"incorrect number of results for callee");
90 for (
unsigned i = 0, e = fnType.getNumResults(); i != e; ++i)
91 if (getResult(i).
getType() != fnType.getResult(i)) {
92 auto diag = emitOpError(
"result type mismatch at index ") << i;
93 diag.attachNote() <<
" op result types: " << getResultTypes();
94 diag.attachNote() <<
"function result types: " << fnType.getResults();
101 FunctionType CallOp::getCalleeType() {
110 LogicalResult CallIndirectOp::canonicalize(CallIndirectOp indirectCall,
113 SymbolRefAttr calledFn;
119 indirectCall.getResultTypes(),
120 indirectCall.getArgOperands());
129 StringRef fnName = getValue();
136 return emitOpError() <<
"reference to undefined function '" << fnName
140 if (fn.getFunctionType() != type)
141 return emitOpError(
"reference to function with mismatched type");
147 return getValueAttr();
150 void ConstantOp::getAsmResultNames(
152 setNameFn(getResult(),
"f");
155 bool ConstantOp::isBuildableWith(
Attribute value,
Type type) {
156 return llvm::isa<FlatSymbolRefAttr>(value) && llvm::isa<FunctionType>(type);
163 FuncOp FuncOp::create(
Location location, StringRef name, FunctionType type,
167 FuncOp::build(builder, state, name, type, attrs);
170 FuncOp FuncOp::create(
Location location, StringRef name, FunctionType type,
175 FuncOp FuncOp::create(
Location location, StringRef name, FunctionType type,
178 FuncOp func = create(location, name, type, attrs);
179 func.setAllArgAttrs(argAttrs);
188 state.addAttribute(getFunctionTypeAttrName(state.name),
TypeAttr::get(type));
189 state.attributes.append(attrs.begin(), attrs.end());
192 if (argAttrs.empty())
194 assert(type.getNumInputs() == argAttrs.size());
196 builder, state, argAttrs, std::nullopt,
197 getArgAttrsAttrName(state.name), getResAttrsAttrName(state.name));
207 parser, result,
false,
208 getFunctionTypeAttrName(result.
name), buildFuncType,
209 getArgAttrsAttrName(result.
name), getResAttrsAttrName(result.
name));
214 p, *
this,
false, getFunctionTypeAttrName(),
215 getArgAttrsAttrName(), getResAttrsAttrName());
220 void FuncOp::cloneInto(FuncOp dest,
IRMapping &mapper) {
222 llvm::MapVector<StringAttr, Attribute> newAttrMap;
223 for (
const auto &attr : dest->getAttrs())
224 newAttrMap.insert({attr.getName(), attr.getValue()});
225 for (
const auto &attr : (*this)->getAttrs())
226 newAttrMap.insert({attr.getName(), attr.getValue()});
228 auto newAttrs = llvm::to_vector(llvm::map_range(
229 newAttrMap, [](std::pair<StringAttr, Attribute> attrPair) {
235 getBody().cloneInto(&dest.getBody(), mapper);
251 FunctionType oldType = getFunctionType();
253 unsigned oldNumArgs = oldType.getNumInputs();
255 newInputs.reserve(oldNumArgs);
256 for (
unsigned i = 0; i != oldNumArgs; ++i)
257 if (!mapper.
contains(getArgument(i)))
258 newInputs.push_back(oldType.getInput(i));
262 if (newInputs.size() != oldNumArgs) {
264 oldType.getResults()));
266 if (ArrayAttr argAttrs = getAllArgAttrs()) {
268 newArgAttrs.reserve(newInputs.size());
269 for (
unsigned i = 0; i != oldNumArgs; ++i)
270 if (!mapper.
contains(getArgument(i)))
271 newArgAttrs.push_back(argAttrs[i]);
272 newFunc.setAllArgAttrs(newArgAttrs);
278 cloneInto(newFunc, mapper);
283 return clone(mapper);
291 auto function = cast<FuncOp>((*this)->getParentOp());
294 const auto &results =
function.getFunctionType().getResults();
295 if (getNumOperands() != results.size())
296 return emitOpError(
"has ")
297 << getNumOperands() <<
" operands, but enclosing function (@"
298 <<
function.getName() <<
") returns " << results.size();
300 for (
unsigned i = 0, e = results.size(); i != e; ++i)
301 if (getOperand(i).
getType() != results[i])
302 return emitError() <<
"type of return operand " << i <<
" ("
303 << getOperand(i).getType()
304 <<
") doesn't match function result type ("
306 <<
" in function @" <<
function.getName();
315 #define GET_OP_CLASSES
316 #include "mlir/Dialect/Func/IR/FuncOps.cpp.inc"
static Operation * materializeConstant(Dialect *dialect, OpBuilder &builder, Attribute value, Type type, Location loc)
A utility function used to materialize a constant for a given attribute and type.
static MLIRContext * getContext(OpFoldResult val)
static std::string diag(const llvm::Value &value)
static void print(spirv::VerCapExtAttr triple, DialectAsmPrinter &printer)
Attributes are known-constant values of operations.
MLIRContext * getContext() const
Return the context this attribute belongs to.
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)
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...
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.
Operation * create(const OperationState &state)
Creates an operation given the fields represented as an OperationState.
This class represents a single result from folding an operation.
Operation is the basic unit of execution within MLIR.
AttrClass getAttrOfType(StringAttr name)
static Operation * create(Location location, OperationName name, TypeRange resultTypes, ValueRange operands, NamedAttrList &&attributes, OpaqueProperties 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...
OpTy replaceOpWithNewOp(Operation *op, Args &&...args)
Replace the results of the given (original) op with a new op that is created without verification (re...
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,...
static StringRef getSymbolAttrName()
Return the name of the attribute used for symbol names.
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.
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.
QueryRef parse(llvm::StringRef line, const QuerySession &qs)
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)
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
Operation * clone(OpBuilder &b, Operation *op, TypeRange newResultTypes, ValueRange newOperands)
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...
detail::constant_op_matcher m_Constant()
Matches a constant foldable operation.
LogicalResult verify(Operation *op, bool verifyRecursively=true)
Perform (potentially expensive) checks of invariants, used to detect compiler bugs,...
This represents an operation in an abstracted form, suitable for use with the builder APIs.