|
16 | 16 | include "mlir/Dialect/EmitC/IR/EmitCAttributes.td"
|
17 | 17 | include "mlir/Dialect/EmitC/IR/EmitCTypes.td"
|
18 | 18 |
|
| 19 | +include "mlir/Interfaces/CallInterfaces.td" |
19 | 20 | include "mlir/Interfaces/CastInterfaces.td"
|
20 | 21 | include "mlir/Interfaces/ControlFlowInterfaces.td"
|
| 22 | +include "mlir/Interfaces/FunctionInterfaces.td" |
21 | 23 | include "mlir/Interfaces/SideEffectInterfaces.td"
|
22 | 24 | include "mlir/IR/RegionKindInterface.td"
|
23 | 25 |
|
@@ -386,6 +388,174 @@ def EmitC_ForOp : EmitC_Op<"for",
|
386 | 388 | let hasRegionVerifier = 1;
|
387 | 389 | }
|
388 | 390 |
|
| 391 | +def EmitC_CallOp : EmitC_Op<"call", |
| 392 | + [CallOpInterface, |
| 393 | + DeclareOpInterfaceMethods<SymbolUserOpInterface>]> { |
| 394 | + let summary = "call operation"; |
| 395 | + let description = [{ |
| 396 | + The `emitc.call` operation represents a direct call to an `emitc.func` |
| 397 | + that is within the same symbol scope as the call. The operands and result type |
| 398 | + of the call must match the specified function type. The callee is encoded as a |
| 399 | + symbol reference attribute named "callee". |
| 400 | + |
| 401 | + Example: |
| 402 | + |
| 403 | + ```mlir |
| 404 | + %2 = emitc.call @my_add(%0, %1) : (f32, f32) -> f32 |
| 405 | + ``` |
| 406 | + }]; |
| 407 | + let arguments = (ins FlatSymbolRefAttr:$callee, Variadic<AnyType>:$operands); |
| 408 | + let results = (outs Variadic<AnyType>); |
| 409 | + |
| 410 | + let builders = [ |
| 411 | + OpBuilder<(ins "FuncOp":$callee, CArg<"ValueRange", "{}">:$operands), [{ |
| 412 | + $_state.addOperands(operands); |
| 413 | + $_state.addAttribute("callee", SymbolRefAttr::get(callee)); |
| 414 | + $_state.addTypes(callee.getFunctionType().getResults()); |
| 415 | + }]>, |
| 416 | + OpBuilder<(ins "SymbolRefAttr":$callee, "TypeRange":$results, |
| 417 | + CArg<"ValueRange", "{}">:$operands), [{ |
| 418 | + $_state.addOperands(operands); |
| 419 | + $_state.addAttribute("callee", callee); |
| 420 | + $_state.addTypes(results); |
| 421 | + }]>, |
| 422 | + OpBuilder<(ins "StringAttr":$callee, "TypeRange":$results, |
| 423 | + CArg<"ValueRange", "{}">:$operands), [{ |
| 424 | + build($_builder, $_state, SymbolRefAttr::get(callee), results, operands); |
| 425 | + }]>, |
| 426 | + OpBuilder<(ins "StringRef":$callee, "TypeRange":$results, |
| 427 | + CArg<"ValueRange", "{}">:$operands), [{ |
| 428 | + build($_builder, $_state, StringAttr::get($_builder.getContext(), callee), |
| 429 | + results, operands); |
| 430 | + }]>]; |
| 431 | + |
| 432 | + let extraClassDeclaration = [{ |
| 433 | + FunctionType getCalleeType(); |
| 434 | + |
| 435 | + /// Get the argument operands to the called function. |
| 436 | + operand_range getArgOperands() { |
| 437 | + return {arg_operand_begin(), arg_operand_end()}; |
| 438 | + } |
| 439 | + |
| 440 | + MutableOperandRange getArgOperandsMutable() { |
| 441 | + return getOperandsMutable(); |
| 442 | + } |
| 443 | + |
| 444 | + operand_iterator arg_operand_begin() { return operand_begin(); } |
| 445 | + operand_iterator arg_operand_end() { return operand_end(); } |
| 446 | + |
| 447 | + /// Return the callee of this operation. |
| 448 | + CallInterfaceCallable getCallableForCallee() { |
| 449 | + return (*this)->getAttrOfType<SymbolRefAttr>("callee"); |
| 450 | + } |
| 451 | + |
| 452 | + /// Set the callee for this operation. |
| 453 | + void setCalleeFromCallable(CallInterfaceCallable callee) { |
| 454 | + (*this)->setAttr("callee", callee.get<SymbolRefAttr>()); |
| 455 | + } |
| 456 | + }]; |
| 457 | + |
| 458 | + let assemblyFormat = [{ |
| 459 | + $callee `(` $operands `)` attr-dict `:` functional-type($operands, results) |
| 460 | + }]; |
| 461 | +} |
| 462 | + |
| 463 | +def EmitC_FuncOp : EmitC_Op<"func", [ |
| 464 | + AutomaticAllocationScope, |
| 465 | + FunctionOpInterface, IsolatedFromAbove |
| 466 | +]> { |
| 467 | + let summary = "An operation with a name containing a single `SSACFG` region"; |
| 468 | + let description = [{ |
| 469 | + Operations within the function cannot implicitly capture values defined |
| 470 | + outside of the function, i.e. Functions are `IsolatedFromAbove`. All |
| 471 | + external references must use function arguments or attributes that establish |
| 472 | + a symbolic connection (e.g. symbols referenced by name via a string |
| 473 | + attribute like SymbolRefAttr). While the MLIR textual form provides a nice |
| 474 | + inline syntax for function arguments, they are internally represented as |
| 475 | + “block arguments” to the first block in the region. |
| 476 | + |
| 477 | + Only dialect attribute names may be specified in the attribute dictionaries |
| 478 | + for function arguments, results, or the function itself. |
| 479 | + |
| 480 | + Example: |
| 481 | + |
| 482 | + ```mlir |
| 483 | + // A function with no results: |
| 484 | + emitc.func @foo(%arg0 : i32) { |
| 485 | + emitc.call_opaque "bar" (%arg0) : (i32) -> () |
| 486 | + emitc.return |
| 487 | + } |
| 488 | + |
| 489 | + // A function with its argument as single result: |
| 490 | + emitc.func @foo(%arg0 : i32) -> i32 { |
| 491 | + emitc.return %arg0 : i32 |
| 492 | + } |
| 493 | + |
| 494 | + // A function with specifiers attribute: |
| 495 | + emitc.func @example_specifiers_fn_attr() -> i32 |
| 496 | + attributes {specifiers = ["static","inline"]} { |
| 497 | + %0 = emitc.call_opaque "foo" (): () -> i32 |
| 498 | + emitc.return %0 : i32 |
| 499 | + } |
| 500 | + |
| 501 | + ``` |
| 502 | + }]; |
| 503 | + let arguments = (ins SymbolNameAttr:$sym_name, |
| 504 | + TypeAttrOf<FunctionType>:$function_type, |
| 505 | + OptionalAttr<StrArrayAttr>:$specifiers, |
| 506 | + OptionalAttr<DictArrayAttr>:$arg_attrs, |
| 507 | + OptionalAttr<DictArrayAttr>:$res_attrs); |
| 508 | + let regions = (region AnyRegion:$body); |
| 509 | + |
| 510 | + let builders = [OpBuilder<(ins |
| 511 | + "StringRef":$name, "FunctionType":$type, |
| 512 | + CArg<"ArrayRef<NamedAttribute>", "{}">:$attrs, |
| 513 | + CArg<"ArrayRef<DictionaryAttr>", "{}">:$argAttrs) |
| 514 | + >]; |
| 515 | + let extraClassDeclaration = [{ |
| 516 | + //===------------------------------------------------------------------===// |
| 517 | + // FunctionOpInterface Methods |
| 518 | + //===------------------------------------------------------------------===// |
| 519 | + |
| 520 | + /// Returns the region on the current operation that is callable. This may |
| 521 | + /// return null in the case of an external callable object, e.g. an external |
| 522 | + /// function. |
| 523 | + ::mlir::Region *getCallableRegion() { return isExternal() ? nullptr : &getBody(); } |
| 524 | + |
| 525 | + /// Returns the argument types of this function. |
| 526 | + ArrayRef<Type> getArgumentTypes() { return getFunctionType().getInputs(); } |
| 527 | + |
| 528 | + /// Returns the result types of this function. |
| 529 | + ArrayRef<Type> getResultTypes() { return getFunctionType().getResults(); } |
| 530 | + }]; |
| 531 | + let hasCustomAssemblyFormat = 1; |
| 532 | + let hasVerifier = 1; |
| 533 | +} |
| 534 | + |
| 535 | +def EmitC_ReturnOp : EmitC_Op<"return", [Pure, HasParent<"FuncOp">, |
| 536 | + ReturnLike, Terminator]> { |
| 537 | + let summary = "Function return operation"; |
| 538 | + let description = [{ |
| 539 | + The `emitc.return` operation represents a return operation within a function. |
| 540 | + The operation takes zero or exactly one operand and produces no results. |
| 541 | + The operand number and type must match the signature of the function |
| 542 | + that contains the operation. |
| 543 | + |
| 544 | + Example: |
| 545 | + |
| 546 | + ```mlir |
| 547 | + emitc.func @foo() : (i32) { |
| 548 | + ... |
| 549 | + emitc.return %0 : i32 |
| 550 | + } |
| 551 | + ``` |
| 552 | + }]; |
| 553 | + let arguments = (ins Optional<AnyType>:$operand); |
| 554 | + |
| 555 | + let assemblyFormat = "attr-dict ($operand^ `:` type($operand))?"; |
| 556 | + let hasVerifier = 1; |
| 557 | +} |
| 558 | + |
389 | 559 | def EmitC_IncludeOp
|
390 | 560 | : EmitC_Op<"include", [HasParent<"ModuleOp">]> {
|
391 | 561 | let summary = "Include operation";
|
|
0 commit comments