clang 24.0.0git
CIRTypesDetails.h
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
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 contains implementation details, such as storage structures, of
10// CIR dialect types.
11//
12//===----------------------------------------------------------------------===//
13#ifndef CIR_DIALECT_IR_CIRTYPESDETAILS_H
14#define CIR_DIALECT_IR_CIRTYPESDETAILS_H
15
16#include "mlir/IR/AttrTypeSubElements.h"
17#include "mlir/IR/BuiltinAttributes.h"
18#include "mlir/Support/LogicalResult.h"
20#include "llvm/ADT/Hashing.h"
21
22namespace cir {
23namespace detail {
24
25//===----------------------------------------------------------------------===//
26// CIR StructTypeStorage
27//===----------------------------------------------------------------------===//
28
29/// Type storage for CIR struct/class types.
30struct StructTypeStorage : public mlir::TypeStorage {
45
47 mlir::StringAttr name;
49 bool packed;
52
54 bool incomplete, bool packed,
56 bool is_class)
59 assert((name || !incomplete) && "Incomplete records must have a name");
60 assert(member_kinds.size() == members.size() &&
61 "every member must say what it holds");
62 }
63
67
68 bool operator==(const KeyTy &key) const {
69 if (name)
70 return (name == key.name) && (is_class == key.is_class);
71 return std::tie(members, name, incomplete, packed, member_kinds,
72 is_class) == std::tie(key.members, key.name, key.incomplete,
73 key.packed, key.member_kinds,
74 key.is_class);
75 }
76
77 static llvm::hash_code hashKey(const KeyTy &key) {
78 if (key.name)
79 return llvm::hash_combine(key.name, key.is_class);
80 return llvm::hash_combine(key.members, key.incomplete, key.packed,
81 key.member_kinds, key.is_class);
82 }
83
84 static StructTypeStorage *construct(mlir::TypeStorageAllocator &allocator,
85 const KeyTy &key) {
86 return new (allocator.allocate<StructTypeStorage>()) StructTypeStorage(
87 allocator.copyInto(key.members), key.name, key.incomplete, key.packed,
88 allocator.copyInto(key.member_kinds), key.is_class);
89 }
90
91 /// Mutates the members and attributes of an identified struct/class.
92 llvm::LogicalResult mutate(mlir::TypeStorageAllocator &allocator,
95 if (!name)
96 return llvm::failure();
97
98 // A second completion must agree with the first in every parameter,
99 // including the kinds: otherwise it silently keeps the kinds it was given
100 // the first time.
101 if (!incomplete)
102 return mlir::success((this->members == members) &&
103 (this->packed == packed) &&
104 (this->member_kinds == memberKinds));
105
106 // mutate is the one entrance verify() never sees, so check the length here
107 // rather than leave it to an assert.
108 if (memberKinds.size() != members.size())
109 return llvm::failure();
110
111 this->members = allocator.copyInto(members);
112 this->packed = packed;
113 this->member_kinds = allocator.copyInto(memberKinds);
114 incomplete = false;
115 return llvm::success();
116 }
117};
118
119//===----------------------------------------------------------------------===//
120// CIR UnionTypeStorage
121//===----------------------------------------------------------------------===//
122
123/// Type storage for CIR union types.
124struct UnionTypeStorage : public mlir::TypeStorage {
139
141 mlir::StringAttr name;
143 bool packed;
144 mlir::Type padding;
146
148 bool incomplete, bool packed, mlir::Type padding,
152 assert((name || !incomplete) && "Incomplete records must have a name");
153 assert(member_kinds.size() == members.size() &&
154 "every member must say what it holds");
155 }
156
160
161 bool operator==(const KeyTy &key) const {
162 if (name)
163 return name == key.name;
164 return std::tie(members, name, incomplete, packed, padding, member_kinds) ==
165 std::tie(key.members, key.name, key.incomplete, key.packed,
166 key.padding, key.member_kinds);
167 }
168
169 static llvm::hash_code hashKey(const KeyTy &key) {
170 if (key.name)
171 return llvm::hash_combine(key.name);
172 return llvm::hash_combine(key.members, key.incomplete, key.packed,
173 key.padding, key.member_kinds);
174 }
175
176 static UnionTypeStorage *construct(mlir::TypeStorageAllocator &allocator,
177 const KeyTy &key) {
178 return new (allocator.allocate<UnionTypeStorage>()) UnionTypeStorage(
179 allocator.copyInto(key.members), key.name, key.incomplete, key.packed,
180 key.padding, allocator.copyInto(key.member_kinds));
181 }
182
183 /// Mutates the members and attributes of an identified union.
184 llvm::LogicalResult mutate(mlir::TypeStorageAllocator &allocator,
186 mlir::Type padding,
188 if (!name)
189 return llvm::failure();
190
191 // A second completion must agree with the first in every parameter,
192 // including the kinds: otherwise it silently keeps the kinds it was given
193 // the first time.
194 if (!incomplete)
195 return mlir::success(
196 (this->members == members) && (this->packed == packed) &&
197 (this->padding == padding) && (this->member_kinds == memberKinds));
198
199 // mutate is the one entrance verify() never sees, so check the length here
200 // rather than leave it to an assert.
201 if (memberKinds.size() != members.size())
202 return llvm::failure();
203
204 this->members = allocator.copyInto(members);
205 this->packed = packed;
206 this->padding = padding;
207 this->member_kinds = allocator.copyInto(memberKinds);
208 incomplete = false;
209 return llvm::success();
210 }
211};
212
213} // namespace detail
214} // namespace cir
215
216namespace mlir {
217
218/// Allow walking and replacing the subelements of a StructTypeStorage key.
219template <>
220struct AttrTypeSubElementHandler<cir::detail::StructTypeStorage::KeyTy> {
222 AttrTypeImmediateSubElementWalker &walker) {
223 walker.walkRange(param.members);
224 }
225 static FailureOr<cir::detail::StructTypeStorage::KeyTy>
227 AttrSubElementReplacements &attrRepls,
228 TypeSubElementReplacements &typeRepls) {
229 // TODO: It's not clear how we support replacing sub-elements of mutable
230 // types.
231 if (param.name)
232 return failure();
233
235 typeRepls.take_front(param.members.size()), param.name,
236 param.incomplete, param.packed, param.member_kinds, param.is_class);
237 }
238};
239
240/// Allow walking and replacing the subelements of a UnionTypeStorage key.
241template <>
242struct AttrTypeSubElementHandler<cir::detail::UnionTypeStorage::KeyTy> {
244 AttrTypeImmediateSubElementWalker &walker) {
245 walker.walkRange(param.members);
246 walker.walk(param.padding);
247 }
248 static FailureOr<cir::detail::UnionTypeStorage::KeyTy>
250 AttrSubElementReplacements &attrRepls,
251 TypeSubElementReplacements &typeRepls) {
252 // TODO: It's not clear how we support replacing sub-elements of mutable
253 // types.
254 if (param.name)
255 return failure();
256
257 llvm::ArrayRef<Type> members = typeRepls.take_front(param.members.size());
258 Type padding = param.padding ? typeRepls.take_front(1)[0] : Type();
259 return cir::detail::UnionTypeStorage::KeyTy(members, param.name,
260 param.incomplete, param.packed,
261 padding, param.member_kinds);
262 }
263};
264
265} // namespace mlir
266
267#endif // CIR_DIALECT_IR_CIRTYPESDETAILS_H
KeyTy(llvm::ArrayRef< mlir::Type > members, mlir::StringAttr name, bool incomplete, bool packed, llvm::ArrayRef< RecordMemberKind > member_kinds, bool is_class)
llvm::ArrayRef< RecordMemberKind > member_kinds
llvm::ArrayRef< mlir::Type > members
static llvm::hash_code hashKey(const KeyTy &key)
llvm::LogicalResult mutate(mlir::TypeStorageAllocator &allocator, llvm::ArrayRef< mlir::Type > members, bool packed, llvm::ArrayRef< RecordMemberKind > memberKinds)
Mutates the members and attributes of an identified struct/class.
llvm::ArrayRef< mlir::Type > members
static StructTypeStorage * construct(mlir::TypeStorageAllocator &allocator, const KeyTy &key)
bool operator==(const KeyTy &key) const
llvm::ArrayRef< RecordMemberKind > member_kinds
StructTypeStorage(llvm::ArrayRef< mlir::Type > members, mlir::StringAttr name, bool incomplete, bool packed, llvm::ArrayRef< RecordMemberKind > member_kinds, bool is_class)
llvm::ArrayRef< RecordMemberKind > member_kinds
llvm::ArrayRef< mlir::Type > members
KeyTy(llvm::ArrayRef< mlir::Type > members, mlir::StringAttr name, bool incomplete, bool packed, mlir::Type padding, llvm::ArrayRef< RecordMemberKind > member_kinds)
llvm::ArrayRef< mlir::Type > members
bool operator==(const KeyTy &key) const
static llvm::hash_code hashKey(const KeyTy &key)
static UnionTypeStorage * construct(mlir::TypeStorageAllocator &allocator, const KeyTy &key)
llvm::ArrayRef< RecordMemberKind > member_kinds
llvm::LogicalResult mutate(mlir::TypeStorageAllocator &allocator, llvm::ArrayRef< mlir::Type > members, bool packed, mlir::Type padding, llvm::ArrayRef< RecordMemberKind > memberKinds)
Mutates the members and attributes of an identified union.
UnionTypeStorage(llvm::ArrayRef< mlir::Type > members, mlir::StringAttr name, bool incomplete, bool packed, mlir::Type padding, llvm::ArrayRef< RecordMemberKind > member_kinds)
static void walk(const cir::detail::StructTypeStorage::KeyTy &param, AttrTypeImmediateSubElementWalker &walker)
static FailureOr< cir::detail::StructTypeStorage::KeyTy > replace(const cir::detail::StructTypeStorage::KeyTy &param, AttrSubElementReplacements &attrRepls, TypeSubElementReplacements &typeRepls)
static void walk(const cir::detail::UnionTypeStorage::KeyTy &param, AttrTypeImmediateSubElementWalker &walker)
static FailureOr< cir::detail::UnionTypeStorage::KeyTy > replace(const cir::detail::UnionTypeStorage::KeyTy &param, AttrSubElementReplacements &attrRepls, TypeSubElementReplacements &typeRepls)