xref: /freebsd-src/contrib/llvm-project/clang/lib/AST/Interp/Program.cpp (revision a7dea1671b87c07d2d266f836bfa8b58efc7c134)
1*a7dea167SDimitry Andric //===--- Program.cpp - Bytecode for the constexpr VM ------------*- C++ -*-===//
2*a7dea167SDimitry Andric //
3*a7dea167SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*a7dea167SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*a7dea167SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*a7dea167SDimitry Andric //
7*a7dea167SDimitry Andric //===----------------------------------------------------------------------===//
8*a7dea167SDimitry Andric 
9*a7dea167SDimitry Andric #include "Program.h"
10*a7dea167SDimitry Andric #include "ByteCodeStmtGen.h"
11*a7dea167SDimitry Andric #include "Context.h"
12*a7dea167SDimitry Andric #include "Function.h"
13*a7dea167SDimitry Andric #include "Opcode.h"
14*a7dea167SDimitry Andric #include "PrimType.h"
15*a7dea167SDimitry Andric #include "clang/AST/Decl.h"
16*a7dea167SDimitry Andric #include "clang/AST/DeclCXX.h"
17*a7dea167SDimitry Andric 
18*a7dea167SDimitry Andric using namespace clang;
19*a7dea167SDimitry Andric using namespace clang::interp;
20*a7dea167SDimitry Andric 
21*a7dea167SDimitry Andric unsigned Program::createGlobalString(const StringLiteral *S) {
22*a7dea167SDimitry Andric   const size_t CharWidth = S->getCharByteWidth();
23*a7dea167SDimitry Andric   const size_t BitWidth = CharWidth * Ctx.getCharBit();
24*a7dea167SDimitry Andric 
25*a7dea167SDimitry Andric   PrimType CharType;
26*a7dea167SDimitry Andric   switch (CharWidth) {
27*a7dea167SDimitry Andric   case 1:
28*a7dea167SDimitry Andric     CharType = PT_Sint8;
29*a7dea167SDimitry Andric     break;
30*a7dea167SDimitry Andric   case 2:
31*a7dea167SDimitry Andric     CharType = PT_Uint16;
32*a7dea167SDimitry Andric     break;
33*a7dea167SDimitry Andric   case 4:
34*a7dea167SDimitry Andric     CharType = PT_Uint32;
35*a7dea167SDimitry Andric     break;
36*a7dea167SDimitry Andric   default:
37*a7dea167SDimitry Andric     llvm_unreachable("unsupported character width");
38*a7dea167SDimitry Andric   }
39*a7dea167SDimitry Andric 
40*a7dea167SDimitry Andric   // Create a descriptor for the string.
41*a7dea167SDimitry Andric   Descriptor *Desc = allocateDescriptor(S, CharType, S->getLength() + 1,
42*a7dea167SDimitry Andric                                         /*isConst=*/true,
43*a7dea167SDimitry Andric                                         /*isTemporary=*/false,
44*a7dea167SDimitry Andric                                         /*isMutable=*/false);
45*a7dea167SDimitry Andric 
46*a7dea167SDimitry Andric   // Allocate storage for the string.
47*a7dea167SDimitry Andric   // The byte length does not include the null terminator.
48*a7dea167SDimitry Andric   unsigned I = Globals.size();
49*a7dea167SDimitry Andric   unsigned Sz = Desc->getAllocSize();
50*a7dea167SDimitry Andric   auto *G = new (Allocator, Sz) Global(Desc, /*isStatic=*/true,
51*a7dea167SDimitry Andric                                        /*isExtern=*/false);
52*a7dea167SDimitry Andric   Globals.push_back(G);
53*a7dea167SDimitry Andric 
54*a7dea167SDimitry Andric   // Construct the string in storage.
55*a7dea167SDimitry Andric   const Pointer Ptr(G->block());
56*a7dea167SDimitry Andric   for (unsigned I = 0, N = S->getLength(); I <= N; ++I) {
57*a7dea167SDimitry Andric     Pointer Field = Ptr.atIndex(I).narrow();
58*a7dea167SDimitry Andric     const uint32_t CodePoint = I == N ? 0 : S->getCodeUnit(I);
59*a7dea167SDimitry Andric     switch (CharType) {
60*a7dea167SDimitry Andric       case PT_Sint8: {
61*a7dea167SDimitry Andric         using T = PrimConv<PT_Sint8>::T;
62*a7dea167SDimitry Andric         Field.deref<T>() = T::from(CodePoint, BitWidth);
63*a7dea167SDimitry Andric         break;
64*a7dea167SDimitry Andric       }
65*a7dea167SDimitry Andric       case PT_Uint16: {
66*a7dea167SDimitry Andric         using T = PrimConv<PT_Uint16>::T;
67*a7dea167SDimitry Andric         Field.deref<T>() = T::from(CodePoint, BitWidth);
68*a7dea167SDimitry Andric         break;
69*a7dea167SDimitry Andric       }
70*a7dea167SDimitry Andric       case PT_Uint32: {
71*a7dea167SDimitry Andric         using T = PrimConv<PT_Uint32>::T;
72*a7dea167SDimitry Andric         Field.deref<T>() = T::from(CodePoint, BitWidth);
73*a7dea167SDimitry Andric         break;
74*a7dea167SDimitry Andric       }
75*a7dea167SDimitry Andric       default:
76*a7dea167SDimitry Andric         llvm_unreachable("unsupported character type");
77*a7dea167SDimitry Andric     }
78*a7dea167SDimitry Andric   }
79*a7dea167SDimitry Andric   return I;
80*a7dea167SDimitry Andric }
81*a7dea167SDimitry Andric 
82*a7dea167SDimitry Andric Pointer Program::getPtrGlobal(unsigned Idx) {
83*a7dea167SDimitry Andric   assert(Idx < Globals.size());
84*a7dea167SDimitry Andric   return Pointer(Globals[Idx]->block());
85*a7dea167SDimitry Andric }
86*a7dea167SDimitry Andric 
87*a7dea167SDimitry Andric llvm::Optional<unsigned> Program::getGlobal(const ValueDecl *VD) {
88*a7dea167SDimitry Andric   auto It = GlobalIndices.find(VD);
89*a7dea167SDimitry Andric   if (It != GlobalIndices.end())
90*a7dea167SDimitry Andric     return It->second;
91*a7dea167SDimitry Andric 
92*a7dea167SDimitry Andric   // Find any previous declarations which were aleady evaluated.
93*a7dea167SDimitry Andric   llvm::Optional<unsigned> Index;
94*a7dea167SDimitry Andric   for (const Decl *P = VD; P; P = P->getPreviousDecl()) {
95*a7dea167SDimitry Andric     auto It = GlobalIndices.find(P);
96*a7dea167SDimitry Andric     if (It != GlobalIndices.end()) {
97*a7dea167SDimitry Andric       Index = It->second;
98*a7dea167SDimitry Andric       break;
99*a7dea167SDimitry Andric     }
100*a7dea167SDimitry Andric   }
101*a7dea167SDimitry Andric 
102*a7dea167SDimitry Andric   // Map the decl to the existing index.
103*a7dea167SDimitry Andric   if (Index) {
104*a7dea167SDimitry Andric     GlobalIndices[VD] = *Index;
105*a7dea167SDimitry Andric     return {};
106*a7dea167SDimitry Andric   }
107*a7dea167SDimitry Andric 
108*a7dea167SDimitry Andric   return Index;
109*a7dea167SDimitry Andric }
110*a7dea167SDimitry Andric 
111*a7dea167SDimitry Andric llvm::Optional<unsigned> Program::getOrCreateGlobal(const ValueDecl *VD) {
112*a7dea167SDimitry Andric   if (auto Idx = getGlobal(VD))
113*a7dea167SDimitry Andric     return Idx;
114*a7dea167SDimitry Andric 
115*a7dea167SDimitry Andric   if (auto Idx = createGlobal(VD)) {
116*a7dea167SDimitry Andric     GlobalIndices[VD] = *Idx;
117*a7dea167SDimitry Andric     return Idx;
118*a7dea167SDimitry Andric   }
119*a7dea167SDimitry Andric   return {};
120*a7dea167SDimitry Andric }
121*a7dea167SDimitry Andric 
122*a7dea167SDimitry Andric llvm::Optional<unsigned> Program::getOrCreateDummy(const ParmVarDecl *PD) {
123*a7dea167SDimitry Andric   auto &ASTCtx = Ctx.getASTContext();
124*a7dea167SDimitry Andric 
125*a7dea167SDimitry Andric   // Create a pointer to an incomplete array of the specified elements.
126*a7dea167SDimitry Andric   QualType ElemTy = PD->getType()->castAs<PointerType>()->getPointeeType();
127*a7dea167SDimitry Andric   QualType Ty = ASTCtx.getIncompleteArrayType(ElemTy, ArrayType::Normal, 0);
128*a7dea167SDimitry Andric 
129*a7dea167SDimitry Andric   // Dedup blocks since they are immutable and pointers cannot be compared.
130*a7dea167SDimitry Andric   auto It = DummyParams.find(PD);
131*a7dea167SDimitry Andric   if (It != DummyParams.end())
132*a7dea167SDimitry Andric     return It->second;
133*a7dea167SDimitry Andric 
134*a7dea167SDimitry Andric   if (auto Idx = createGlobal(PD, Ty, /*isStatic=*/true, /*isExtern=*/true)) {
135*a7dea167SDimitry Andric     DummyParams[PD] = *Idx;
136*a7dea167SDimitry Andric     return Idx;
137*a7dea167SDimitry Andric   }
138*a7dea167SDimitry Andric   return {};
139*a7dea167SDimitry Andric }
140*a7dea167SDimitry Andric 
141*a7dea167SDimitry Andric llvm::Optional<unsigned> Program::createGlobal(const ValueDecl *VD) {
142*a7dea167SDimitry Andric   bool IsStatic, IsExtern;
143*a7dea167SDimitry Andric   if (auto *Var = dyn_cast<VarDecl>(VD)) {
144*a7dea167SDimitry Andric     IsStatic = !Var->hasLocalStorage();
145*a7dea167SDimitry Andric     IsExtern = !Var->getAnyInitializer();
146*a7dea167SDimitry Andric   } else {
147*a7dea167SDimitry Andric     IsStatic = false;
148*a7dea167SDimitry Andric     IsExtern = true;
149*a7dea167SDimitry Andric   }
150*a7dea167SDimitry Andric   if (auto Idx = createGlobal(VD, VD->getType(), IsStatic, IsExtern)) {
151*a7dea167SDimitry Andric     for (const Decl *P = VD; P; P = P->getPreviousDecl())
152*a7dea167SDimitry Andric       GlobalIndices[P] = *Idx;
153*a7dea167SDimitry Andric     return *Idx;
154*a7dea167SDimitry Andric   }
155*a7dea167SDimitry Andric   return {};
156*a7dea167SDimitry Andric }
157*a7dea167SDimitry Andric 
158*a7dea167SDimitry Andric llvm::Optional<unsigned> Program::createGlobal(const Expr *E) {
159*a7dea167SDimitry Andric   return createGlobal(E, E->getType(), /*isStatic=*/true, /*isExtern=*/false);
160*a7dea167SDimitry Andric }
161*a7dea167SDimitry Andric 
162*a7dea167SDimitry Andric llvm::Optional<unsigned> Program::createGlobal(const DeclTy &D, QualType Ty,
163*a7dea167SDimitry Andric                                                bool IsStatic, bool IsExtern) {
164*a7dea167SDimitry Andric   // Create a descriptor for the global.
165*a7dea167SDimitry Andric   Descriptor *Desc;
166*a7dea167SDimitry Andric   const bool IsConst = Ty.isConstQualified();
167*a7dea167SDimitry Andric   const bool IsTemporary = D.dyn_cast<const Expr *>();
168*a7dea167SDimitry Andric   if (auto T = Ctx.classify(Ty)) {
169*a7dea167SDimitry Andric     Desc = createDescriptor(D, *T, IsConst, IsTemporary);
170*a7dea167SDimitry Andric   } else {
171*a7dea167SDimitry Andric     Desc = createDescriptor(D, Ty.getTypePtr(), IsConst, IsTemporary);
172*a7dea167SDimitry Andric   }
173*a7dea167SDimitry Andric   if (!Desc)
174*a7dea167SDimitry Andric     return {};
175*a7dea167SDimitry Andric 
176*a7dea167SDimitry Andric   // Allocate a block for storage.
177*a7dea167SDimitry Andric   unsigned I = Globals.size();
178*a7dea167SDimitry Andric 
179*a7dea167SDimitry Andric   auto *G = new (Allocator, Desc->getAllocSize())
180*a7dea167SDimitry Andric       Global(getCurrentDecl(), Desc, IsStatic, IsExtern);
181*a7dea167SDimitry Andric   G->block()->invokeCtor();
182*a7dea167SDimitry Andric 
183*a7dea167SDimitry Andric   Globals.push_back(G);
184*a7dea167SDimitry Andric 
185*a7dea167SDimitry Andric   return I;
186*a7dea167SDimitry Andric }
187*a7dea167SDimitry Andric 
188*a7dea167SDimitry Andric Function *Program::getFunction(const FunctionDecl *F) {
189*a7dea167SDimitry Andric   F = F->getDefinition();
190*a7dea167SDimitry Andric   auto It = Funcs.find(F);
191*a7dea167SDimitry Andric   return It == Funcs.end() ? nullptr : It->second.get();
192*a7dea167SDimitry Andric }
193*a7dea167SDimitry Andric 
194*a7dea167SDimitry Andric llvm::Expected<Function *> Program::getOrCreateFunction(const FunctionDecl *F) {
195*a7dea167SDimitry Andric   if (Function *Func = getFunction(F)) {
196*a7dea167SDimitry Andric     return Func;
197*a7dea167SDimitry Andric   }
198*a7dea167SDimitry Andric 
199*a7dea167SDimitry Andric   // Try to compile the function if it wasn't compiled yet.
200*a7dea167SDimitry Andric   if (const FunctionDecl *FD = F->getDefinition())
201*a7dea167SDimitry Andric     return ByteCodeStmtGen<ByteCodeEmitter>(Ctx, *this).compileFunc(FD);
202*a7dea167SDimitry Andric 
203*a7dea167SDimitry Andric   // A relocation which traps if not resolved.
204*a7dea167SDimitry Andric   return nullptr;
205*a7dea167SDimitry Andric }
206*a7dea167SDimitry Andric 
207*a7dea167SDimitry Andric Record *Program::getOrCreateRecord(const RecordDecl *RD) {
208*a7dea167SDimitry Andric   // Use the actual definition as a key.
209*a7dea167SDimitry Andric   RD = RD->getDefinition();
210*a7dea167SDimitry Andric   if (!RD)
211*a7dea167SDimitry Andric     return nullptr;
212*a7dea167SDimitry Andric 
213*a7dea167SDimitry Andric   // Deduplicate records.
214*a7dea167SDimitry Andric   auto It = Records.find(RD);
215*a7dea167SDimitry Andric   if (It != Records.end()) {
216*a7dea167SDimitry Andric     return It->second;
217*a7dea167SDimitry Andric   }
218*a7dea167SDimitry Andric 
219*a7dea167SDimitry Andric   // Number of bytes required by fields and base classes.
220*a7dea167SDimitry Andric   unsigned Size = 0;
221*a7dea167SDimitry Andric   // Number of bytes required by virtual base.
222*a7dea167SDimitry Andric   unsigned VirtSize = 0;
223*a7dea167SDimitry Andric 
224*a7dea167SDimitry Andric   // Helper to get a base descriptor.
225*a7dea167SDimitry Andric   auto GetBaseDesc = [this](const RecordDecl *BD, Record *BR) -> Descriptor * {
226*a7dea167SDimitry Andric     if (!BR)
227*a7dea167SDimitry Andric       return nullptr;
228*a7dea167SDimitry Andric     return allocateDescriptor(BD, BR, /*isConst=*/false,
229*a7dea167SDimitry Andric                               /*isTemporary=*/false,
230*a7dea167SDimitry Andric                               /*isMutable=*/false);
231*a7dea167SDimitry Andric   };
232*a7dea167SDimitry Andric 
233*a7dea167SDimitry Andric   // Reserve space for base classes.
234*a7dea167SDimitry Andric   Record::BaseList Bases;
235*a7dea167SDimitry Andric   Record::VirtualBaseList VirtBases;
236*a7dea167SDimitry Andric   if (auto *CD = dyn_cast<CXXRecordDecl>(RD)) {
237*a7dea167SDimitry Andric     for (const CXXBaseSpecifier &Spec : CD->bases()) {
238*a7dea167SDimitry Andric       if (Spec.isVirtual())
239*a7dea167SDimitry Andric         continue;
240*a7dea167SDimitry Andric 
241*a7dea167SDimitry Andric       const RecordDecl *BD = Spec.getType()->castAs<RecordType>()->getDecl();
242*a7dea167SDimitry Andric       Record *BR = getOrCreateRecord(BD);
243*a7dea167SDimitry Andric       if (Descriptor *Desc = GetBaseDesc(BD, BR)) {
244*a7dea167SDimitry Andric         Size += align(sizeof(InlineDescriptor));
245*a7dea167SDimitry Andric         Bases.push_back({BD, Size, Desc, BR});
246*a7dea167SDimitry Andric         Size += align(BR->getSize());
247*a7dea167SDimitry Andric         continue;
248*a7dea167SDimitry Andric       }
249*a7dea167SDimitry Andric       return nullptr;
250*a7dea167SDimitry Andric     }
251*a7dea167SDimitry Andric 
252*a7dea167SDimitry Andric     for (const CXXBaseSpecifier &Spec : CD->vbases()) {
253*a7dea167SDimitry Andric       const RecordDecl *BD = Spec.getType()->castAs<RecordType>()->getDecl();
254*a7dea167SDimitry Andric       Record *BR = getOrCreateRecord(BD);
255*a7dea167SDimitry Andric 
256*a7dea167SDimitry Andric       if (Descriptor *Desc = GetBaseDesc(BD, BR)) {
257*a7dea167SDimitry Andric         VirtSize += align(sizeof(InlineDescriptor));
258*a7dea167SDimitry Andric         VirtBases.push_back({BD, VirtSize, Desc, BR});
259*a7dea167SDimitry Andric         VirtSize += align(BR->getSize());
260*a7dea167SDimitry Andric         continue;
261*a7dea167SDimitry Andric       }
262*a7dea167SDimitry Andric       return nullptr;
263*a7dea167SDimitry Andric     }
264*a7dea167SDimitry Andric   }
265*a7dea167SDimitry Andric 
266*a7dea167SDimitry Andric   // Reserve space for fields.
267*a7dea167SDimitry Andric   Record::FieldList Fields;
268*a7dea167SDimitry Andric   for (const FieldDecl *FD : RD->fields()) {
269*a7dea167SDimitry Andric     // Reserve space for the field's descriptor and the offset.
270*a7dea167SDimitry Andric     Size += align(sizeof(InlineDescriptor));
271*a7dea167SDimitry Andric 
272*a7dea167SDimitry Andric     // Classify the field and add its metadata.
273*a7dea167SDimitry Andric     QualType FT = FD->getType();
274*a7dea167SDimitry Andric     const bool IsConst = FT.isConstQualified();
275*a7dea167SDimitry Andric     const bool IsMutable = FD->isMutable();
276*a7dea167SDimitry Andric     Descriptor *Desc;
277*a7dea167SDimitry Andric     if (llvm::Optional<PrimType> T = Ctx.classify(FT)) {
278*a7dea167SDimitry Andric       Desc = createDescriptor(FD, *T, IsConst, /*isTemporary=*/false,
279*a7dea167SDimitry Andric                               IsMutable);
280*a7dea167SDimitry Andric     } else {
281*a7dea167SDimitry Andric       Desc = createDescriptor(FD, FT.getTypePtr(), IsConst,
282*a7dea167SDimitry Andric                               /*isTemporary=*/false, IsMutable);
283*a7dea167SDimitry Andric     }
284*a7dea167SDimitry Andric     if (!Desc)
285*a7dea167SDimitry Andric       return nullptr;
286*a7dea167SDimitry Andric     Fields.push_back({FD, Size, Desc});
287*a7dea167SDimitry Andric     Size += align(Desc->getAllocSize());
288*a7dea167SDimitry Andric   }
289*a7dea167SDimitry Andric 
290*a7dea167SDimitry Andric   Record *R = new (Allocator) Record(RD, std::move(Bases), std::move(Fields),
291*a7dea167SDimitry Andric                                      std::move(VirtBases), VirtSize, Size);
292*a7dea167SDimitry Andric   Records.insert({RD, R});
293*a7dea167SDimitry Andric   return R;
294*a7dea167SDimitry Andric }
295*a7dea167SDimitry Andric 
296*a7dea167SDimitry Andric Descriptor *Program::createDescriptor(const DeclTy &D, const Type *Ty,
297*a7dea167SDimitry Andric                                       bool IsConst, bool IsTemporary,
298*a7dea167SDimitry Andric                                       bool IsMutable) {
299*a7dea167SDimitry Andric   // Classes and structures.
300*a7dea167SDimitry Andric   if (auto *RT = Ty->getAs<RecordType>()) {
301*a7dea167SDimitry Andric     if (auto *Record = getOrCreateRecord(RT->getDecl()))
302*a7dea167SDimitry Andric       return allocateDescriptor(D, Record, IsConst, IsTemporary, IsMutable);
303*a7dea167SDimitry Andric   }
304*a7dea167SDimitry Andric 
305*a7dea167SDimitry Andric   // Arrays.
306*a7dea167SDimitry Andric   if (auto ArrayType = Ty->getAsArrayTypeUnsafe()) {
307*a7dea167SDimitry Andric     QualType ElemTy = ArrayType->getElementType();
308*a7dea167SDimitry Andric     // Array of well-known bounds.
309*a7dea167SDimitry Andric     if (auto CAT = dyn_cast<ConstantArrayType>(ArrayType)) {
310*a7dea167SDimitry Andric       size_t NumElems = CAT->getSize().getZExtValue();
311*a7dea167SDimitry Andric       if (llvm::Optional<PrimType> T = Ctx.classify(ElemTy)) {
312*a7dea167SDimitry Andric         // Arrays of primitives.
313*a7dea167SDimitry Andric         unsigned ElemSize = primSize(*T);
314*a7dea167SDimitry Andric         if (std::numeric_limits<unsigned>::max() / ElemSize <= NumElems) {
315*a7dea167SDimitry Andric           return {};
316*a7dea167SDimitry Andric         }
317*a7dea167SDimitry Andric         return allocateDescriptor(D, *T, NumElems, IsConst, IsTemporary,
318*a7dea167SDimitry Andric                                   IsMutable);
319*a7dea167SDimitry Andric       } else {
320*a7dea167SDimitry Andric         // Arrays of composites. In this case, the array is a list of pointers,
321*a7dea167SDimitry Andric         // followed by the actual elements.
322*a7dea167SDimitry Andric         Descriptor *Desc =
323*a7dea167SDimitry Andric             createDescriptor(D, ElemTy.getTypePtr(), IsConst, IsTemporary);
324*a7dea167SDimitry Andric         if (!Desc)
325*a7dea167SDimitry Andric           return nullptr;
326*a7dea167SDimitry Andric         InterpSize ElemSize = Desc->getAllocSize() + sizeof(InlineDescriptor);
327*a7dea167SDimitry Andric         if (std::numeric_limits<unsigned>::max() / ElemSize <= NumElems)
328*a7dea167SDimitry Andric           return {};
329*a7dea167SDimitry Andric         return allocateDescriptor(D, Desc, NumElems, IsConst, IsTemporary,
330*a7dea167SDimitry Andric                                   IsMutable);
331*a7dea167SDimitry Andric       }
332*a7dea167SDimitry Andric     }
333*a7dea167SDimitry Andric 
334*a7dea167SDimitry Andric     // Array of unknown bounds - cannot be accessed and pointer arithmetic
335*a7dea167SDimitry Andric     // is forbidden on pointers to such objects.
336*a7dea167SDimitry Andric     if (isa<IncompleteArrayType>(ArrayType)) {
337*a7dea167SDimitry Andric       if (llvm::Optional<PrimType> T = Ctx.classify(ElemTy)) {
338*a7dea167SDimitry Andric         return allocateDescriptor(D, *T, IsTemporary,
339*a7dea167SDimitry Andric                                   Descriptor::UnknownSize{});
340*a7dea167SDimitry Andric       } else {
341*a7dea167SDimitry Andric         Descriptor *Desc =
342*a7dea167SDimitry Andric             createDescriptor(D, ElemTy.getTypePtr(), IsConst, IsTemporary);
343*a7dea167SDimitry Andric         if (!Desc)
344*a7dea167SDimitry Andric           return nullptr;
345*a7dea167SDimitry Andric         return allocateDescriptor(D, Desc, IsTemporary,
346*a7dea167SDimitry Andric                                   Descriptor::UnknownSize{});
347*a7dea167SDimitry Andric       }
348*a7dea167SDimitry Andric     }
349*a7dea167SDimitry Andric   }
350*a7dea167SDimitry Andric 
351*a7dea167SDimitry Andric   // Atomic types.
352*a7dea167SDimitry Andric   if (auto *AT = Ty->getAs<AtomicType>()) {
353*a7dea167SDimitry Andric     const Type *InnerTy = AT->getValueType().getTypePtr();
354*a7dea167SDimitry Andric     return createDescriptor(D, InnerTy, IsConst, IsTemporary, IsMutable);
355*a7dea167SDimitry Andric   }
356*a7dea167SDimitry Andric 
357*a7dea167SDimitry Andric   // Complex types - represented as arrays of elements.
358*a7dea167SDimitry Andric   if (auto *CT = Ty->getAs<ComplexType>()) {
359*a7dea167SDimitry Andric     PrimType ElemTy = *Ctx.classify(CT->getElementType());
360*a7dea167SDimitry Andric     return allocateDescriptor(D, ElemTy, 2, IsConst, IsTemporary, IsMutable);
361*a7dea167SDimitry Andric   }
362*a7dea167SDimitry Andric 
363*a7dea167SDimitry Andric   return nullptr;
364*a7dea167SDimitry Andric }
365