xref: /llvm-project/clang/lib/AST/ByteCode/Descriptor.cpp (revision 51c7338cc671c90ba9345b53c7ca01dc461341ed)
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