29 reinterpret_cast<T *
>(Ptr)->~T();
33static void moveTy(
Block *,
const std::byte *Src, std::byte *Dst,
35 const auto *SrcPtr =
reinterpret_cast<const T *
>(Src);
36 auto *DstPtr =
reinterpret_cast<T *
>(Dst);
37 new (DstPtr) T(std::move(*SrcPtr));
47 new (&
reinterpret_cast<T *
>(Ptr)[I]) T();
59 reinterpret_cast<T *
>(Ptr)[I].~T();
67 const auto *SrcPtr = &
reinterpret_cast<const T *
>(Src)[I];
68 auto *DstPtr = &
reinterpret_cast<T *
>(Dst)[I];
69 new (DstPtr) T(std::move(*SrcPtr));
74 bool IsMutable,
bool IsActive,
const Descriptor *D) {
76 const unsigned ElemSize =
79 unsigned ElemOffset = 0;
80 for (
unsigned I = 0; I < NumElems; ++I, ElemOffset += ElemSize) {
81 auto *ElemPtr = Ptr + ElemOffset;
83 auto *ElemLoc =
reinterpret_cast<std::byte *
>(Desc + 1);
88 Desc->IsInitialized =
true;
90 Desc->IsActive = IsActive;
92 Desc->IsFieldMutable = IsMutable || D->
IsMutable;
94 Fn(B, ElemLoc, Desc->IsConst, Desc->IsFieldMutable, IsActive,
101 const unsigned ElemSize =
104 unsigned ElemOffset = 0;
105 for (
unsigned I = 0; I < NumElems; ++I, ElemOffset += ElemSize) {
106 auto *ElemPtr = Ptr + ElemOffset;
108 auto *ElemLoc =
reinterpret_cast<std::byte *
>(Desc + 1);
117 const unsigned ElemSize =
120 unsigned ElemOffset = 0;
121 for (
unsigned I = 0; I < NumElems; ++I, ElemOffset += ElemSize) {
122 const auto *SrcPtr = Src + ElemOffset;
123 auto *DstPtr = Dst + ElemOffset;
126 const auto *SrcElemLoc =
reinterpret_cast<const std::byte *
>(SrcDesc + 1);
128 auto *DstElemLoc =
reinterpret_cast<std::byte *
>(DstDesc + 1);
132 Fn(B, SrcElemLoc, DstElemLoc, D->
ElemDesc);
139 auto CtorSub = [=](
unsigned SubOff,
Descriptor *F,
bool IsBase) {
143 Desc->IsInitialized = F->IsArray && !IsBase;
144 Desc->IsBase = IsBase;
145 Desc->IsActive = IsActive && !IsUnion;
146 Desc->IsConst = IsConst || F->IsConst;
147 Desc->IsFieldMutable = IsMutable || F->IsMutable;
148 if (
auto Fn = F->CtorFn)
149 Fn(B, Ptr + SubOff, Desc->IsConst, Desc->IsFieldMutable, Desc->IsActive,
153 CtorSub(B.Offset, B.
Desc,
true);
155 CtorSub(F.Offset, F.Desc,
false);
157 CtorSub(
V.Offset,
V.Desc,
true);
161 auto DtorSub = [=](
unsigned SubOff,
Descriptor *F) {
162 if (
auto Fn = F->DtorFn)
163 Fn(B, Ptr + SubOff, F);
166 DtorSub(F.Offset, F.Desc);
168 DtorSub(F.Offset, F.Desc);
170 DtorSub(F.Offset, F.Desc);
176 auto FieldOff = F.Offset;
177 auto *FieldDesc = F.Desc;
179 if (
auto Fn = FieldDesc->MoveFn)
180 Fn(B, Src + FieldOff, Dst + FieldOff, FieldDesc);
188 return ctorTy<PrimConv<PT_Float>::T>;
190 return ctorTy<PrimConv<PT_IntAP>::T>;
192 return ctorTy<PrimConv<PT_IntAPS>::T>;
201 return dtorTy<PrimConv<PT_Float>::T>;
203 return dtorTy<PrimConv<PT_IntAP>::T>;
205 return dtorTy<PrimConv<PT_IntAPS>::T>;
216 llvm_unreachable(
"unknown Expr");
221 llvm_unreachable(
"unknown Expr");
226 llvm_unreachable(
"unknown Expr");
231 bool IsConst,
bool IsTemporary,
bool IsMutable)
233 MDSize(MD.value_or(0)), AllocSize(
align(Size + MDSize)), IsConst(IsConst),
234 IsMutable(IsMutable), IsTemporary(IsTemporary), CtorFn(
getCtorPrim(
Type)),
236 assert(AllocSize >= Size);
237 assert(Source &&
"Missing source");
242 size_t NumElems,
bool IsConst,
bool IsTemporary,
244 : Source(D), ElemSize(
primSize(
Type)), Size(ElemSize * NumElems),
245 MDSize(MD.value_or(0)),
246 AllocSize(
align(Size) + sizeof(
InitMapPtr) + MDSize), IsConst(IsConst),
247 IsMutable(IsMutable), IsTemporary(IsTemporary), IsArray(
true),
250 assert(Source &&
"Missing source");
256 : Source(D), ElemSize(
primSize(
Type)), Size(UnknownSizeMark), MDSize(0),
258 IsMutable(
false), IsTemporary(IsTemporary), IsArray(
true),
261 assert(Source &&
"Missing source");
266 unsigned NumElems,
bool IsConst,
bool IsTemporary,
269 Size(ElemSize * NumElems), MDSize(MD.value_or(0)),
270 AllocSize(
std::
max<
size_t>(alignof(void *), Size) + MDSize),
271 ElemDesc(Elem), IsConst(IsConst), IsMutable(IsMutable),
274 assert(Source &&
"Missing source");
281 Size(UnknownSizeMark), MDSize(0),
282 AllocSize(alignof(void *) + sizeof(
InitMapPtr)), ElemDesc(Elem),
283 IsConst(
true), IsMutable(
false), IsTemporary(IsTemporary), IsArray(
true),
285 assert(Source &&
"Missing source");
290 bool IsConst,
bool IsTemporary,
bool IsMutable)
291 : Source(D), ElemSize(
std::
max<
size_t>(alignof(void *), R->getFullSize())),
292 Size(ElemSize), MDSize(MD.value_or(0)), AllocSize(Size + MDSize),
293 ElemRecord(R), IsConst(IsConst), IsMutable(IsMutable),
296 assert(Source &&
"Missing source");
300 : Source(D), ElemSize(1), Size(ElemSize), MDSize(MD.value_or(0)),
301 AllocSize(Size + MDSize), ElemRecord(nullptr), IsConst(
true),
303 assert(Source &&
"Missing source");
311 if (
auto *T = dyn_cast<TypeDecl>(
asDecl()))
312 return QualType(T->getTypeForDecl(), 0);
313 llvm_unreachable(
"Invalid descriptor type");
318 const auto *AT = cast<ArrayType>(
getType());
319 return AT->getElementType();
323 if (
auto *D = Source.dyn_cast<
const Decl *>())
324 return D->getLocation();
325 if (
auto *E = Source.dyn_cast<
const Expr *>())
326 return E->getExprLoc();
327 llvm_unreachable(
"Invalid descriptor type");
331 : UninitFields(N),
Data(
std::make_unique<T[]>(numFields(N))) {
332 std::fill_n(data(), numFields(N), 0);
335bool InitMap::initializeElement(
unsigned I) {
336 unsigned Bucket = I / PER_FIELD;
337 T Mask = T(1) << (I % PER_FIELD);
338 if (!(data()[Bucket] & Mask)) {
339 data()[Bucket] |= Mask;
342 return UninitFields == 0;
345bool InitMap::isElementInitialized(
unsigned I)
const {
346 unsigned Bucket = I / PER_FIELD;
347 return data()[Bucket] & (T(1) << (I % PER_FIELD));
static void dtorTy(Block *, std::byte *Ptr, const Descriptor *)
static BlockCtorFn getCtorArrayPrim(PrimType Type)
static BlockMoveFn getMoveArrayPrim(PrimType Type)
static void dtorArrayTy(Block *, std::byte *Ptr, const Descriptor *D)
static BlockMoveFn getMovePrim(PrimType Type)
static void ctorTy(Block *, std::byte *Ptr, bool, bool, bool, const Descriptor *)
static void ctorArrayTy(Block *, std::byte *Ptr, bool, bool, bool, const Descriptor *D)
static void moveRecord(Block *B, const std::byte *Src, std::byte *Dst, const Descriptor *D)
static void dtorArrayDesc(Block *B, std::byte *Ptr, const Descriptor *D)
static void moveTy(Block *, const std::byte *Src, std::byte *Dst, const Descriptor *)
static BlockDtorFn getDtorPrim(PrimType Type)
static BlockCtorFn getCtorPrim(PrimType Type)
static void ctorArrayDesc(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable, bool IsActive, const Descriptor *D)
static BlockDtorFn getDtorArrayPrim(PrimType Type)
static void moveArrayDesc(Block *B, const std::byte *Src, std::byte *Dst, const Descriptor *D)
static void ctorRecord(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable, bool IsActive, const Descriptor *D)
static void dtorRecord(Block *B, std::byte *Ptr, const Descriptor *D)
static void moveArrayTy(Block *, const std::byte *Src, std::byte *Dst, const Descriptor *D)
#define COMPOSITE_TYPE_SWITCH(Expr, B, D)
#define TYPE_SWITCH(Expr, B)
__DEVICE__ int max(int __a, int __b)
Decl - This represents one declaration (or definition), e.g.
This represents one expression.
A (possibly-)qualified type.
Encodes a location in the source.
The base class of the type hierarchy.
A memory block, either on the stack or in the heap.
const Descriptor * Desc
Pointer to the stack slot descriptor.
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
std::optional< std::pair< bool, std::shared_ptr< InitMap > > > InitMapPtr
bool NE(InterpState &S, CodePtr OpPC)
void(*)(Block *Storage, std::byte *FieldPtr, const Descriptor *FieldDesc) BlockDtorFn
Invoked when a block is destroyed.
constexpr size_t align(size_t Size)
Aligns a size to the pointer alignment.
PrimType
Enumeration of the primitive types of the VM.
void(*)(Block *Storage, const std::byte *SrcFieldPtr, std::byte *DstFieldPtr, const Descriptor *FieldDesc) BlockMoveFn
Invoked when a block with pointers referencing it goes out of scope.
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 IsActive, const Descriptor *FieldDesc) BlockCtorFn
Invoked whenever a block is created.
llvm::PointerUnion< const Decl *, const Expr * > DeclTy
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.
QualType getElemQualType() const
const ValueDecl * asValueDecl() const
const BlockCtorFn CtorFn
Storage management methods.
const Decl * asDecl() const
const Descriptor *const ElemDesc
Descriptor of the array element.
SourceLocation getLocation() const
const bool IsMutable
Flag indicating if a field is mutable.
std::optional< unsigned > MetadataSize
Descriptor(const DeclTy &D, PrimType Type, MetadataSize MD, bool IsConst, bool IsTemporary, bool IsMutable)
Allocates a descriptor for a primitive.
const Expr * asExpr() const
Record *const ElemRecord
Pointer to the record, if block contains records.
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.