xref: /freebsd-src/contrib/llvm-project/clang/lib/AST/Interp/Descriptor.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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