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>)
40static void ctorTy(
Block *, std::byte *Ptr,
bool,
bool,
bool,
bool,
bool,
49 reinterpret_cast<T *
>(Ptr)->~
T();
60 new (&
reinterpret_cast<T *
>(Ptr)[I])
T();
75 reinterpret_cast<T *
>(Ptr)[I].~
T();
81 bool IsMutable,
bool IsVolatile,
bool IsActive,
84 const unsigned ElemSize =
87 unsigned ElemOffset = 0;
88 for (
unsigned I = 0; I < NumElems; ++I, ElemOffset += ElemSize) {
89 auto *ElemPtr = Ptr + ElemOffset;
91 auto *ElemLoc =
reinterpret_cast<std::byte *
>(Desc + 1);
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 Fn(B, ElemLoc, Desc->IsConst, Desc->IsFieldMutable, IsVolatile, IsActive,
107 Desc->InUnion || SD->isUnion(), D->
ElemDesc);
113 const unsigned ElemSize =
116 unsigned ElemOffset = 0;
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;
123 auto *ElemLoc =
reinterpret_cast<std::byte *
>(Desc + 1);
129 bool IsVolatile,
bool IsActive,
bool IsUnionField,
130 bool InUnion,
const Descriptor *D,
unsigned FieldOffset) {
132 Desc->
Offset = FieldOffset;
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;
142 Desc->IsConstInMutable = Desc->IsConst && IsMutable;
145 Fn(B, Ptr + FieldOffset, Desc->IsConst, Desc->IsFieldMutable,
146 Desc->IsVolatile, Desc->IsActive, InUnion || D->
isUnion(), D);
150 bool IsVolatile,
bool IsActive,
bool InUnion,
152 bool IsVirtualBase) {
158 Desc->
Offset = FieldOffset;
160 Desc->IsInitialized = D->
IsArray;
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;
170 initBase(B, Ptr + FieldOffset, IsConst, IsMutable, IsVolatile, IsActive,
171 InUnion,
V.Desc,
V.Offset,
false);
173 initField(B, Ptr + FieldOffset, IsConst, IsMutable, IsVolatile, IsActive,
174 InUnion, InUnion, F.Desc, F.Offset);
178 bool IsVolatile,
bool IsActive,
bool InUnion,
181 initBase(B, Ptr, IsConst, IsMutable, IsVolatile, IsActive, InUnion,
V.Desc,
185 bool IsUnionField = D->
isUnion();
186 initField(B, Ptr, IsConst, IsMutable, IsVolatile, IsActive, IsUnionField,
187 InUnion || IsUnionField, F.Desc, F.Offset);
190 initBase(B, Ptr, IsConst, IsMutable, IsVolatile, IsActive, InUnion,
V.Desc,
196 unsigned FieldOffset) {
198 Fn(B, Ptr + FieldOffset, D);
202 unsigned FieldOffset) {
223 for (
const auto &B : R->
bases()) {
228 for (
const auto &F : R->
fields()) {
255 llvm_unreachable(
"Unhandled PrimType");
273 llvm_unreachable(
"Unhandled PrimType");
278 llvm_unreachable(
"unknown Expr");
283 llvm_unreachable(
"unknown Expr");
290 : Source(D), SourceType(SourceTy), ElemSize(
primSize(
Type)), Size(ElemSize),
291 MDSize(MD.value_or(0)), AllocSize(
align(Size + MDSize)),
PrimT(
Type),
295 assert(AllocSize >= Size);
296 assert(Source &&
"Missing source");
303 : Source(D), ElemSize(
primSize(
Type)), Size(ElemSize * NumElems),
304 MDSize(MD.value_or(0)),
309 assert(Source &&
"Missing source");
316 : Source(D), ElemSize(
primSize(
Type)), Size(UnknownSizeMark),
317 MDSize(MD.value_or(0)),
322 assert(Source &&
"Missing source");
330 : Source(D), SourceType(SourceTy),
332 Size(ElemSize * NumElems), MDSize(MD.value_or(0)),
333 AllocSize(
std::
max<
size_t>(alignof(void *), Size) + MDSize),
337 assert(Source &&
"Missing source");
344 Size(UnknownSizeMark), MDSize(MD.value_or(0)),
348 assert(Source &&
"Missing source");
355 : Source(D), ElemSize(
std::
max<
size_t>(alignof(void *), R->getFullSize())),
356 Size(ElemSize), MDSize(MD.value_or(0)), AllocSize(Size + MDSize),
360 assert(Source &&
"Missing source");
365 : Source(D), ElemSize(1), Size(1), MDSize(MD.value_or(0)),
368 assert(Source &&
"Missing source");
376 if (
const auto *
T = dyn_cast_if_present<TypeDecl>(
asDecl()))
377 return T->getASTContext().getTypeDeclType(
T);
385 if (
const auto *E =
asExpr())
387 llvm_unreachable(
"Invalid descriptor type");
393 if (
T->isPointerOrReferenceType())
394 T =
T->getPointeeType();
396 if (
const auto *AT =
T->getAsArrayTypeUnsafe()) {
400 while (
T->isArrayType())
401 T =
T->getAsArrayTypeUnsafe()->getElementType();
404 return AT->getElementType();
407 return CT->getElementType();
409 return CT->getElementType();
423 if (
const auto *E =
asExpr()) {
425 return MakeArrayType(E->getType()->getPointeeType());
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());
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");
447 if (
const auto *D = dyn_cast<const Decl *>(Source))
449 if (
const auto *E = dyn_cast<const Expr *>(Source))
451 llvm_unreachable(
"Invalid descriptor type");
472 : UninitFields(N), Data(
std::make_unique<T[]>(numFields(N))) {}
474bool InitMap::initializeElement(
unsigned I) {
475 unsigned Bucket = I / PER_FIELD;
476 T Mask =
T(1) << (I % PER_FIELD);
477 if (!(data()[Bucket] & Mask)) {
478 data()[Bucket] |= Mask;
481 return UninitFields == 0;
484bool InitMap::isElementInitialized(
unsigned I)
const {
485 unsigned Bucket = I / PER_FIELD;
486 return data()[Bucket] & (
T(1) << (I % PER_FIELD));
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 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.
CanQualType getCanonicalTagType(const TagDecl *TD) 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.
llvm::PointerUnion< const Decl *, const Expr * > DeclTy
bool NE(InterpState &S, CodePtr OpPC)
constexpr size_t align(size_t Size)
Aligns a size to the pointer alignment.
PrimType
Enumeration of the primitive types of the VM.
std::optional< std::pair< bool, std::shared_ptr< InitMap > > > InitMapPtr
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.
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
nullptr
This class represents a compute construct, representing a 'Kind' of βparallelβ, 'serial',...
const FunctionProtoType * T
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
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.
SourceLocation getLocation() const
const bool IsMutable
Flag indicating if a field is mutable.
QualType getDataType(const ASTContext &Ctx) const
std::optional< unsigned > MetadataSize
const bool IsArray
Flag indicating if the block is an array.
bool isPrimitiveArray() const
Checks if the descriptor is of an array of primitives.
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.
InitMap(unsigned N)
Initializes the map with no fields set.
Inline descriptor embedded in structures and arrays.
unsigned Offset
Offset inside the structure/array.