1//===- BuiltinOps.td - Builtin operation definitions -------*- 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// Defines the set of builtin MLIR operations, or the set of operations
10// necessary for the validity of and defining the IR.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef BUILTIN_OPS
15#define BUILTIN_OPS
16
17include "mlir/IR/SymbolInterfaces.td"
18include "mlir/Interfaces/CallInterfaces.td"
19
20def Builtin_Dialect : Dialect {
21  let summary =
22    "A dialect containing the builtin Attributes, Operations, and Types";
23
24  let name = "";
25  let cppNamespace = "::mlir";
26}
27
28// Base class for Builtin dialect ops.
29class Builtin_Op<string mnemonic, list<OpTrait> traits = []> :
30    Op<Builtin_Dialect, mnemonic, traits>;
31
32//===----------------------------------------------------------------------===//
33// FuncOp
34//===----------------------------------------------------------------------===//
35
36def FuncOp : Builtin_Op<"func", [
37  AffineScope, AutomaticAllocationScope, CallableOpInterface, FunctionLike,
38  IsolatedFromAbove, Symbol
39]> {
40  let summary = "An operation with a name containing a single `SSACFG` region";
41  let description = [{
42    Operations within the function cannot implicitly capture values defined
43    outside of the function, i.e. Functions are `IsolatedFromAbove`. All
44    external references must use function arguments or attributes that establish
45    a symbolic connection (e.g. symbols referenced by name via a string
46    attribute like SymbolRefAttr). An external function declaration (used when
47    referring to a function declared in some other module) has no body. While
48    the MLIR textual form provides a nice inline syntax for function arguments,
49    they are internally represented as “block arguments” to the first block in
50    the region.
51
52    Only dialect attribute names may be specified in the attribute dictionaries
53    for function arguments, results, or the function itself.
54
55    Example:
56
57    ```mlir
58    // External function definitions.
59    func @abort()
60    func @scribble(i32, i64, memref<? x 128 x f32, #layout_map0>) -> f64
61
62    // A function that returns its argument twice:
63    func @count(%x: i64) -> (i64, i64)
64      attributes {fruit: "banana"} {
65      return %x, %x: i64, i64
66    }
67
68    // A function with an argument attribute
69    func @example_fn_arg(%x: i32 {swift.self = unit})
70
71    // A function with a result attribute
72    func @example_fn_result() -> (f64 {dialectName.attrName = 0 : i64})
73
74    // A function with an attribute
75    func @example_fn_attr() attributes {dialectName.attrName = false}
76    ```
77  }];
78
79  let arguments = (ins SymbolNameAttr:$sym_name,
80                       TypeAttr:$type,
81                       OptionalAttr<StrAttr>:$sym_visibility);
82  let regions = (region AnyRegion:$body);
83
84  let builders = [OpBuilderDAG<(ins
85    "StringRef":$name, "FunctionType":$type,
86    CArg<"ArrayRef<NamedAttribute>", "{}">:$attrs,
87    CArg<"ArrayRef<MutableDictionaryAttr>", "{}">:$argAttrs)
88  >];
89  let extraClassDeclaration = [{
90    static FuncOp create(Location location, StringRef name, FunctionType type,
91                         ArrayRef<NamedAttribute> attrs = {});
92    static FuncOp create(Location location, StringRef name, FunctionType type,
93                         iterator_range<dialect_attr_iterator> attrs);
94    static FuncOp create(Location location, StringRef name, FunctionType type,
95                         ArrayRef<NamedAttribute> attrs,
96                         ArrayRef<MutableDictionaryAttr> argAttrs);
97
98    /// Create a deep copy of this function and all of its blocks, remapping any
99    /// operands that use values outside of the function using the map that is
100    /// provided (leaving them alone if no entry is present). If the mapper
101    /// contains entries for function arguments, these arguments are not
102    /// included in the new function. Replaces references to cloned sub-values
103    /// with the corresponding value that is copied, and adds those mappings to
104    /// the mapper.
105    FuncOp clone(BlockAndValueMapping &mapper);
106    FuncOp clone();
107
108    /// Clone the internal blocks and attributes from this function into dest.
109    /// Any cloned blocks are appended to the back of dest. This function
110    /// asserts that the attributes of the current function and dest are
111    /// compatible.
112    void cloneInto(FuncOp dest, BlockAndValueMapping &mapper);
113
114    //===------------------------------------------------------------------===//
115    // CallableOpInterface
116    //===------------------------------------------------------------------===//
117
118    /// Returns the region on the current operation that is callable. This may
119    /// return null in the case of an external callable object, e.g. an external
120    /// function.
121    Region *getCallableRegion() { return isExternal() ? nullptr : &getBody(); }
122
123    /// Returns the results types that the callable region produces when
124    /// executed.
125    ArrayRef<Type> getCallableResults() { return getType().getResults(); }
126
127    //===------------------------------------------------------------------===//
128    // SymbolOpInterface Methods
129    //===------------------------------------------------------------------===//
130
131    bool isDeclaration() { return isExternal(); }
132
133  private:
134    // This trait needs access to the hooks defined below.
135    friend class OpTrait::FunctionLike<FuncOp>;
136
137    /// Returns the number of arguments. This is a hook for
138    /// OpTrait::FunctionLike.
139    unsigned getNumFuncArguments() { return getType().getInputs().size(); }
140
141    /// Returns the number of results. This is a hook for OpTrait::FunctionLike.
142    unsigned getNumFuncResults() { return getType().getResults().size(); }
143
144    /// Hook for OpTrait::FunctionLike, called after verifying that the 'type'
145    /// attribute is present and checks if it holds a function type. Ensures
146    /// getType, getNumFuncArguments, and getNumFuncResults can be called
147    /// safely.
148    LogicalResult verifyType() {
149      auto type = getTypeAttr().getValue();
150      if (!type.isa<FunctionType>())
151        return emitOpError("requires '" + getTypeAttrName() +
152                           "' attribute of function type");
153      return success();
154    }
155  }];
156  let parser = [{ return ::parseFuncOp(parser, result); }];
157  let printer = [{ return ::print(*this, p); }];
158  let verifier = [{ return ::verify(*this); }];
159}
160
161//===----------------------------------------------------------------------===//
162// ModuleOp
163//===----------------------------------------------------------------------===//
164
165def ModuleOp : Builtin_Op<"module", [
166  AffineScope, IsolatedFromAbove, NoRegionArguments, SymbolTable, Symbol,
167  SingleBlockImplicitTerminator<"ModuleTerminatorOp">
168]> {
169  let summary = "A top level container operation";
170  let description = [{
171    A `module` represents a top-level container operation. It contains a single
172    SSACFG region containing a single block which can contain any
173    operations. Operations within this region cannot implicitly capture values
174    defined outside the module, i.e. Modules are `IsolatedFromAbove`. Modules
175    have an optional symbol name which can be used to refer to them in
176    operations.
177
178    Example:
179
180    ```mlir
181    module {
182      func @foo()
183    }
184    ```
185  }];
186
187  let arguments = (ins OptionalAttr<SymbolNameAttr>:$sym_name,
188                       OptionalAttr<StrAttr>:$sym_visibility);
189  let regions = (region SizedRegion<1>:$body);
190
191  let assemblyFormat = "($sym_name^)? attr-dict-with-keyword $body";
192  let builders = [OpBuilderDAG<(ins CArg<"Optional<StringRef>", "{}">:$name)>];
193  let extraClassDeclaration = [{
194    /// Construct a module from the given location with an optional name.
195    static ModuleOp create(Location loc, Optional<StringRef> name = llvm::None);
196
197    /// Return the name of this module if present.
198    Optional<StringRef> getName() { return sym_name(); }
199
200    //===------------------------------------------------------------------===//
201    // SymbolOpInterface Methods
202    //===------------------------------------------------------------------===//
203
204    /// A ModuleOp may optionally define a symbol.
205    bool isOptionalSymbol() { return true; }
206  }];
207  let verifier = [{ return ::verify(*this); }];
208
209  // We need to ensure the block inside the region is properly terminated;
210  // the auto-generated builders do not guarantee that.
211  let skipDefaultBuilders = 1;
212}
213
214//===----------------------------------------------------------------------===//
215// ModuleTerminatorOp
216//===----------------------------------------------------------------------===//
217
218def ModuleTerminatorOp : Builtin_Op<"module_terminator", [
219  Terminator, HasParent<"ModuleOp">
220]> {
221  let summary = "A pseudo op that marks the end of a module";
222  let description = [{
223    `module_terminator` is a special terminator operation for the body of a
224    `module`, it has no semantic meaning beyond keeping the body of a `module`
225    well-formed.
226  }];
227  let assemblyFormat = "attr-dict";
228}
229
230#endif // BUILTIN_OPS
231