clang 20.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
20using namespace clang;
21using namespace clang::interp;
22
23template <typename T>
24static void ctorTy(Block *, std::byte *Ptr, bool, bool, bool, bool,
25 const Descriptor *) {
26 new (Ptr) T();
27}
28
29template <typename T>
30static void dtorTy(Block *, std::byte *Ptr, const Descriptor *) {
31 reinterpret_cast<T *>(Ptr)->~T();
32}
33
34template <typename T>
35static void moveTy(Block *, std::byte *Src, std::byte *Dst,
36 const Descriptor *) {
37 auto *SrcPtr = reinterpret_cast<T *>(Src);
38 auto *DstPtr = reinterpret_cast<T *>(Dst);
39 new (DstPtr) T(std::move(*SrcPtr));
40}
41
42template <typename T>
43static void ctorArrayTy(Block *, std::byte *Ptr, bool, bool, bool, bool,
44 const Descriptor *D) {
45 new (Ptr) InitMapPtr(std::nullopt);
46
47 Ptr += sizeof(InitMapPtr);
48 for (unsigned I = 0, NE = D->getNumElems(); I < NE; ++I) {
49 new (&reinterpret_cast<T *>(Ptr)[I]) T();
50 }
51}
52
53template <typename T>
54static void dtorArrayTy(Block *, std::byte *Ptr, const Descriptor *D) {
55 InitMapPtr &IMP = *reinterpret_cast<InitMapPtr *>(Ptr);
56
57 if (IMP)
58 IMP = std::nullopt;
59 Ptr += sizeof(InitMapPtr);
60 for (unsigned I = 0, NE = D->getNumElems(); I < NE; ++I) {
61 reinterpret_cast<T *>(Ptr)[I].~T();
62 }
63}
64
65template <typename T>
66static void moveArrayTy(Block *, std::byte *Src, std::byte *Dst,
67 const Descriptor *D) {
68 InitMapPtr &SrcIMP = *reinterpret_cast<InitMapPtr *>(Src);
69 if (SrcIMP) {
70 // We only ever invoke the moveFunc when moving block contents to a
71 // DeadBlock. DeadBlocks don't need InitMaps, so we destroy them here.
72 SrcIMP = std::nullopt;
73 }
74 Src += sizeof(InitMapPtr);
75 Dst += sizeof(InitMapPtr);
76 for (unsigned I = 0, NE = D->getNumElems(); I < NE; ++I) {
77 auto *SrcPtr = &reinterpret_cast<T *>(Src)[I];
78 auto *DstPtr = &reinterpret_cast<T *>(Dst)[I];
79 new (DstPtr) T(std::move(*SrcPtr));
80 }
81}
82
83static void ctorArrayDesc(Block *B, std::byte *Ptr, bool IsConst,
84 bool IsMutable, bool IsActive, bool InUnion,
85 const Descriptor *D) {
86 const unsigned NumElems = D->getNumElems();
87 const unsigned ElemSize =
88 D->ElemDesc->getAllocSize() + sizeof(InlineDescriptor);
89
90 unsigned ElemOffset = 0;
91 for (unsigned I = 0; I < NumElems; ++I, ElemOffset += ElemSize) {
92 auto *ElemPtr = Ptr + ElemOffset;
93 auto *Desc = reinterpret_cast<InlineDescriptor *>(ElemPtr);
94 auto *ElemLoc = reinterpret_cast<std::byte *>(Desc + 1);
95 auto *SD = D->ElemDesc;
96
97 Desc->Offset = ElemOffset + sizeof(InlineDescriptor);
98 Desc->Desc = SD;
99 Desc->IsInitialized = true;
100 Desc->IsBase = false;
101 Desc->IsActive = IsActive;
102 Desc->IsConst = IsConst || D->IsConst;
103 Desc->IsFieldMutable = IsMutable || D->IsMutable;
104 Desc->InUnion = InUnion;
105 Desc->IsArrayElement = true;
106
107 if (auto Fn = D->ElemDesc->CtorFn)
108 Fn(B, ElemLoc, Desc->IsConst, Desc->IsFieldMutable, IsActive,
109 Desc->InUnion || SD->isUnion(), D->ElemDesc);
110 }
111}
112
113static void dtorArrayDesc(Block *B, std::byte *Ptr, const Descriptor *D) {
114 const unsigned NumElems = D->getNumElems();
115 const unsigned ElemSize =
116 D->ElemDesc->getAllocSize() + sizeof(InlineDescriptor);
117
118 unsigned ElemOffset = 0;
119 for (unsigned I = 0; I < NumElems; ++I, ElemOffset += ElemSize) {
120 auto *ElemPtr = Ptr + ElemOffset;
121 auto *Desc = reinterpret_cast<InlineDescriptor *>(ElemPtr);
122 auto *ElemLoc = reinterpret_cast<std::byte *>(Desc + 1);
123 if (auto Fn = D->ElemDesc->DtorFn)
124 Fn(B, ElemLoc, D->ElemDesc);
125 }
126}
127
128static void moveArrayDesc(Block *B, std::byte *Src, std::byte *Dst,
129 const Descriptor *D) {
130 const unsigned NumElems = D->getNumElems();
131 const unsigned ElemSize =
132 D->ElemDesc->getAllocSize() + sizeof(InlineDescriptor);
133
134 unsigned ElemOffset = 0;
135 for (unsigned I = 0; I < NumElems; ++I, ElemOffset += ElemSize) {
136 auto *SrcPtr = Src + ElemOffset;
137 auto *DstPtr = Dst + ElemOffset;
138
139 auto *SrcDesc = reinterpret_cast<InlineDescriptor *>(SrcPtr);
140 auto *SrcElemLoc = reinterpret_cast<std::byte *>(SrcDesc + 1);
141 auto *DstDesc = reinterpret_cast<InlineDescriptor *>(DstPtr);
142 auto *DstElemLoc = reinterpret_cast<std::byte *>(DstDesc + 1);
143
144 *DstDesc = *SrcDesc;
145 if (auto Fn = D->ElemDesc->MoveFn)
146 Fn(B, SrcElemLoc, DstElemLoc, D->ElemDesc);
147 }
148}
149
150static void initField(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable,
151 bool IsActive, bool IsUnionField, bool InUnion,
152 const Descriptor *D, unsigned FieldOffset) {
153 auto *Desc = reinterpret_cast<InlineDescriptor *>(Ptr + FieldOffset) - 1;
154 Desc->Offset = FieldOffset;
155 Desc->Desc = D;
156 Desc->IsInitialized = D->IsArray;
157 Desc->IsBase = false;
158 Desc->IsActive = IsActive && !IsUnionField;
159 Desc->InUnion = InUnion;
160 Desc->IsConst = IsConst || D->IsConst;
161 Desc->IsFieldMutable = IsMutable || D->IsMutable;
162
163 if (auto Fn = D->CtorFn)
164 Fn(B, Ptr + FieldOffset, Desc->IsConst, Desc->IsFieldMutable,
165 Desc->IsActive, InUnion || D->isUnion(), D);
166}
167
168static void initBase(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable,
169 bool IsActive, bool InUnion, const Descriptor *D,
170 unsigned FieldOffset, bool IsVirtualBase) {
171 assert(D);
172 assert(D->ElemRecord);
173 assert(!D->ElemRecord->isUnion()); // Unions cannot be base classes.
174
175 auto *Desc = reinterpret_cast<InlineDescriptor *>(Ptr + FieldOffset) - 1;
176 Desc->Offset = FieldOffset;
177 Desc->Desc = D;
178 Desc->IsInitialized = D->IsArray;
179 Desc->IsBase = true;
180 Desc->IsVirtualBase = IsVirtualBase;
181 Desc->IsActive = IsActive && !InUnion;
182 Desc->IsConst = IsConst || D->IsConst;
183 Desc->IsFieldMutable = IsMutable || D->IsMutable;
184 Desc->InUnion = InUnion;
185
186 for (const auto &V : D->ElemRecord->bases())
187 initBase(B, Ptr + FieldOffset, IsConst, IsMutable, IsActive, InUnion,
188 V.Desc, V.Offset, false);
189 for (const auto &F : D->ElemRecord->fields())
190 initField(B, Ptr + FieldOffset, IsConst, IsMutable, IsActive, InUnion,
191 InUnion, F.Desc, F.Offset);
192}
193
194static void ctorRecord(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable,
195 bool IsActive, bool InUnion, const Descriptor *D) {
196 for (const auto &V : D->ElemRecord->bases())
197 initBase(B, Ptr, IsConst, IsMutable, IsActive, InUnion, V.Desc, V.Offset,
198 false);
199 for (const auto &F : D->ElemRecord->fields()) {
200 bool IsUnionField = D->isUnion();
201 initField(B, Ptr, IsConst, IsMutable, IsActive, IsUnionField,
202 InUnion || IsUnionField, F.Desc, F.Offset);
203 }
204 for (const auto &V : D->ElemRecord->virtual_bases())
205 initBase(B, Ptr, IsConst, IsMutable, IsActive, InUnion, V.Desc, V.Offset,
206 true);
207}
208
209static void destroyField(Block *B, std::byte *Ptr, const Descriptor *D,
210 unsigned FieldOffset) {
211 if (auto Fn = D->DtorFn)
212 Fn(B, Ptr + FieldOffset, D);
213}
214
215static void destroyBase(Block *B, std::byte *Ptr, const Descriptor *D,
216 unsigned FieldOffset) {
217 assert(D);
218 assert(D->ElemRecord);
219
220 for (const auto &V : D->ElemRecord->bases())
221 destroyBase(B, Ptr + FieldOffset, V.Desc, V.Offset);
222 for (const auto &F : D->ElemRecord->fields())
223 destroyField(B, Ptr + FieldOffset, F.Desc, F.Offset);
224}
225
226static void dtorRecord(Block *B, std::byte *Ptr, const Descriptor *D) {
227 for (const auto &F : D->ElemRecord->bases())
228 destroyBase(B, Ptr, F.Desc, F.Offset);
229 for (const auto &F : D->ElemRecord->fields())
230 destroyField(B, Ptr, F.Desc, F.Offset);
231 for (const auto &F : D->ElemRecord->virtual_bases())
232 destroyBase(B, Ptr, F.Desc, F.Offset);
233}
234
235static void moveRecord(Block *B, std::byte *Src, std::byte *Dst,
236 const Descriptor *D) {
237 assert(D);
238 assert(D->ElemRecord);
239
240 // FIXME: There might be cases where we need to move over the (v)bases as
241 // well.
242 for (const auto &F : D->ElemRecord->fields()) {
243 auto FieldOffset = F.Offset;
244 const auto *SrcDesc =
245 reinterpret_cast<const InlineDescriptor *>(Src + FieldOffset) - 1;
246 auto *DestDesc =
247 reinterpret_cast<InlineDescriptor *>(Dst + FieldOffset) - 1;
248 std::memcpy(DestDesc, SrcDesc, sizeof(InlineDescriptor));
249
250 if (auto Fn = F.Desc->MoveFn)
251 Fn(B, Src + FieldOffset, Dst + FieldOffset, F.Desc);
252 }
253}
254
256 // Floating types are special. They are primitives, but need their
257 // constructor called.
258 if (Type == PT_Float)
259 return ctorTy<PrimConv<PT_Float>::T>;
260 if (Type == PT_IntAP)
261 return ctorTy<PrimConv<PT_IntAP>::T>;
262 if (Type == PT_IntAPS)
263 return ctorTy<PrimConv<PT_IntAPS>::T>;
264 if (Type == PT_MemberPtr)
265 return ctorTy<PrimConv<PT_MemberPtr>::T>;
266
267 COMPOSITE_TYPE_SWITCH(Type, return ctorTy<T>, return nullptr);
268}
269
271 // Floating types are special. They are primitives, but need their
272 // destructor called, since they might allocate memory.
273 if (Type == PT_Float)
274 return dtorTy<PrimConv<PT_Float>::T>;
275 if (Type == PT_IntAP)
276 return dtorTy<PrimConv<PT_IntAP>::T>;
277 if (Type == PT_IntAPS)
278 return dtorTy<PrimConv<PT_IntAPS>::T>;
279 if (Type == PT_MemberPtr)
280 return dtorTy<PrimConv<PT_MemberPtr>::T>;
281
282 COMPOSITE_TYPE_SWITCH(Type, return dtorTy<T>, return nullptr);
283}
284
286 if (Type == PT_Float)
287 return moveTy<PrimConv<PT_Float>::T>;
288 if (Type == PT_IntAP)
289 return moveTy<PrimConv<PT_IntAP>::T>;
290 if (Type == PT_IntAPS)
291 return moveTy<PrimConv<PT_IntAPS>::T>;
292 if (Type == PT_MemberPtr)
293 return moveTy<PrimConv<PT_MemberPtr>::T>;
294 COMPOSITE_TYPE_SWITCH(Type, return moveTy<T>, return nullptr);
295}
296
298 TYPE_SWITCH(Type, return ctorArrayTy<T>);
299 llvm_unreachable("unknown Expr");
300}
301
303 TYPE_SWITCH(Type, return dtorArrayTy<T>);
304 llvm_unreachable("unknown Expr");
305}
306
308 TYPE_SWITCH(Type, return moveArrayTy<T>);
309 llvm_unreachable("unknown Expr");
310}
311
312/// Primitives.
314 bool IsConst, bool IsTemporary, bool IsMutable)
315 : Source(D), ElemSize(primSize(Type)), Size(ElemSize),
316 MDSize(MD.value_or(0)), AllocSize(align(Size + MDSize)), PrimT(Type),
317 IsConst(IsConst), IsMutable(IsMutable), IsTemporary(IsTemporary),
318 CtorFn(getCtorPrim(Type)), DtorFn(getDtorPrim(Type)),
319 MoveFn(getMovePrim(Type)) {
320 assert(AllocSize >= Size);
321 assert(Source && "Missing source");
322}
323
324/// Primitive arrays.
326 size_t NumElems, bool IsConst, bool IsTemporary,
327 bool IsMutable)
328 : Source(D), ElemSize(primSize(Type)), Size(ElemSize * NumElems),
329 MDSize(MD.value_or(0)),
330 AllocSize(align(MDSize) + align(Size) + sizeof(InitMapPtr)), PrimT(Type),
331 IsConst(IsConst), IsMutable(IsMutable), IsTemporary(IsTemporary),
332 IsArray(true), CtorFn(getCtorArrayPrim(Type)),
333 DtorFn(getDtorArrayPrim(Type)), MoveFn(getMoveArrayPrim(Type)) {
334 assert(Source && "Missing source");
335 assert(NumElems <= (MaxArrayElemBytes / ElemSize));
336}
337
338/// Primitive unknown-size arrays.
340 bool IsTemporary, UnknownSize)
341 : Source(D), ElemSize(primSize(Type)), Size(UnknownSizeMark),
342 MDSize(MD.value_or(0)),
343 AllocSize(MDSize + sizeof(InitMapPtr) + alignof(void *)), IsConst(true),
344 IsMutable(false), IsTemporary(IsTemporary), IsArray(true),
345 CtorFn(getCtorArrayPrim(Type)), DtorFn(getDtorArrayPrim(Type)),
346 MoveFn(getMoveArrayPrim(Type)) {
347 assert(Source && "Missing source");
348}
349
350/// Arrays of composite elements.
352 unsigned NumElems, bool IsConst, bool IsTemporary,
353 bool IsMutable)
354 : Source(D), ElemSize(Elem->getAllocSize() + sizeof(InlineDescriptor)),
355 Size(ElemSize * NumElems), MDSize(MD.value_or(0)),
356 AllocSize(std::max<size_t>(alignof(void *), Size) + MDSize),
357 ElemDesc(Elem), IsConst(IsConst), IsMutable(IsMutable),
358 IsTemporary(IsTemporary), IsArray(true), CtorFn(ctorArrayDesc),
359 DtorFn(dtorArrayDesc), MoveFn(moveArrayDesc) {
360 assert(Source && "Missing source");
361}
362
363/// Unknown-size arrays of composite elements.
365 bool IsTemporary, UnknownSize)
366 : Source(D), ElemSize(Elem->getAllocSize() + sizeof(InlineDescriptor)),
367 Size(UnknownSizeMark), MDSize(MD.value_or(0)),
368 AllocSize(MDSize + alignof(void *)), ElemDesc(Elem), IsConst(true),
369 IsMutable(false), IsTemporary(IsTemporary), IsArray(true),
370 CtorFn(ctorArrayDesc), DtorFn(dtorArrayDesc), MoveFn(moveArrayDesc) {
371 assert(Source && "Missing source");
372}
373
374/// Composite records.
376 bool IsConst, bool IsTemporary, bool IsMutable)
377 : Source(D), ElemSize(std::max<size_t>(alignof(void *), R->getFullSize())),
378 Size(ElemSize), MDSize(MD.value_or(0)), AllocSize(Size + MDSize),
379 ElemRecord(R), IsConst(IsConst), IsMutable(IsMutable),
380 IsTemporary(IsTemporary), CtorFn(ctorRecord), DtorFn(dtorRecord),
381 MoveFn(moveRecord) {
382 assert(Source && "Missing source");
383}
384
385/// Dummy.
387 : Source(D), ElemSize(1), Size(1), MDSize(0), AllocSize(MDSize),
388 ElemRecord(nullptr), IsConst(true), IsMutable(false), IsTemporary(false),
389 IsDummy(true) {
390 assert(Source && "Missing source");
391}
392
394 if (const auto *D = asValueDecl())
395 return D->getType();
396 if (const auto *T = dyn_cast_if_present<TypeDecl>(asDecl()))
397 return QualType(T->getTypeForDecl(), 0);
398
399 // The Source sometimes has a different type than the once
400 // we really save. Try to consult the Record first.
401 if (isRecord())
402 return QualType(ElemRecord->getDecl()->getTypeForDecl(), 0);
403 if (const auto *E = asExpr())
404 return E->getType();
405 llvm_unreachable("Invalid descriptor type");
406}
407
409 assert(isArray());
410 QualType T = getType();
412 return T->getPointeeType();
413 if (const auto *AT = T->getAsArrayTypeUnsafe()) {
414 // For primitive arrays, we don't save a QualType at all,
415 // just a PrimType. Try to figure out the QualType here.
416 if (isPrimitiveArray()) {
417 while (T->isArrayType())
419 return T;
420 }
421 return AT->getElementType();
422 }
423 if (const auto *CT = T->getAs<ComplexType>())
424 return CT->getElementType();
425 if (const auto *CT = T->getAs<VectorType>())
426 return CT->getElementType();
427 llvm_unreachable("Array that's not an array/complex/vector type?");
428}
429
431 if (auto *D = Source.dyn_cast<const Decl *>())
432 return D->getLocation();
433 if (auto *E = Source.dyn_cast<const Expr *>())
434 return E->getExprLoc();
435 llvm_unreachable("Invalid descriptor type");
436}
437
439 if (const auto *D = Source.dyn_cast<const Decl *>())
440 return SourceInfo(D);
441 if (const auto *E = Source.dyn_cast<const Expr *>())
442 return SourceInfo(E);
443 llvm_unreachable("Invalid descriptor type");
444}
445
446bool Descriptor::isUnion() const { return isRecord() && ElemRecord->isUnion(); }
447
449 : UninitFields(N), Data(std::make_unique<T[]>(numFields(N))) {
450 std::fill_n(data(), numFields(N), 0);
451}
452
453bool InitMap::initializeElement(unsigned I) {
454 unsigned Bucket = I / PER_FIELD;
455 T Mask = T(1) << (I % PER_FIELD);
456 if (!(data()[Bucket] & Mask)) {
457 data()[Bucket] |= Mask;
458 UninitFields -= 1;
459 }
460 return UninitFields == 0;
461}
462
463bool InitMap::isElementInitialized(unsigned I) const {
464 unsigned Bucket = I / PER_FIELD;
465 return data()[Bucket] & (T(1) << (I % PER_FIELD));
466}
#define V(N, I)
Definition: ASTContext.h:3443
const Decl * D
Expr * E
static void moveArrayTy(Block *, std::byte *Src, std::byte *Dst, const Descriptor *D)
Definition: Descriptor.cpp:66
static void dtorTy(Block *, std::byte *Ptr, const Descriptor *)
Definition: Descriptor.cpp:30
static BlockCtorFn getCtorArrayPrim(PrimType Type)
Definition: Descriptor.cpp:297
static void initField(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable, bool IsActive, bool IsUnionField, bool InUnion, const Descriptor *D, unsigned FieldOffset)
Definition: Descriptor.cpp:150
static void initBase(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable, bool IsActive, bool InUnion, const Descriptor *D, unsigned FieldOffset, bool IsVirtualBase)
Definition: Descriptor.cpp:168
static BlockMoveFn getMoveArrayPrim(PrimType Type)
Definition: Descriptor.cpp:307
static void destroyField(Block *B, std::byte *Ptr, const Descriptor *D, unsigned FieldOffset)
Definition: Descriptor.cpp:209
static void dtorArrayTy(Block *, std::byte *Ptr, const Descriptor *D)
Definition: Descriptor.cpp:54
static BlockMoveFn getMovePrim(PrimType Type)
Definition: Descriptor.cpp:285
static void moveRecord(Block *B, std::byte *Src, std::byte *Dst, const Descriptor *D)
Definition: Descriptor.cpp:235
static void moveTy(Block *, std::byte *Src, std::byte *Dst, const Descriptor *)
Definition: Descriptor.cpp:35
static void ctorArrayTy(Block *, std::byte *Ptr, bool, bool, bool, bool, const Descriptor *D)
Definition: Descriptor.cpp:43
static void destroyBase(Block *B, std::byte *Ptr, const Descriptor *D, unsigned FieldOffset)
Definition: Descriptor.cpp:215
static void dtorArrayDesc(Block *B, std::byte *Ptr, const Descriptor *D)
Definition: Descriptor.cpp:113
static void ctorTy(Block *, std::byte *Ptr, bool, bool, bool, bool, const Descriptor *)
Definition: Descriptor.cpp:24
static BlockDtorFn getDtorPrim(PrimType Type)
Definition: Descriptor.cpp:270
static BlockCtorFn getCtorPrim(PrimType Type)
Definition: Descriptor.cpp:255
static BlockDtorFn getDtorArrayPrim(PrimType Type)
Definition: Descriptor.cpp:302
static void moveArrayDesc(Block *B, std::byte *Src, std::byte *Dst, const Descriptor *D)
Definition: Descriptor.cpp:128
static void dtorRecord(Block *B, std::byte *Ptr, const Descriptor *D)
Definition: Descriptor.cpp:226
static void ctorArrayDesc(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable, bool IsActive, bool InUnion, const Descriptor *D)
Definition: Descriptor.cpp:83
static void ctorRecord(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable, bool IsActive, bool InUnion, const Descriptor *D)
Definition: Descriptor.cpp:194
#define COMPOSITE_TYPE_SWITCH(Expr, B, D)
Definition: PrimType.h:212
#define TYPE_SWITCH(Expr, B)
Definition: PrimType.h:153
__DEVICE__ int max(int __a, int __b)
__SIZE_TYPE__ size_t
QualType getElementType() const
Definition: Type.h:3589
Complex values, per C99 6.2.5p11.
Definition: Type.h:3145
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
SourceLocation getLocation() const
Definition: DeclBase.h:442
This represents one expression.
Definition: Expr.h:110
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition: Expr.cpp:277
QualType getType() const
Definition: Expr.h:142
A (possibly-)qualified type.
Definition: Type.h:929
Encodes a location in the source.
const Type * getTypeForDecl() const
Definition: Decl.h:3395
The base class of the type hierarchy.
Definition: Type.h:1828
bool isArrayType() const
Definition: Type.h:8258
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition: Type.cpp:738
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
Definition: Type.h:8786
bool isPointerOrReferenceType() const
Definition: Type.h:8190
const T * getAs() const
Member-template getAs<specific type>'.
Definition: Type.h:8731
Represents a GCC generic vector type.
Definition: Type.h:4034
A memory block, either on the stack or in the heap.
Definition: InterpBlock.h:49
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
Describes the statement/declaration an opcode was generated from.
Definition: Source.h:77
std::optional< std::pair< bool, std::shared_ptr< InitMap > > > InitMapPtr
Definition: Descriptor.h:30
void(*)(Block *Storage, std::byte *FieldPtr, bool IsConst, bool IsMutable, bool IsActive, bool InUnion, const Descriptor *FieldDesc) BlockCtorFn
Invoked whenever a block is created.
Definition: Descriptor.h:37
bool NE(InterpState &S, CodePtr OpPC)
Definition: Interp.h:1157
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:131
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
void(*)(Block *Storage, std::byte *SrcFieldPtr, std::byte *DstFieldPtr, const Descriptor *FieldDesc) BlockMoveFn
Invoked when a block with pointers referencing it goes out of scope.
Definition: Descriptor.h:50
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:134
Describes a memory block created by an allocation site.
Definition: Descriptor.h:116
QualType getElemQualType() const
Definition: Descriptor.cpp:408
const ValueDecl * asValueDecl() const
Definition: Descriptor.h:208
static constexpr unsigned MaxArrayElemBytes
Maximum number of bytes to be used for array elements.
Definition: Descriptor.h:141
QualType getType() const
Definition: Descriptor.cpp:393
const Decl * asDecl() const
Definition: Descriptor.h:204
SourceInfo getLoc() const
Definition: Descriptor.cpp:438
SourceLocation getLocation() const
Definition: Descriptor.cpp:430
std::optional< unsigned > MetadataSize
Definition: Descriptor.h:136
bool isPrimitiveArray() const
Checks if the descriptor is of an array of primitives.
Definition: Descriptor.h:248
Descriptor(const DeclTy &D, PrimType Type, MetadataSize MD, bool IsConst, bool IsTemporary, bool IsMutable)
Allocates a descriptor for a primitive.
Definition: Descriptor.cpp:313
bool isRecord() const
Checks if the descriptor is of a record.
Definition: Descriptor.h:262
const Record *const ElemRecord
Pointer to the record, if block contains records.
Definition: Descriptor.h:146
bool isUnion() const
Checks if the descriptor is of a union.
Definition: Descriptor.cpp:446
const Expr * asExpr() const
Definition: Descriptor.h:205
bool isArray() const
Checks if the descriptor is of an array.
Definition: Descriptor.h:260
InitMap(unsigned N)
Initializes the map with no fields set.
Definition: Descriptor.cpp:448
Inline descriptor embedded in structures and arrays.
Definition: Descriptor.h:70
unsigned Offset
Offset inside the structure/array.
Definition: Descriptor.h:72