1a7dea167SDimitry Andric //===--- Descriptor.cpp - Types for the constexpr VM ------------*- C++ -*-===// 2a7dea167SDimitry Andric // 3a7dea167SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4a7dea167SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5a7dea167SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6a7dea167SDimitry Andric // 7a7dea167SDimitry Andric //===----------------------------------------------------------------------===// 8a7dea167SDimitry Andric 9a7dea167SDimitry Andric #include "Descriptor.h" 10bdd1243dSDimitry Andric #include "Boolean.h" 1106c3fb27SDimitry Andric #include "Floating.h" 1206c3fb27SDimitry Andric #include "FunctionPointer.h" 135f757f3fSDimitry Andric #include "IntegralAP.h" 14*0fca6ea1SDimitry Andric #include "MemberPointer.h" 15a7dea167SDimitry Andric #include "Pointer.h" 16a7dea167SDimitry Andric #include "PrimType.h" 17a7dea167SDimitry Andric #include "Record.h" 18a7dea167SDimitry Andric 19a7dea167SDimitry Andric using namespace clang; 20a7dea167SDimitry Andric using namespace clang::interp; 21a7dea167SDimitry Andric 22a7dea167SDimitry Andric template <typename T> 235f757f3fSDimitry Andric static void ctorTy(Block *, std::byte *Ptr, bool, bool, bool, 245f757f3fSDimitry Andric const Descriptor *) { 25a7dea167SDimitry Andric new (Ptr) T(); 26a7dea167SDimitry Andric } 27a7dea167SDimitry Andric 2806c3fb27SDimitry Andric template <typename T> 295f757f3fSDimitry Andric static void dtorTy(Block *, std::byte *Ptr, const Descriptor *) { 30a7dea167SDimitry Andric reinterpret_cast<T *>(Ptr)->~T(); 31a7dea167SDimitry Andric } 32a7dea167SDimitry Andric 33a7dea167SDimitry Andric template <typename T> 345f757f3fSDimitry Andric static void moveTy(Block *, const std::byte *Src, std::byte *Dst, 355f757f3fSDimitry Andric const Descriptor *) { 3606c3fb27SDimitry Andric const auto *SrcPtr = reinterpret_cast<const T *>(Src); 37a7dea167SDimitry Andric auto *DstPtr = reinterpret_cast<T *>(Dst); 38a7dea167SDimitry Andric new (DstPtr) T(std::move(*SrcPtr)); 39a7dea167SDimitry Andric } 40a7dea167SDimitry Andric 41a7dea167SDimitry Andric template <typename T> 425f757f3fSDimitry Andric static void ctorArrayTy(Block *, std::byte *Ptr, bool, bool, bool, 4306c3fb27SDimitry Andric const Descriptor *D) { 445f757f3fSDimitry Andric new (Ptr) InitMapPtr(std::nullopt); 455f757f3fSDimitry Andric 465f757f3fSDimitry Andric Ptr += sizeof(InitMapPtr); 47a7dea167SDimitry Andric for (unsigned I = 0, NE = D->getNumElems(); I < NE; ++I) { 48a7dea167SDimitry Andric new (&reinterpret_cast<T *>(Ptr)[I]) T(); 49a7dea167SDimitry Andric } 50a7dea167SDimitry Andric } 51a7dea167SDimitry Andric 52a7dea167SDimitry Andric template <typename T> 535f757f3fSDimitry Andric static void dtorArrayTy(Block *, std::byte *Ptr, const Descriptor *D) { 545f757f3fSDimitry Andric InitMapPtr &IMP = *reinterpret_cast<InitMapPtr *>(Ptr); 55bdd1243dSDimitry Andric 565f757f3fSDimitry Andric if (IMP) 575f757f3fSDimitry Andric IMP = std::nullopt; 585f757f3fSDimitry Andric Ptr += sizeof(InitMapPtr); 59a7dea167SDimitry Andric for (unsigned I = 0, NE = D->getNumElems(); I < NE; ++I) { 60a7dea167SDimitry Andric reinterpret_cast<T *>(Ptr)[I].~T(); 61a7dea167SDimitry Andric } 62a7dea167SDimitry Andric } 63a7dea167SDimitry Andric 64a7dea167SDimitry Andric template <typename T> 655f757f3fSDimitry Andric static void moveArrayTy(Block *, const std::byte *Src, std::byte *Dst, 6606c3fb27SDimitry Andric const Descriptor *D) { 67*0fca6ea1SDimitry Andric // FIXME: Get rid of the const_cast. 68*0fca6ea1SDimitry Andric InitMapPtr &SrcIMP = 69*0fca6ea1SDimitry Andric *reinterpret_cast<InitMapPtr *>(const_cast<std::byte *>(Src)); 70*0fca6ea1SDimitry Andric if (SrcIMP) { 71*0fca6ea1SDimitry Andric // We only ever invoke the moveFunc when moving block contents to a 72*0fca6ea1SDimitry Andric // DeadBlock. DeadBlocks don't need InitMaps, so we destroy them here. 73*0fca6ea1SDimitry Andric SrcIMP = std::nullopt; 74*0fca6ea1SDimitry Andric } 75*0fca6ea1SDimitry Andric Src += sizeof(InitMapPtr); 76*0fca6ea1SDimitry Andric Dst += sizeof(InitMapPtr); 77a7dea167SDimitry Andric for (unsigned I = 0, NE = D->getNumElems(); I < NE; ++I) { 7806c3fb27SDimitry Andric const auto *SrcPtr = &reinterpret_cast<const T *>(Src)[I]; 79a7dea167SDimitry Andric auto *DstPtr = &reinterpret_cast<T *>(Dst)[I]; 80a7dea167SDimitry Andric new (DstPtr) T(std::move(*SrcPtr)); 81a7dea167SDimitry Andric } 82a7dea167SDimitry Andric } 83a7dea167SDimitry Andric 845f757f3fSDimitry Andric static void ctorArrayDesc(Block *B, std::byte *Ptr, bool IsConst, 855f757f3fSDimitry Andric bool IsMutable, bool IsActive, const Descriptor *D) { 86a7dea167SDimitry Andric const unsigned NumElems = D->getNumElems(); 87a7dea167SDimitry Andric const unsigned ElemSize = 88a7dea167SDimitry Andric D->ElemDesc->getAllocSize() + sizeof(InlineDescriptor); 89a7dea167SDimitry Andric 90a7dea167SDimitry Andric unsigned ElemOffset = 0; 91a7dea167SDimitry Andric for (unsigned I = 0; I < NumElems; ++I, ElemOffset += ElemSize) { 92a7dea167SDimitry Andric auto *ElemPtr = Ptr + ElemOffset; 93a7dea167SDimitry Andric auto *Desc = reinterpret_cast<InlineDescriptor *>(ElemPtr); 945f757f3fSDimitry Andric auto *ElemLoc = reinterpret_cast<std::byte *>(Desc + 1); 95a7dea167SDimitry Andric auto *SD = D->ElemDesc; 96a7dea167SDimitry Andric 97a7dea167SDimitry Andric Desc->Offset = ElemOffset + sizeof(InlineDescriptor); 98a7dea167SDimitry Andric Desc->Desc = SD; 99a7dea167SDimitry Andric Desc->IsInitialized = true; 100a7dea167SDimitry Andric Desc->IsBase = false; 101a7dea167SDimitry Andric Desc->IsActive = IsActive; 102a7dea167SDimitry Andric Desc->IsConst = IsConst || D->IsConst; 103bdd1243dSDimitry Andric Desc->IsFieldMutable = IsMutable || D->IsMutable; 104a7dea167SDimitry Andric if (auto Fn = D->ElemDesc->CtorFn) 105bdd1243dSDimitry Andric Fn(B, ElemLoc, Desc->IsConst, Desc->IsFieldMutable, IsActive, 106bdd1243dSDimitry Andric D->ElemDesc); 107a7dea167SDimitry Andric } 108a7dea167SDimitry Andric } 109a7dea167SDimitry Andric 1105f757f3fSDimitry Andric static void dtorArrayDesc(Block *B, std::byte *Ptr, const Descriptor *D) { 111a7dea167SDimitry Andric const unsigned NumElems = D->getNumElems(); 112a7dea167SDimitry Andric const unsigned ElemSize = 113a7dea167SDimitry Andric D->ElemDesc->getAllocSize() + sizeof(InlineDescriptor); 114a7dea167SDimitry Andric 115a7dea167SDimitry Andric unsigned ElemOffset = 0; 116a7dea167SDimitry Andric for (unsigned I = 0; I < NumElems; ++I, ElemOffset += ElemSize) { 117a7dea167SDimitry Andric auto *ElemPtr = Ptr + ElemOffset; 118a7dea167SDimitry Andric auto *Desc = reinterpret_cast<InlineDescriptor *>(ElemPtr); 1195f757f3fSDimitry Andric auto *ElemLoc = reinterpret_cast<std::byte *>(Desc + 1); 120a7dea167SDimitry Andric if (auto Fn = D->ElemDesc->DtorFn) 121a7dea167SDimitry Andric Fn(B, ElemLoc, D->ElemDesc); 122a7dea167SDimitry Andric } 123a7dea167SDimitry Andric } 124a7dea167SDimitry Andric 1255f757f3fSDimitry Andric static void moveArrayDesc(Block *B, const std::byte *Src, std::byte *Dst, 12606c3fb27SDimitry Andric const Descriptor *D) { 127a7dea167SDimitry Andric const unsigned NumElems = D->getNumElems(); 128a7dea167SDimitry Andric const unsigned ElemSize = 129a7dea167SDimitry Andric D->ElemDesc->getAllocSize() + sizeof(InlineDescriptor); 130a7dea167SDimitry Andric 131a7dea167SDimitry Andric unsigned ElemOffset = 0; 132a7dea167SDimitry Andric for (unsigned I = 0; I < NumElems; ++I, ElemOffset += ElemSize) { 13306c3fb27SDimitry Andric const auto *SrcPtr = Src + ElemOffset; 134a7dea167SDimitry Andric auto *DstPtr = Dst + ElemOffset; 135a7dea167SDimitry Andric 13606c3fb27SDimitry Andric const auto *SrcDesc = reinterpret_cast<const InlineDescriptor *>(SrcPtr); 1375f757f3fSDimitry Andric const auto *SrcElemLoc = reinterpret_cast<const std::byte *>(SrcDesc + 1); 138a7dea167SDimitry Andric auto *DstDesc = reinterpret_cast<InlineDescriptor *>(DstPtr); 1395f757f3fSDimitry Andric auto *DstElemLoc = reinterpret_cast<std::byte *>(DstDesc + 1); 140a7dea167SDimitry Andric 141a7dea167SDimitry Andric *DstDesc = *SrcDesc; 142a7dea167SDimitry Andric if (auto Fn = D->ElemDesc->MoveFn) 143a7dea167SDimitry Andric Fn(B, SrcElemLoc, DstElemLoc, D->ElemDesc); 144a7dea167SDimitry Andric } 145a7dea167SDimitry Andric } 146a7dea167SDimitry Andric 147*0fca6ea1SDimitry Andric static void initField(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable, 148*0fca6ea1SDimitry Andric bool IsActive, bool IsUnion, const Descriptor *D, 149*0fca6ea1SDimitry Andric unsigned FieldOffset) { 150*0fca6ea1SDimitry Andric auto *Desc = reinterpret_cast<InlineDescriptor *>(Ptr + FieldOffset) - 1; 151*0fca6ea1SDimitry Andric Desc->Offset = FieldOffset; 152*0fca6ea1SDimitry Andric Desc->Desc = D; 153*0fca6ea1SDimitry Andric Desc->IsInitialized = D->IsArray; 154*0fca6ea1SDimitry Andric Desc->IsBase = false; 155*0fca6ea1SDimitry Andric Desc->IsActive = IsActive && !IsUnion; 156*0fca6ea1SDimitry Andric Desc->IsConst = IsConst || D->IsConst; 157*0fca6ea1SDimitry Andric Desc->IsFieldMutable = IsMutable || D->IsMutable; 158*0fca6ea1SDimitry Andric 159*0fca6ea1SDimitry Andric if (auto Fn = D->CtorFn) 160*0fca6ea1SDimitry Andric Fn(B, Ptr + FieldOffset, Desc->IsConst, Desc->IsFieldMutable, 161*0fca6ea1SDimitry Andric Desc->IsActive, D); 162*0fca6ea1SDimitry Andric } 163*0fca6ea1SDimitry Andric 164*0fca6ea1SDimitry Andric static void initBase(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable, 165*0fca6ea1SDimitry Andric bool IsActive, const Descriptor *D, unsigned FieldOffset, 166*0fca6ea1SDimitry Andric bool IsVirtualBase) { 167*0fca6ea1SDimitry Andric assert(D); 168*0fca6ea1SDimitry Andric assert(D->ElemRecord); 169*0fca6ea1SDimitry Andric 170*0fca6ea1SDimitry Andric bool IsUnion = D->ElemRecord->isUnion(); 171*0fca6ea1SDimitry Andric auto *Desc = reinterpret_cast<InlineDescriptor *>(Ptr + FieldOffset) - 1; 172*0fca6ea1SDimitry Andric Desc->Offset = FieldOffset; 173*0fca6ea1SDimitry Andric Desc->Desc = D; 174*0fca6ea1SDimitry Andric Desc->IsInitialized = D->IsArray; 175*0fca6ea1SDimitry Andric Desc->IsBase = true; 176*0fca6ea1SDimitry Andric Desc->IsVirtualBase = IsVirtualBase; 177*0fca6ea1SDimitry Andric Desc->IsActive = IsActive && !IsUnion; 178*0fca6ea1SDimitry Andric Desc->IsConst = IsConst || D->IsConst; 179*0fca6ea1SDimitry Andric Desc->IsFieldMutable = IsMutable || D->IsMutable; 180*0fca6ea1SDimitry Andric 181*0fca6ea1SDimitry Andric for (const auto &V : D->ElemRecord->bases()) 182*0fca6ea1SDimitry Andric initBase(B, Ptr + FieldOffset, IsConst, IsMutable, IsActive, V.Desc, 183*0fca6ea1SDimitry Andric V.Offset, false); 184*0fca6ea1SDimitry Andric for (const auto &F : D->ElemRecord->fields()) 185*0fca6ea1SDimitry Andric initField(B, Ptr + FieldOffset, IsConst, IsMutable, IsActive, IsUnion, 186*0fca6ea1SDimitry Andric F.Desc, F.Offset); 187*0fca6ea1SDimitry Andric } 188*0fca6ea1SDimitry Andric 1895f757f3fSDimitry Andric static void ctorRecord(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable, 19006c3fb27SDimitry Andric bool IsActive, const Descriptor *D) { 191*0fca6ea1SDimitry Andric for (const auto &V : D->ElemRecord->bases()) 192*0fca6ea1SDimitry Andric initBase(B, Ptr, IsConst, IsMutable, IsActive, V.Desc, V.Offset, false); 193a7dea167SDimitry Andric for (const auto &F : D->ElemRecord->fields()) 194*0fca6ea1SDimitry Andric initField(B, Ptr, IsConst, IsMutable, IsActive, D->ElemRecord->isUnion(), F.Desc, F.Offset); 195a7dea167SDimitry Andric for (const auto &V : D->ElemRecord->virtual_bases()) 196*0fca6ea1SDimitry Andric initBase(B, Ptr, IsConst, IsMutable, IsActive, V.Desc, V.Offset, true); 197*0fca6ea1SDimitry Andric } 198*0fca6ea1SDimitry Andric 199*0fca6ea1SDimitry Andric static void destroyField(Block *B, std::byte *Ptr, const Descriptor *D, 200*0fca6ea1SDimitry Andric unsigned FieldOffset) { 201*0fca6ea1SDimitry Andric if (auto Fn = D->DtorFn) 202*0fca6ea1SDimitry Andric Fn(B, Ptr + FieldOffset, D); 203*0fca6ea1SDimitry Andric } 204*0fca6ea1SDimitry Andric 205*0fca6ea1SDimitry Andric static void destroyBase(Block *B, std::byte *Ptr, const Descriptor *D, 206*0fca6ea1SDimitry Andric unsigned FieldOffset) { 207*0fca6ea1SDimitry Andric assert(D); 208*0fca6ea1SDimitry Andric assert(D->ElemRecord); 209*0fca6ea1SDimitry Andric 210*0fca6ea1SDimitry Andric for (const auto &V : D->ElemRecord->bases()) 211*0fca6ea1SDimitry Andric destroyBase(B, Ptr + FieldOffset, V.Desc, V.Offset); 212*0fca6ea1SDimitry Andric for (const auto &F : D->ElemRecord->fields()) 213*0fca6ea1SDimitry Andric destroyField(B, Ptr + FieldOffset, F.Desc, F.Offset); 214a7dea167SDimitry Andric } 215a7dea167SDimitry Andric 2165f757f3fSDimitry Andric static void dtorRecord(Block *B, std::byte *Ptr, const Descriptor *D) { 217a7dea167SDimitry Andric for (const auto &F : D->ElemRecord->bases()) 218*0fca6ea1SDimitry Andric destroyBase(B, Ptr, F.Desc, F.Offset); 219a7dea167SDimitry Andric for (const auto &F : D->ElemRecord->fields()) 220*0fca6ea1SDimitry Andric destroyField(B, Ptr, F.Desc, F.Offset); 221a7dea167SDimitry Andric for (const auto &F : D->ElemRecord->virtual_bases()) 222*0fca6ea1SDimitry Andric destroyBase(B, Ptr, F.Desc, F.Offset); 223a7dea167SDimitry Andric } 224a7dea167SDimitry Andric 2255f757f3fSDimitry Andric static void moveRecord(Block *B, const std::byte *Src, std::byte *Dst, 22606c3fb27SDimitry Andric const Descriptor *D) { 227a7dea167SDimitry Andric for (const auto &F : D->ElemRecord->fields()) { 228a7dea167SDimitry Andric auto FieldOff = F.Offset; 2295f757f3fSDimitry Andric auto *FieldDesc = F.Desc; 230a7dea167SDimitry Andric 231a7dea167SDimitry Andric if (auto Fn = FieldDesc->MoveFn) 232a7dea167SDimitry Andric Fn(B, Src + FieldOff, Dst + FieldOff, FieldDesc); 233a7dea167SDimitry Andric } 234a7dea167SDimitry Andric } 235a7dea167SDimitry Andric 236a7dea167SDimitry Andric static BlockCtorFn getCtorPrim(PrimType Type) { 23706c3fb27SDimitry Andric // Floating types are special. They are primitives, but need their 23806c3fb27SDimitry Andric // constructor called. 23906c3fb27SDimitry Andric if (Type == PT_Float) 24006c3fb27SDimitry Andric return ctorTy<PrimConv<PT_Float>::T>; 2415f757f3fSDimitry Andric if (Type == PT_IntAP) 2425f757f3fSDimitry Andric return ctorTy<PrimConv<PT_IntAP>::T>; 2435f757f3fSDimitry Andric if (Type == PT_IntAPS) 2445f757f3fSDimitry Andric return ctorTy<PrimConv<PT_IntAPS>::T>; 245*0fca6ea1SDimitry Andric if (Type == PT_MemberPtr) 246*0fca6ea1SDimitry Andric return ctorTy<PrimConv<PT_MemberPtr>::T>; 24706c3fb27SDimitry Andric 248a7dea167SDimitry Andric COMPOSITE_TYPE_SWITCH(Type, return ctorTy<T>, return nullptr); 249a7dea167SDimitry Andric } 250a7dea167SDimitry Andric 251a7dea167SDimitry Andric static BlockDtorFn getDtorPrim(PrimType Type) { 25206c3fb27SDimitry Andric // Floating types are special. They are primitives, but need their 25306c3fb27SDimitry Andric // destructor called, since they might allocate memory. 25406c3fb27SDimitry Andric if (Type == PT_Float) 25506c3fb27SDimitry Andric return dtorTy<PrimConv<PT_Float>::T>; 2565f757f3fSDimitry Andric if (Type == PT_IntAP) 2575f757f3fSDimitry Andric return dtorTy<PrimConv<PT_IntAP>::T>; 2585f757f3fSDimitry Andric if (Type == PT_IntAPS) 2595f757f3fSDimitry Andric return dtorTy<PrimConv<PT_IntAPS>::T>; 260*0fca6ea1SDimitry Andric if (Type == PT_MemberPtr) 261*0fca6ea1SDimitry Andric return dtorTy<PrimConv<PT_MemberPtr>::T>; 26206c3fb27SDimitry Andric 263a7dea167SDimitry Andric COMPOSITE_TYPE_SWITCH(Type, return dtorTy<T>, return nullptr); 264a7dea167SDimitry Andric } 265a7dea167SDimitry Andric 266a7dea167SDimitry Andric static BlockMoveFn getMovePrim(PrimType Type) { 267a7dea167SDimitry Andric COMPOSITE_TYPE_SWITCH(Type, return moveTy<T>, return nullptr); 268a7dea167SDimitry Andric } 269a7dea167SDimitry Andric 270a7dea167SDimitry Andric static BlockCtorFn getCtorArrayPrim(PrimType Type) { 2715f757f3fSDimitry Andric TYPE_SWITCH(Type, return ctorArrayTy<T>); 2725f757f3fSDimitry Andric llvm_unreachable("unknown Expr"); 273a7dea167SDimitry Andric } 274a7dea167SDimitry Andric 275a7dea167SDimitry Andric static BlockDtorFn getDtorArrayPrim(PrimType Type) { 276bdd1243dSDimitry Andric TYPE_SWITCH(Type, return dtorArrayTy<T>); 277bdd1243dSDimitry Andric llvm_unreachable("unknown Expr"); 278a7dea167SDimitry Andric } 279a7dea167SDimitry Andric 280a7dea167SDimitry Andric static BlockMoveFn getMoveArrayPrim(PrimType Type) { 2815f757f3fSDimitry Andric TYPE_SWITCH(Type, return moveArrayTy<T>); 2825f757f3fSDimitry Andric llvm_unreachable("unknown Expr"); 283a7dea167SDimitry Andric } 284a7dea167SDimitry Andric 2855f757f3fSDimitry Andric /// Primitives. 286bdd1243dSDimitry Andric Descriptor::Descriptor(const DeclTy &D, PrimType Type, MetadataSize MD, 287bdd1243dSDimitry Andric bool IsConst, bool IsTemporary, bool IsMutable) 288bdd1243dSDimitry Andric : Source(D), ElemSize(primSize(Type)), Size(ElemSize), 289*0fca6ea1SDimitry Andric MDSize(MD.value_or(0)), AllocSize(align(Size + MDSize)), PrimT(Type), 290*0fca6ea1SDimitry Andric IsConst(IsConst), IsMutable(IsMutable), IsTemporary(IsTemporary), 291*0fca6ea1SDimitry Andric CtorFn(getCtorPrim(Type)), DtorFn(getDtorPrim(Type)), 292*0fca6ea1SDimitry Andric MoveFn(getMovePrim(Type)) { 293bdd1243dSDimitry Andric assert(AllocSize >= Size); 294a7dea167SDimitry Andric assert(Source && "Missing source"); 295a7dea167SDimitry Andric } 296a7dea167SDimitry Andric 2975f757f3fSDimitry Andric /// Primitive arrays. 298bdd1243dSDimitry Andric Descriptor::Descriptor(const DeclTy &D, PrimType Type, MetadataSize MD, 299bdd1243dSDimitry Andric size_t NumElems, bool IsConst, bool IsTemporary, 300bdd1243dSDimitry Andric bool IsMutable) 301a7dea167SDimitry Andric : Source(D), ElemSize(primSize(Type)), Size(ElemSize * NumElems), 302bdd1243dSDimitry Andric MDSize(MD.value_or(0)), 303*0fca6ea1SDimitry Andric AllocSize(align(MDSize) + align(Size) + sizeof(InitMapPtr)), PrimT(Type), 304*0fca6ea1SDimitry Andric IsConst(IsConst), IsMutable(IsMutable), IsTemporary(IsTemporary), 305*0fca6ea1SDimitry Andric IsArray(true), CtorFn(getCtorArrayPrim(Type)), 306*0fca6ea1SDimitry Andric DtorFn(getDtorArrayPrim(Type)), MoveFn(getMoveArrayPrim(Type)) { 307a7dea167SDimitry Andric assert(Source && "Missing source"); 308*0fca6ea1SDimitry Andric assert(NumElems <= (MaxArrayElemBytes / ElemSize)); 309a7dea167SDimitry Andric } 310a7dea167SDimitry Andric 3115f757f3fSDimitry Andric /// Primitive unknown-size arrays. 312*0fca6ea1SDimitry Andric Descriptor::Descriptor(const DeclTy &D, PrimType Type, MetadataSize MD, 313*0fca6ea1SDimitry Andric bool IsTemporary, UnknownSize) 314*0fca6ea1SDimitry Andric : Source(D), ElemSize(primSize(Type)), Size(UnknownSizeMark), 315*0fca6ea1SDimitry Andric MDSize(MD.value_or(0)), 316*0fca6ea1SDimitry Andric AllocSize(MDSize + sizeof(InitMapPtr) + alignof(void *)), IsConst(true), 3175f757f3fSDimitry Andric IsMutable(false), IsTemporary(IsTemporary), IsArray(true), 3185f757f3fSDimitry Andric CtorFn(getCtorArrayPrim(Type)), DtorFn(getDtorArrayPrim(Type)), 3195f757f3fSDimitry Andric MoveFn(getMoveArrayPrim(Type)) { 320a7dea167SDimitry Andric assert(Source && "Missing source"); 321a7dea167SDimitry Andric } 322a7dea167SDimitry Andric 3235f757f3fSDimitry Andric /// Arrays of composite elements. 3245f757f3fSDimitry Andric Descriptor::Descriptor(const DeclTy &D, const Descriptor *Elem, MetadataSize MD, 325bdd1243dSDimitry Andric unsigned NumElems, bool IsConst, bool IsTemporary, 326bdd1243dSDimitry Andric bool IsMutable) 327a7dea167SDimitry Andric : Source(D), ElemSize(Elem->getAllocSize() + sizeof(InlineDescriptor)), 328bdd1243dSDimitry Andric Size(ElemSize * NumElems), MDSize(MD.value_or(0)), 329bdd1243dSDimitry Andric AllocSize(std::max<size_t>(alignof(void *), Size) + MDSize), 330bdd1243dSDimitry Andric ElemDesc(Elem), IsConst(IsConst), IsMutable(IsMutable), 331bdd1243dSDimitry Andric IsTemporary(IsTemporary), IsArray(true), CtorFn(ctorArrayDesc), 332bdd1243dSDimitry Andric DtorFn(dtorArrayDesc), MoveFn(moveArrayDesc) { 333a7dea167SDimitry Andric assert(Source && "Missing source"); 334a7dea167SDimitry Andric } 335a7dea167SDimitry Andric 3365f757f3fSDimitry Andric /// Unknown-size arrays of composite elements. 337*0fca6ea1SDimitry Andric Descriptor::Descriptor(const DeclTy &D, const Descriptor *Elem, MetadataSize MD, 338297eecfbSDimitry Andric bool IsTemporary, UnknownSize) 339a7dea167SDimitry Andric : Source(D), ElemSize(Elem->getAllocSize() + sizeof(InlineDescriptor)), 340*0fca6ea1SDimitry Andric Size(UnknownSizeMark), MDSize(MD.value_or(0)), 341*0fca6ea1SDimitry Andric AllocSize(MDSize + alignof(void *)), ElemDesc(Elem), IsConst(true), 342*0fca6ea1SDimitry Andric IsMutable(false), IsTemporary(IsTemporary), IsArray(true), 3435f757f3fSDimitry Andric CtorFn(ctorArrayDesc), DtorFn(dtorArrayDesc), MoveFn(moveArrayDesc) { 344a7dea167SDimitry Andric assert(Source && "Missing source"); 345a7dea167SDimitry Andric } 346a7dea167SDimitry Andric 3475f757f3fSDimitry Andric /// Composite records. 348297eecfbSDimitry Andric Descriptor::Descriptor(const DeclTy &D, const Record *R, MetadataSize MD, 349bdd1243dSDimitry Andric bool IsConst, bool IsTemporary, bool IsMutable) 350a7dea167SDimitry Andric : Source(D), ElemSize(std::max<size_t>(alignof(void *), R->getFullSize())), 351bdd1243dSDimitry Andric Size(ElemSize), MDSize(MD.value_or(0)), AllocSize(Size + MDSize), 352bdd1243dSDimitry Andric ElemRecord(R), IsConst(IsConst), IsMutable(IsMutable), 353bdd1243dSDimitry Andric IsTemporary(IsTemporary), CtorFn(ctorRecord), DtorFn(dtorRecord), 354bdd1243dSDimitry Andric MoveFn(moveRecord) { 355a7dea167SDimitry Andric assert(Source && "Missing source"); 356a7dea167SDimitry Andric } 357a7dea167SDimitry Andric 358*0fca6ea1SDimitry Andric /// Dummy. 359*0fca6ea1SDimitry Andric Descriptor::Descriptor(const DeclTy &D) 360*0fca6ea1SDimitry Andric : Source(D), ElemSize(1), Size(1), MDSize(0), AllocSize(MDSize), 361*0fca6ea1SDimitry Andric ElemRecord(nullptr), IsConst(true), IsMutable(false), IsTemporary(false), 362*0fca6ea1SDimitry Andric IsDummy(true) { 3635f757f3fSDimitry Andric assert(Source && "Missing source"); 3645f757f3fSDimitry Andric } 3655f757f3fSDimitry Andric 366a7dea167SDimitry Andric QualType Descriptor::getType() const { 367*0fca6ea1SDimitry Andric if (const auto *E = asExpr()) 368a7dea167SDimitry Andric return E->getType(); 369*0fca6ea1SDimitry Andric if (const auto *D = asValueDecl()) 370a7dea167SDimitry Andric return D->getType(); 371*0fca6ea1SDimitry Andric if (const auto *T = dyn_cast<TypeDecl>(asDecl())) 37206c3fb27SDimitry Andric return QualType(T->getTypeForDecl(), 0); 373a7dea167SDimitry Andric llvm_unreachable("Invalid descriptor type"); 374a7dea167SDimitry Andric } 375a7dea167SDimitry Andric 3765f757f3fSDimitry Andric QualType Descriptor::getElemQualType() const { 3775f757f3fSDimitry Andric assert(isArray()); 378*0fca6ea1SDimitry Andric QualType T = getType(); 379*0fca6ea1SDimitry Andric if (const auto *AT = T->getAsArrayTypeUnsafe()) 3805f757f3fSDimitry Andric return AT->getElementType(); 381*0fca6ea1SDimitry Andric if (const auto *CT = T->getAs<ComplexType>()) 382*0fca6ea1SDimitry Andric return CT->getElementType(); 383*0fca6ea1SDimitry Andric if (const auto *CT = T->getAs<VectorType>()) 384*0fca6ea1SDimitry Andric return CT->getElementType(); 385*0fca6ea1SDimitry Andric llvm_unreachable("Array that's not an array/complex/vector type?"); 3865f757f3fSDimitry Andric } 3875f757f3fSDimitry Andric 388a7dea167SDimitry Andric SourceLocation Descriptor::getLocation() const { 389a7dea167SDimitry Andric if (auto *D = Source.dyn_cast<const Decl *>()) 390a7dea167SDimitry Andric return D->getLocation(); 391a7dea167SDimitry Andric if (auto *E = Source.dyn_cast<const Expr *>()) 392a7dea167SDimitry Andric return E->getExprLoc(); 393a7dea167SDimitry Andric llvm_unreachable("Invalid descriptor type"); 394a7dea167SDimitry Andric } 395a7dea167SDimitry Andric 3965f757f3fSDimitry Andric InitMap::InitMap(unsigned N) 3975f757f3fSDimitry Andric : UninitFields(N), Data(std::make_unique<T[]>(numFields(N))) { 3985f757f3fSDimitry Andric std::fill_n(data(), numFields(N), 0); 399a7dea167SDimitry Andric } 400a7dea167SDimitry Andric 4015f757f3fSDimitry Andric bool InitMap::initializeElement(unsigned I) { 402a7dea167SDimitry Andric unsigned Bucket = I / PER_FIELD; 403bdd1243dSDimitry Andric T Mask = T(1) << (I % PER_FIELD); 404a7dea167SDimitry Andric if (!(data()[Bucket] & Mask)) { 405a7dea167SDimitry Andric data()[Bucket] |= Mask; 406a7dea167SDimitry Andric UninitFields -= 1; 407a7dea167SDimitry Andric } 408a7dea167SDimitry Andric return UninitFields == 0; 409a7dea167SDimitry Andric } 410a7dea167SDimitry Andric 4115f757f3fSDimitry Andric bool InitMap::isElementInitialized(unsigned I) const { 412a7dea167SDimitry Andric unsigned Bucket = I / PER_FIELD; 413bdd1243dSDimitry Andric return data()[Bucket] & (T(1) << (I % PER_FIELD)); 414a7dea167SDimitry Andric } 415