1//===- FunctionInterfaces.td - Function interfaces --------*- tablegen -*-===// 2// 3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4// See https://llvm.org/LICENSE.txt for license information. 5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6// 7//===----------------------------------------------------------------------===// 8// 9// This file contains definitions for interfaces that support the definition of 10// "function-like" operations. 11// 12//===----------------------------------------------------------------------===// 13 14#ifndef MLIR_INTERFACES_FUNCTIONINTERFACES_TD_ 15#define MLIR_INTERFACES_FUNCTIONINTERFACES_TD_ 16 17include "mlir/IR/SymbolInterfaces.td" 18include "mlir/Interfaces/CallInterfaces.td" 19 20//===----------------------------------------------------------------------===// 21// FunctionOpInterface 22//===----------------------------------------------------------------------===// 23 24def FunctionOpInterface : OpInterface<"FunctionOpInterface", [ 25 Symbol, CallableOpInterface 26 ]> { 27 let cppNamespace = "::mlir"; 28 let description = [{ 29 This interfaces provides support for interacting with operations that 30 behave like functions. In particular, these operations: 31 32 - must be symbols, i.e. have the `Symbol` trait. 33 - must have a single region, that may be comprised with multiple blocks, 34 that corresponds to the function body. 35 * when this region is empty, the operation corresponds to an external 36 function. 37 * leading arguments of the first block of the region are treated as 38 function arguments. 39 40 The function, aside from implementing the various interface methods, 41 should have the following ODS arguments: 42 43 - `function_type` (required) 44 * A TypeAttr that holds the signature type of the function. 45 46 - `arg_attrs` (optional) 47 * An ArrayAttr of DictionaryAttr that contains attribute dictionaries 48 for each of the function arguments. 49 50 - `res_attrs` (optional) 51 * An ArrayAttr of DictionaryAttr that contains attribute dictionaries 52 for each of the function results. 53 }]; 54 let methods = [ 55 InterfaceMethod<[{ 56 Returns the type of the function. 57 }], 58 "::mlir::Type", "getFunctionType">, 59 InterfaceMethod<[{ 60 Set the type of the function. This method should perform an unsafe 61 modification to the function type; it should not update argument or 62 result attributes. 63 }], 64 "void", "setFunctionTypeAttr", (ins "::mlir::TypeAttr":$type)>, 65 66 InterfaceMethod<[{ 67 Returns a clone of the function type with the given argument and 68 result types. 69 70 Note: The default implementation assumes the function type has 71 an appropriate clone method: 72 `Type clone(ArrayRef<Type> inputs, ArrayRef<Type> results)` 73 }], 74 "::mlir::Type", "cloneTypeWith", (ins 75 "::mlir::TypeRange":$inputs, "::mlir::TypeRange":$results 76 ), /*methodBody=*/[{}], /*defaultImplementation=*/[{ 77 return $_op.getFunctionType().clone(inputs, results); 78 }]>, 79 80 InterfaceMethod<[{ 81 Verify the contents of the body of this function. 82 83 Note: The default implementation merely checks that if the entry block 84 exists, it has the same number and type of arguments as the function type. 85 }], 86 "::llvm::LogicalResult", "verifyBody", (ins), 87 /*methodBody=*/[{}], /*defaultImplementation=*/[{ 88 if ($_op.isExternal()) 89 return success(); 90 ArrayRef<Type> fnInputTypes = $_op.getArgumentTypes(); 91 // NOTE: This should just be $_op.front() but access generically 92 // because the interface methods defined here may be shadowed in 93 // arbitrary ways. https://github.com/llvm/llvm-project/issues/54807 94 Block &entryBlock = $_op->getRegion(0).front(); 95 96 unsigned numArguments = fnInputTypes.size(); 97 if (entryBlock.getNumArguments() != numArguments) 98 return $_op.emitOpError("entry block must have ") 99 << numArguments << " arguments to match function signature"; 100 101 for (unsigned i = 0, e = fnInputTypes.size(); i != e; ++i) { 102 Type argType = entryBlock.getArgument(i).getType(); 103 if (fnInputTypes[i] != argType) { 104 return $_op.emitOpError("type of entry block argument #") 105 << i << '(' << argType 106 << ") must match the type of the corresponding argument in " 107 << "function signature(" << fnInputTypes[i] << ')'; 108 } 109 } 110 111 return success(); 112 }]>, 113 InterfaceMethod<[{ 114 Verify the type attribute of the function for derived op-specific 115 invariants. 116 }], 117 "::llvm::LogicalResult", "verifyType", (ins), 118 /*methodBody=*/[{}], /*defaultImplementation=*/[{ 119 return success(); 120 }]>, 121 ]; 122 123 let extraTraitClassDeclaration = [{ 124 //===------------------------------------------------------------------===// 125 // Builders 126 //===------------------------------------------------------------------===// 127 128 /// Build the function with the given name, attributes, and type. This 129 /// builder also inserts an entry block into the function body with the 130 /// given argument types. 131 static void buildWithEntryBlock( 132 OpBuilder &builder, OperationState &state, StringRef name, Type type, 133 ArrayRef<NamedAttribute> attrs, TypeRange inputTypes) { 134 OpBuilder::InsertionGuard g(builder); 135 state.addAttribute(SymbolTable::getSymbolAttrName(), 136 builder.getStringAttr(name)); 137 state.addAttribute(ConcreteOp::getFunctionTypeAttrName(state.name), 138 TypeAttr::get(type)); 139 state.attributes.append(attrs.begin(), attrs.end()); 140 141 // Add the function body. 142 Region *bodyRegion = state.addRegion(); 143 Block *body = builder.createBlock(bodyRegion); 144 for (Type input : inputTypes) 145 body->addArgument(input, state.location); 146 } 147 }]; 148 let extraSharedClassDeclaration = [{ 149 /// Block list iterator types. 150 using BlockListType = ::mlir::Region::BlockListType; 151 using iterator = BlockListType::iterator; 152 using reverse_iterator = BlockListType::reverse_iterator; 153 154 /// Block argument iterator types. 155 using BlockArgListType = ::mlir::Region::BlockArgListType; 156 using args_iterator = BlockArgListType::iterator; 157 158 //===------------------------------------------------------------------===// 159 // Body Handling 160 //===------------------------------------------------------------------===// 161 162 /// Returns true if this function is external, i.e. it has no body. 163 bool isExternal() { return empty(); } 164 165 /// Return the region containing the body of this function. 166 ::mlir::Region &getFunctionBody() { return $_op->getRegion(0); } 167 168 /// Delete all blocks from this function. 169 void eraseBody() { 170 getFunctionBody().dropAllReferences(); 171 getFunctionBody().getBlocks().clear(); 172 } 173 174 /// Return the list of blocks within the function body. 175 BlockListType &getBlocks() { return getFunctionBody().getBlocks(); } 176 177 iterator begin() { return getFunctionBody().begin(); } 178 iterator end() { return getFunctionBody().end(); } 179 reverse_iterator rbegin() { return getFunctionBody().rbegin(); } 180 reverse_iterator rend() { return getFunctionBody().rend(); } 181 182 /// Returns true if this function has no blocks within the body. 183 bool empty() { return getFunctionBody().empty(); } 184 185 /// Push a new block to the back of the body region. 186 void push_back(::mlir::Block *block) { getFunctionBody().push_back(block); } 187 188 /// Push a new block to the front of the body region. 189 void push_front(::mlir::Block *block) { getFunctionBody().push_front(block); } 190 191 /// Return the last block in the body region. 192 ::mlir::Block &back() { return getFunctionBody().back(); } 193 194 /// Return the first block in the body region. 195 ::mlir::Block &front() { return getFunctionBody().front(); } 196 197 /// Add an entry block to an empty function, and set up the block arguments 198 /// to match the signature of the function. The newly inserted entry block 199 /// is returned. 200 ::mlir::Block *addEntryBlock() { 201 assert(empty() && "function already has an entry block"); 202 ::mlir::Block *entry = new ::mlir::Block(); 203 push_back(entry); 204 205 // FIXME: Allow for passing in locations for these arguments instead of using 206 // the operations location. 207 ::llvm::ArrayRef<::mlir::Type> inputTypes = $_op.getArgumentTypes(); 208 ::llvm::SmallVector<::mlir::Location> locations(inputTypes.size(), 209 $_op.getOperation()->getLoc()); 210 entry->addArguments(inputTypes, locations); 211 return entry; 212 } 213 214 /// Add a normal block to the end of the function's block list. The function 215 /// should at least already have an entry block. 216 ::mlir::Block *addBlock() { 217 assert(!empty() && "function should at least have an entry block"); 218 push_back(new ::mlir::Block()); 219 return &back(); 220 } 221 222 //===------------------------------------------------------------------===// 223 // Type Attribute Handling 224 //===------------------------------------------------------------------===// 225 226 /// Change the type of this function in place. This is an extremely dangerous 227 /// operation and it is up to the caller to ensure that this is legal for 228 /// this function, and to restore invariants: 229 /// - the entry block args must be updated to match the function params. 230 /// - the argument/result attributes may need an update: if the new type 231 /// has less parameters we drop the extra attributes, if there are more 232 /// parameters they won't have any attributes. 233 void setType(::mlir::Type newType) { 234 ::mlir::function_interface_impl::setFunctionType($_op, newType); 235 } 236 237 //===------------------------------------------------------------------===// 238 // Argument and Result Handling 239 //===------------------------------------------------------------------===// 240 241 /// Returns the number of function arguments. 242 unsigned getNumArguments() { return $_op.getArgumentTypes().size(); } 243 244 /// Returns the number of function results. 245 unsigned getNumResults() { return $_op.getResultTypes().size(); } 246 247 /// Returns the entry block function argument at the given index. 248 ::mlir::BlockArgument getArgument(unsigned idx) { 249 return getFunctionBody().getArgument(idx); 250 } 251 252 /// Support argument iteration. 253 args_iterator args_begin() { return getFunctionBody().args_begin(); } 254 args_iterator args_end() { return getFunctionBody().args_end(); } 255 BlockArgListType getArguments() { return getFunctionBody().getArguments(); } 256 257 /// Insert a single argument of type `argType` with attributes `argAttrs` and 258 /// location `argLoc` at `argIndex`. 259 void insertArgument(unsigned argIndex, ::mlir::Type argType, ::mlir::DictionaryAttr argAttrs, 260 ::mlir::Location argLoc) { 261 insertArguments({argIndex}, {argType}, {argAttrs}, {argLoc}); 262 } 263 264 /// Inserts arguments with the listed types, attributes, and locations at the 265 /// listed indices. `argIndices` must be sorted. Arguments are inserted in the 266 /// order they are listed, such that arguments with identical index will 267 /// appear in the same order that they were listed here. 268 void insertArguments(::llvm::ArrayRef<unsigned> argIndices, ::mlir::TypeRange argTypes, 269 ::llvm::ArrayRef<::mlir::DictionaryAttr> argAttrs, 270 ::llvm::ArrayRef<::mlir::Location> argLocs) { 271 unsigned originalNumArgs = $_op.getNumArguments(); 272 ::mlir::Type newType = $_op.getTypeWithArgsAndResults( 273 argIndices, argTypes, /*resultIndices=*/{}, /*resultTypes=*/{}); 274 ::mlir::function_interface_impl::insertFunctionArguments( 275 $_op, argIndices, argTypes, argAttrs, argLocs, 276 originalNumArgs, newType); 277 } 278 279 /// Insert a single result of type `resultType` at `resultIndex`. 280 void insertResult(unsigned resultIndex, ::mlir::Type resultType, 281 ::mlir::DictionaryAttr resultAttrs) { 282 insertResults({resultIndex}, {resultType}, {resultAttrs}); 283 } 284 285 /// Inserts results with the listed types at the listed indices. 286 /// `resultIndices` must be sorted. Results are inserted in the order they are 287 /// listed, such that results with identical index will appear in the same 288 /// order that they were listed here. 289 void insertResults(::llvm::ArrayRef<unsigned> resultIndices, ::mlir::TypeRange resultTypes, 290 ::llvm::ArrayRef<::mlir::DictionaryAttr> resultAttrs) { 291 unsigned originalNumResults = $_op.getNumResults(); 292 ::mlir::Type newType = $_op.getTypeWithArgsAndResults( 293 /*argIndices=*/{}, /*argTypes=*/{}, resultIndices, resultTypes); 294 ::mlir::function_interface_impl::insertFunctionResults( 295 $_op, resultIndices, resultTypes, resultAttrs, 296 originalNumResults, newType); 297 } 298 299 /// Erase a single argument at `argIndex`. 300 void eraseArgument(unsigned argIndex) { 301 ::llvm::BitVector argsToErase($_op.getNumArguments()); 302 argsToErase.set(argIndex); 303 eraseArguments(argsToErase); 304 } 305 306 /// Erases the arguments listed in `argIndices`. 307 void eraseArguments(const ::llvm::BitVector &argIndices) { 308 ::mlir::Type newType = $_op.getTypeWithoutArgs(argIndices); 309 ::mlir::function_interface_impl::eraseFunctionArguments( 310 $_op, argIndices, newType); 311 } 312 313 /// Erase a single result at `resultIndex`. 314 void eraseResult(unsigned resultIndex) { 315 ::llvm::BitVector resultsToErase($_op.getNumResults()); 316 resultsToErase.set(resultIndex); 317 eraseResults(resultsToErase); 318 } 319 320 /// Erases the results listed in `resultIndices`. 321 void eraseResults(const ::llvm::BitVector &resultIndices) { 322 ::mlir::Type newType = $_op.getTypeWithoutResults(resultIndices); 323 ::mlir::function_interface_impl::eraseFunctionResults( 324 $_op, resultIndices, newType); 325 } 326 327 /// Return the type of this function with the specified arguments and 328 /// results inserted. This is used to update the function's signature in 329 /// the `insertArguments` and `insertResults` methods. The arrays must be 330 /// sorted by increasing index. 331 ::mlir::Type getTypeWithArgsAndResults( 332 ::llvm::ArrayRef<unsigned> argIndices, ::mlir::TypeRange argTypes, 333 ::llvm::ArrayRef<unsigned> resultIndices, ::mlir::TypeRange resultTypes) { 334 ::llvm::SmallVector<::mlir::Type> argStorage, resultStorage; 335 ::mlir::TypeRange newArgTypes = insertTypesInto( 336 $_op.getArgumentTypes(), argIndices, argTypes, argStorage); 337 ::mlir::TypeRange newResultTypes = insertTypesInto( 338 $_op.getResultTypes(), resultIndices, resultTypes, resultStorage); 339 return $_op.cloneTypeWith(newArgTypes, newResultTypes); 340 } 341 342 /// Return the type of this function without the specified arguments and 343 /// results. This is used to update the function's signature in the 344 /// `eraseArguments` and `eraseResults` methods. 345 ::mlir::Type getTypeWithoutArgsAndResults( 346 const ::llvm::BitVector &argIndices, const ::llvm::BitVector &resultIndices) { 347 ::llvm::SmallVector<::mlir::Type> argStorage, resultStorage; 348 ::mlir::TypeRange newArgTypes = filterTypesOut( 349 $_op.getArgumentTypes(), argIndices, argStorage); 350 ::mlir::TypeRange newResultTypes = filterTypesOut( 351 $_op.getResultTypes(), resultIndices, resultStorage); 352 return $_op.cloneTypeWith(newArgTypes, newResultTypes); 353 } 354 ::mlir::Type getTypeWithoutArgs(const ::llvm::BitVector &argIndices) { 355 ::llvm::SmallVector<::mlir::Type> argStorage; 356 ::mlir::TypeRange newArgTypes = filterTypesOut( 357 $_op.getArgumentTypes(), argIndices, argStorage); 358 return $_op.cloneTypeWith(newArgTypes, $_op.getResultTypes()); 359 } 360 ::mlir::Type getTypeWithoutResults(const ::llvm::BitVector &resultIndices) { 361 ::llvm::SmallVector<::mlir::Type> resultStorage; 362 ::mlir::TypeRange newResultTypes = filterTypesOut( 363 $_op.getResultTypes(), resultIndices, resultStorage); 364 return $_op.cloneTypeWith($_op.getArgumentTypes(), newResultTypes); 365 } 366 367 //===------------------------------------------------------------------===// 368 // Argument Attributes 369 //===------------------------------------------------------------------===// 370 371 /// Return all of the attributes for the argument at 'index'. 372 ::llvm::ArrayRef<::mlir::NamedAttribute> getArgAttrs(unsigned index) { 373 return ::mlir::function_interface_impl::getArgAttrs($_op, index); 374 } 375 376 /// Return an ArrayAttr containing all argument attribute dictionaries of 377 /// this function, or nullptr if no arguments have attributes. 378 ::mlir::ArrayAttr getAllArgAttrs() { return $_op.getArgAttrsAttr(); } 379 380 /// Return all argument attributes of this function. 381 void getAllArgAttrs(::llvm::SmallVectorImpl<::mlir::DictionaryAttr> &result) { 382 if (::mlir::ArrayAttr argAttrs = getAllArgAttrs()) { 383 auto argAttrRange = argAttrs.template getAsRange<::mlir::DictionaryAttr>(); 384 result.append(argAttrRange.begin(), argAttrRange.end()); 385 } else { 386 result.append($_op.getNumArguments(), 387 ::mlir::DictionaryAttr::get(this->getOperation()->getContext())); 388 } 389 } 390 391 /// Return the specified attribute, if present, for the argument at 'index', 392 /// null otherwise. 393 ::mlir::Attribute getArgAttr(unsigned index, ::mlir::StringAttr name) { 394 auto argDict = getArgAttrDict(index); 395 return argDict ? argDict.get(name) : nullptr; 396 } 397 ::mlir::Attribute getArgAttr(unsigned index, ::llvm::StringRef name) { 398 auto argDict = getArgAttrDict(index); 399 return argDict ? argDict.get(name) : nullptr; 400 } 401 402 template <typename AttrClass> 403 AttrClass getArgAttrOfType(unsigned index, ::mlir::StringAttr name) { 404 return ::llvm::dyn_cast_or_null<AttrClass>(getArgAttr(index, name)); 405 } 406 template <typename AttrClass> 407 AttrClass getArgAttrOfType(unsigned index, ::llvm::StringRef name) { 408 return ::llvm::dyn_cast_or_null<AttrClass>(getArgAttr(index, name)); 409 } 410 411 /// Set the attributes held by the argument at 'index'. 412 void setArgAttrs(unsigned index, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes) { 413 ::mlir::function_interface_impl::setArgAttrs($_op, index, attributes); 414 } 415 416 /// Set the attributes held by the argument at 'index'. `attributes` may be 417 /// null, in which case any existing argument attributes are removed. 418 void setArgAttrs(unsigned index, ::mlir::DictionaryAttr attributes) { 419 ::mlir::function_interface_impl::setArgAttrs($_op, index, attributes); 420 } 421 void setAllArgAttrs(::llvm::ArrayRef<::mlir::DictionaryAttr> attributes) { 422 assert(attributes.size() == $_op.getNumArguments()); 423 ::mlir::function_interface_impl::setAllArgAttrDicts($_op, attributes); 424 } 425 void setAllArgAttrs(::llvm::ArrayRef<::mlir::Attribute> attributes) { 426 assert(attributes.size() == $_op.getNumArguments()); 427 ::mlir::function_interface_impl::setAllArgAttrDicts($_op, attributes); 428 } 429 void setAllArgAttrs(::mlir::ArrayAttr attributes) { 430 assert(attributes.size() == $_op.getNumArguments()); 431 $_op.setArgAttrsAttr(attributes); 432 } 433 434 /// If the an attribute exists with the specified name, change it to the new 435 /// value. Otherwise, add a new attribute with the specified name/value. 436 void setArgAttr(unsigned index, ::mlir::StringAttr name, ::mlir::Attribute value) { 437 ::mlir::function_interface_impl::setArgAttr($_op, index, name, value); 438 } 439 void setArgAttr(unsigned index, ::llvm::StringRef name, ::mlir::Attribute value) { 440 setArgAttr(index, 441 ::mlir::StringAttr::get(this->getOperation()->getContext(), name), 442 value); 443 } 444 445 /// Remove the attribute 'name' from the argument at 'index'. Return the 446 /// attribute that was erased, or nullptr if there was no attribute with 447 /// such name. 448 ::mlir::Attribute removeArgAttr(unsigned index, ::mlir::StringAttr name) { 449 return ::mlir::function_interface_impl::removeArgAttr($_op, index, name); 450 } 451 ::mlir::Attribute removeArgAttr(unsigned index, ::llvm::StringRef name) { 452 return removeArgAttr( 453 index, ::mlir::StringAttr::get(this->getOperation()->getContext(), name)); 454 } 455 456 //===------------------------------------------------------------------===// 457 // Result Attributes 458 //===------------------------------------------------------------------===// 459 460 /// Return all of the attributes for the result at 'index'. 461 ::llvm::ArrayRef<::mlir::NamedAttribute> getResultAttrs(unsigned index) { 462 return ::mlir::function_interface_impl::getResultAttrs($_op, index); 463 } 464 465 /// Return an ArrayAttr containing all result attribute dictionaries of this 466 /// function, or nullptr if no result have attributes. 467 ::mlir::ArrayAttr getAllResultAttrs() { return $_op.getResAttrsAttr(); } 468 469 /// Return all result attributes of this function. 470 void getAllResultAttrs(::llvm::SmallVectorImpl<::mlir::DictionaryAttr> &result) { 471 if (::mlir::ArrayAttr argAttrs = getAllResultAttrs()) { 472 auto argAttrRange = argAttrs.template getAsRange<::mlir::DictionaryAttr>(); 473 result.append(argAttrRange.begin(), argAttrRange.end()); 474 } else { 475 result.append($_op.getNumResults(), 476 ::mlir::DictionaryAttr::get(this->getOperation()->getContext())); 477 } 478 } 479 480 /// Return the specified attribute, if present, for the result at 'index', 481 /// null otherwise. 482 ::mlir::Attribute getResultAttr(unsigned index, ::mlir::StringAttr name) { 483 auto argDict = getResultAttrDict(index); 484 return argDict ? argDict.get(name) : nullptr; 485 } 486 ::mlir::Attribute getResultAttr(unsigned index, ::llvm::StringRef name) { 487 auto argDict = getResultAttrDict(index); 488 return argDict ? argDict.get(name) : nullptr; 489 } 490 491 template <typename AttrClass> 492 AttrClass getResultAttrOfType(unsigned index, ::mlir::StringAttr name) { 493 return ::llvm::dyn_cast_or_null<AttrClass>(getResultAttr(index, name)); 494 } 495 template <typename AttrClass> 496 AttrClass getResultAttrOfType(unsigned index, ::llvm::StringRef name) { 497 return ::llvm::dyn_cast_or_null<AttrClass>(getResultAttr(index, name)); 498 } 499 500 /// Set the attributes held by the result at 'index'. 501 void setResultAttrs(unsigned index, ::llvm::ArrayRef<::mlir::NamedAttribute> attributes) { 502 ::mlir::function_interface_impl::setResultAttrs($_op, index, attributes); 503 } 504 505 /// Set the attributes held by the result at 'index'. `attributes` may be 506 /// null, in which case any existing argument attributes are removed. 507 void setResultAttrs(unsigned index, ::mlir::DictionaryAttr attributes) { 508 ::mlir::function_interface_impl::setResultAttrs($_op, index, attributes); 509 } 510 void setAllResultAttrs(::llvm::ArrayRef<::mlir::DictionaryAttr> attributes) { 511 assert(attributes.size() == $_op.getNumResults()); 512 ::mlir::function_interface_impl::setAllResultAttrDicts( 513 $_op, attributes); 514 } 515 void setAllResultAttrs(::llvm::ArrayRef<::mlir::Attribute> attributes) { 516 assert(attributes.size() == $_op.getNumResults()); 517 ::mlir::function_interface_impl::setAllResultAttrDicts( 518 $_op, attributes); 519 } 520 void setAllResultAttrs(::mlir::ArrayAttr attributes) { 521 assert(attributes.size() == $_op.getNumResults()); 522 $_op.setResAttrsAttr(attributes); 523 } 524 525 /// If the an attribute exists with the specified name, change it to the new 526 /// value. Otherwise, add a new attribute with the specified name/value. 527 void setResultAttr(unsigned index, ::mlir::StringAttr name, ::mlir::Attribute value) { 528 ::mlir::function_interface_impl::setResultAttr($_op, index, name, value); 529 } 530 void setResultAttr(unsigned index, ::llvm::StringRef name, ::mlir::Attribute value) { 531 setResultAttr(index, 532 ::mlir::StringAttr::get(this->getOperation()->getContext(), name), 533 value); 534 } 535 536 /// Remove the attribute 'name' from the result at 'index'. Return the 537 /// attribute that was erased, or nullptr if there was no attribute with 538 /// such name. 539 ::mlir::Attribute removeResultAttr(unsigned index, ::mlir::StringAttr name) { 540 return ::mlir::function_interface_impl::removeResultAttr($_op, index, name); 541 } 542 543 /// Returns the dictionary attribute corresponding to the argument at 544 /// 'index'. If there are no argument attributes at 'index', a null 545 /// attribute is returned. 546 ::mlir::DictionaryAttr getArgAttrDict(unsigned index) { 547 assert(index < $_op.getNumArguments() && "invalid argument number"); 548 return ::mlir::function_interface_impl::getArgAttrDict($_op, index); 549 } 550 551 /// Returns the dictionary attribute corresponding to the result at 'index'. 552 /// If there are no result attributes at 'index', a null attribute is 553 /// returned. 554 ::mlir::DictionaryAttr getResultAttrDict(unsigned index) { 555 assert(index < $_op.getNumResults() && "invalid result number"); 556 return ::mlir::function_interface_impl::getResultAttrDict($_op, index); 557 } 558 }]; 559 560 let verify = "return function_interface_impl::verifyTrait(cast<ConcreteOp>($_op));"; 561} 562 563#endif // MLIR_INTERFACES_FUNCTIONINTERFACES_TD_ 564