xref: /netbsd-src/external/apache2/llvm/dist/clang/lib/AST/Interp/Descriptor.cpp (revision 7330f729ccf0bd976a06f95fad452fe774fc7fd1)
1*7330f729Sjoerg //===--- Descriptor.cpp - Types for the constexpr VM ------------*- C++ -*-===//
2*7330f729Sjoerg //
3*7330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*7330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
5*7330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*7330f729Sjoerg //
7*7330f729Sjoerg //===----------------------------------------------------------------------===//
8*7330f729Sjoerg 
9*7330f729Sjoerg #include "Descriptor.h"
10*7330f729Sjoerg #include "Pointer.h"
11*7330f729Sjoerg #include "PrimType.h"
12*7330f729Sjoerg #include "Record.h"
13*7330f729Sjoerg 
14*7330f729Sjoerg using namespace clang;
15*7330f729Sjoerg using namespace clang::interp;
16*7330f729Sjoerg 
17*7330f729Sjoerg template <typename T>
ctorTy(Block *,char * Ptr,bool,bool,bool,Descriptor *)18*7330f729Sjoerg static void ctorTy(Block *, char *Ptr, bool, bool, bool, Descriptor *) {
19*7330f729Sjoerg   new (Ptr) T();
20*7330f729Sjoerg }
21*7330f729Sjoerg 
dtorTy(Block *,char * Ptr,Descriptor *)22*7330f729Sjoerg template <typename T> static void dtorTy(Block *, char *Ptr, Descriptor *) {
23*7330f729Sjoerg   reinterpret_cast<T *>(Ptr)->~T();
24*7330f729Sjoerg }
25*7330f729Sjoerg 
26*7330f729Sjoerg template <typename T>
moveTy(Block *,char * Src,char * Dst,Descriptor *)27*7330f729Sjoerg static void moveTy(Block *, char *Src, char *Dst, Descriptor *) {
28*7330f729Sjoerg   auto *SrcPtr = reinterpret_cast<T *>(Src);
29*7330f729Sjoerg   auto *DstPtr = reinterpret_cast<T *>(Dst);
30*7330f729Sjoerg   new (DstPtr) T(std::move(*SrcPtr));
31*7330f729Sjoerg }
32*7330f729Sjoerg 
33*7330f729Sjoerg template <typename T>
ctorArrayTy(Block *,char * Ptr,bool,bool,bool,Descriptor * D)34*7330f729Sjoerg static void ctorArrayTy(Block *, char *Ptr, bool, bool, bool, Descriptor *D) {
35*7330f729Sjoerg   for (unsigned I = 0, NE = D->getNumElems(); I < NE; ++I) {
36*7330f729Sjoerg     new (&reinterpret_cast<T *>(Ptr)[I]) T();
37*7330f729Sjoerg   }
38*7330f729Sjoerg }
39*7330f729Sjoerg 
40*7330f729Sjoerg template <typename T>
dtorArrayTy(Block *,char * Ptr,Descriptor * D)41*7330f729Sjoerg static void dtorArrayTy(Block *, char *Ptr, Descriptor *D) {
42*7330f729Sjoerg   for (unsigned I = 0, NE = D->getNumElems(); I < NE; ++I) {
43*7330f729Sjoerg     reinterpret_cast<T *>(Ptr)[I].~T();
44*7330f729Sjoerg   }
45*7330f729Sjoerg }
46*7330f729Sjoerg 
47*7330f729Sjoerg template <typename T>
moveArrayTy(Block *,char * Src,char * Dst,Descriptor * D)48*7330f729Sjoerg static void moveArrayTy(Block *, char *Src, char *Dst, Descriptor *D) {
49*7330f729Sjoerg   for (unsigned I = 0, NE = D->getNumElems(); I < NE; ++I) {
50*7330f729Sjoerg     auto *SrcPtr = &reinterpret_cast<T *>(Src)[I];
51*7330f729Sjoerg     auto *DstPtr = &reinterpret_cast<T *>(Dst)[I];
52*7330f729Sjoerg     new (DstPtr) T(std::move(*SrcPtr));
53*7330f729Sjoerg   }
54*7330f729Sjoerg }
55*7330f729Sjoerg 
ctorArrayDesc(Block * B,char * Ptr,bool IsConst,bool IsMutable,bool IsActive,Descriptor * D)56*7330f729Sjoerg static void ctorArrayDesc(Block *B, char *Ptr, bool IsConst, bool IsMutable,
57*7330f729Sjoerg                           bool IsActive, Descriptor *D) {
58*7330f729Sjoerg   const unsigned NumElems = D->getNumElems();
59*7330f729Sjoerg   const unsigned ElemSize =
60*7330f729Sjoerg       D->ElemDesc->getAllocSize() + sizeof(InlineDescriptor);
61*7330f729Sjoerg 
62*7330f729Sjoerg   unsigned ElemOffset = 0;
63*7330f729Sjoerg   for (unsigned I = 0; I < NumElems; ++I, ElemOffset += ElemSize) {
64*7330f729Sjoerg     auto *ElemPtr = Ptr + ElemOffset;
65*7330f729Sjoerg     auto *Desc = reinterpret_cast<InlineDescriptor *>(ElemPtr);
66*7330f729Sjoerg     auto *ElemLoc = reinterpret_cast<char *>(Desc + 1);
67*7330f729Sjoerg     auto *SD = D->ElemDesc;
68*7330f729Sjoerg 
69*7330f729Sjoerg     Desc->Offset = ElemOffset + sizeof(InlineDescriptor);
70*7330f729Sjoerg     Desc->Desc = SD;
71*7330f729Sjoerg     Desc->IsInitialized = true;
72*7330f729Sjoerg     Desc->IsBase = false;
73*7330f729Sjoerg     Desc->IsActive = IsActive;
74*7330f729Sjoerg     Desc->IsConst = IsConst || D->IsConst;
75*7330f729Sjoerg     Desc->IsMutable = IsMutable || D->IsMutable;
76*7330f729Sjoerg     if (auto Fn = D->ElemDesc->CtorFn)
77*7330f729Sjoerg       Fn(B, ElemLoc, Desc->IsConst, Desc->IsMutable, IsActive, D->ElemDesc);
78*7330f729Sjoerg   }
79*7330f729Sjoerg }
80*7330f729Sjoerg 
dtorArrayDesc(Block * B,char * Ptr,Descriptor * D)81*7330f729Sjoerg static void dtorArrayDesc(Block *B, char *Ptr, Descriptor *D) {
82*7330f729Sjoerg   const unsigned NumElems = D->getNumElems();
83*7330f729Sjoerg   const unsigned ElemSize =
84*7330f729Sjoerg       D->ElemDesc->getAllocSize() + sizeof(InlineDescriptor);
85*7330f729Sjoerg 
86*7330f729Sjoerg   unsigned ElemOffset = 0;
87*7330f729Sjoerg   for (unsigned I = 0; I < NumElems; ++I, ElemOffset += ElemSize) {
88*7330f729Sjoerg     auto *ElemPtr = Ptr + ElemOffset;
89*7330f729Sjoerg     auto *Desc = reinterpret_cast<InlineDescriptor *>(ElemPtr);
90*7330f729Sjoerg     auto *ElemLoc = reinterpret_cast<char *>(Desc + 1);
91*7330f729Sjoerg     if (auto Fn = D->ElemDesc->DtorFn)
92*7330f729Sjoerg       Fn(B, ElemLoc, D->ElemDesc);
93*7330f729Sjoerg   }
94*7330f729Sjoerg }
95*7330f729Sjoerg 
moveArrayDesc(Block * B,char * Src,char * Dst,Descriptor * D)96*7330f729Sjoerg static void moveArrayDesc(Block *B, char *Src, char *Dst, Descriptor *D) {
97*7330f729Sjoerg   const unsigned NumElems = D->getNumElems();
98*7330f729Sjoerg   const unsigned ElemSize =
99*7330f729Sjoerg       D->ElemDesc->getAllocSize() + sizeof(InlineDescriptor);
100*7330f729Sjoerg 
101*7330f729Sjoerg   unsigned ElemOffset = 0;
102*7330f729Sjoerg   for (unsigned I = 0; I < NumElems; ++I, ElemOffset += ElemSize) {
103*7330f729Sjoerg     auto *SrcPtr = Src + ElemOffset;
104*7330f729Sjoerg     auto *DstPtr = Dst + ElemOffset;
105*7330f729Sjoerg 
106*7330f729Sjoerg     auto *SrcDesc = reinterpret_cast<InlineDescriptor *>(SrcPtr);
107*7330f729Sjoerg     auto *SrcElemLoc = reinterpret_cast<char *>(SrcDesc + 1);
108*7330f729Sjoerg     auto *DstDesc = reinterpret_cast<InlineDescriptor *>(DstPtr);
109*7330f729Sjoerg     auto *DstElemLoc = reinterpret_cast<char *>(DstDesc + 1);
110*7330f729Sjoerg 
111*7330f729Sjoerg     *DstDesc = *SrcDesc;
112*7330f729Sjoerg     if (auto Fn = D->ElemDesc->MoveFn)
113*7330f729Sjoerg       Fn(B, SrcElemLoc, DstElemLoc, D->ElemDesc);
114*7330f729Sjoerg   }
115*7330f729Sjoerg }
116*7330f729Sjoerg 
ctorRecord(Block * B,char * Ptr,bool IsConst,bool IsMutable,bool IsActive,Descriptor * D)117*7330f729Sjoerg static void ctorRecord(Block *B, char *Ptr, bool IsConst, bool IsMutable,
118*7330f729Sjoerg                        bool IsActive, Descriptor *D) {
119*7330f729Sjoerg   const bool IsUnion = D->ElemRecord->isUnion();
120*7330f729Sjoerg   auto CtorSub = [=](unsigned SubOff, Descriptor *F, bool IsBase) {
121*7330f729Sjoerg     auto *Desc = reinterpret_cast<InlineDescriptor *>(Ptr + SubOff) - 1;
122*7330f729Sjoerg     Desc->Offset = SubOff;
123*7330f729Sjoerg     Desc->Desc = F;
124*7330f729Sjoerg     Desc->IsInitialized = (B->isStatic() || F->IsArray) && !IsBase;
125*7330f729Sjoerg     Desc->IsBase = IsBase;
126*7330f729Sjoerg     Desc->IsActive = IsActive && !IsUnion;
127*7330f729Sjoerg     Desc->IsConst = IsConst || F->IsConst;
128*7330f729Sjoerg     Desc->IsMutable = IsMutable || F->IsMutable;
129*7330f729Sjoerg     if (auto Fn = F->CtorFn)
130*7330f729Sjoerg       Fn(B, Ptr + SubOff, Desc->IsConst, Desc->IsMutable, Desc->IsActive, F);
131*7330f729Sjoerg   };
132*7330f729Sjoerg   for (const auto &B : D->ElemRecord->bases())
133*7330f729Sjoerg     CtorSub(B.Offset, B.Desc, /*isBase=*/true);
134*7330f729Sjoerg   for (const auto &F : D->ElemRecord->fields())
135*7330f729Sjoerg     CtorSub(F.Offset, F.Desc, /*isBase=*/false);
136*7330f729Sjoerg   for (const auto &V : D->ElemRecord->virtual_bases())
137*7330f729Sjoerg     CtorSub(V.Offset, V.Desc, /*isBase=*/true);
138*7330f729Sjoerg }
139*7330f729Sjoerg 
dtorRecord(Block * B,char * Ptr,Descriptor * D)140*7330f729Sjoerg static void dtorRecord(Block *B, char *Ptr, Descriptor *D) {
141*7330f729Sjoerg   auto DtorSub = [=](unsigned SubOff, Descriptor *F) {
142*7330f729Sjoerg     if (auto Fn = F->DtorFn)
143*7330f729Sjoerg       Fn(B, Ptr + SubOff, F);
144*7330f729Sjoerg   };
145*7330f729Sjoerg   for (const auto &F : D->ElemRecord->bases())
146*7330f729Sjoerg     DtorSub(F.Offset, F.Desc);
147*7330f729Sjoerg   for (const auto &F : D->ElemRecord->fields())
148*7330f729Sjoerg     DtorSub(F.Offset, F.Desc);
149*7330f729Sjoerg   for (const auto &F : D->ElemRecord->virtual_bases())
150*7330f729Sjoerg     DtorSub(F.Offset, F.Desc);
151*7330f729Sjoerg }
152*7330f729Sjoerg 
moveRecord(Block * B,char * Src,char * Dst,Descriptor * D)153*7330f729Sjoerg static void moveRecord(Block *B, char *Src, char *Dst, Descriptor *D) {
154*7330f729Sjoerg   for (const auto &F : D->ElemRecord->fields()) {
155*7330f729Sjoerg     auto FieldOff = F.Offset;
156*7330f729Sjoerg     auto FieldDesc = F.Desc;
157*7330f729Sjoerg 
158*7330f729Sjoerg     *(reinterpret_cast<Descriptor **>(Dst + FieldOff) - 1) = FieldDesc;
159*7330f729Sjoerg     if (auto Fn = FieldDesc->MoveFn)
160*7330f729Sjoerg       Fn(B, Src + FieldOff, Dst + FieldOff, FieldDesc);
161*7330f729Sjoerg   }
162*7330f729Sjoerg }
163*7330f729Sjoerg 
getCtorPrim(PrimType Type)164*7330f729Sjoerg static BlockCtorFn getCtorPrim(PrimType Type) {
165*7330f729Sjoerg   COMPOSITE_TYPE_SWITCH(Type, return ctorTy<T>, return nullptr);
166*7330f729Sjoerg }
167*7330f729Sjoerg 
getDtorPrim(PrimType Type)168*7330f729Sjoerg static BlockDtorFn getDtorPrim(PrimType Type) {
169*7330f729Sjoerg   COMPOSITE_TYPE_SWITCH(Type, return dtorTy<T>, return nullptr);
170*7330f729Sjoerg }
171*7330f729Sjoerg 
getMovePrim(PrimType Type)172*7330f729Sjoerg static BlockMoveFn getMovePrim(PrimType Type) {
173*7330f729Sjoerg   COMPOSITE_TYPE_SWITCH(Type, return moveTy<T>, return nullptr);
174*7330f729Sjoerg }
175*7330f729Sjoerg 
getCtorArrayPrim(PrimType Type)176*7330f729Sjoerg static BlockCtorFn getCtorArrayPrim(PrimType Type) {
177*7330f729Sjoerg   COMPOSITE_TYPE_SWITCH(Type, return ctorArrayTy<T>, return nullptr);
178*7330f729Sjoerg }
179*7330f729Sjoerg 
getDtorArrayPrim(PrimType Type)180*7330f729Sjoerg static BlockDtorFn getDtorArrayPrim(PrimType Type) {
181*7330f729Sjoerg   COMPOSITE_TYPE_SWITCH(Type, return dtorArrayTy<T>, return nullptr);
182*7330f729Sjoerg }
183*7330f729Sjoerg 
getMoveArrayPrim(PrimType Type)184*7330f729Sjoerg static BlockMoveFn getMoveArrayPrim(PrimType Type) {
185*7330f729Sjoerg   COMPOSITE_TYPE_SWITCH(Type, return moveArrayTy<T>, return nullptr);
186*7330f729Sjoerg }
187*7330f729Sjoerg 
Descriptor(const DeclTy & D,PrimType Type,bool IsConst,bool IsTemporary,bool IsMutable)188*7330f729Sjoerg Descriptor::Descriptor(const DeclTy &D, PrimType Type, bool IsConst,
189*7330f729Sjoerg                        bool IsTemporary, bool IsMutable)
190*7330f729Sjoerg     : Source(D), ElemSize(primSize(Type)), Size(ElemSize), AllocSize(Size),
191*7330f729Sjoerg       IsConst(IsConst), IsMutable(IsMutable), IsTemporary(IsTemporary),
192*7330f729Sjoerg       CtorFn(getCtorPrim(Type)), DtorFn(getDtorPrim(Type)),
193*7330f729Sjoerg       MoveFn(getMovePrim(Type)) {
194*7330f729Sjoerg   assert(Source && "Missing source");
195*7330f729Sjoerg }
196*7330f729Sjoerg 
Descriptor(const DeclTy & D,PrimType Type,size_t NumElems,bool IsConst,bool IsTemporary,bool IsMutable)197*7330f729Sjoerg Descriptor::Descriptor(const DeclTy &D, PrimType Type, size_t NumElems,
198*7330f729Sjoerg                        bool IsConst, bool IsTemporary, bool IsMutable)
199*7330f729Sjoerg     : Source(D), ElemSize(primSize(Type)), Size(ElemSize * NumElems),
200*7330f729Sjoerg       AllocSize(align(Size) + sizeof(InitMap *)), IsConst(IsConst),
201*7330f729Sjoerg       IsMutable(IsMutable), IsTemporary(IsTemporary), IsArray(true),
202*7330f729Sjoerg       CtorFn(getCtorArrayPrim(Type)), DtorFn(getDtorArrayPrim(Type)),
203*7330f729Sjoerg       MoveFn(getMoveArrayPrim(Type)) {
204*7330f729Sjoerg   assert(Source && "Missing source");
205*7330f729Sjoerg }
206*7330f729Sjoerg 
Descriptor(const DeclTy & D,PrimType Type,bool IsTemporary,UnknownSize)207*7330f729Sjoerg Descriptor::Descriptor(const DeclTy &D, PrimType Type, bool IsTemporary,
208*7330f729Sjoerg                        UnknownSize)
209*7330f729Sjoerg     : Source(D), ElemSize(primSize(Type)), Size(UnknownSizeMark),
210*7330f729Sjoerg       AllocSize(alignof(void *)), IsConst(true), IsMutable(false),
211*7330f729Sjoerg       IsTemporary(IsTemporary), IsArray(true), CtorFn(getCtorArrayPrim(Type)),
212*7330f729Sjoerg       DtorFn(getDtorArrayPrim(Type)), MoveFn(getMoveArrayPrim(Type)) {
213*7330f729Sjoerg   assert(Source && "Missing source");
214*7330f729Sjoerg }
215*7330f729Sjoerg 
Descriptor(const DeclTy & D,Descriptor * Elem,unsigned NumElems,bool IsConst,bool IsTemporary,bool IsMutable)216*7330f729Sjoerg Descriptor::Descriptor(const DeclTy &D, Descriptor *Elem, unsigned NumElems,
217*7330f729Sjoerg                        bool IsConst, bool IsTemporary, bool IsMutable)
218*7330f729Sjoerg     : Source(D), ElemSize(Elem->getAllocSize() + sizeof(InlineDescriptor)),
219*7330f729Sjoerg       Size(ElemSize * NumElems),
220*7330f729Sjoerg       AllocSize(std::max<size_t>(alignof(void *), Size)), ElemDesc(Elem),
221*7330f729Sjoerg       IsConst(IsConst), IsMutable(IsMutable), IsTemporary(IsTemporary),
222*7330f729Sjoerg       IsArray(true), CtorFn(ctorArrayDesc), DtorFn(dtorArrayDesc),
223*7330f729Sjoerg       MoveFn(moveArrayDesc) {
224*7330f729Sjoerg   assert(Source && "Missing source");
225*7330f729Sjoerg }
226*7330f729Sjoerg 
Descriptor(const DeclTy & D,Descriptor * Elem,bool IsTemporary,UnknownSize)227*7330f729Sjoerg Descriptor::Descriptor(const DeclTy &D, Descriptor *Elem, bool IsTemporary,
228*7330f729Sjoerg                        UnknownSize)
229*7330f729Sjoerg     : Source(D), ElemSize(Elem->getAllocSize() + sizeof(InlineDescriptor)),
230*7330f729Sjoerg       Size(UnknownSizeMark), AllocSize(alignof(void *)), ElemDesc(Elem),
231*7330f729Sjoerg       IsConst(true), IsMutable(false), IsTemporary(IsTemporary), IsArray(true),
232*7330f729Sjoerg       CtorFn(ctorArrayDesc), DtorFn(dtorArrayDesc), MoveFn(moveArrayDesc) {
233*7330f729Sjoerg   assert(Source && "Missing source");
234*7330f729Sjoerg }
235*7330f729Sjoerg 
Descriptor(const DeclTy & D,Record * R,bool IsConst,bool IsTemporary,bool IsMutable)236*7330f729Sjoerg Descriptor::Descriptor(const DeclTy &D, Record *R, bool IsConst,
237*7330f729Sjoerg                        bool IsTemporary, bool IsMutable)
238*7330f729Sjoerg     : Source(D), ElemSize(std::max<size_t>(alignof(void *), R->getFullSize())),
239*7330f729Sjoerg       Size(ElemSize), AllocSize(Size), ElemRecord(R), IsConst(IsConst),
240*7330f729Sjoerg       IsMutable(IsMutable), IsTemporary(IsTemporary), CtorFn(ctorRecord),
241*7330f729Sjoerg       DtorFn(dtorRecord), MoveFn(moveRecord) {
242*7330f729Sjoerg   assert(Source && "Missing source");
243*7330f729Sjoerg }
244*7330f729Sjoerg 
getType() const245*7330f729Sjoerg QualType Descriptor::getType() const {
246*7330f729Sjoerg   if (auto *E = asExpr())
247*7330f729Sjoerg     return E->getType();
248*7330f729Sjoerg   if (auto *D = asValueDecl())
249*7330f729Sjoerg     return D->getType();
250*7330f729Sjoerg   llvm_unreachable("Invalid descriptor type");
251*7330f729Sjoerg }
252*7330f729Sjoerg 
getLocation() const253*7330f729Sjoerg SourceLocation Descriptor::getLocation() const {
254*7330f729Sjoerg   if (auto *D = Source.dyn_cast<const Decl *>())
255*7330f729Sjoerg     return D->getLocation();
256*7330f729Sjoerg   if (auto *E = Source.dyn_cast<const Expr *>())
257*7330f729Sjoerg     return E->getExprLoc();
258*7330f729Sjoerg   llvm_unreachable("Invalid descriptor type");
259*7330f729Sjoerg }
260*7330f729Sjoerg 
InitMap(unsigned N)261*7330f729Sjoerg InitMap::InitMap(unsigned N) : UninitFields(N) {
262*7330f729Sjoerg   for (unsigned I = 0; I < N / PER_FIELD; ++I) {
263*7330f729Sjoerg     data()[I] = 0;
264*7330f729Sjoerg   }
265*7330f729Sjoerg }
266*7330f729Sjoerg 
data()267*7330f729Sjoerg InitMap::T *InitMap::data() {
268*7330f729Sjoerg   auto *Start = reinterpret_cast<char *>(this) + align(sizeof(InitMap));
269*7330f729Sjoerg   return reinterpret_cast<T *>(Start);
270*7330f729Sjoerg }
271*7330f729Sjoerg 
initialize(unsigned I)272*7330f729Sjoerg bool InitMap::initialize(unsigned I) {
273*7330f729Sjoerg   unsigned Bucket = I / PER_FIELD;
274*7330f729Sjoerg   unsigned Mask = 1ull << static_cast<uint64_t>(I % PER_FIELD);
275*7330f729Sjoerg   if (!(data()[Bucket] & Mask)) {
276*7330f729Sjoerg     data()[Bucket] |= Mask;
277*7330f729Sjoerg     UninitFields -= 1;
278*7330f729Sjoerg   }
279*7330f729Sjoerg   return UninitFields == 0;
280*7330f729Sjoerg }
281*7330f729Sjoerg 
isInitialized(unsigned I)282*7330f729Sjoerg bool InitMap::isInitialized(unsigned I) {
283*7330f729Sjoerg   unsigned Bucket = I / PER_FIELD;
284*7330f729Sjoerg   unsigned Mask = 1ull << static_cast<uint64_t>(I % PER_FIELD);
285*7330f729Sjoerg   return data()[Bucket] & Mask;
286*7330f729Sjoerg }
287*7330f729Sjoerg 
allocate(unsigned N)288*7330f729Sjoerg InitMap *InitMap::allocate(unsigned N) {
289*7330f729Sjoerg   const size_t NumFields = ((N + PER_FIELD - 1) / PER_FIELD);
290*7330f729Sjoerg   const size_t Size = align(sizeof(InitMap)) + NumFields * PER_FIELD;
291*7330f729Sjoerg   return new (malloc(Size)) InitMap(N);
292*7330f729Sjoerg }
293