25template <
typename T>
static constexpr bool needsCtor() {
26 if constexpr (std::is_same_v<T, Char<true>> ||
27 std::is_same_v<T, Char<false>> ||
28 std::is_same_v<T, Integral<16, true>> ||
29 std::is_same_v<T, Integral<16, false>> ||
30 std::is_same_v<T, Integral<32, true>> ||
31 std::is_same_v<T, Integral<32, false>> ||
32 std::is_same_v<T, Integral<64, true>> ||
33 std::is_same_v<T, Integral<64, false>> ||
34 std::is_same_v<T, IntegralAP<true>> ||
35 std::is_same_v<T, IntegralAP<false>> ||
36 std::is_same_v<T, Floating> || std::is_same_v<T, Boolean>)
43static void ctorTy(
Block *, std::byte *Ptr,
bool,
bool,
bool,
bool,
bool,
52 reinterpret_cast<T *
>(Ptr)->~
T();
63 new (&
reinterpret_cast<T *
>(Ptr)[I])
T();
76 reinterpret_cast<T *
>(Ptr)[I].~
T();
82 bool IsMutable,
bool IsVolatile,
bool IsActive,
85 const unsigned ElemSize =
88 unsigned ElemOffset = 0;
89 for (
unsigned I = 0; I != NumElems; ++I, ElemOffset += ElemSize) {
90 auto *ElemPtr = Ptr + ElemOffset;
96 Desc->IsInitialized =
true;
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;
106 auto *ElemLoc =
reinterpret_cast<std::byte *
>(Desc + 1);
107 Fn(B, ElemLoc, Desc->IsConst, Desc->IsFieldMutable, IsVolatile, IsActive,
108 Desc->InUnion || SD->isUnion(), D->
ElemDesc);
115 const unsigned ElemSize =
118 unsigned ElemOffset = 0;
121 "a composite array without an elem dtor shouldn't have a dtor itself");
122 for (
unsigned I = 0; I != NumElems; ++I, ElemOffset += ElemSize) {
123 auto *ElemPtr = Ptr + ElemOffset;
125 auto *ElemLoc =
reinterpret_cast<std::byte *
>(Desc + 1);
131 bool IsVolatile,
bool IsActive,
bool IsUnionField,
132 bool InUnion,
const Descriptor *D,
unsigned FieldOffset) {
134 Desc->
Offset = FieldOffset;
136 Desc->IsInitialized = D->
IsArray;
137 Desc->IsBase =
false;
138 Desc->IsActive = IsActive && !IsUnionField;
139 Desc->InUnion = InUnion;
140 Desc->IsConst = IsConst || D->
IsConst;
141 Desc->IsFieldMutable = IsMutable || D->
IsMutable;
142 Desc->IsVolatile = IsVolatile || D->
IsVolatile;
144 Desc->IsConstInMutable = Desc->IsConst && IsMutable;
151 Fn(B, Ptr + FieldOffset, Desc->IsConst, Desc->IsFieldMutable,
152 Desc->IsVolatile, Desc->IsActive, InUnion || D->
isUnion(), D);
156 bool IsVolatile,
bool IsActive,
bool InUnion,
158 bool IsVirtualBase) {
164 Desc->
Offset = FieldOffset;
166 Desc->IsInitialized = D->
IsArray;
168 Desc->IsVirtualBase = IsVirtualBase;
169 Desc->IsActive = IsActive && !InUnion;
170 Desc->IsConst = IsConst || D->
IsConst;
171 Desc->IsFieldMutable = IsMutable || D->
IsMutable;
172 Desc->InUnion = InUnion;
173 Desc->IsVolatile =
false;
176 initBase(B, Ptr + FieldOffset, IsConst, IsMutable, IsVolatile, IsActive,
177 InUnion,
V.Desc,
V.Offset,
false);
179 initField(B, Ptr + FieldOffset, IsConst, IsMutable, IsVolatile, IsActive,
180 InUnion, InUnion, F.Desc, F.Offset);
184 bool IsVolatile,
bool IsActive,
bool InUnion,
187 initBase(B, Ptr, IsConst, IsMutable, IsVolatile, IsActive, InUnion,
V.Desc,
191 bool IsUnionField = D->
isUnion();
192 initField(B, Ptr, IsConst, IsMutable, IsVolatile, IsActive, IsUnionField,
193 InUnion || IsUnionField, F.Desc, F.Offset);
196 initBase(B, Ptr, IsConst, IsMutable, IsVolatile, IsActive, InUnion,
V.Desc,
202 unsigned FieldOffset) {
204 Fn(B, Ptr + FieldOffset, D);
208 unsigned FieldOffset) {
229 for (
const auto &B : R->bases()) {
234 for (
const auto &F : R->fields()) {
239 for (
const auto &
V : R->virtual_bases()) {
255 llvm_unreachable(
"Unhandled PrimType");
267 llvm_unreachable(
"Unhandled PrimType");
273 llvm_unreachable(
"unknown Expr");
278 llvm_unreachable(
"unknown Expr");
285 : Source(D), SourceType(SourceTy), ElemSize(
primSize(
Type)), Size(ElemSize),
289 assert(Source &&
"Missing source");
296 : Source(D), SourceType(SourceTy), ElemSize(
primSize(
Type)),
297 Size(ElemSize * NumElems), AllocSize(
align(Size) + sizeof(
InitMapPtr)),
301 assert(Source &&
"Missing source");
308 : Source(D), ElemSize(
primSize(
Type)), Size(UnknownSizeMark),
313 assert(Source &&
"Missing source");
320 : Source(D), SourceType(SourceTy),
322 Size(ElemSize * NumElems),
327 assert(Source &&
"Missing source");
334 Size(UnknownSizeMark), AllocSize(alignof(void *)),
ElemDesc(Elem),
337 assert(Source &&
"Missing source");
343 : Source(D), ElemSize(
std::
max<
size_t>(alignof(void *), R->getFullSize())),
347 assert(Source &&
"Missing source");
354 assert(Source &&
"Missing source");
361 if (
const auto *
T = dyn_cast_if_present<TypeDecl>(
asDecl()))
362 return T->getASTContext().getTypeDeclType(
T);
369 std::nullopt, RD,
false);
371 return T.withConst();
375 if (
const auto *E =
asExpr()) {
377 return E->getType()->getPointeeType();
380 if (
const auto *ME = dyn_cast<CXXMemberCallExpr>(E);
381 ME && ME->getRecordDecl()->getName() ==
"allocator" &&
382 ME->getMethodDecl()->getName() ==
"allocate")
383 return E->getType()->getPointeeType();
390 llvm_unreachable(
"Invalid descriptor type");
399 }
else if (
const auto *TDecl = dyn_cast_if_present<TypeDecl>(
asDecl())) {
400 T = TDecl->getASTContext().getTypeDeclType(TDecl);
404 std::nullopt, RD,
false);
407 }
else if (
const auto *E =
asExpr()) {
416 T = AT->getValueType();
417 if (
T->isPointerOrReferenceType())
418 T =
T->getPointeeType();
420 if (
const auto *AT =
T->getAsArrayTypeUnsafe()) {
424 while (
T->isArrayType())
425 T =
T->getAsArrayTypeUnsafe()->getElementType();
428 return AT->getElementType();
431 return CT->getElementType();
433 return CT->getElementType();
447 if (
const auto *E =
asExpr()) {
449 return MakeArrayType(E->getType()->getPointeeType());
452 if (
const auto *ME = dyn_cast<CXXMemberCallExpr>(E);
453 ME && ME->getRecordDecl()->getName() ==
"allocator" &&
454 ME->getMethodDecl()->getName() ==
"allocate")
455 return MakeArrayType(E->getType()->getPointeeType());
463 if (
auto *D = Source.asDecl())
464 return D->getLocation();
465 if (
auto *E = Source.asExpr())
466 return E->getExprLoc();
467 llvm_unreachable(
"Invalid descriptor type");
471 if (
const auto *D = Source.asDecl())
473 if (
const auto *E = Source.asExpr())
475 llvm_unreachable(
"Invalid descriptor type");
static void ctorRecord(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable, bool IsVolatile, bool IsActive, bool InUnion, const Descriptor *D)
static void dtorTy(Block *, std::byte *Ptr, const Descriptor *)
static BlockCtorFn getCtorArrayPrim(PrimType Type)
static void destroyField(Block *B, std::byte *Ptr, const Descriptor *D, unsigned FieldOffset)
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)
static void dtorArrayTy(Block *, std::byte *Ptr, const Descriptor *D)
static void ctorTy(Block *, std::byte *Ptr, bool, bool, bool, bool, bool, const Descriptor *)
static void ctorArrayDesc(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable, bool IsVolatile, bool IsActive, bool InUnion, const Descriptor *D)
static void destroyBase(Block *B, std::byte *Ptr, const Descriptor *D, unsigned FieldOffset)
static constexpr bool needsCtor()
static void dtorArrayDesc(Block *B, std::byte *Ptr, const Descriptor *D)
static BlockCtorFn getCtorPrim(PrimType T)
static bool needsRecordDtor(const Record *R)
Whether a record needs its descriptor dtor function called.
static BlockDtorFn getDtorArrayPrim(PrimType Type)
static void ctorArrayTy(Block *, std::byte *Ptr, bool, bool, bool, bool, bool, const Descriptor *D)
static BlockDtorFn getDtorPrim(PrimType T)
static void dtorRecord(Block *B, std::byte *Ptr, const Descriptor *D)
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)
Defines the clang::Expr interface and subclasses for C++ expressions.
#define FIXED_SIZE_INT_TYPE_SWITCH(Expr, B)
#define TYPE_SWITCH(Expr, B)
__DEVICE__ int max(int __a, int __b)
__SIZE_TYPE__ size_t
The unsigned integer type of the result of the sizeof operator.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
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.
QualType getTagType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier Qualifier, const TagDecl *TD, bool OwnsTag) const
Complex values, per C99 6.2.5p11.
ASTContext & getASTContext() const LLVM_READONLY
A (possibly-)qualified type.
Represents a struct/union/class.
Encodes a location in the source.
The base class of the type hierarchy.
Represents a GCC generic vector type.
A memory block, either on the stack or in the heap.
Structure/Class descriptor.
bool isUnion() const
Checks if the record is a union.
llvm::iterator_range< const_virtual_iter > virtual_bases() const
llvm::iterator_range< const_base_iter > bases() const
llvm::iterator_range< const_field_iter > fields() const
Describes the statement/declaration an opcode was generated from.
void(*)(Block *Storage, std::byte *FieldPtr, const Descriptor *FieldDesc) BlockDtorFn
Invoked when a block is destroyed.
bool NE(InterpState &S, CodePtr OpPC)
constexpr size_t align(size_t Size)
Aligns a size to the pointer alignment.
constexpr bool isIntegerOrBoolType(PrimType T)
PrimType
Enumeration of the primitive types of the VM.
size_t primSize(PrimType Type)
Returns the size of a primitive type in bytes.
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.
Top level wrappers for InstallAPI frontend operations.
bool isa(CodeGen::Address addr)
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
const FunctionProtoType * T
@ None
No keyword precedes the qualified type name.
Token to denote structures of unknown size.
Describes a memory block created by an allocation site.
const bool IsConst
Flag indicating if the block is mutable.
unsigned getAllocSize() const
Returns the allocated size, including metadata.
unsigned getNumElems() const
Returns the number of elements stored in the block.
bool isPrimitive() const
Checks if the descriptor is of a primitive.
QualType getElemQualType() const
bool hasTrivialDtor() const
Whether variables of this descriptor need their destructor called or not.
const OptPrimType PrimT
The primitive type this descriptor was created for, or the primitive element type in case this is a p...
const ValueDecl * asValueDecl() const
const BlockCtorFn CtorFn
Storage management methods.
static constexpr unsigned MaxArrayElemBytes
Maximum number of bytes to be used for array elements.
const Decl * asDecl() const
const Descriptor *const ElemDesc
Descriptor of the array element.
SourceInfo getLoc() const
SourceLocation getLocation() const
const bool IsMutable
Flag indicating if a field is mutable.
QualType getDataType(const ASTContext &Ctx) const
const bool IsArray
Flag indicating if the block is an array.
unsigned getElemDataSize() const
Returns the element data size, i.e.
bool isPrimitiveArray() const
Checks if the descriptor is of an array of primitives.
Descriptor(DeclOrExpr D, const Type *SourceTy, PrimType Type, bool IsConst, bool IsTemporary, bool IsMutable, bool IsVolatile)
Allocates a descriptor for a primitive.
PrimType getPrimType() const
bool isRecord() const
Checks if the descriptor is of a record.
const bool IsTemporary
Flag indicating if the block is a temporary.
const Record *const ElemRecord
Pointer to the record, if block contains records.
bool isUnion() const
Checks if the descriptor is of a union.
const Expr * asExpr() const
bool isArray() const
Checks if the descriptor is of an array.
A pointer-sized struct we use to allocate into data storage.
void deleteInitMap()
Delete the InitMap if one exists.
Inline descriptor embedded in structures and arrays.
unsigned Offset
Offset inside the structure/array.