xref: /llvm-project/mlir/include/mlir/Dialect/LLVMIR/LLVMInterfaces.td (revision 40afff7bd95090a75bc68a0d26b8017cc0ae65c1)
1//===-- LLVMInterfaces.td - LLVM 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 defines interfaces for the LLVM dialect in MLIR.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVMIR_INTERFACES
14#define LLVMIR_INTERFACES
15
16include "mlir/IR/OpBase.td"
17
18def FastmathFlagsInterface : OpInterface<"FastmathFlagsInterface"> {
19  let description = [{
20    Access to op fastmath flags.
21  }];
22
23  let cppNamespace = "::mlir::LLVM";
24
25  let methods = [
26    InterfaceMethod<
27      /*desc=*/        "Returns a FastmathFlagsAttr attribute for the operation",
28      /*returnType=*/  "::mlir::LLVM::FastmathFlagsAttr",
29      /*methodName=*/  "getFastmathAttr",
30      /*args=*/        (ins),
31      /*methodBody=*/  [{}],
32      /*defaultImpl=*/ [{
33        auto op = cast<ConcreteOp>(this->getOperation());
34        return op.getFastmathFlagsAttr();
35      }]
36      >,
37    StaticInterfaceMethod<
38      /*desc=*/        [{Returns the name of the FastmathFlagsAttr attribute
39                         for the operation}],
40      /*returnType=*/  "::llvm::StringRef",
41      /*methodName=*/  "getFastmathAttrName",
42      /*args=*/        (ins),
43      /*methodBody=*/  [{}],
44      /*defaultImpl=*/ [{
45        return "fastmathFlags";
46      }]
47      >
48  ];
49}
50
51def IntegerOverflowFlagsInterface : OpInterface<"IntegerOverflowFlagsInterface"> {
52  let description = [{
53    This interface defines an LLVM operation with integer overflow flags and
54    provides a uniform API for accessing them.
55  }];
56
57  let cppNamespace = "::mlir::LLVM";
58
59  let methods = [
60    InterfaceMethod<[{
61      Get the integer overflow flags for the operation.
62    }], "IntegerOverflowFlags", "getOverflowFlags", (ins), [{}], [{
63      return $_op.getProperties().overflowFlags;
64    }]>,
65    InterfaceMethod<[{
66      Set the integer overflow flags for the operation.
67    }], "void", "setOverflowFlags", (ins "IntegerOverflowFlags":$flags), [{}], [{
68      $_op.getProperties().overflowFlags = flags;
69    }]>,
70    InterfaceMethod<[{
71      Returns whether the operation has the No Unsigned Wrap keyword.
72    }], "bool", "hasNoUnsignedWrap", (ins), [{}], [{
73      return bitEnumContainsAll($_op.getOverflowFlags(),
74                                IntegerOverflowFlags::nuw);
75    }]>,
76    InterfaceMethod<[{
77      Returns whether the operation has the No Signed Wrap keyword.
78    }], "bool", "hasNoSignedWrap", (ins), [{}], [{
79      return bitEnumContainsAll($_op.getOverflowFlags(),
80                                IntegerOverflowFlags::nsw);
81    }]>,
82    StaticInterfaceMethod<[{
83      Get the attribute name of the overflow flags property.
84    }], "StringRef", "getOverflowFlagsAttrName", (ins), [{}], [{
85      return "overflowFlags";
86    }]>,
87  ];
88}
89
90def ExactFlagInterface : OpInterface<"ExactFlagInterface"> {
91  let description = [{
92    This interface defines an LLVM operation with an exact flag and
93    provides a uniform API for accessing it.
94  }];
95
96  let cppNamespace = "::mlir::LLVM";
97
98  let methods = [
99    InterfaceMethod<[{
100      Get the exact flag for the operation.
101    }], "bool", "getIsExact", (ins), [{}], [{
102      return $_op.getProperties().isExact;
103    }]>,
104    InterfaceMethod<[{
105      Set the exact flag for the operation.
106    }], "void", "setIsExact", (ins "bool":$isExact), [{}], [{
107      $_op.getProperties().isExact = isExact;
108    }]>,
109    StaticInterfaceMethod<[{
110      Get the attribute name of the isExact property.
111    }], "StringRef", "getIsExactName", (ins), [{}], [{
112      return "isExact";
113    }]>,
114  ];
115}
116
117def DisjointFlagInterface : OpInterface<"DisjointFlagInterface"> {
118  let description = [{
119    This interface defines an LLVM operation with a disjoint flag and
120    provides a uniform API for accessing it.
121  }];
122
123  let cppNamespace = "::mlir::LLVM";
124
125  let methods = [
126    InterfaceMethod<[{
127      Get the disjoint flag for the operation.
128    }], "bool", "getIsDisjoint", (ins), [{}], [{
129      return $_op.getProperties().isDisjoint;
130    }]>,
131    InterfaceMethod<[{
132      Set the disjoint flag for the operation.
133    }], "void", "setIsDisjoint", (ins "bool":$isDisjoint), [{}], [{
134      $_op.getProperties().isDisjoint = isDisjoint;
135    }]>,
136    StaticInterfaceMethod<[{
137      Get the attribute name of the isDisjoint property.
138    }], "StringRef", "getIsDisjointName", (ins), [{}], [{
139      return "isDisjoint";
140    }]>,
141  ];
142}
143
144def NonNegFlagInterface : OpInterface<"NonNegFlagInterface"> {
145  let description = [{
146    This interface defines an LLVM operation with an nneg flag and
147    provides a uniform API for accessing it.
148  }];
149
150  let cppNamespace = "::mlir::LLVM";
151
152  let methods = [
153    InterfaceMethod<[{
154      Get the nneg flag for the operation.
155    }], "bool", "getNonNeg", (ins), [{}], [{
156      return $_op.getProperties().nonNeg;
157    }]>,
158    InterfaceMethod<[{
159      Set the nneg flag for the operation.
160    }], "void", "setNonNeg", (ins "bool":$nonNeg), [{}], [{
161      $_op.getProperties().nonNeg = nonNeg;
162    }]>,
163    StaticInterfaceMethod<[{
164      Get the attribute name of the nonNeg property.
165    }], "StringRef", "getNonNegName", (ins), [{}], [{
166      return "nonNeg";
167    }]>,
168  ];
169}
170
171def BranchWeightOpInterface : OpInterface<"BranchWeightOpInterface"> {
172  let description = [{
173    An interface for operations that can carry branch weights metadata. It
174    provides setters and getters for the operation's branch weights attribute.
175    The default implementation of the interface methods expect the operation to
176    have an attribute of type DenseI32ArrayAttr named branch_weights.
177  }];
178
179  let cppNamespace = "::mlir::LLVM";
180
181  let methods = [
182    InterfaceMethod<
183      /*desc=*/        "Returns the branch weights attribute or nullptr",
184      /*returnType=*/  "::mlir::DenseI32ArrayAttr",
185      /*methodName=*/  "getBranchWeightsOrNull",
186      /*args=*/        (ins),
187      /*methodBody=*/  [{}],
188      /*defaultImpl=*/ [{
189        auto op = cast<ConcreteOp>(this->getOperation());
190        return op.getBranchWeightsAttr();
191      }]
192      >,
193    InterfaceMethod<
194      /*desc=*/        "Sets the branch weights attribute",
195      /*returnType=*/  "void",
196      /*methodName=*/  "setBranchWeights",
197      /*args=*/        (ins "::mlir::DenseI32ArrayAttr":$attr),
198      /*methodBody=*/  [{}],
199      /*defaultImpl=*/ [{
200        auto op = cast<ConcreteOp>(this->getOperation());
201        op.setBranchWeightsAttr(attr);
202      }]
203      >
204  ];
205}
206
207def AccessGroupOpInterface : OpInterface<"AccessGroupOpInterface"> {
208  let description = [{
209    An interface for memory operations that can carry access groups metadata.
210    It provides setters and getters for the operation's access groups attribute.
211    The default implementations of the interface methods expect the operation
212    to have an attribute of type ArrayAttr named access_groups.
213  }];
214
215  let cppNamespace = "::mlir::LLVM";
216  let verify = [{ return detail::verifyAccessGroupOpInterface($_op); }];
217
218  let methods = [
219    InterfaceMethod<
220      /*desc=*/        "Returns the access groups attribute or nullptr",
221      /*returnType=*/  "::mlir::ArrayAttr",
222      /*methodName=*/  "getAccessGroupsOrNull",
223      /*args=*/        (ins),
224      /*methodBody=*/  [{}],
225      /*defaultImpl=*/ [{
226        auto op = cast<ConcreteOp>(this->getOperation());
227        return op.getAccessGroupsAttr();
228      }]
229      >,
230    InterfaceMethod<
231      /*desc=*/        "Sets the access groups attribute",
232      /*returnType=*/  "void",
233      /*methodName=*/  "setAccessGroups",
234      /*args=*/        (ins "const ::mlir::ArrayAttr":$attr),
235      /*methodBody=*/  [{}],
236      /*defaultImpl=*/ [{
237        auto op = cast<ConcreteOp>(this->getOperation());
238        op.setAccessGroupsAttr(attr);
239      }]
240      >
241  ];
242}
243
244def AliasAnalysisOpInterface : OpInterface<"AliasAnalysisOpInterface"> {
245  let description = [{
246    An interface for memory operations that can carry alias analysis metadata.
247    It provides setters and getters for the operation's alias analysis
248    attributes. The default implementations of the interface methods expect
249    the operation to have attributes of type ArrayAttr named alias_scopes,
250    noalias_scopes, and tbaa.
251  }];
252
253  let cppNamespace = "::mlir::LLVM";
254  let verify = [{ return detail::verifyAliasAnalysisOpInterface($_op); }];
255
256  let methods = [
257    InterfaceMethod<
258      /*desc=*/        "Returns the alias scopes attribute or nullptr",
259      /*returnType=*/  "::mlir::ArrayAttr",
260      /*methodName=*/  "getAliasScopesOrNull",
261      /*args=*/        (ins),
262      /*methodBody=*/  [{}],
263      /*defaultImpl=*/ [{
264        auto op = cast<ConcreteOp>(this->getOperation());
265        return op.getAliasScopesAttr();
266      }]
267      >,
268    InterfaceMethod<
269      /*desc=*/        "Sets the alias scopes attribute",
270      /*returnType=*/  "void",
271      /*methodName=*/  "setAliasScopes",
272      /*args=*/        (ins "const ::mlir::ArrayAttr":$attr),
273      /*methodBody=*/  [{}],
274      /*defaultImpl=*/ [{
275        auto op = cast<ConcreteOp>(this->getOperation());
276        op.setAliasScopesAttr(attr);
277      }]
278      >,
279    InterfaceMethod<
280      /*desc=*/        "Returns the noalias scopes attribute or nullptr",
281      /*returnType=*/  "::mlir::ArrayAttr",
282      /*methodName=*/  "getNoAliasScopesOrNull",
283      /*args=*/        (ins),
284      /*methodBody=*/  [{}],
285      /*defaultImpl=*/ [{
286        auto op = cast<ConcreteOp>(this->getOperation());
287        return op.getNoaliasScopesAttr();
288      }]
289      >,
290    InterfaceMethod<
291      /*desc=*/        "Sets the noalias scopes attribute",
292      /*returnType=*/  "void",
293      /*methodName=*/  "setNoAliasScopes",
294      /*args=*/        (ins "const ::mlir::ArrayAttr":$attr),
295      /*methodBody=*/  [{}],
296      /*defaultImpl=*/ [{
297        auto op = cast<ConcreteOp>(this->getOperation());
298        op.setNoaliasScopesAttr(attr);
299      }]
300      >,
301    InterfaceMethod<
302      /*desc=*/        "Returns the tbaa attribute or nullptr",
303      /*returnType=*/  "::mlir::ArrayAttr",
304      /*methodName=*/  "getTBAATagsOrNull",
305      /*args=*/        (ins),
306      /*methodBody=*/  [{}],
307      /*defaultImpl=*/ [{
308        auto op = cast<ConcreteOp>(this->getOperation());
309        return op.getTbaaAttr();
310      }]
311      >,
312    InterfaceMethod<
313      /*desc=*/        "Sets the tbaa attribute",
314      /*returnType=*/  "void",
315      /*methodName=*/  "setTBAATags",
316      /*args=*/        (ins "const ::mlir::ArrayAttr":$attr),
317      /*methodBody=*/  [{}],
318      /*defaultImpl=*/ [{
319        auto op = cast<ConcreteOp>(this->getOperation());
320        op.setTbaaAttr(attr);
321      }]
322      >,
323    InterfaceMethod<
324      /*desc=*/        "Returns a list of all pointer operands accessed by the "
325                       "operation",
326      /*returnType=*/  "::llvm::SmallVector<::mlir::Value>",
327      /*methodName=*/  "getAccessedOperands",
328      /*args=*/        (ins)
329      >
330  ];
331}
332
333def FPExceptionBehaviorOpInterface : OpInterface<"FPExceptionBehaviorOpInterface"> {
334  let description = [{
335    An interface for operations receiving an exception behavior attribute
336    controlling FP exception behavior.
337  }];
338
339  let cppNamespace = "::mlir::LLVM";
340
341  let methods = [
342    InterfaceMethod<
343      /*desc=*/        "Returns a FPExceptionBehavior attribute for the operation",
344      /*returnType=*/  "::mlir::LLVM::FPExceptionBehaviorAttr",
345      /*methodName=*/  "getFPExceptionBehaviorAttr",
346      /*args=*/        (ins),
347      /*methodBody=*/  [{}],
348      /*defaultImpl=*/ [{
349        auto op = cast<ConcreteOp>(this->getOperation());
350        return op.getFpExceptionBehaviorAttr();
351      }]
352    >,
353    StaticInterfaceMethod<
354      /*desc=*/        [{Returns the name of the FPExceptionBehaviorAttr
355                        attribute for the operation}],
356      /*returnType=*/  "::llvm::StringRef",
357      /*methodName=*/  "getFPExceptionBehaviorAttrName",
358      /*args=*/        (ins),
359      /*methodBody=*/  [{}],
360      /*defaultImpl=*/ [{
361        return "fpExceptionBehavior";
362      }]
363    >
364  ];
365}
366
367def RoundingModeOpInterface : OpInterface<"RoundingModeOpInterface"> {
368  let description = [{
369    An interface for operations receiving a rounding mode attribute
370    controlling FP rounding mode.
371  }];
372
373  let cppNamespace = "::mlir::LLVM";
374
375  let methods = [
376    InterfaceMethod<
377      /*desc=*/        "Returns a RoundingMode attribute for the operation",
378      /*returnType=*/  "::mlir::LLVM::RoundingModeAttr",
379      /*methodName=*/  "getRoundingModeAttr",
380      /*args=*/        (ins),
381      /*methodBody=*/  [{}],
382      /*defaultImpl=*/ [{
383        auto op = cast<ConcreteOp>(this->getOperation());
384        return op.getRoundingmodeAttr();
385      }]
386    >,
387    StaticInterfaceMethod<
388      /*desc=*/        [{Returns the name of the RoundingModeAttr attribute
389                         for the operation}],
390      /*returnType=*/  "::llvm::StringRef",
391      /*methodName=*/  "getRoundingModeAttrName",
392      /*args=*/        (ins),
393      /*methodBody=*/  [{}],
394      /*defaultImpl=*/ [{
395        return "roundingmode";
396      }]
397    >,
398  ];
399}
400
401//===----------------------------------------------------------------------===//
402// LLVM dialect type interfaces.
403//===----------------------------------------------------------------------===//
404
405// An interface for LLVM pointer element types.
406def LLVM_PointerElementTypeInterface
407    : TypeInterface<"PointerElementTypeInterface"> {
408  let cppNamespace = "::mlir::LLVM";
409
410  let description = [{
411    An interface for types that are allowed as elements of LLVM pointer type.
412    Such types must have a size.
413  }];
414
415  let methods = [
416    InterfaceMethod<
417      /*description=*/"Returns the size of the type in bytes.",
418      /*retTy=*/"unsigned",
419      /*methodName=*/"getSizeInBytes",
420      /*args=*/(ins "const ::mlir::DataLayout &":$dataLayout),
421      /*methodBody=*/"",
422      /*defaultImplementation=*/[{
423        return dataLayout.getTypeSize($_type);
424      }]
425    >
426  ];
427}
428
429//===----------------------------------------------------------------------===//
430// LLVM dialect attr interfaces.
431//===----------------------------------------------------------------------===//
432
433def LLVM_DIRecursiveTypeAttrInterface
434  : AttrInterface<"DIRecursiveTypeAttrInterface"> {
435  let description = [{
436    This attribute represents a DITypeAttr that is recursive. Only DITypeAttrs
437    that translate to LLVM DITypes that support mutation should implement this
438    interface.
439
440    There are two modes for conforming attributes:
441
442    1. "rec-decl":
443      - This attr is a recursive declaration identified by a recId.
444
445    2. "rec-self":
446      - This attr is considered a recursive self reference.
447      - This attr itself is a placeholder type that should be conceptually
448        replaced with the closest parent attr of the same type with the same
449        recId.
450
451    For example, to represent a linked list struct:
452
453      #rec_self = di_composite_type<recId = 0>
454      #ptr = di_derived_type<baseType: #rec_self, ...>
455      #field = di_derived_type<name = "next", baseType: #ptr, ...>
456      #rec = di_composite_type<recId = 0, name = "Node", elements: #field, ...>
457      #var = di_local_variable<type = #rec, ...>
458
459    Note that a rec-self without an outer rec-decl with the same recId is
460    conceptually the same as an "unbound" variable. The context needs to provide
461    meaning to the rec-self.
462  }];
463  let cppNamespace = "::mlir::LLVM";
464  let methods = [
465    InterfaceMethod<[{
466      Get whether this attr describes a recursive self reference.
467    }], "bool", "getIsRecSelf", (ins)>,
468    InterfaceMethod<[{
469      Get the recursive ID used for matching "rec-decl" with "rec-self".
470      If this attr instance is not recursive, return a null attribute.
471    }], "DistinctAttr", "getRecId", (ins)>,
472    InterfaceMethod<[{
473      Get a copy of this type attr but with the recursive ID set to `recId`.
474    }], "DIRecursiveTypeAttrInterface", "withRecId",
475    (ins "DistinctAttr":$recId)>,
476    StaticInterfaceMethod<[{
477      Build a rec-self instance using the provided `recId`.
478    }], "DIRecursiveTypeAttrInterface", "getRecSelf",
479    (ins "DistinctAttr":$recId)>
480  ];
481}
482
483#endif // LLVMIR_INTERFACES
484