1a07aba5dSTimm Baeder //===--- Descriptor.cpp - Types for the constexpr VM ------------*- C++ -*-===// 2a07aba5dSTimm Baeder // 3a07aba5dSTimm Baeder // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4a07aba5dSTimm Baeder // See https://llvm.org/LICENSE.txt for license information. 5a07aba5dSTimm Baeder // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6a07aba5dSTimm Baeder // 7a07aba5dSTimm Baeder //===----------------------------------------------------------------------===// 8a07aba5dSTimm Baeder 9a07aba5dSTimm Baeder #include "Descriptor.h" 10a07aba5dSTimm Baeder #include "Boolean.h" 11048bc672STimm Baeder #include "FixedPoint.h" 12a07aba5dSTimm Baeder #include "Floating.h" 13a07aba5dSTimm Baeder #include "IntegralAP.h" 14a07aba5dSTimm Baeder #include "MemberPointer.h" 15a07aba5dSTimm Baeder #include "Pointer.h" 16a07aba5dSTimm Baeder #include "PrimType.h" 17a07aba5dSTimm Baeder #include "Record.h" 183ea55d3cSTimm Baeder #include "Source.h" 19a07aba5dSTimm Baeder 20a07aba5dSTimm Baeder using namespace clang; 21a07aba5dSTimm Baeder using namespace clang::interp; 22a07aba5dSTimm Baeder 23a07aba5dSTimm Baeder template <typename T> 24a07aba5dSTimm Baeder static void ctorTy(Block *, std::byte *Ptr, bool, bool, bool, bool, 25a07aba5dSTimm Baeder const Descriptor *) { 26a07aba5dSTimm Baeder new (Ptr) T(); 27a07aba5dSTimm Baeder } 28a07aba5dSTimm Baeder 29a07aba5dSTimm Baeder template <typename T> 30a07aba5dSTimm Baeder static void dtorTy(Block *, std::byte *Ptr, const Descriptor *) { 31a07aba5dSTimm Baeder reinterpret_cast<T *>(Ptr)->~T(); 32a07aba5dSTimm Baeder } 33a07aba5dSTimm Baeder 34a07aba5dSTimm Baeder template <typename T> 35a69ba0a5STimm Baeder static void moveTy(Block *, std::byte *Src, std::byte *Dst, 36a07aba5dSTimm Baeder const Descriptor *) { 37a69ba0a5STimm Baeder auto *SrcPtr = reinterpret_cast<T *>(Src); 38a07aba5dSTimm Baeder auto *DstPtr = reinterpret_cast<T *>(Dst); 39a07aba5dSTimm Baeder new (DstPtr) T(std::move(*SrcPtr)); 40a07aba5dSTimm Baeder } 41a07aba5dSTimm Baeder 42a07aba5dSTimm Baeder template <typename T> 43a07aba5dSTimm Baeder static void ctorArrayTy(Block *, std::byte *Ptr, bool, bool, bool, bool, 44a07aba5dSTimm Baeder const Descriptor *D) { 45a07aba5dSTimm Baeder new (Ptr) InitMapPtr(std::nullopt); 46a07aba5dSTimm Baeder 47a07aba5dSTimm Baeder Ptr += sizeof(InitMapPtr); 48a07aba5dSTimm Baeder for (unsigned I = 0, NE = D->getNumElems(); I < NE; ++I) { 49a07aba5dSTimm Baeder new (&reinterpret_cast<T *>(Ptr)[I]) T(); 50a07aba5dSTimm Baeder } 51a07aba5dSTimm Baeder } 52a07aba5dSTimm Baeder 53a07aba5dSTimm Baeder template <typename T> 54a07aba5dSTimm Baeder static void dtorArrayTy(Block *, std::byte *Ptr, const Descriptor *D) { 55a07aba5dSTimm Baeder InitMapPtr &IMP = *reinterpret_cast<InitMapPtr *>(Ptr); 56a07aba5dSTimm Baeder 57a07aba5dSTimm Baeder if (IMP) 58a07aba5dSTimm Baeder IMP = std::nullopt; 59a07aba5dSTimm Baeder Ptr += sizeof(InitMapPtr); 60a07aba5dSTimm Baeder for (unsigned I = 0, NE = D->getNumElems(); I < NE; ++I) { 61a07aba5dSTimm Baeder reinterpret_cast<T *>(Ptr)[I].~T(); 62a07aba5dSTimm Baeder } 63a07aba5dSTimm Baeder } 64a07aba5dSTimm Baeder 65a07aba5dSTimm Baeder template <typename T> 66a69ba0a5STimm Baeder static void moveArrayTy(Block *, std::byte *Src, std::byte *Dst, 67a07aba5dSTimm Baeder const Descriptor *D) { 68a69ba0a5STimm Baeder InitMapPtr &SrcIMP = *reinterpret_cast<InitMapPtr *>(Src); 69a07aba5dSTimm Baeder if (SrcIMP) { 70a07aba5dSTimm Baeder // We only ever invoke the moveFunc when moving block contents to a 71a07aba5dSTimm Baeder // DeadBlock. DeadBlocks don't need InitMaps, so we destroy them here. 72a07aba5dSTimm Baeder SrcIMP = std::nullopt; 73a07aba5dSTimm Baeder } 74a07aba5dSTimm Baeder Src += sizeof(InitMapPtr); 75a07aba5dSTimm Baeder Dst += sizeof(InitMapPtr); 76a07aba5dSTimm Baeder for (unsigned I = 0, NE = D->getNumElems(); I < NE; ++I) { 77a69ba0a5STimm Baeder auto *SrcPtr = &reinterpret_cast<T *>(Src)[I]; 78a07aba5dSTimm Baeder auto *DstPtr = &reinterpret_cast<T *>(Dst)[I]; 79a07aba5dSTimm Baeder new (DstPtr) T(std::move(*SrcPtr)); 80a07aba5dSTimm Baeder } 81a07aba5dSTimm Baeder } 82a07aba5dSTimm Baeder 83a07aba5dSTimm Baeder static void ctorArrayDesc(Block *B, std::byte *Ptr, bool IsConst, 84a07aba5dSTimm Baeder bool IsMutable, bool IsActive, bool InUnion, 85a07aba5dSTimm Baeder const Descriptor *D) { 86a07aba5dSTimm Baeder const unsigned NumElems = D->getNumElems(); 87a07aba5dSTimm Baeder const unsigned ElemSize = 88a07aba5dSTimm Baeder D->ElemDesc->getAllocSize() + sizeof(InlineDescriptor); 89a07aba5dSTimm Baeder 90a07aba5dSTimm Baeder unsigned ElemOffset = 0; 91a07aba5dSTimm Baeder for (unsigned I = 0; I < NumElems; ++I, ElemOffset += ElemSize) { 92a07aba5dSTimm Baeder auto *ElemPtr = Ptr + ElemOffset; 93a07aba5dSTimm Baeder auto *Desc = reinterpret_cast<InlineDescriptor *>(ElemPtr); 94a07aba5dSTimm Baeder auto *ElemLoc = reinterpret_cast<std::byte *>(Desc + 1); 95a07aba5dSTimm Baeder auto *SD = D->ElemDesc; 96a07aba5dSTimm Baeder 97a07aba5dSTimm Baeder Desc->Offset = ElemOffset + sizeof(InlineDescriptor); 98a07aba5dSTimm Baeder Desc->Desc = SD; 99a07aba5dSTimm Baeder Desc->IsInitialized = true; 100a07aba5dSTimm Baeder Desc->IsBase = false; 101a07aba5dSTimm Baeder Desc->IsActive = IsActive; 102a07aba5dSTimm Baeder Desc->IsConst = IsConst || D->IsConst; 103a07aba5dSTimm Baeder Desc->IsFieldMutable = IsMutable || D->IsMutable; 104a07aba5dSTimm Baeder Desc->InUnion = InUnion; 105800b0739STimm Baeder Desc->IsArrayElement = true; 106a07aba5dSTimm Baeder 107a07aba5dSTimm Baeder if (auto Fn = D->ElemDesc->CtorFn) 108a07aba5dSTimm Baeder Fn(B, ElemLoc, Desc->IsConst, Desc->IsFieldMutable, IsActive, 109a07aba5dSTimm Baeder Desc->InUnion || SD->isUnion(), D->ElemDesc); 110a07aba5dSTimm Baeder } 111a07aba5dSTimm Baeder } 112a07aba5dSTimm Baeder 113a07aba5dSTimm Baeder static void dtorArrayDesc(Block *B, std::byte *Ptr, const Descriptor *D) { 114a07aba5dSTimm Baeder const unsigned NumElems = D->getNumElems(); 115a07aba5dSTimm Baeder const unsigned ElemSize = 116a07aba5dSTimm Baeder D->ElemDesc->getAllocSize() + sizeof(InlineDescriptor); 117a07aba5dSTimm Baeder 118a07aba5dSTimm Baeder unsigned ElemOffset = 0; 119a07aba5dSTimm Baeder for (unsigned I = 0; I < NumElems; ++I, ElemOffset += ElemSize) { 120a07aba5dSTimm Baeder auto *ElemPtr = Ptr + ElemOffset; 121a07aba5dSTimm Baeder auto *Desc = reinterpret_cast<InlineDescriptor *>(ElemPtr); 122a07aba5dSTimm Baeder auto *ElemLoc = reinterpret_cast<std::byte *>(Desc + 1); 123a07aba5dSTimm Baeder if (auto Fn = D->ElemDesc->DtorFn) 124a07aba5dSTimm Baeder Fn(B, ElemLoc, D->ElemDesc); 125a07aba5dSTimm Baeder } 126a07aba5dSTimm Baeder } 127a07aba5dSTimm Baeder 128a69ba0a5STimm Baeder static void moveArrayDesc(Block *B, std::byte *Src, std::byte *Dst, 129a07aba5dSTimm Baeder const Descriptor *D) { 130a07aba5dSTimm Baeder const unsigned NumElems = D->getNumElems(); 131a07aba5dSTimm Baeder const unsigned ElemSize = 132a07aba5dSTimm Baeder D->ElemDesc->getAllocSize() + sizeof(InlineDescriptor); 133a07aba5dSTimm Baeder 134a07aba5dSTimm Baeder unsigned ElemOffset = 0; 135a07aba5dSTimm Baeder for (unsigned I = 0; I < NumElems; ++I, ElemOffset += ElemSize) { 136a69ba0a5STimm Baeder auto *SrcPtr = Src + ElemOffset; 137a07aba5dSTimm Baeder auto *DstPtr = Dst + ElemOffset; 138a07aba5dSTimm Baeder 139a69ba0a5STimm Baeder auto *SrcDesc = reinterpret_cast<InlineDescriptor *>(SrcPtr); 140a69ba0a5STimm Baeder auto *SrcElemLoc = reinterpret_cast<std::byte *>(SrcDesc + 1); 141a07aba5dSTimm Baeder auto *DstDesc = reinterpret_cast<InlineDescriptor *>(DstPtr); 142a07aba5dSTimm Baeder auto *DstElemLoc = reinterpret_cast<std::byte *>(DstDesc + 1); 143a07aba5dSTimm Baeder 144a07aba5dSTimm Baeder *DstDesc = *SrcDesc; 145a07aba5dSTimm Baeder if (auto Fn = D->ElemDesc->MoveFn) 146a07aba5dSTimm Baeder Fn(B, SrcElemLoc, DstElemLoc, D->ElemDesc); 147a07aba5dSTimm Baeder } 148a07aba5dSTimm Baeder } 149a07aba5dSTimm Baeder 150a07aba5dSTimm Baeder static void initField(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable, 151a07aba5dSTimm Baeder bool IsActive, bool IsUnionField, bool InUnion, 152a07aba5dSTimm Baeder const Descriptor *D, unsigned FieldOffset) { 153a07aba5dSTimm Baeder auto *Desc = reinterpret_cast<InlineDescriptor *>(Ptr + FieldOffset) - 1; 154a07aba5dSTimm Baeder Desc->Offset = FieldOffset; 155a07aba5dSTimm Baeder Desc->Desc = D; 156a07aba5dSTimm Baeder Desc->IsInitialized = D->IsArray; 157a07aba5dSTimm Baeder Desc->IsBase = false; 158a07aba5dSTimm Baeder Desc->IsActive = IsActive && !IsUnionField; 159a07aba5dSTimm Baeder Desc->InUnion = InUnion; 160a07aba5dSTimm Baeder Desc->IsConst = IsConst || D->IsConst; 161a07aba5dSTimm Baeder Desc->IsFieldMutable = IsMutable || D->IsMutable; 162a07aba5dSTimm Baeder 163a07aba5dSTimm Baeder if (auto Fn = D->CtorFn) 164a07aba5dSTimm Baeder Fn(B, Ptr + FieldOffset, Desc->IsConst, Desc->IsFieldMutable, 165a07aba5dSTimm Baeder Desc->IsActive, InUnion || D->isUnion(), D); 166a07aba5dSTimm Baeder } 167a07aba5dSTimm Baeder 168a07aba5dSTimm Baeder static void initBase(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable, 169a07aba5dSTimm Baeder bool IsActive, bool InUnion, const Descriptor *D, 170a07aba5dSTimm Baeder unsigned FieldOffset, bool IsVirtualBase) { 171a07aba5dSTimm Baeder assert(D); 172a07aba5dSTimm Baeder assert(D->ElemRecord); 173a07aba5dSTimm Baeder assert(!D->ElemRecord->isUnion()); // Unions cannot be base classes. 174a07aba5dSTimm Baeder 175a07aba5dSTimm Baeder auto *Desc = reinterpret_cast<InlineDescriptor *>(Ptr + FieldOffset) - 1; 176a07aba5dSTimm Baeder Desc->Offset = FieldOffset; 177a07aba5dSTimm Baeder Desc->Desc = D; 178a07aba5dSTimm Baeder Desc->IsInitialized = D->IsArray; 179a07aba5dSTimm Baeder Desc->IsBase = true; 180a07aba5dSTimm Baeder Desc->IsVirtualBase = IsVirtualBase; 181a07aba5dSTimm Baeder Desc->IsActive = IsActive && !InUnion; 182a07aba5dSTimm Baeder Desc->IsConst = IsConst || D->IsConst; 183a07aba5dSTimm Baeder Desc->IsFieldMutable = IsMutable || D->IsMutable; 184a07aba5dSTimm Baeder Desc->InUnion = InUnion; 185a07aba5dSTimm Baeder 186a07aba5dSTimm Baeder for (const auto &V : D->ElemRecord->bases()) 187a07aba5dSTimm Baeder initBase(B, Ptr + FieldOffset, IsConst, IsMutable, IsActive, InUnion, 188a07aba5dSTimm Baeder V.Desc, V.Offset, false); 189a07aba5dSTimm Baeder for (const auto &F : D->ElemRecord->fields()) 190a07aba5dSTimm Baeder initField(B, Ptr + FieldOffset, IsConst, IsMutable, IsActive, InUnion, 191a07aba5dSTimm Baeder InUnion, F.Desc, F.Offset); 192a07aba5dSTimm Baeder } 193a07aba5dSTimm Baeder 194a07aba5dSTimm Baeder static void ctorRecord(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable, 195a07aba5dSTimm Baeder bool IsActive, bool InUnion, const Descriptor *D) { 196a07aba5dSTimm Baeder for (const auto &V : D->ElemRecord->bases()) 197a07aba5dSTimm Baeder initBase(B, Ptr, IsConst, IsMutable, IsActive, InUnion, V.Desc, V.Offset, 198a07aba5dSTimm Baeder false); 199a07aba5dSTimm Baeder for (const auto &F : D->ElemRecord->fields()) { 200a07aba5dSTimm Baeder bool IsUnionField = D->isUnion(); 201a07aba5dSTimm Baeder initField(B, Ptr, IsConst, IsMutable, IsActive, IsUnionField, 202a07aba5dSTimm Baeder InUnion || IsUnionField, F.Desc, F.Offset); 203a07aba5dSTimm Baeder } 204a07aba5dSTimm Baeder for (const auto &V : D->ElemRecord->virtual_bases()) 205a07aba5dSTimm Baeder initBase(B, Ptr, IsConst, IsMutable, IsActive, InUnion, V.Desc, V.Offset, 206a07aba5dSTimm Baeder true); 207a07aba5dSTimm Baeder } 208a07aba5dSTimm Baeder 209a07aba5dSTimm Baeder static void destroyField(Block *B, std::byte *Ptr, const Descriptor *D, 210a07aba5dSTimm Baeder unsigned FieldOffset) { 211a07aba5dSTimm Baeder if (auto Fn = D->DtorFn) 212a07aba5dSTimm Baeder Fn(B, Ptr + FieldOffset, D); 213a07aba5dSTimm Baeder } 214a07aba5dSTimm Baeder 215a07aba5dSTimm Baeder static void destroyBase(Block *B, std::byte *Ptr, const Descriptor *D, 216a07aba5dSTimm Baeder unsigned FieldOffset) { 217a07aba5dSTimm Baeder assert(D); 218a07aba5dSTimm Baeder assert(D->ElemRecord); 219a07aba5dSTimm Baeder 220a07aba5dSTimm Baeder for (const auto &V : D->ElemRecord->bases()) 221a07aba5dSTimm Baeder destroyBase(B, Ptr + FieldOffset, V.Desc, V.Offset); 222a07aba5dSTimm Baeder for (const auto &F : D->ElemRecord->fields()) 223a07aba5dSTimm Baeder destroyField(B, Ptr + FieldOffset, F.Desc, F.Offset); 224a07aba5dSTimm Baeder } 225a07aba5dSTimm Baeder 226a07aba5dSTimm Baeder static void dtorRecord(Block *B, std::byte *Ptr, const Descriptor *D) { 227a07aba5dSTimm Baeder for (const auto &F : D->ElemRecord->bases()) 228a07aba5dSTimm Baeder destroyBase(B, Ptr, F.Desc, F.Offset); 229a07aba5dSTimm Baeder for (const auto &F : D->ElemRecord->fields()) 230a07aba5dSTimm Baeder destroyField(B, Ptr, F.Desc, F.Offset); 231a07aba5dSTimm Baeder for (const auto &F : D->ElemRecord->virtual_bases()) 232a07aba5dSTimm Baeder destroyBase(B, Ptr, F.Desc, F.Offset); 233a07aba5dSTimm Baeder } 234a07aba5dSTimm Baeder 235a69ba0a5STimm Baeder static void moveRecord(Block *B, std::byte *Src, std::byte *Dst, 236a07aba5dSTimm Baeder const Descriptor *D) { 237a07aba5dSTimm Baeder assert(D); 238a07aba5dSTimm Baeder assert(D->ElemRecord); 239a07aba5dSTimm Baeder 240a07aba5dSTimm Baeder // FIXME: There might be cases where we need to move over the (v)bases as 241a07aba5dSTimm Baeder // well. 242a07aba5dSTimm Baeder for (const auto &F : D->ElemRecord->fields()) { 243a07aba5dSTimm Baeder auto FieldOffset = F.Offset; 244a07aba5dSTimm Baeder const auto *SrcDesc = 245a07aba5dSTimm Baeder reinterpret_cast<const InlineDescriptor *>(Src + FieldOffset) - 1; 246a07aba5dSTimm Baeder auto *DestDesc = 247a07aba5dSTimm Baeder reinterpret_cast<InlineDescriptor *>(Dst + FieldOffset) - 1; 248a07aba5dSTimm Baeder std::memcpy(DestDesc, SrcDesc, sizeof(InlineDescriptor)); 249a07aba5dSTimm Baeder 250a07aba5dSTimm Baeder if (auto Fn = F.Desc->MoveFn) 251a07aba5dSTimm Baeder Fn(B, Src + FieldOffset, Dst + FieldOffset, F.Desc); 252a07aba5dSTimm Baeder } 253a07aba5dSTimm Baeder } 254a07aba5dSTimm Baeder 255a07aba5dSTimm Baeder static BlockCtorFn getCtorPrim(PrimType Type) { 256a07aba5dSTimm Baeder // Floating types are special. They are primitives, but need their 257a07aba5dSTimm Baeder // constructor called. 258a07aba5dSTimm Baeder if (Type == PT_Float) 259a07aba5dSTimm Baeder return ctorTy<PrimConv<PT_Float>::T>; 260a07aba5dSTimm Baeder if (Type == PT_IntAP) 261a07aba5dSTimm Baeder return ctorTy<PrimConv<PT_IntAP>::T>; 262a07aba5dSTimm Baeder if (Type == PT_IntAPS) 263a07aba5dSTimm Baeder return ctorTy<PrimConv<PT_IntAPS>::T>; 264a07aba5dSTimm Baeder if (Type == PT_MemberPtr) 265a07aba5dSTimm Baeder return ctorTy<PrimConv<PT_MemberPtr>::T>; 266a07aba5dSTimm Baeder 267a07aba5dSTimm Baeder COMPOSITE_TYPE_SWITCH(Type, return ctorTy<T>, return nullptr); 268a07aba5dSTimm Baeder } 269a07aba5dSTimm Baeder 270a07aba5dSTimm Baeder static BlockDtorFn getDtorPrim(PrimType Type) { 271a07aba5dSTimm Baeder // Floating types are special. They are primitives, but need their 272a07aba5dSTimm Baeder // destructor called, since they might allocate memory. 273a07aba5dSTimm Baeder if (Type == PT_Float) 274a07aba5dSTimm Baeder return dtorTy<PrimConv<PT_Float>::T>; 275a07aba5dSTimm Baeder if (Type == PT_IntAP) 276a07aba5dSTimm Baeder return dtorTy<PrimConv<PT_IntAP>::T>; 277a07aba5dSTimm Baeder if (Type == PT_IntAPS) 278a07aba5dSTimm Baeder return dtorTy<PrimConv<PT_IntAPS>::T>; 279a07aba5dSTimm Baeder if (Type == PT_MemberPtr) 280a07aba5dSTimm Baeder return dtorTy<PrimConv<PT_MemberPtr>::T>; 281a07aba5dSTimm Baeder 282a07aba5dSTimm Baeder COMPOSITE_TYPE_SWITCH(Type, return dtorTy<T>, return nullptr); 283a07aba5dSTimm Baeder } 284a07aba5dSTimm Baeder 285a07aba5dSTimm Baeder static BlockMoveFn getMovePrim(PrimType Type) { 286a07aba5dSTimm Baeder if (Type == PT_Float) 287a07aba5dSTimm Baeder return moveTy<PrimConv<PT_Float>::T>; 288a07aba5dSTimm Baeder if (Type == PT_IntAP) 289a07aba5dSTimm Baeder return moveTy<PrimConv<PT_IntAP>::T>; 290a07aba5dSTimm Baeder if (Type == PT_IntAPS) 291a07aba5dSTimm Baeder return moveTy<PrimConv<PT_IntAPS>::T>; 292a07aba5dSTimm Baeder if (Type == PT_MemberPtr) 293a07aba5dSTimm Baeder return moveTy<PrimConv<PT_MemberPtr>::T>; 294a07aba5dSTimm Baeder COMPOSITE_TYPE_SWITCH(Type, return moveTy<T>, return nullptr); 295a07aba5dSTimm Baeder } 296a07aba5dSTimm Baeder 297a07aba5dSTimm Baeder static BlockCtorFn getCtorArrayPrim(PrimType Type) { 298a07aba5dSTimm Baeder TYPE_SWITCH(Type, return ctorArrayTy<T>); 299a07aba5dSTimm Baeder llvm_unreachable("unknown Expr"); 300a07aba5dSTimm Baeder } 301a07aba5dSTimm Baeder 302a07aba5dSTimm Baeder static BlockDtorFn getDtorArrayPrim(PrimType Type) { 303a07aba5dSTimm Baeder TYPE_SWITCH(Type, return dtorArrayTy<T>); 304a07aba5dSTimm Baeder llvm_unreachable("unknown Expr"); 305a07aba5dSTimm Baeder } 306a07aba5dSTimm Baeder 307a07aba5dSTimm Baeder static BlockMoveFn getMoveArrayPrim(PrimType Type) { 308a07aba5dSTimm Baeder TYPE_SWITCH(Type, return moveArrayTy<T>); 309a07aba5dSTimm Baeder llvm_unreachable("unknown Expr"); 310a07aba5dSTimm Baeder } 311a07aba5dSTimm Baeder 312a07aba5dSTimm Baeder /// Primitives. 313a07aba5dSTimm Baeder Descriptor::Descriptor(const DeclTy &D, PrimType Type, MetadataSize MD, 314a07aba5dSTimm Baeder bool IsConst, bool IsTemporary, bool IsMutable) 315a07aba5dSTimm Baeder : Source(D), ElemSize(primSize(Type)), Size(ElemSize), 316a07aba5dSTimm Baeder MDSize(MD.value_or(0)), AllocSize(align(Size + MDSize)), PrimT(Type), 317a07aba5dSTimm Baeder IsConst(IsConst), IsMutable(IsMutable), IsTemporary(IsTemporary), 318a07aba5dSTimm Baeder CtorFn(getCtorPrim(Type)), DtorFn(getDtorPrim(Type)), 319a07aba5dSTimm Baeder MoveFn(getMovePrim(Type)) { 320a07aba5dSTimm Baeder assert(AllocSize >= Size); 321a07aba5dSTimm Baeder assert(Source && "Missing source"); 322a07aba5dSTimm Baeder } 323a07aba5dSTimm Baeder 324a07aba5dSTimm Baeder /// Primitive arrays. 325a07aba5dSTimm Baeder Descriptor::Descriptor(const DeclTy &D, PrimType Type, MetadataSize MD, 326a07aba5dSTimm Baeder size_t NumElems, bool IsConst, bool IsTemporary, 327a07aba5dSTimm Baeder bool IsMutable) 328a07aba5dSTimm Baeder : Source(D), ElemSize(primSize(Type)), Size(ElemSize * NumElems), 329a07aba5dSTimm Baeder MDSize(MD.value_or(0)), 330a07aba5dSTimm Baeder AllocSize(align(MDSize) + align(Size) + sizeof(InitMapPtr)), PrimT(Type), 331a07aba5dSTimm Baeder IsConst(IsConst), IsMutable(IsMutable), IsTemporary(IsTemporary), 332a07aba5dSTimm Baeder IsArray(true), CtorFn(getCtorArrayPrim(Type)), 333a07aba5dSTimm Baeder DtorFn(getDtorArrayPrim(Type)), MoveFn(getMoveArrayPrim(Type)) { 334a07aba5dSTimm Baeder assert(Source && "Missing source"); 335a07aba5dSTimm Baeder assert(NumElems <= (MaxArrayElemBytes / ElemSize)); 336a07aba5dSTimm Baeder } 337a07aba5dSTimm Baeder 338a07aba5dSTimm Baeder /// Primitive unknown-size arrays. 339a07aba5dSTimm Baeder Descriptor::Descriptor(const DeclTy &D, PrimType Type, MetadataSize MD, 340a07aba5dSTimm Baeder bool IsTemporary, UnknownSize) 341a07aba5dSTimm Baeder : Source(D), ElemSize(primSize(Type)), Size(UnknownSizeMark), 342a07aba5dSTimm Baeder MDSize(MD.value_or(0)), 343a07aba5dSTimm Baeder AllocSize(MDSize + sizeof(InitMapPtr) + alignof(void *)), IsConst(true), 344a07aba5dSTimm Baeder IsMutable(false), IsTemporary(IsTemporary), IsArray(true), 345a07aba5dSTimm Baeder CtorFn(getCtorArrayPrim(Type)), DtorFn(getDtorArrayPrim(Type)), 346a07aba5dSTimm Baeder MoveFn(getMoveArrayPrim(Type)) { 347a07aba5dSTimm Baeder assert(Source && "Missing source"); 348a07aba5dSTimm Baeder } 349a07aba5dSTimm Baeder 350a07aba5dSTimm Baeder /// Arrays of composite elements. 351a07aba5dSTimm Baeder Descriptor::Descriptor(const DeclTy &D, const Descriptor *Elem, MetadataSize MD, 352a07aba5dSTimm Baeder unsigned NumElems, bool IsConst, bool IsTemporary, 353a07aba5dSTimm Baeder bool IsMutable) 354a07aba5dSTimm Baeder : Source(D), ElemSize(Elem->getAllocSize() + sizeof(InlineDescriptor)), 355a07aba5dSTimm Baeder Size(ElemSize * NumElems), MDSize(MD.value_or(0)), 356a07aba5dSTimm Baeder AllocSize(std::max<size_t>(alignof(void *), Size) + MDSize), 357a07aba5dSTimm Baeder ElemDesc(Elem), IsConst(IsConst), IsMutable(IsMutable), 358a07aba5dSTimm Baeder IsTemporary(IsTemporary), IsArray(true), CtorFn(ctorArrayDesc), 359a07aba5dSTimm Baeder DtorFn(dtorArrayDesc), MoveFn(moveArrayDesc) { 360a07aba5dSTimm Baeder assert(Source && "Missing source"); 361a07aba5dSTimm Baeder } 362a07aba5dSTimm Baeder 363a07aba5dSTimm Baeder /// Unknown-size arrays of composite elements. 364a07aba5dSTimm Baeder Descriptor::Descriptor(const DeclTy &D, const Descriptor *Elem, MetadataSize MD, 365a07aba5dSTimm Baeder bool IsTemporary, UnknownSize) 366a07aba5dSTimm Baeder : Source(D), ElemSize(Elem->getAllocSize() + sizeof(InlineDescriptor)), 367a07aba5dSTimm Baeder Size(UnknownSizeMark), MDSize(MD.value_or(0)), 368a07aba5dSTimm Baeder AllocSize(MDSize + alignof(void *)), ElemDesc(Elem), IsConst(true), 369a07aba5dSTimm Baeder IsMutable(false), IsTemporary(IsTemporary), IsArray(true), 370a07aba5dSTimm Baeder CtorFn(ctorArrayDesc), DtorFn(dtorArrayDesc), MoveFn(moveArrayDesc) { 371a07aba5dSTimm Baeder assert(Source && "Missing source"); 372a07aba5dSTimm Baeder } 373a07aba5dSTimm Baeder 374a07aba5dSTimm Baeder /// Composite records. 375a07aba5dSTimm Baeder Descriptor::Descriptor(const DeclTy &D, const Record *R, MetadataSize MD, 376a07aba5dSTimm Baeder bool IsConst, bool IsTemporary, bool IsMutable) 377a07aba5dSTimm Baeder : Source(D), ElemSize(std::max<size_t>(alignof(void *), R->getFullSize())), 378a07aba5dSTimm Baeder Size(ElemSize), MDSize(MD.value_or(0)), AllocSize(Size + MDSize), 379a07aba5dSTimm Baeder ElemRecord(R), IsConst(IsConst), IsMutable(IsMutable), 380a07aba5dSTimm Baeder IsTemporary(IsTemporary), CtorFn(ctorRecord), DtorFn(dtorRecord), 381a07aba5dSTimm Baeder MoveFn(moveRecord) { 382a07aba5dSTimm Baeder assert(Source && "Missing source"); 383a07aba5dSTimm Baeder } 384a07aba5dSTimm Baeder 385a07aba5dSTimm Baeder /// Dummy. 386a07aba5dSTimm Baeder Descriptor::Descriptor(const DeclTy &D) 387a07aba5dSTimm Baeder : Source(D), ElemSize(1), Size(1), MDSize(0), AllocSize(MDSize), 388a07aba5dSTimm Baeder ElemRecord(nullptr), IsConst(true), IsMutable(false), IsTemporary(false), 389a07aba5dSTimm Baeder IsDummy(true) { 390a07aba5dSTimm Baeder assert(Source && "Missing source"); 391a07aba5dSTimm Baeder } 392a07aba5dSTimm Baeder 393a07aba5dSTimm Baeder QualType Descriptor::getType() const { 394a07aba5dSTimm Baeder if (const auto *D = asValueDecl()) 395a07aba5dSTimm Baeder return D->getType(); 3964bd3a62cSTimm Baeder if (const auto *T = dyn_cast_if_present<TypeDecl>(asDecl())) 397a07aba5dSTimm Baeder return QualType(T->getTypeForDecl(), 0); 3984bd3a62cSTimm Baeder 3994bd3a62cSTimm Baeder // The Source sometimes has a different type than the once 4004bd3a62cSTimm Baeder // we really save. Try to consult the Record first. 4014bd3a62cSTimm Baeder if (isRecord()) 4024bd3a62cSTimm Baeder return QualType(ElemRecord->getDecl()->getTypeForDecl(), 0); 4034bd3a62cSTimm Baeder if (const auto *E = asExpr()) 4044bd3a62cSTimm Baeder return E->getType(); 405a07aba5dSTimm Baeder llvm_unreachable("Invalid descriptor type"); 406a07aba5dSTimm Baeder } 407a07aba5dSTimm Baeder 408a07aba5dSTimm Baeder QualType Descriptor::getElemQualType() const { 409a07aba5dSTimm Baeder assert(isArray()); 410a07aba5dSTimm Baeder QualType T = getType(); 411800b0739STimm Baeder if (T->isPointerOrReferenceType()) 412*51c7338cSTimm Baeder T = T->getPointeeType(); 413*51c7338cSTimm Baeder 4142c820799STimm Baeder if (const auto *AT = T->getAsArrayTypeUnsafe()) { 4152c820799STimm Baeder // For primitive arrays, we don't save a QualType at all, 4162c820799STimm Baeder // just a PrimType. Try to figure out the QualType here. 4172c820799STimm Baeder if (isPrimitiveArray()) { 4182c820799STimm Baeder while (T->isArrayType()) 4192c820799STimm Baeder T = T->getAsArrayTypeUnsafe()->getElementType(); 4202c820799STimm Baeder return T; 4212c820799STimm Baeder } 422a07aba5dSTimm Baeder return AT->getElementType(); 4232c820799STimm Baeder } 424a07aba5dSTimm Baeder if (const auto *CT = T->getAs<ComplexType>()) 425a07aba5dSTimm Baeder return CT->getElementType(); 426a07aba5dSTimm Baeder if (const auto *CT = T->getAs<VectorType>()) 427a07aba5dSTimm Baeder return CT->getElementType(); 428*51c7338cSTimm Baeder 429*51c7338cSTimm Baeder return T; 430a07aba5dSTimm Baeder } 431a07aba5dSTimm Baeder 432a07aba5dSTimm Baeder SourceLocation Descriptor::getLocation() const { 433b4ef11d0SKazu Hirata if (auto *D = dyn_cast<const Decl *>(Source)) 434a07aba5dSTimm Baeder return D->getLocation(); 435b4ef11d0SKazu Hirata if (auto *E = dyn_cast<const Expr *>(Source)) 436a07aba5dSTimm Baeder return E->getExprLoc(); 437a07aba5dSTimm Baeder llvm_unreachable("Invalid descriptor type"); 438a07aba5dSTimm Baeder } 439a07aba5dSTimm Baeder 4403ea55d3cSTimm Baeder SourceInfo Descriptor::getLoc() const { 441b4ef11d0SKazu Hirata if (const auto *D = dyn_cast<const Decl *>(Source)) 4423ea55d3cSTimm Baeder return SourceInfo(D); 443b4ef11d0SKazu Hirata if (const auto *E = dyn_cast<const Expr *>(Source)) 4443ea55d3cSTimm Baeder return SourceInfo(E); 4453ea55d3cSTimm Baeder llvm_unreachable("Invalid descriptor type"); 4463ea55d3cSTimm Baeder } 4473ea55d3cSTimm Baeder 448a07aba5dSTimm Baeder bool Descriptor::isUnion() const { return isRecord() && ElemRecord->isUnion(); } 449a07aba5dSTimm Baeder 450a07aba5dSTimm Baeder InitMap::InitMap(unsigned N) 451a07aba5dSTimm Baeder : UninitFields(N), Data(std::make_unique<T[]>(numFields(N))) { 452a07aba5dSTimm Baeder std::fill_n(data(), numFields(N), 0); 453a07aba5dSTimm Baeder } 454a07aba5dSTimm Baeder 455a07aba5dSTimm Baeder bool InitMap::initializeElement(unsigned I) { 456a07aba5dSTimm Baeder unsigned Bucket = I / PER_FIELD; 457a07aba5dSTimm Baeder T Mask = T(1) << (I % PER_FIELD); 458a07aba5dSTimm Baeder if (!(data()[Bucket] & Mask)) { 459a07aba5dSTimm Baeder data()[Bucket] |= Mask; 460a07aba5dSTimm Baeder UninitFields -= 1; 461a07aba5dSTimm Baeder } 462a07aba5dSTimm Baeder return UninitFields == 0; 463a07aba5dSTimm Baeder } 464a07aba5dSTimm Baeder 465a07aba5dSTimm Baeder bool InitMap::isElementInitialized(unsigned I) const { 466a07aba5dSTimm Baeder unsigned Bucket = I / PER_FIELD; 467a07aba5dSTimm Baeder return data()[Bucket] & (T(1) << (I % PER_FIELD)); 468a07aba5dSTimm Baeder } 469