1//===-- TestTypeDefs.td - Test dialect type 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// TableGen data type definitions for Test dialect.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef TEST_TYPEDEFS
14#define TEST_TYPEDEFS
15
16// To get the test dialect def.
17include "TestOps.td"
18include "mlir/IR/BuiltinTypes.td"
19include "mlir/Interfaces/DataLayoutInterfaces.td"
20
21// All of the types will extend this class.
22class Test_Type<string name, list<Trait> traits = []>
23  : TypeDef<Test_Dialect, name, traits>;
24
25def SimpleTypeA : Test_Type<"SimpleA"> {
26  let mnemonic = "smpla";
27}
28
29// A more complex parameterized type.
30def CompoundTypeA : Test_Type<"CompoundA"> {
31  let mnemonic = "cmpnd_a";
32
33  // List of type parameters.
34  let parameters = (
35    ins
36    "int":$widthOfSomething,
37    "::mlir::Type":$oneType,
38    // This is special syntax since ArrayRefs require allocation in the
39    // constructor.
40    ArrayRefParameter<
41      "int", // The parameter C++ type.
42      "An example of an array of ints" // Parameter description.
43      >: $arrayOfInts
44  );
45
46  let extraClassDeclaration = [{
47    struct SomeCppStruct {};
48  }];
49}
50
51// An example of how one could implement a standard integer.
52def IntegerType : Test_Type<"TestInteger"> {
53  let mnemonic = "int";
54  let genVerifyDecl = 1;
55  let parameters = (
56    ins
57    "unsigned":$width,
58    // SignednessSemantics is defined below.
59    "::test::TestIntegerType::SignednessSemantics":$signedness
60  );
61
62  // We define the printer inline.
63  let printer = [{
64    $_printer << "int<";
65    printSignedness($_printer, getImpl()->signedness);
66    $_printer << ", " << getImpl()->width << ">";
67  }];
68
69  // Define custom builder methods.
70  let builders = [
71    TypeBuilder<(ins "unsigned":$width,
72                     CArg<"SignednessSemantics", "Signless">:$signedness), [{
73      return $_get($_ctxt, width, signedness);
74    }]>
75  ];
76  let skipDefaultBuilders = 1;
77
78  // The parser is defined here also.
79  let parser = [{
80    if (parser.parseLess()) return Type();
81    SignednessSemantics signedness;
82    if (parseSignedness($_parser, signedness)) return mlir::Type();
83    if ($_parser.parseComma()) return Type();
84    int width;
85    if ($_parser.parseInteger(width)) return Type();
86    if ($_parser.parseGreater()) return Type();
87    ::mlir::Location loc = $_parser.getEncodedSourceLoc($_parser.getNameLoc());
88    return getChecked(loc, loc.getContext(), width, signedness);
89  }];
90
91  // Any extra code one wants in the type's class declaration.
92  let extraClassDeclaration = [{
93    /// Signedness semantics.
94    enum SignednessSemantics {
95      Signless, /// No signedness semantics
96      Signed,   /// Signed integer
97      Unsigned, /// Unsigned integer
98    };
99
100    /// Return true if this is a signless integer type.
101    bool isSignless() const { return getSignedness() == Signless; }
102    /// Return true if this is a signed integer type.
103    bool isSigned() const { return getSignedness() == Signed; }
104    /// Return true if this is an unsigned integer type.
105    bool isUnsigned() const { return getSignedness() == Unsigned; }
106  }];
107}
108
109// A parent type for any type which is just a list of fields (e.g. structs,
110// unions).
111class FieldInfo_Type<string name> : Test_Type<name> {
112  let parameters = (
113    ins
114    // An ArrayRef of something which requires allocation in the storage
115    // constructor.
116    ArrayRefOfSelfAllocationParameter<
117      "::test::FieldInfo", // FieldInfo is defined/declared in TestTypes.h.
118      "Models struct fields">: $fields
119  );
120
121  // Prints the type in this format:
122  //   struct<[{field1Name, field1Type}, {field2Name, field2Type}]
123  let printer = [{
124    $_printer << "struct" << "<";
125    for (size_t i=0, e = getImpl()->fields.size(); i < e; i++) {
126      const auto& field = getImpl()->fields[i];
127      $_printer << "{" << field.name << "," << field.type << "}";
128      if (i < getImpl()->fields.size() - 1)
129          $_printer << ",";
130    }
131    $_printer << ">";
132  }];
133
134  // Parses the above format
135  let parser = [{
136    llvm::SmallVector<FieldInfo, 4> parameters;
137    if ($_parser.parseLess()) return Type();
138    while (mlir::succeeded($_parser.parseOptionalLBrace())) {
139      llvm::StringRef name;
140      if ($_parser.parseKeyword(&name)) return Type();
141      if ($_parser.parseComma()) return Type();
142      Type type;
143      if ($_parser.parseType(type)) return Type();
144      if ($_parser.parseRBrace()) return Type();
145      parameters.push_back(FieldInfo {name, type});
146      if ($_parser.parseOptionalComma()) break;
147    }
148    if ($_parser.parseGreater()) return Type();
149    return get($_ctxt, parameters);
150  }];
151}
152
153def StructType : FieldInfo_Type<"Struct"> {
154    let mnemonic = "struct";
155}
156
157def TestType : Test_Type<"Test", [
158  DeclareTypeInterfaceMethods<TestTypeInterface>
159]> {
160  let mnemonic = "test_type";
161}
162
163def TestTypeWithLayoutType : Test_Type<"TestTypeWithLayout", [
164  DeclareTypeInterfaceMethods<DataLayoutTypeInterface, ["areCompatible"]>
165]> {
166  let mnemonic = "test_type_with_layout";
167  let parameters = (ins "unsigned":$key);
168  let extraClassDeclaration = [{
169    ::mlir::LogicalResult verifyEntries(::mlir::DataLayoutEntryListRef params,
170                                ::mlir::Location loc) const;
171
172  private:
173    unsigned extractKind(::mlir::DataLayoutEntryListRef params,
174                         ::llvm::StringRef expectedKind) const;
175
176  public:
177  }];
178}
179
180def TestMemRefElementType : Test_Type<"TestMemRefElementType",
181                                      [MemRefElementTypeInterface]> {
182  let mnemonic = "memref_element";
183}
184
185def TestTypeTrait : NativeTypeTrait<"TestTypeTrait">;
186
187// The definition of a singleton type that has a trait.
188def TestTypeWithTrait : Test_Type<"TestTypeWithTrait", [TestTypeTrait]> {
189  let mnemonic = "test_type_with_trait";
190}
191
192#endif // TEST_TYPEDEFS
193