clang 22.0.0git
Descriptor.cpp
Go to the documentation of this file.
1//===--- Descriptor.cpp - Types for the constexpr VM ------------*- C++ -*-===//
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#include "Descriptor.h"
10#include "Boolean.h"
11#include "FixedPoint.h"
12#include "Floating.h"
13#include "IntegralAP.h"
14#include "MemberPointer.h"
15#include "Pointer.h"
16#include "PrimType.h"
17#include "Record.h"
18#include "Source.h"
19#include "clang/AST/ExprCXX.h"
20
21using namespace clang;
22using namespace clang::interp;
23
24template <typename T> static constexpr bool needsCtor() {
25 if constexpr (std::is_same_v<T, Integral<8, true>> ||
26 std::is_same_v<T, Integral<8, false>> ||
27 std::is_same_v<T, Integral<16, true>> ||
28 std::is_same_v<T, Integral<16, false>> ||
29 std::is_same_v<T, Integral<32, true>> ||
30 std::is_same_v<T, Integral<32, false>> ||
31 std::is_same_v<T, Integral<64, true>> ||
32 std::is_same_v<T, Integral<64, false>> ||
33 std::is_same_v<T, Boolean>)
34 return false;
35
36 return true;
37}
38
39template <typename T>
40static void ctorTy(Block *, std::byte *Ptr, bool, bool, bool, bool, bool,
41 const Descriptor *) {
42 static_assert(needsCtor<T>());
43 new (Ptr) T();
44}
45
46template <typename T>
47static void dtorTy(Block *, std::byte *Ptr, const Descriptor *) {
48 static_assert(needsCtor<T>());
49 reinterpret_cast<T *>(Ptr)->~T();
50}
51
52template <typename T>
53static void ctorArrayTy(Block *, std::byte *Ptr, bool, bool, bool, bool, bool,
54 const Descriptor *D) {
55 new (Ptr) InitMapPtr(std::nullopt);
56
57 if constexpr (needsCtor<T>()) {
58 Ptr += sizeof(InitMapPtr);
59 for (unsigned I = 0, NE = D->getNumElems(); I < NE; ++I) {
60 new (&reinterpret_cast<T *>(Ptr)[I]) T();
61 }
62 }
63}
64
65template <typename T>
66static void dtorArrayTy(Block *, std::byte *Ptr, const Descriptor *D) {
67 InitMapPtr &IMP = *reinterpret_cast<InitMapPtr *>(Ptr);
68
69 if (IMP)
70 IMP = std::nullopt;
71
72 if constexpr (needsCtor<T>()) {
73 Ptr += sizeof(InitMapPtr);
74 for (unsigned I = 0, NE = D->getNumElems(); I < NE; ++I) {
75 reinterpret_cast<T *>(Ptr)[I].~T();
76 }
77 }
78}
79
80static void ctorArrayDesc(Block *B, std::byte *Ptr, bool IsConst,
81 bool IsMutable, bool IsVolatile, bool IsActive,
82 bool InUnion, const Descriptor *D) {
83 const unsigned NumElems = D->getNumElems();
84 const unsigned ElemSize =
85 D->ElemDesc->getAllocSize() + sizeof(InlineDescriptor);
86
87 unsigned ElemOffset = 0;
88 for (unsigned I = 0; I < NumElems; ++I, ElemOffset += ElemSize) {
89 auto *ElemPtr = Ptr + ElemOffset;
90 auto *Desc = reinterpret_cast<InlineDescriptor *>(ElemPtr);
91 auto *ElemLoc = reinterpret_cast<std::byte *>(Desc + 1);
92 auto *SD = D->ElemDesc;
93
94 Desc->Offset = ElemOffset + sizeof(InlineDescriptor);
95 Desc->Desc = SD;
96 Desc->IsInitialized = true;
97 Desc->IsBase = false;
98 Desc->IsActive = IsActive;
99 Desc->IsConst = IsConst || D->IsConst;
100 Desc->IsFieldMutable = IsMutable || D->IsMutable;
101 Desc->InUnion = InUnion;
102 Desc->IsArrayElement = true;
103 Desc->IsVolatile = IsVolatile;
104
105 if (auto Fn = D->ElemDesc->CtorFn)
106 Fn(B, ElemLoc, Desc->IsConst, Desc->IsFieldMutable, IsVolatile, IsActive,
107 Desc->InUnion || SD->isUnion(), D->ElemDesc);
108 }
109}
110
111static void dtorArrayDesc(Block *B, std::byte *Ptr, const Descriptor *D) {
112 const unsigned NumElems = D->getNumElems();
113 const unsigned ElemSize =
114 D->ElemDesc->getAllocSize() + sizeof(InlineDescriptor);
115
116 unsigned ElemOffset = 0;
117 auto Dtor = D->ElemDesc->DtorFn;
118 assert(Dtor &&
119 "a composite array without an elem dtor shouldn't have a dtor itself");
120 for (unsigned I = 0; I != NumElems; ++I, ElemOffset += ElemSize) {
121 auto *ElemPtr = Ptr + ElemOffset;
122 auto *Desc = reinterpret_cast<InlineDescriptor *>(ElemPtr);
123 auto *ElemLoc = reinterpret_cast<std::byte *>(Desc + 1);
124 Dtor(B, ElemLoc, D->ElemDesc);
125 }
126}
127
128static void initField(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable,
129 bool IsVolatile, bool IsActive, bool IsUnionField,
130 bool InUnion, const Descriptor *D, unsigned FieldOffset) {
131 auto *Desc = reinterpret_cast<InlineDescriptor *>(Ptr + FieldOffset) - 1;
132 Desc->Offset = FieldOffset;
133 Desc->Desc = D;
134 Desc->IsInitialized = D->IsArray;
135 Desc->IsBase = false;
136 Desc->IsActive = IsActive && !IsUnionField;
137 Desc->InUnion = InUnion;
138 Desc->IsConst = IsConst || D->IsConst;
139 Desc->IsFieldMutable = IsMutable || D->IsMutable;
140 Desc->IsVolatile = IsVolatile || D->IsVolatile;
141 // True if this field is const AND the parent is mutable.
142 Desc->IsConstInMutable = Desc->IsConst && IsMutable;
143
144 if (auto Fn = D->CtorFn)
145 Fn(B, Ptr + FieldOffset, Desc->IsConst, Desc->IsFieldMutable,
146 Desc->IsVolatile, Desc->IsActive, InUnion || D->isUnion(), D);
147}
148
149static void initBase(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable,
150 bool IsVolatile, bool IsActive, bool InUnion,
151 const Descriptor *D, unsigned FieldOffset,
152 bool IsVirtualBase) {
153 assert(D);
154 assert(D->ElemRecord);
155 assert(!D->ElemRecord->isUnion()); // Unions cannot be base classes.
156
157 auto *Desc = reinterpret_cast<InlineDescriptor *>(Ptr + FieldOffset) - 1;
158 Desc->Offset = FieldOffset;
159 Desc->Desc = D;
160 Desc->IsInitialized = D->IsArray;
161 Desc->IsBase = true;
162 Desc->IsVirtualBase = IsVirtualBase;
163 Desc->IsActive = IsActive && !InUnion;
164 Desc->IsConst = IsConst || D->IsConst;
165 Desc->IsFieldMutable = IsMutable || D->IsMutable;
166 Desc->InUnion = InUnion;
167 Desc->IsVolatile = false;
168
169 for (const auto &V : D->ElemRecord->bases())
170 initBase(B, Ptr + FieldOffset, IsConst, IsMutable, IsVolatile, IsActive,
171 InUnion, V.Desc, V.Offset, false);
172 for (const auto &F : D->ElemRecord->fields())
173 initField(B, Ptr + FieldOffset, IsConst, IsMutable, IsVolatile, IsActive,
174 InUnion, InUnion, F.Desc, F.Offset);
175}
176
177static void ctorRecord(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable,
178 bool IsVolatile, bool IsActive, bool InUnion,
179 const Descriptor *D) {
180 for (const auto &V : D->ElemRecord->bases())
181 initBase(B, Ptr, IsConst, IsMutable, IsVolatile, IsActive, InUnion, V.Desc,
182 V.Offset,
183 /*IsVirtualBase=*/false);
184 for (const auto &F : D->ElemRecord->fields()) {
185 bool IsUnionField = D->isUnion();
186 initField(B, Ptr, IsConst, IsMutable, IsVolatile, IsActive, IsUnionField,
187 InUnion || IsUnionField, F.Desc, F.Offset);
188 }
189 for (const auto &V : D->ElemRecord->virtual_bases())
190 initBase(B, Ptr, IsConst, IsMutable, IsVolatile, IsActive, InUnion, V.Desc,
191 V.Offset,
192 /*IsVirtualBase=*/true);
193}
194
195static void destroyField(Block *B, std::byte *Ptr, const Descriptor *D,
196 unsigned FieldOffset) {
197 if (auto Fn = D->DtorFn)
198 Fn(B, Ptr + FieldOffset, D);
199}
200
201static void destroyBase(Block *B, std::byte *Ptr, const Descriptor *D,
202 unsigned FieldOffset) {
203 assert(D);
204 assert(D->ElemRecord);
205
206 for (const auto &V : D->ElemRecord->bases())
207 destroyBase(B, Ptr + FieldOffset, V.Desc, V.Offset);
208 for (const auto &F : D->ElemRecord->fields())
209 destroyField(B, Ptr + FieldOffset, F.Desc, F.Offset);
210}
211
212static void dtorRecord(Block *B, std::byte *Ptr, const Descriptor *D) {
213 for (const auto &F : D->ElemRecord->bases())
214 destroyBase(B, Ptr, F.Desc, F.Offset);
215 for (const auto &F : D->ElemRecord->fields())
216 destroyField(B, Ptr, F.Desc, F.Offset);
217 for (const auto &F : D->ElemRecord->virtual_bases())
218 destroyBase(B, Ptr, F.Desc, F.Offset);
219}
220
221/// Whether a record needs its descriptor dtor function called.
222static bool needsRecordDtor(const Record *R) {
223 for (const auto &B : R->bases()) {
224 if (B.Desc->DtorFn)
225 return true;
226 }
227
228 for (const auto &F : R->fields()) {
229 if (F.Desc->DtorFn)
230 return true;
231 }
232
233 for (const auto &V : R->virtual_bases()) {
234 if (V.Desc->DtorFn)
235 return true;
236 }
237 return false;
238}
239
241 switch (T) {
242 case PT_Float:
243 return ctorTy<PrimConv<PT_Float>::T>;
244 case PT_IntAP:
245 return ctorTy<PrimConv<PT_IntAP>::T>;
246 case PT_IntAPS:
247 return ctorTy<PrimConv<PT_IntAPS>::T>;
248 case PT_Ptr:
249 return ctorTy<PrimConv<PT_Ptr>::T>;
250 case PT_MemberPtr:
251 return ctorTy<PrimConv<PT_MemberPtr>::T>;
252 default:
253 return nullptr;
254 }
255 llvm_unreachable("Unhandled PrimType");
256}
257
259 switch (T) {
260 case PT_Float:
261 return dtorTy<PrimConv<PT_Float>::T>;
262 case PT_IntAP:
263 return dtorTy<PrimConv<PT_IntAP>::T>;
264 case PT_IntAPS:
265 return dtorTy<PrimConv<PT_IntAPS>::T>;
266 case PT_Ptr:
267 return dtorTy<PrimConv<PT_Ptr>::T>;
268 case PT_MemberPtr:
269 return dtorTy<PrimConv<PT_MemberPtr>::T>;
270 default:
271 return nullptr;
272 }
273 llvm_unreachable("Unhandled PrimType");
274}
275
277 TYPE_SWITCH(Type, return ctorArrayTy<T>);
278 llvm_unreachable("unknown Expr");
279}
280
282 TYPE_SWITCH(Type, return dtorArrayTy<T>);
283 llvm_unreachable("unknown Expr");
284}
285
286/// Primitives.
288 MetadataSize MD, bool IsConst, bool IsTemporary,
289 bool IsMutable, bool IsVolatile)
290 : Source(D), SourceType(SourceTy), ElemSize(primSize(Type)), Size(ElemSize),
291 MDSize(MD.value_or(0)), AllocSize(align(Size + MDSize)), PrimT(Type),
292 IsConst(IsConst), IsMutable(IsMutable), IsTemporary(IsTemporary),
293 IsVolatile(IsVolatile), CtorFn(getCtorPrim(Type)),
294 DtorFn(getDtorPrim(Type)) {
295 assert(AllocSize >= Size);
296 assert(Source && "Missing source");
297}
298
299/// Primitive arrays.
301 size_t NumElems, bool IsConst, bool IsTemporary,
302 bool IsMutable)
303 : Source(D), ElemSize(primSize(Type)), Size(ElemSize * NumElems),
304 MDSize(MD.value_or(0)),
305 AllocSize(align(MDSize) + align(Size) + sizeof(InitMapPtr)), PrimT(Type),
306 IsConst(IsConst), IsMutable(IsMutable), IsTemporary(IsTemporary),
307 IsArray(true), CtorFn(getCtorArrayPrim(Type)),
308 DtorFn(getDtorArrayPrim(Type)) {
309 assert(Source && "Missing source");
310 assert(NumElems <= (MaxArrayElemBytes / ElemSize));
311}
312
313/// Primitive unknown-size arrays.
315 bool IsTemporary, bool IsConst, UnknownSize)
316 : Source(D), ElemSize(primSize(Type)), Size(UnknownSizeMark),
317 MDSize(MD.value_or(0)),
318 AllocSize(MDSize + sizeof(InitMapPtr) + alignof(void *)), PrimT(Type),
319 IsConst(IsConst), IsMutable(false), IsTemporary(IsTemporary),
320 IsArray(true), CtorFn(getCtorArrayPrim(Type)),
321 DtorFn(getDtorArrayPrim(Type)) {
322 assert(Source && "Missing source");
323}
324
325/// Arrays of composite elements.
326Descriptor::Descriptor(const DeclTy &D, const Type *SourceTy,
327 const Descriptor *Elem, MetadataSize MD,
328 unsigned NumElems, bool IsConst, bool IsTemporary,
329 bool IsMutable)
330 : Source(D), SourceType(SourceTy),
331 ElemSize(Elem->getAllocSize() + sizeof(InlineDescriptor)),
332 Size(ElemSize * NumElems), MDSize(MD.value_or(0)),
333 AllocSize(std::max<size_t>(alignof(void *), Size) + MDSize),
334 ElemDesc(Elem), IsConst(IsConst), IsMutable(IsMutable),
335 IsTemporary(IsTemporary), IsArray(true), CtorFn(ctorArrayDesc),
336 DtorFn(Elem->DtorFn ? dtorArrayDesc : nullptr) {
337 assert(Source && "Missing source");
338}
339
340/// Unknown-size arrays of composite elements.
342 bool IsTemporary, UnknownSize)
343 : Source(D), ElemSize(Elem->getAllocSize() + sizeof(InlineDescriptor)),
344 Size(UnknownSizeMark), MDSize(MD.value_or(0)),
345 AllocSize(MDSize + alignof(void *)), ElemDesc(Elem), IsConst(true),
346 IsMutable(false), IsTemporary(IsTemporary), IsArray(true),
347 CtorFn(ctorArrayDesc), DtorFn(Elem->DtorFn ? dtorArrayDesc : nullptr) {
348 assert(Source && "Missing source");
349}
350
351/// Composite records.
353 bool IsConst, bool IsTemporary, bool IsMutable,
354 bool IsVolatile)
355 : Source(D), ElemSize(std::max<size_t>(alignof(void *), R->getFullSize())),
356 Size(ElemSize), MDSize(MD.value_or(0)), AllocSize(Size + MDSize),
357 ElemRecord(R), IsConst(IsConst), IsMutable(IsMutable),
358 IsTemporary(IsTemporary), IsVolatile(IsVolatile), CtorFn(ctorRecord),
359 DtorFn(needsRecordDtor(R) ? dtorRecord : nullptr) {
360 assert(Source && "Missing source");
361}
362
363/// Dummy.
365 : Source(D), ElemSize(1), Size(1), MDSize(MD.value_or(0)),
366 AllocSize(MDSize), ElemRecord(nullptr), IsConst(true), IsMutable(false),
367 IsTemporary(false) {
368 assert(Source && "Missing source");
369}
370
372 if (SourceType)
373 return QualType(SourceType, 0);
374 if (const auto *D = asValueDecl())
375 return D->getType();
376 if (const auto *T = dyn_cast_if_present<TypeDecl>(asDecl()))
377 return T->getASTContext().getTypeDeclType(T);
378
379 // The Source sometimes has a different type than the once
380 // we really save. Try to consult the Record first.
381 if (isRecord()) {
382 const RecordDecl *RD = ElemRecord->getDecl();
383 return RD->getASTContext().getCanonicalTagType(RD);
384 }
385 if (const auto *E = asExpr())
386 return E->getType();
387 llvm_unreachable("Invalid descriptor type");
388}
389
391 assert(isArray());
392 QualType T = getType();
394 T = T->getPointeeType();
395
396 if (const auto *AT = T->getAsArrayTypeUnsafe()) {
397 // For primitive arrays, we don't save a QualType at all,
398 // just a PrimType. Try to figure out the QualType here.
399 if (isPrimitiveArray()) {
400 while (T->isArrayType())
402 return T;
403 }
404 return AT->getElementType();
405 }
406 if (const auto *CT = T->getAs<ComplexType>())
407 return CT->getElementType();
408 if (const auto *CT = T->getAs<VectorType>())
409 return CT->getElementType();
410
411 return T;
412}
413
415 auto MakeArrayType = [&](QualType ElemType) -> QualType {
416 if (IsArray)
417 return Ctx.getConstantArrayType(
418 ElemType, APInt(64, static_cast<uint64_t>(getNumElems()), false),
419 nullptr, ArraySizeModifier::Normal, 0);
420 return ElemType;
421 };
422
423 if (const auto *E = asExpr()) {
424 if (isa<CXXNewExpr>(E))
425 return MakeArrayType(E->getType()->getPointeeType());
426
427 // std::allocator.allocate() call.
428 if (const auto *ME = dyn_cast<CXXMemberCallExpr>(E);
429 ME && ME->getRecordDecl()->getName() == "allocator" &&
430 ME->getMethodDecl()->getName() == "allocate")
431 return MakeArrayType(E->getType()->getPointeeType());
432 return E->getType();
433 }
434
435 return getType();
436}
437
439 if (auto *D = dyn_cast<const Decl *>(Source))
440 return D->getLocation();
441 if (auto *E = dyn_cast<const Expr *>(Source))
442 return E->getExprLoc();
443 llvm_unreachable("Invalid descriptor type");
444}
445
447 if (const auto *D = dyn_cast<const Decl *>(Source))
448 return SourceInfo(D);
449 if (const auto *E = dyn_cast<const Expr *>(Source))
450 return SourceInfo(E);
451 llvm_unreachable("Invalid descriptor type");
452}
453
455 if (isPrimitive() || isPrimitiveArray())
456 return true;
457
458 if (isRecord()) {
459 assert(ElemRecord);
461 return !Dtor || Dtor->isTrivial();
462 }
463
464 if (!ElemDesc)
465 return true;
466 // Composite arrays.
467 return ElemDesc->hasTrivialDtor();
468}
469
470bool Descriptor::isUnion() const { return isRecord() && ElemRecord->isUnion(); }
471
473 : UninitFields(N), Data(std::make_unique<T[]>(numFields(N))) {}
474
475bool InitMap::initializeElement(unsigned I) {
476 unsigned Bucket = I / PER_FIELD;
477 T Mask = T(1) << (I % PER_FIELD);
478 if (!(data()[Bucket] & Mask)) {
479 data()[Bucket] |= Mask;
480 UninitFields -= 1;
481 }
482 return UninitFields == 0;
483}
484
485bool InitMap::isElementInitialized(unsigned I) const {
486 unsigned Bucket = I / PER_FIELD;
487 return data()[Bucket] & (T(1) << (I % PER_FIELD));
488}
#define V(N, I)
Definition: ASTContext.h:3597
const Decl * D
Expr * E
static void ctorRecord(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable, bool IsVolatile, bool IsActive, bool InUnion, const Descriptor *D)
Definition: Descriptor.cpp:177
static void dtorTy(Block *, std::byte *Ptr, const Descriptor *)
Definition: Descriptor.cpp:47
static BlockCtorFn getCtorArrayPrim(PrimType Type)
Definition: Descriptor.cpp:276
static void destroyField(Block *B, std::byte *Ptr, const Descriptor *D, unsigned FieldOffset)
Definition: Descriptor.cpp:195
static void initField(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable, bool IsVolatile, bool IsActive, bool IsUnionField, bool InUnion, const Descriptor *D, unsigned FieldOffset)
Definition: Descriptor.cpp:128
static void dtorArrayTy(Block *, std::byte *Ptr, const Descriptor *D)
Definition: Descriptor.cpp:66
static void ctorTy(Block *, std::byte *Ptr, bool, bool, bool, bool, bool, const Descriptor *)
Definition: Descriptor.cpp:40
static void ctorArrayDesc(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable, bool IsVolatile, bool IsActive, bool InUnion, const Descriptor *D)
Definition: Descriptor.cpp:80
static void destroyBase(Block *B, std::byte *Ptr, const Descriptor *D, unsigned FieldOffset)
Definition: Descriptor.cpp:201
static constexpr bool needsCtor()
Definition: Descriptor.cpp:24
static void dtorArrayDesc(Block *B, std::byte *Ptr, const Descriptor *D)
Definition: Descriptor.cpp:111
static BlockCtorFn getCtorPrim(PrimType T)
Definition: Descriptor.cpp:240
static bool needsRecordDtor(const Record *R)
Whether a record needs its descriptor dtor function called.
Definition: Descriptor.cpp:222
static BlockDtorFn getDtorArrayPrim(PrimType Type)
Definition: Descriptor.cpp:281
static void ctorArrayTy(Block *, std::byte *Ptr, bool, bool, bool, bool, bool, const Descriptor *D)
Definition: Descriptor.cpp:53
static BlockDtorFn getDtorPrim(PrimType T)
Definition: Descriptor.cpp:258
static void dtorRecord(Block *B, std::byte *Ptr, const Descriptor *D)
Definition: Descriptor.cpp:212
static void initBase(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable, bool IsVolatile, bool IsActive, bool InUnion, const Descriptor *D, unsigned FieldOffset, bool IsVirtualBase)
Definition: Descriptor.cpp:149
Defines the clang::Expr interface and subclasses for C++ expressions.
#define TYPE_SWITCH(Expr, B)
Definition: PrimType.h:207
__DEVICE__ int max(int __a, int __b)
__SIZE_TYPE__ size_t
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:188
QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize, const Expr *SizeExpr, ArraySizeModifier ASM, unsigned IndexTypeQuals) const
Return the unique reference to the type for a constant array of the specified element type.
CanQualType getCanonicalTagType(const TagDecl *TD) const
QualType getElementType() const
Definition: TypeBase.h:3750
Represents a C++ destructor within a class.
Definition: DeclCXX.h:2869
Complex values, per C99 6.2.5p11.
Definition: TypeBase.h:3293
ASTContext & getASTContext() const LLVM_READONLY
Definition: DeclBase.cpp:524
SourceLocation getLocation() const
Definition: DeclBase.h:439
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition: Expr.cpp:273
QualType getType() const
Definition: Expr.h:144
bool isTrivial() const
Whether this function is "trivial" in some specialized C++ senses.
Definition: Decl.h:2376
A (possibly-)qualified type.
Definition: TypeBase.h:937
Represents a struct/union/class.
Definition: Decl.h:4309
Encodes a location in the source.
The base class of the type hierarchy.
Definition: TypeBase.h:1833
bool isArrayType() const
Definition: TypeBase.h:8679
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition: Type.cpp:752
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
Definition: TypeBase.h:9212
bool isPointerOrReferenceType() const
Definition: TypeBase.h:8584
const T * getAs() const
Member-template getAs<specific type>'.
Definition: TypeBase.h:9159
Represents a GCC generic vector type.
Definition: TypeBase.h:4191
A memory block, either on the stack or in the heap.
Definition: InterpBlock.h:44
Structure/Class descriptor.
Definition: Record.h:25
const RecordDecl * getDecl() const
Returns the underlying declaration.
Definition: Record.h:53
bool isUnion() const
Checks if the record is a union.
Definition: Record.h:57
const CXXDestructorDecl * getDestructor() const
Returns the destructor of the record, if any.
Definition: Record.h:73
llvm::iterator_range< const_virtual_iter > virtual_bases() const
Definition: Record.h:99
llvm::iterator_range< const_base_iter > bases() const
Definition: Record.h:88
llvm::iterator_range< const_field_iter > fields() const
Definition: Record.h:80
Describes the statement/declaration an opcode was generated from.
Definition: Source.h:73
void(*)(Block *Storage, std::byte *FieldPtr, bool IsConst, bool IsMutable, bool IsVolatile, bool IsActive, bool InUnion, const Descriptor *FieldDesc) BlockCtorFn
Invoked whenever a block is created.
Definition: Descriptor.h:37
std::optional< std::pair< bool, std::shared_ptr< InitMap > > > InitMapPtr
Definition: Descriptor.h:30
llvm::APInt APInt
Definition: FixedPoint.h:19
bool NE(InterpState &S, CodePtr OpPC)
Definition: Interp.h:1260
void(*)(Block *Storage, std::byte *FieldPtr, const Descriptor *FieldDesc) BlockDtorFn
Invoked when a block is destroyed.
Definition: Descriptor.h:42
constexpr size_t align(size_t Size)
Aligns a size to the pointer alignment.
Definition: PrimType.h:185
PrimType
Enumeration of the primitive types of the VM.
Definition: PrimType.h:34
size_t primSize(PrimType Type)
Returns the size of a primitive type in bytes.
Definition: PrimType.cpp:23
llvm::PointerUnion< const Decl *, const Expr * > DeclTy
Definition: Descriptor.h:29
The JSON file list parser is used to communicate input to InstallAPI.
const FunctionProtoType * T
#define true
Definition: stdbool.h:25
#define false
Definition: stdbool.h:26
Token to denote structures of unknown size.
Definition: Descriptor.h:141
Describes a memory block created by an allocation site.
Definition: Descriptor.h:122
unsigned getNumElems() const
Returns the number of elements stored in the block.
Definition: Descriptor.h:249
bool isPrimitive() const
Checks if the descriptor is of a primitive.
Definition: Descriptor.h:263
QualType getElemQualType() const
Definition: Descriptor.cpp:390
bool hasTrivialDtor() const
Whether variables of this descriptor need their destructor called or not.
Definition: Descriptor.cpp:454
const ValueDecl * asValueDecl() const
Definition: Descriptor.h:214
static constexpr unsigned MaxArrayElemBytes
Maximum number of bytes to be used for array elements.
Definition: Descriptor.h:148
QualType getType() const
Definition: Descriptor.cpp:371
const Decl * asDecl() const
Definition: Descriptor.h:210
const Descriptor *const ElemDesc
Descriptor of the array element.
Definition: Descriptor.h:155
SourceInfo getLoc() const
Definition: Descriptor.cpp:446
Descriptor(const DeclTy &D, const Type *SourceTy, PrimType Type, MetadataSize MD, bool IsConst, bool IsTemporary, bool IsMutable, bool IsVolatile)
Allocates a descriptor for a primitive.
Definition: Descriptor.cpp:287
SourceLocation getLocation() const
Definition: Descriptor.cpp:438
QualType getDataType(const ASTContext &Ctx) const
Definition: Descriptor.cpp:414
std::optional< unsigned > MetadataSize
Definition: Descriptor.h:143
const bool IsArray
Flag indicating if the block is an array.
Definition: Descriptor.h:168
bool isPrimitiveArray() const
Checks if the descriptor is of an array of primitives.
Definition: Descriptor.h:254
bool isRecord() const
Checks if the descriptor is of a record.
Definition: Descriptor.h:268
const Record *const ElemRecord
Pointer to the record, if block contains records.
Definition: Descriptor.h:153
bool isUnion() const
Checks if the descriptor is of a union.
Definition: Descriptor.cpp:470
const Expr * asExpr() const
Definition: Descriptor.h:211
bool isArray() const
Checks if the descriptor is of an array.
Definition: Descriptor.h:266
InitMap(unsigned N)
Initializes the map with no fields set.
Definition: Descriptor.cpp:472
Inline descriptor embedded in structures and arrays.
Definition: Descriptor.h:67
unsigned Offset
Offset inside the structure/array.
Definition: Descriptor.h:69