/src/llvm-project/clang/lib/AST/Interp/Descriptor.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===--- Descriptor.cpp - Types for the constexpr VM ------------*- C++ -*-===// |
2 | | // |
3 | | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | | // See https://llvm.org/LICENSE.txt for license information. |
5 | | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | | // |
7 | | //===----------------------------------------------------------------------===// |
8 | | |
9 | | #include "Descriptor.h" |
10 | | #include "Boolean.h" |
11 | | #include "Floating.h" |
12 | | #include "FunctionPointer.h" |
13 | | #include "IntegralAP.h" |
14 | | #include "Pointer.h" |
15 | | #include "PrimType.h" |
16 | | #include "Record.h" |
17 | | |
18 | | using namespace clang; |
19 | | using namespace clang::interp; |
20 | | |
21 | | template <typename T> |
22 | | static void ctorTy(Block *, std::byte *Ptr, bool, bool, bool, |
23 | 0 | const Descriptor *) { |
24 | 0 | new (Ptr) T(); |
25 | 0 | } Unexecuted instantiation: Descriptor.cpp:void ctorTy<clang::interp::Floating>(clang::interp::Block*, std::byte*, bool, bool, bool, clang::interp::Descriptor const*) Unexecuted instantiation: Descriptor.cpp:void ctorTy<clang::interp::IntegralAP<false> >(clang::interp::Block*, std::byte*, bool, bool, bool, clang::interp::Descriptor const*) Unexecuted instantiation: Descriptor.cpp:void ctorTy<clang::interp::IntegralAP<true> >(clang::interp::Block*, std::byte*, bool, bool, bool, clang::interp::Descriptor const*) Unexecuted instantiation: Descriptor.cpp:void ctorTy<clang::interp::Pointer>(clang::interp::Block*, std::byte*, bool, bool, bool, clang::interp::Descriptor const*) |
26 | | |
27 | | template <typename T> |
28 | 0 | static void dtorTy(Block *, std::byte *Ptr, const Descriptor *) { |
29 | 0 | reinterpret_cast<T *>(Ptr)->~T(); |
30 | 0 | } Unexecuted instantiation: Descriptor.cpp:void dtorTy<clang::interp::Floating>(clang::interp::Block*, std::byte*, clang::interp::Descriptor const*) Unexecuted instantiation: Descriptor.cpp:void dtorTy<clang::interp::IntegralAP<false> >(clang::interp::Block*, std::byte*, clang::interp::Descriptor const*) Unexecuted instantiation: Descriptor.cpp:void dtorTy<clang::interp::IntegralAP<true> >(clang::interp::Block*, std::byte*, clang::interp::Descriptor const*) Unexecuted instantiation: Descriptor.cpp:void dtorTy<clang::interp::Pointer>(clang::interp::Block*, std::byte*, clang::interp::Descriptor const*) |
31 | | |
32 | | template <typename T> |
33 | | static void moveTy(Block *, const std::byte *Src, std::byte *Dst, |
34 | 0 | const Descriptor *) { |
35 | 0 | const auto *SrcPtr = reinterpret_cast<const T *>(Src); |
36 | 0 | auto *DstPtr = reinterpret_cast<T *>(Dst); |
37 | 0 | new (DstPtr) T(std::move(*SrcPtr)); |
38 | 0 | } |
39 | | |
40 | | template <typename T> |
41 | | static void ctorArrayTy(Block *, std::byte *Ptr, bool, bool, bool, |
42 | 0 | const Descriptor *D) { |
43 | 0 | new (Ptr) InitMapPtr(std::nullopt); |
44 | |
|
45 | 0 | Ptr += sizeof(InitMapPtr); |
46 | 0 | for (unsigned I = 0, NE = D->getNumElems(); I < NE; ++I) { |
47 | 0 | new (&reinterpret_cast<T *>(Ptr)[I]) T(); |
48 | 0 | } |
49 | 0 | } Unexecuted instantiation: Descriptor.cpp:void ctorArrayTy<clang::interp::Integral<8u, true> >(clang::interp::Block*, std::byte*, bool, bool, bool, clang::interp::Descriptor const*) Unexecuted instantiation: Descriptor.cpp:void ctorArrayTy<clang::interp::Integral<8u, false> >(clang::interp::Block*, std::byte*, bool, bool, bool, clang::interp::Descriptor const*) Unexecuted instantiation: Descriptor.cpp:void ctorArrayTy<clang::interp::Integral<16u, true> >(clang::interp::Block*, std::byte*, bool, bool, bool, clang::interp::Descriptor const*) Unexecuted instantiation: Descriptor.cpp:void ctorArrayTy<clang::interp::Integral<16u, false> >(clang::interp::Block*, std::byte*, bool, bool, bool, clang::interp::Descriptor const*) Unexecuted instantiation: Descriptor.cpp:void ctorArrayTy<clang::interp::Integral<32u, true> >(clang::interp::Block*, std::byte*, bool, bool, bool, clang::interp::Descriptor const*) Unexecuted instantiation: Descriptor.cpp:void ctorArrayTy<clang::interp::Integral<32u, false> >(clang::interp::Block*, std::byte*, bool, bool, bool, clang::interp::Descriptor const*) Unexecuted instantiation: Descriptor.cpp:void ctorArrayTy<clang::interp::Integral<64u, true> >(clang::interp::Block*, std::byte*, bool, bool, bool, clang::interp::Descriptor const*) Unexecuted instantiation: Descriptor.cpp:void ctorArrayTy<clang::interp::Integral<64u, false> >(clang::interp::Block*, std::byte*, bool, bool, bool, clang::interp::Descriptor const*) Unexecuted instantiation: Descriptor.cpp:void ctorArrayTy<clang::interp::IntegralAP<false> >(clang::interp::Block*, std::byte*, bool, bool, bool, clang::interp::Descriptor const*) Unexecuted instantiation: Descriptor.cpp:void ctorArrayTy<clang::interp::IntegralAP<true> >(clang::interp::Block*, std::byte*, bool, bool, bool, clang::interp::Descriptor const*) Unexecuted instantiation: Descriptor.cpp:void ctorArrayTy<clang::interp::Floating>(clang::interp::Block*, std::byte*, bool, bool, bool, clang::interp::Descriptor const*) Unexecuted instantiation: Descriptor.cpp:void ctorArrayTy<clang::interp::Boolean>(clang::interp::Block*, std::byte*, bool, bool, bool, clang::interp::Descriptor const*) Unexecuted instantiation: Descriptor.cpp:void ctorArrayTy<clang::interp::Pointer>(clang::interp::Block*, std::byte*, bool, bool, bool, clang::interp::Descriptor const*) Unexecuted instantiation: Descriptor.cpp:void ctorArrayTy<clang::interp::FunctionPointer>(clang::interp::Block*, std::byte*, bool, bool, bool, clang::interp::Descriptor const*) |
50 | | |
51 | | template <typename T> |
52 | 0 | static void dtorArrayTy(Block *, std::byte *Ptr, const Descriptor *D) { |
53 | 0 | InitMapPtr &IMP = *reinterpret_cast<InitMapPtr *>(Ptr); |
54 | |
|
55 | 0 | if (IMP) |
56 | 0 | IMP = std::nullopt; |
57 | 0 | Ptr += sizeof(InitMapPtr); |
58 | 0 | for (unsigned I = 0, NE = D->getNumElems(); I < NE; ++I) { |
59 | 0 | reinterpret_cast<T *>(Ptr)[I].~T(); |
60 | 0 | } |
61 | 0 | } Unexecuted instantiation: Descriptor.cpp:void dtorArrayTy<clang::interp::Integral<8u, true> >(clang::interp::Block*, std::byte*, clang::interp::Descriptor const*) Unexecuted instantiation: Descriptor.cpp:void dtorArrayTy<clang::interp::Integral<8u, false> >(clang::interp::Block*, std::byte*, clang::interp::Descriptor const*) Unexecuted instantiation: Descriptor.cpp:void dtorArrayTy<clang::interp::Integral<16u, true> >(clang::interp::Block*, std::byte*, clang::interp::Descriptor const*) Unexecuted instantiation: Descriptor.cpp:void dtorArrayTy<clang::interp::Integral<16u, false> >(clang::interp::Block*, std::byte*, clang::interp::Descriptor const*) Unexecuted instantiation: Descriptor.cpp:void dtorArrayTy<clang::interp::Integral<32u, true> >(clang::interp::Block*, std::byte*, clang::interp::Descriptor const*) Unexecuted instantiation: Descriptor.cpp:void dtorArrayTy<clang::interp::Integral<32u, false> >(clang::interp::Block*, std::byte*, clang::interp::Descriptor const*) Unexecuted instantiation: Descriptor.cpp:void dtorArrayTy<clang::interp::Integral<64u, true> >(clang::interp::Block*, std::byte*, clang::interp::Descriptor const*) Unexecuted instantiation: Descriptor.cpp:void dtorArrayTy<clang::interp::Integral<64u, false> >(clang::interp::Block*, std::byte*, clang::interp::Descriptor const*) Unexecuted instantiation: Descriptor.cpp:void dtorArrayTy<clang::interp::IntegralAP<false> >(clang::interp::Block*, std::byte*, clang::interp::Descriptor const*) Unexecuted instantiation: Descriptor.cpp:void dtorArrayTy<clang::interp::IntegralAP<true> >(clang::interp::Block*, std::byte*, clang::interp::Descriptor const*) Unexecuted instantiation: Descriptor.cpp:void dtorArrayTy<clang::interp::Floating>(clang::interp::Block*, std::byte*, clang::interp::Descriptor const*) Unexecuted instantiation: Descriptor.cpp:void dtorArrayTy<clang::interp::Boolean>(clang::interp::Block*, std::byte*, clang::interp::Descriptor const*) Unexecuted instantiation: Descriptor.cpp:void dtorArrayTy<clang::interp::Pointer>(clang::interp::Block*, std::byte*, clang::interp::Descriptor const*) Unexecuted instantiation: Descriptor.cpp:void dtorArrayTy<clang::interp::FunctionPointer>(clang::interp::Block*, std::byte*, clang::interp::Descriptor const*) |
62 | | |
63 | | template <typename T> |
64 | | static void moveArrayTy(Block *, const std::byte *Src, std::byte *Dst, |
65 | 0 | const Descriptor *D) { |
66 | 0 | for (unsigned I = 0, NE = D->getNumElems(); I < NE; ++I) { |
67 | 0 | const auto *SrcPtr = &reinterpret_cast<const T *>(Src)[I]; |
68 | 0 | auto *DstPtr = &reinterpret_cast<T *>(Dst)[I]; |
69 | 0 | new (DstPtr) T(std::move(*SrcPtr)); |
70 | 0 | } |
71 | 0 | } Unexecuted instantiation: Descriptor.cpp:void moveArrayTy<clang::interp::Integral<8u, true> >(clang::interp::Block*, std::byte const*, std::byte*, clang::interp::Descriptor const*) Unexecuted instantiation: Descriptor.cpp:void moveArrayTy<clang::interp::Integral<8u, false> >(clang::interp::Block*, std::byte const*, std::byte*, clang::interp::Descriptor const*) Unexecuted instantiation: Descriptor.cpp:void moveArrayTy<clang::interp::Integral<16u, true> >(clang::interp::Block*, std::byte const*, std::byte*, clang::interp::Descriptor const*) Unexecuted instantiation: Descriptor.cpp:void moveArrayTy<clang::interp::Integral<16u, false> >(clang::interp::Block*, std::byte const*, std::byte*, clang::interp::Descriptor const*) Unexecuted instantiation: Descriptor.cpp:void moveArrayTy<clang::interp::Integral<32u, true> >(clang::interp::Block*, std::byte const*, std::byte*, clang::interp::Descriptor const*) Unexecuted instantiation: Descriptor.cpp:void moveArrayTy<clang::interp::Integral<32u, false> >(clang::interp::Block*, std::byte const*, std::byte*, clang::interp::Descriptor const*) Unexecuted instantiation: Descriptor.cpp:void moveArrayTy<clang::interp::Integral<64u, true> >(clang::interp::Block*, std::byte const*, std::byte*, clang::interp::Descriptor const*) Unexecuted instantiation: Descriptor.cpp:void moveArrayTy<clang::interp::Integral<64u, false> >(clang::interp::Block*, std::byte const*, std::byte*, clang::interp::Descriptor const*) Unexecuted instantiation: Descriptor.cpp:void moveArrayTy<clang::interp::IntegralAP<false> >(clang::interp::Block*, std::byte const*, std::byte*, clang::interp::Descriptor const*) Unexecuted instantiation: Descriptor.cpp:void moveArrayTy<clang::interp::IntegralAP<true> >(clang::interp::Block*, std::byte const*, std::byte*, clang::interp::Descriptor const*) Unexecuted instantiation: Descriptor.cpp:void moveArrayTy<clang::interp::Floating>(clang::interp::Block*, std::byte const*, std::byte*, clang::interp::Descriptor const*) Unexecuted instantiation: Descriptor.cpp:void moveArrayTy<clang::interp::Boolean>(clang::interp::Block*, std::byte const*, std::byte*, clang::interp::Descriptor const*) Unexecuted instantiation: Descriptor.cpp:void moveArrayTy<clang::interp::Pointer>(clang::interp::Block*, std::byte const*, std::byte*, clang::interp::Descriptor const*) Unexecuted instantiation: Descriptor.cpp:void moveArrayTy<clang::interp::FunctionPointer>(clang::interp::Block*, std::byte const*, std::byte*, clang::interp::Descriptor const*) |
72 | | |
73 | | static void ctorArrayDesc(Block *B, std::byte *Ptr, bool IsConst, |
74 | 0 | bool IsMutable, bool IsActive, const Descriptor *D) { |
75 | 0 | const unsigned NumElems = D->getNumElems(); |
76 | 0 | const unsigned ElemSize = |
77 | 0 | D->ElemDesc->getAllocSize() + sizeof(InlineDescriptor); |
78 | |
|
79 | 0 | unsigned ElemOffset = 0; |
80 | 0 | for (unsigned I = 0; I < NumElems; ++I, ElemOffset += ElemSize) { |
81 | 0 | auto *ElemPtr = Ptr + ElemOffset; |
82 | 0 | auto *Desc = reinterpret_cast<InlineDescriptor *>(ElemPtr); |
83 | 0 | auto *ElemLoc = reinterpret_cast<std::byte *>(Desc + 1); |
84 | 0 | auto *SD = D->ElemDesc; |
85 | |
|
86 | 0 | Desc->Offset = ElemOffset + sizeof(InlineDescriptor); |
87 | 0 | Desc->Desc = SD; |
88 | 0 | Desc->IsInitialized = true; |
89 | 0 | Desc->IsBase = false; |
90 | 0 | Desc->IsActive = IsActive; |
91 | 0 | Desc->IsConst = IsConst || D->IsConst; |
92 | 0 | Desc->IsFieldMutable = IsMutable || D->IsMutable; |
93 | 0 | if (auto Fn = D->ElemDesc->CtorFn) |
94 | 0 | Fn(B, ElemLoc, Desc->IsConst, Desc->IsFieldMutable, IsActive, |
95 | 0 | D->ElemDesc); |
96 | 0 | } |
97 | 0 | } |
98 | | |
99 | 0 | static void dtorArrayDesc(Block *B, std::byte *Ptr, const Descriptor *D) { |
100 | 0 | const unsigned NumElems = D->getNumElems(); |
101 | 0 | const unsigned ElemSize = |
102 | 0 | D->ElemDesc->getAllocSize() + sizeof(InlineDescriptor); |
103 | |
|
104 | 0 | unsigned ElemOffset = 0; |
105 | 0 | for (unsigned I = 0; I < NumElems; ++I, ElemOffset += ElemSize) { |
106 | 0 | auto *ElemPtr = Ptr + ElemOffset; |
107 | 0 | auto *Desc = reinterpret_cast<InlineDescriptor *>(ElemPtr); |
108 | 0 | auto *ElemLoc = reinterpret_cast<std::byte *>(Desc + 1); |
109 | 0 | if (auto Fn = D->ElemDesc->DtorFn) |
110 | 0 | Fn(B, ElemLoc, D->ElemDesc); |
111 | 0 | } |
112 | 0 | } |
113 | | |
114 | | static void moveArrayDesc(Block *B, const std::byte *Src, std::byte *Dst, |
115 | 0 | const Descriptor *D) { |
116 | 0 | const unsigned NumElems = D->getNumElems(); |
117 | 0 | const unsigned ElemSize = |
118 | 0 | D->ElemDesc->getAllocSize() + sizeof(InlineDescriptor); |
119 | |
|
120 | 0 | unsigned ElemOffset = 0; |
121 | 0 | for (unsigned I = 0; I < NumElems; ++I, ElemOffset += ElemSize) { |
122 | 0 | const auto *SrcPtr = Src + ElemOffset; |
123 | 0 | auto *DstPtr = Dst + ElemOffset; |
124 | |
|
125 | 0 | const auto *SrcDesc = reinterpret_cast<const InlineDescriptor *>(SrcPtr); |
126 | 0 | const auto *SrcElemLoc = reinterpret_cast<const std::byte *>(SrcDesc + 1); |
127 | 0 | auto *DstDesc = reinterpret_cast<InlineDescriptor *>(DstPtr); |
128 | 0 | auto *DstElemLoc = reinterpret_cast<std::byte *>(DstDesc + 1); |
129 | |
|
130 | 0 | *DstDesc = *SrcDesc; |
131 | 0 | if (auto Fn = D->ElemDesc->MoveFn) |
132 | 0 | Fn(B, SrcElemLoc, DstElemLoc, D->ElemDesc); |
133 | 0 | } |
134 | 0 | } |
135 | | |
136 | | static void ctorRecord(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable, |
137 | 0 | bool IsActive, const Descriptor *D) { |
138 | 0 | const bool IsUnion = D->ElemRecord->isUnion(); |
139 | 0 | auto CtorSub = [=](unsigned SubOff, Descriptor *F, bool IsBase) { |
140 | 0 | auto *Desc = reinterpret_cast<InlineDescriptor *>(Ptr + SubOff) - 1; |
141 | 0 | Desc->Offset = SubOff; |
142 | 0 | Desc->Desc = F; |
143 | 0 | Desc->IsInitialized = F->IsArray && !IsBase; |
144 | 0 | Desc->IsBase = IsBase; |
145 | 0 | Desc->IsActive = IsActive && !IsUnion; |
146 | 0 | Desc->IsConst = IsConst || F->IsConst; |
147 | 0 | Desc->IsFieldMutable = IsMutable || F->IsMutable; |
148 | 0 | if (auto Fn = F->CtorFn) |
149 | 0 | Fn(B, Ptr + SubOff, Desc->IsConst, Desc->IsFieldMutable, Desc->IsActive, |
150 | 0 | F); |
151 | 0 | }; |
152 | 0 | for (const auto &B : D->ElemRecord->bases()) |
153 | 0 | CtorSub(B.Offset, B.Desc, /*isBase=*/true); |
154 | 0 | for (const auto &F : D->ElemRecord->fields()) |
155 | 0 | CtorSub(F.Offset, F.Desc, /*isBase=*/false); |
156 | 0 | for (const auto &V : D->ElemRecord->virtual_bases()) |
157 | 0 | CtorSub(V.Offset, V.Desc, /*isBase=*/true); |
158 | 0 | } |
159 | | |
160 | 0 | static void dtorRecord(Block *B, std::byte *Ptr, const Descriptor *D) { |
161 | 0 | auto DtorSub = [=](unsigned SubOff, Descriptor *F) { |
162 | 0 | if (auto Fn = F->DtorFn) |
163 | 0 | Fn(B, Ptr + SubOff, F); |
164 | 0 | }; |
165 | 0 | for (const auto &F : D->ElemRecord->bases()) |
166 | 0 | DtorSub(F.Offset, F.Desc); |
167 | 0 | for (const auto &F : D->ElemRecord->fields()) |
168 | 0 | DtorSub(F.Offset, F.Desc); |
169 | 0 | for (const auto &F : D->ElemRecord->virtual_bases()) |
170 | 0 | DtorSub(F.Offset, F.Desc); |
171 | 0 | } |
172 | | |
173 | | static void moveRecord(Block *B, const std::byte *Src, std::byte *Dst, |
174 | 0 | const Descriptor *D) { |
175 | 0 | for (const auto &F : D->ElemRecord->fields()) { |
176 | 0 | auto FieldOff = F.Offset; |
177 | 0 | auto *FieldDesc = F.Desc; |
178 | |
|
179 | 0 | if (auto Fn = FieldDesc->MoveFn) |
180 | 0 | Fn(B, Src + FieldOff, Dst + FieldOff, FieldDesc); |
181 | 0 | } |
182 | 0 | } |
183 | | |
184 | 0 | static BlockCtorFn getCtorPrim(PrimType Type) { |
185 | | // Floating types are special. They are primitives, but need their |
186 | | // constructor called. |
187 | 0 | if (Type == PT_Float) |
188 | 0 | return ctorTy<PrimConv<PT_Float>::T>; |
189 | 0 | if (Type == PT_IntAP) |
190 | 0 | return ctorTy<PrimConv<PT_IntAP>::T>; |
191 | 0 | if (Type == PT_IntAPS) |
192 | 0 | return ctorTy<PrimConv<PT_IntAPS>::T>; |
193 | | |
194 | 0 | COMPOSITE_TYPE_SWITCH(Type, return ctorTy<T>, return nullptr); |
195 | 0 | } |
196 | | |
197 | 0 | static BlockDtorFn getDtorPrim(PrimType Type) { |
198 | | // Floating types are special. They are primitives, but need their |
199 | | // destructor called, since they might allocate memory. |
200 | 0 | if (Type == PT_Float) |
201 | 0 | return dtorTy<PrimConv<PT_Float>::T>; |
202 | 0 | if (Type == PT_IntAP) |
203 | 0 | return dtorTy<PrimConv<PT_IntAP>::T>; |
204 | 0 | if (Type == PT_IntAPS) |
205 | 0 | return dtorTy<PrimConv<PT_IntAPS>::T>; |
206 | | |
207 | 0 | COMPOSITE_TYPE_SWITCH(Type, return dtorTy<T>, return nullptr); |
208 | 0 | } |
209 | | |
210 | 0 | static BlockMoveFn getMovePrim(PrimType Type) { |
211 | 0 | COMPOSITE_TYPE_SWITCH(Type, return moveTy<T>, return nullptr); |
212 | 0 | } |
213 | | |
214 | 0 | static BlockCtorFn getCtorArrayPrim(PrimType Type) { |
215 | 0 | TYPE_SWITCH(Type, return ctorArrayTy<T>); |
216 | 0 | llvm_unreachable("unknown Expr"); |
217 | 0 | } |
218 | | |
219 | 0 | static BlockDtorFn getDtorArrayPrim(PrimType Type) { |
220 | 0 | TYPE_SWITCH(Type, return dtorArrayTy<T>); |
221 | 0 | llvm_unreachable("unknown Expr"); |
222 | 0 | } |
223 | | |
224 | 0 | static BlockMoveFn getMoveArrayPrim(PrimType Type) { |
225 | 0 | TYPE_SWITCH(Type, return moveArrayTy<T>); |
226 | 0 | llvm_unreachable("unknown Expr"); |
227 | 0 | } |
228 | | |
229 | | /// Primitives. |
230 | | Descriptor::Descriptor(const DeclTy &D, PrimType Type, MetadataSize MD, |
231 | | bool IsConst, bool IsTemporary, bool IsMutable) |
232 | | : Source(D), ElemSize(primSize(Type)), Size(ElemSize), |
233 | | MDSize(MD.value_or(0)), AllocSize(align(Size + MDSize)), IsConst(IsConst), |
234 | | IsMutable(IsMutable), IsTemporary(IsTemporary), CtorFn(getCtorPrim(Type)), |
235 | 0 | DtorFn(getDtorPrim(Type)), MoveFn(getMovePrim(Type)) { |
236 | 0 | assert(AllocSize >= Size); |
237 | 0 | assert(Source && "Missing source"); |
238 | 0 | } |
239 | | |
240 | | /// Primitive arrays. |
241 | | Descriptor::Descriptor(const DeclTy &D, PrimType Type, MetadataSize MD, |
242 | | size_t NumElems, bool IsConst, bool IsTemporary, |
243 | | bool IsMutable) |
244 | | : Source(D), ElemSize(primSize(Type)), Size(ElemSize * NumElems), |
245 | | MDSize(MD.value_or(0)), |
246 | | AllocSize(align(Size) + sizeof(InitMapPtr) + MDSize), IsConst(IsConst), |
247 | | IsMutable(IsMutable), IsTemporary(IsTemporary), IsArray(true), |
248 | | CtorFn(getCtorArrayPrim(Type)), DtorFn(getDtorArrayPrim(Type)), |
249 | 0 | MoveFn(getMoveArrayPrim(Type)) { |
250 | 0 | assert(Source && "Missing source"); |
251 | 0 | } |
252 | | |
253 | | /// Primitive unknown-size arrays. |
254 | | Descriptor::Descriptor(const DeclTy &D, PrimType Type, bool IsTemporary, |
255 | | UnknownSize) |
256 | | : Source(D), ElemSize(primSize(Type)), Size(UnknownSizeMark), MDSize(0), |
257 | | AllocSize(alignof(void *) + sizeof(InitMapPtr)), IsConst(true), |
258 | | IsMutable(false), IsTemporary(IsTemporary), IsArray(true), |
259 | | CtorFn(getCtorArrayPrim(Type)), DtorFn(getDtorArrayPrim(Type)), |
260 | 0 | MoveFn(getMoveArrayPrim(Type)) { |
261 | 0 | assert(Source && "Missing source"); |
262 | 0 | } |
263 | | |
264 | | /// Arrays of composite elements. |
265 | | Descriptor::Descriptor(const DeclTy &D, const Descriptor *Elem, MetadataSize MD, |
266 | | unsigned NumElems, bool IsConst, bool IsTemporary, |
267 | | bool IsMutable) |
268 | | : Source(D), ElemSize(Elem->getAllocSize() + sizeof(InlineDescriptor)), |
269 | | Size(ElemSize * NumElems), MDSize(MD.value_or(0)), |
270 | | AllocSize(std::max<size_t>(alignof(void *), Size) + MDSize), |
271 | | ElemDesc(Elem), IsConst(IsConst), IsMutable(IsMutable), |
272 | | IsTemporary(IsTemporary), IsArray(true), CtorFn(ctorArrayDesc), |
273 | 0 | DtorFn(dtorArrayDesc), MoveFn(moveArrayDesc) { |
274 | 0 | assert(Source && "Missing source"); |
275 | 0 | } |
276 | | |
277 | | /// Unknown-size arrays of composite elements. |
278 | | Descriptor::Descriptor(const DeclTy &D, const Descriptor *Elem, |
279 | | bool IsTemporary, UnknownSize) |
280 | | : Source(D), ElemSize(Elem->getAllocSize() + sizeof(InlineDescriptor)), |
281 | | Size(UnknownSizeMark), MDSize(0), |
282 | | AllocSize(alignof(void *) + sizeof(InitMapPtr)), ElemDesc(Elem), |
283 | | IsConst(true), IsMutable(false), IsTemporary(IsTemporary), IsArray(true), |
284 | 0 | CtorFn(ctorArrayDesc), DtorFn(dtorArrayDesc), MoveFn(moveArrayDesc) { |
285 | 0 | assert(Source && "Missing source"); |
286 | 0 | } |
287 | | |
288 | | /// Composite records. |
289 | | Descriptor::Descriptor(const DeclTy &D, const Record *R, MetadataSize MD, |
290 | | bool IsConst, bool IsTemporary, bool IsMutable) |
291 | | : Source(D), ElemSize(std::max<size_t>(alignof(void *), R->getFullSize())), |
292 | | Size(ElemSize), MDSize(MD.value_or(0)), AllocSize(Size + MDSize), |
293 | | ElemRecord(R), IsConst(IsConst), IsMutable(IsMutable), |
294 | | IsTemporary(IsTemporary), CtorFn(ctorRecord), DtorFn(dtorRecord), |
295 | 0 | MoveFn(moveRecord) { |
296 | 0 | assert(Source && "Missing source"); |
297 | 0 | } |
298 | | |
299 | | Descriptor::Descriptor(const DeclTy &D, MetadataSize MD) |
300 | | : Source(D), ElemSize(1), Size(ElemSize), MDSize(MD.value_or(0)), |
301 | | AllocSize(Size + MDSize), ElemRecord(nullptr), IsConst(true), |
302 | 0 | IsMutable(false), IsTemporary(false), IsDummy(true) { |
303 | 0 | assert(Source && "Missing source"); |
304 | 0 | } |
305 | | |
306 | 0 | QualType Descriptor::getType() const { |
307 | 0 | if (auto *E = asExpr()) |
308 | 0 | return E->getType(); |
309 | 0 | if (auto *D = asValueDecl()) |
310 | 0 | return D->getType(); |
311 | 0 | if (auto *T = dyn_cast<TypeDecl>(asDecl())) |
312 | 0 | return QualType(T->getTypeForDecl(), 0); |
313 | 0 | llvm_unreachable("Invalid descriptor type"); |
314 | 0 | } |
315 | | |
316 | 0 | QualType Descriptor::getElemQualType() const { |
317 | 0 | assert(isArray()); |
318 | 0 | const auto *AT = cast<ArrayType>(getType()); |
319 | 0 | return AT->getElementType(); |
320 | 0 | } |
321 | | |
322 | 0 | SourceLocation Descriptor::getLocation() const { |
323 | 0 | if (auto *D = Source.dyn_cast<const Decl *>()) |
324 | 0 | return D->getLocation(); |
325 | 0 | if (auto *E = Source.dyn_cast<const Expr *>()) |
326 | 0 | return E->getExprLoc(); |
327 | 0 | llvm_unreachable("Invalid descriptor type"); |
328 | 0 | } |
329 | | |
330 | | InitMap::InitMap(unsigned N) |
331 | 0 | : UninitFields(N), Data(std::make_unique<T[]>(numFields(N))) { |
332 | 0 | std::fill_n(data(), numFields(N), 0); |
333 | 0 | } |
334 | | |
335 | 0 | bool InitMap::initializeElement(unsigned I) { |
336 | 0 | unsigned Bucket = I / PER_FIELD; |
337 | 0 | T Mask = T(1) << (I % PER_FIELD); |
338 | 0 | if (!(data()[Bucket] & Mask)) { |
339 | 0 | data()[Bucket] |= Mask; |
340 | 0 | UninitFields -= 1; |
341 | 0 | } |
342 | 0 | return UninitFields == 0; |
343 | 0 | } |
344 | | |
345 | 0 | bool InitMap::isElementInitialized(unsigned I) const { |
346 | 0 | unsigned Bucket = I / PER_FIELD; |
347 | 0 | return data()[Bucket] & (T(1) << (I % PER_FIELD)); |
348 | 0 | } |