|
16 | 16 | #include "mlir/IR/BuiltinAttributes.h" |
17 | 17 | #include "mlir/IR/Types.h" |
18 | 18 | #include "mlir/Interfaces/DataLayoutInterfaces.h" |
19 | | -#include "clang/CIR/Interfaces/CIRFPTypeInterface.h" |
20 | | - |
21 | | -#include "clang/CIR/Interfaces/ASTAttrInterfaces.h" |
22 | | - |
23 | 19 | #include "clang/CIR/Dialect/IR/CIROpsEnums.h" |
24 | | - |
25 | | -//===----------------------------------------------------------------------===// |
26 | | -// CIR StructType |
27 | | -// |
28 | | -// The base type for all RecordDecls. |
29 | | -//===----------------------------------------------------------------------===// |
| 20 | +#include "clang/CIR/Interfaces/ASTAttrInterfaces.h" |
| 21 | +#include "clang/CIR/Interfaces/CIRFPTypeInterface.h" |
30 | 22 |
|
31 | 23 | namespace cir { |
32 | | - |
33 | 24 | namespace detail { |
34 | 25 | struct StructTypeStorage; |
35 | 26 | } // namespace detail |
36 | 27 |
|
37 | | -/// Each unique clang::RecordDecl is mapped to a `cir.struct` and any object in |
38 | | -/// C/C++ that has a struct type will have a `cir.struct` in CIR. |
39 | | -/// |
40 | | -/// There are three possible formats for this type: |
41 | | -/// |
42 | | -/// - Identified and complete structs: unique name and a known body. |
43 | | -/// - Identified and incomplete structs: unique name and unknown body. |
44 | | -/// - Anonymous structs: no name and a known body. |
45 | | -/// |
46 | | -/// Identified structs are uniqued by their name, and anonymous structs are |
47 | | -/// uniqued by their body. This means that two anonymous structs with the same |
48 | | -/// body will be the same type, and two identified structs with the same name |
49 | | -/// will be the same type. Attempting to build a struct with an existing name, |
50 | | -/// but a different body will result in an error. |
51 | | -/// |
52 | | -/// A few examples: |
53 | | -/// |
54 | | -/// ```mlir |
55 | | -/// !complete = !cir.struct<struct "complete" {!cir.int<u, 8>}> |
56 | | -/// !incomplete = !cir.struct<struct "incomplete" incomplete> |
57 | | -/// !anonymous = !cir.struct<struct {!cir.int<u, 8>}> |
58 | | -/// ``` |
59 | | -/// |
60 | | -/// Incomplete structs are mutable, meaning they can be later completed with a |
61 | | -/// body automatically updating in place every type in the code that uses the |
62 | | -/// incomplete struct. Mutability allows for recursive types to be represented, |
63 | | -/// meaning the struct can have members that refer to itself. This is useful for |
64 | | -/// representing recursive records and is implemented through a special syntax. |
65 | | -/// In the example below, the `Node` struct has a member that is a pointer to a |
66 | | -/// `Node` struct: |
67 | | -/// |
68 | | -/// ```mlir |
69 | | -/// !struct = !cir.struct<struct "Node" {!cir.ptr<!cir.struct<struct |
70 | | -/// "Node">>}> |
71 | | -/// ``` |
72 | | -class StructType |
73 | | - : public mlir::Type::TypeBase< |
74 | | - StructType, mlir::Type, detail::StructTypeStorage, |
75 | | - mlir::DataLayoutTypeInterface::Trait, mlir::TypeTrait::IsMutable> { |
76 | | - // FIXME(cir): migrate this type to Tablegen once mutable types are supported. |
77 | | -public: |
78 | | - using Base::Base; |
79 | | - using Base::getChecked; |
80 | | - using Base::verifyInvariants; |
81 | | - |
82 | | - static constexpr llvm::StringLiteral name = "cir.struct"; |
83 | | - |
84 | | - enum RecordKind : uint32_t { Class, Union, Struct }; |
85 | | - |
86 | | - /// Create an identified and complete struct type. |
87 | | - static StructType get(mlir::MLIRContext *context, |
88 | | - llvm::ArrayRef<mlir::Type> members, |
89 | | - mlir::StringAttr name, bool packed, bool padded, |
90 | | - RecordKind kind, ASTRecordDeclInterface ast = {}); |
91 | | - static StructType |
92 | | - getChecked(llvm::function_ref<mlir::InFlightDiagnostic()> emitError, |
93 | | - mlir::MLIRContext *context, llvm::ArrayRef<mlir::Type> members, |
94 | | - mlir::StringAttr name, bool packed, bool padded, RecordKind kind, |
95 | | - ASTRecordDeclInterface ast = {}); |
96 | | - |
97 | | - /// Create an identified and incomplete struct type. |
98 | | - static StructType get(mlir::MLIRContext *context, mlir::StringAttr name, |
99 | | - RecordKind kind); |
100 | | - static StructType |
101 | | - getChecked(llvm::function_ref<mlir::InFlightDiagnostic()> emitError, |
102 | | - mlir::MLIRContext *context, mlir::StringAttr name, |
103 | | - RecordKind kind); |
104 | | - |
105 | | - /// Create an anonymous struct type (always complete). |
106 | | - static StructType get(mlir::MLIRContext *context, |
107 | | - llvm::ArrayRef<mlir::Type> members, bool packed, |
108 | | - bool padded, RecordKind kind, |
109 | | - ASTRecordDeclInterface ast = {}); |
110 | | - static StructType |
111 | | - getChecked(llvm::function_ref<mlir::InFlightDiagnostic()> emitError, |
112 | | - mlir::MLIRContext *context, llvm::ArrayRef<mlir::Type> members, |
113 | | - bool packed, bool padded, RecordKind kind, |
114 | | - ASTRecordDeclInterface ast = {}); |
115 | | - |
116 | | - /// Validate the struct about to be constructed. |
117 | | - static llvm::LogicalResult |
118 | | - verifyInvariants(llvm::function_ref<mlir::InFlightDiagnostic()> emitError, |
119 | | - llvm::ArrayRef<mlir::Type> members, mlir::StringAttr name, |
120 | | - bool incomplete, bool packed, bool padded, |
121 | | - StructType::RecordKind kind, ASTRecordDeclInterface ast); |
122 | | - |
123 | | - // Parse/print methods. |
124 | | - static constexpr llvm::StringLiteral getMnemonic() { return {"struct"}; } |
125 | | - static mlir::Type parse(mlir::AsmParser &odsParser); |
126 | | - void print(mlir::AsmPrinter &odsPrinter) const; |
127 | | - |
128 | | - // Accessors |
129 | | - ASTRecordDeclInterface getAst() const; |
130 | | - llvm::ArrayRef<mlir::Type> getMembers() const; |
131 | | - mlir::StringAttr getName() const; |
132 | | - StructType::RecordKind getKind() const; |
133 | | - bool getIncomplete() const; |
134 | | - bool getPacked() const; |
135 | | - bool getPadded() const; |
136 | | - void dropAst(); |
137 | | - |
138 | | - // Predicates |
139 | | - bool isClass() const { return getKind() == RecordKind::Class; }; |
140 | | - bool isStruct() const { return getKind() == RecordKind::Struct; }; |
141 | | - bool isUnion() const { return getKind() == RecordKind::Union; }; |
142 | | - bool isComplete() const { return !isIncomplete(); }; |
143 | | - bool isIncomplete() const; |
144 | | - |
145 | | - // Utilities |
146 | | - mlir::Type getLargestMember(const mlir::DataLayout &dataLayout) const; |
147 | | - size_t getNumElements() const { return getMembers().size(); }; |
148 | | - std::string getKindAsStr() { |
149 | | - switch (getKind()) { |
150 | | - case RecordKind::Class: |
151 | | - return "class"; |
152 | | - case RecordKind::Union: |
153 | | - return "union"; |
154 | | - case RecordKind::Struct: |
155 | | - return "struct"; |
156 | | - } |
157 | | - llvm_unreachable("Invalid value for StructType::getKind()"); |
158 | | - } |
159 | | - std::string getPrefixedName() { |
160 | | - return getKindAsStr() + "." + getName().getValue().str(); |
161 | | - } |
162 | | - |
163 | | - /// Complete the struct type by mutating its members and attributes. |
164 | | - void complete(llvm::ArrayRef<mlir::Type> members, bool packed, bool isPadded, |
165 | | - ASTRecordDeclInterface ast = {}); |
166 | | - |
167 | | - /// DataLayoutTypeInterface methods. |
168 | | - llvm::TypeSize getTypeSizeInBits(const mlir::DataLayout &dataLayout, |
169 | | - mlir::DataLayoutEntryListRef params) const; |
170 | | - uint64_t getABIAlignment(const mlir::DataLayout &dataLayout, |
171 | | - mlir::DataLayoutEntryListRef params) const; |
172 | | - uint64_t getElementOffset(const mlir::DataLayout &dataLayout, |
173 | | - unsigned idx) const; |
174 | | - |
175 | | - bool isLayoutIdentical(const StructType &other); |
176 | | - |
177 | | - // Utilities for lazily computing and cacheing data layout info. |
178 | | -private: |
179 | | - // FIXME: currently opaque because there's a cycle if CIRTypes.types include |
180 | | - // from CIRAttrs.h. The implementation operates in terms of StructLayoutAttr |
181 | | - // instead. |
182 | | - mutable mlir::Attribute layoutInfo; |
183 | | - void computeSizeAndAlignment(const mlir::DataLayout &dataLayout) const; |
184 | | -}; |
185 | | - |
186 | 28 | bool isAnyFloatingPointType(mlir::Type t); |
187 | 29 | bool isScalarType(mlir::Type t); |
188 | 30 | bool isFPOrFPVectorTy(mlir::Type); |
|
0 commit comments