1950b70dcSNandor Licker //===--- Program.cpp - Bytecode for the constexpr VM ------------*- C++ -*-===//
2950b70dcSNandor Licker //
3950b70dcSNandor Licker // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4950b70dcSNandor Licker // See https://llvm.org/LICENSE.txt for license information.
5950b70dcSNandor Licker // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6950b70dcSNandor Licker //
7950b70dcSNandor Licker //===----------------------------------------------------------------------===//
8950b70dcSNandor Licker 
9950b70dcSNandor Licker #include "Program.h"
10950b70dcSNandor Licker #include "ByteCodeStmtGen.h"
11950b70dcSNandor Licker #include "Context.h"
12950b70dcSNandor Licker #include "Function.h"
13950b70dcSNandor Licker #include "Opcode.h"
14950b70dcSNandor Licker #include "PrimType.h"
15950b70dcSNandor Licker #include "clang/AST/Decl.h"
16950b70dcSNandor Licker #include "clang/AST/DeclCXX.h"
17950b70dcSNandor Licker 
18950b70dcSNandor Licker using namespace clang;
19950b70dcSNandor Licker using namespace clang::interp;
20950b70dcSNandor Licker 
getOrCreateNativePointer(const void * Ptr)2140080e7eSJessica Clarke unsigned Program::getOrCreateNativePointer(const void *Ptr) {
2240080e7eSJessica Clarke   auto It = NativePointerIndices.find(Ptr);
2340080e7eSJessica Clarke   if (It != NativePointerIndices.end())
2440080e7eSJessica Clarke     return It->second;
2540080e7eSJessica Clarke 
2640080e7eSJessica Clarke   unsigned Idx = NativePointers.size();
2740080e7eSJessica Clarke   NativePointers.push_back(Ptr);
2840080e7eSJessica Clarke   NativePointerIndices[Ptr] = Idx;
2940080e7eSJessica Clarke   return Idx;
3040080e7eSJessica Clarke }
3140080e7eSJessica Clarke 
getNativePointer(unsigned Idx)3240080e7eSJessica Clarke const void *Program::getNativePointer(unsigned Idx) {
3340080e7eSJessica Clarke   return NativePointers[Idx];
3440080e7eSJessica Clarke }
3540080e7eSJessica Clarke 
createGlobalString(const StringLiteral * S)36950b70dcSNandor Licker unsigned Program::createGlobalString(const StringLiteral *S) {
37950b70dcSNandor Licker   const size_t CharWidth = S->getCharByteWidth();
38950b70dcSNandor Licker   const size_t BitWidth = CharWidth * Ctx.getCharBit();
39950b70dcSNandor Licker 
40950b70dcSNandor Licker   PrimType CharType;
41950b70dcSNandor Licker   switch (CharWidth) {
42950b70dcSNandor Licker   case 1:
43950b70dcSNandor Licker     CharType = PT_Sint8;
44950b70dcSNandor Licker     break;
45950b70dcSNandor Licker   case 2:
46950b70dcSNandor Licker     CharType = PT_Uint16;
47950b70dcSNandor Licker     break;
48950b70dcSNandor Licker   case 4:
49950b70dcSNandor Licker     CharType = PT_Uint32;
50950b70dcSNandor Licker     break;
51950b70dcSNandor Licker   default:
52950b70dcSNandor Licker     llvm_unreachable("unsupported character width");
53950b70dcSNandor Licker   }
54950b70dcSNandor Licker 
55950b70dcSNandor Licker   // Create a descriptor for the string.
56950b70dcSNandor Licker   Descriptor *Desc = allocateDescriptor(S, CharType, S->getLength() + 1,
57950b70dcSNandor Licker                                         /*isConst=*/true,
58950b70dcSNandor Licker                                         /*isTemporary=*/false,
59950b70dcSNandor Licker                                         /*isMutable=*/false);
60950b70dcSNandor Licker 
61950b70dcSNandor Licker   // Allocate storage for the string.
62950b70dcSNandor Licker   // The byte length does not include the null terminator.
63950b70dcSNandor Licker   unsigned I = Globals.size();
64950b70dcSNandor Licker   unsigned Sz = Desc->getAllocSize();
65950b70dcSNandor Licker   auto *G = new (Allocator, Sz) Global(Desc, /*isStatic=*/true,
66950b70dcSNandor Licker                                        /*isExtern=*/false);
67950b70dcSNandor Licker   Globals.push_back(G);
68950b70dcSNandor Licker 
69950b70dcSNandor Licker   // Construct the string in storage.
70950b70dcSNandor Licker   const Pointer Ptr(G->block());
71950b70dcSNandor Licker   for (unsigned I = 0, N = S->getLength(); I <= N; ++I) {
72950b70dcSNandor Licker     Pointer Field = Ptr.atIndex(I).narrow();
73950b70dcSNandor Licker     const uint32_t CodePoint = I == N ? 0 : S->getCodeUnit(I);
74950b70dcSNandor Licker     switch (CharType) {
75950b70dcSNandor Licker       case PT_Sint8: {
76950b70dcSNandor Licker         using T = PrimConv<PT_Sint8>::T;
77950b70dcSNandor Licker         Field.deref<T>() = T::from(CodePoint, BitWidth);
78950b70dcSNandor Licker         break;
79950b70dcSNandor Licker       }
80950b70dcSNandor Licker       case PT_Uint16: {
81950b70dcSNandor Licker         using T = PrimConv<PT_Uint16>::T;
82950b70dcSNandor Licker         Field.deref<T>() = T::from(CodePoint, BitWidth);
83950b70dcSNandor Licker         break;
84950b70dcSNandor Licker       }
85950b70dcSNandor Licker       case PT_Uint32: {
86950b70dcSNandor Licker         using T = PrimConv<PT_Uint32>::T;
87950b70dcSNandor Licker         Field.deref<T>() = T::from(CodePoint, BitWidth);
88950b70dcSNandor Licker         break;
89950b70dcSNandor Licker       }
90950b70dcSNandor Licker       default:
91950b70dcSNandor Licker         llvm_unreachable("unsupported character type");
92950b70dcSNandor Licker     }
93950b70dcSNandor Licker   }
94950b70dcSNandor Licker   return I;
95950b70dcSNandor Licker }
96950b70dcSNandor Licker 
getPtrGlobal(unsigned Idx)97950b70dcSNandor Licker Pointer Program::getPtrGlobal(unsigned Idx) {
98950b70dcSNandor Licker   assert(Idx < Globals.size());
99950b70dcSNandor Licker   return Pointer(Globals[Idx]->block());
100950b70dcSNandor Licker }
101950b70dcSNandor Licker 
getGlobal(const ValueDecl * VD)102950b70dcSNandor Licker llvm::Optional<unsigned> Program::getGlobal(const ValueDecl *VD) {
103950b70dcSNandor Licker   auto It = GlobalIndices.find(VD);
104950b70dcSNandor Licker   if (It != GlobalIndices.end())
105950b70dcSNandor Licker     return It->second;
106950b70dcSNandor Licker 
107*60ab6861SNico Weber   // Find any previous declarations which were already evaluated.
108950b70dcSNandor Licker   llvm::Optional<unsigned> Index;
109950b70dcSNandor Licker   for (const Decl *P = VD; P; P = P->getPreviousDecl()) {
110950b70dcSNandor Licker     auto It = GlobalIndices.find(P);
111950b70dcSNandor Licker     if (It != GlobalIndices.end()) {
112950b70dcSNandor Licker       Index = It->second;
113950b70dcSNandor Licker       break;
114950b70dcSNandor Licker     }
115950b70dcSNandor Licker   }
116950b70dcSNandor Licker 
117950b70dcSNandor Licker   // Map the decl to the existing index.
118950b70dcSNandor Licker   if (Index) {
119950b70dcSNandor Licker     GlobalIndices[VD] = *Index;
120950b70dcSNandor Licker     return {};
121950b70dcSNandor Licker   }
122950b70dcSNandor Licker 
123950b70dcSNandor Licker   return Index;
124950b70dcSNandor Licker }
125950b70dcSNandor Licker 
getOrCreateGlobal(const ValueDecl * VD)126950b70dcSNandor Licker llvm::Optional<unsigned> Program::getOrCreateGlobal(const ValueDecl *VD) {
127950b70dcSNandor Licker   if (auto Idx = getGlobal(VD))
128950b70dcSNandor Licker     return Idx;
129950b70dcSNandor Licker 
130950b70dcSNandor Licker   if (auto Idx = createGlobal(VD)) {
131950b70dcSNandor Licker     GlobalIndices[VD] = *Idx;
132950b70dcSNandor Licker     return Idx;
133950b70dcSNandor Licker   }
134950b70dcSNandor Licker   return {};
135950b70dcSNandor Licker }
136950b70dcSNandor Licker 
getOrCreateDummy(const ParmVarDecl * PD)137950b70dcSNandor Licker llvm::Optional<unsigned> Program::getOrCreateDummy(const ParmVarDecl *PD) {
138950b70dcSNandor Licker   auto &ASTCtx = Ctx.getASTContext();
139950b70dcSNandor Licker 
140950b70dcSNandor Licker   // Create a pointer to an incomplete array of the specified elements.
1413459a4c7SSimon Pilgrim   QualType ElemTy = PD->getType()->castAs<PointerType>()->getPointeeType();
142950b70dcSNandor Licker   QualType Ty = ASTCtx.getIncompleteArrayType(ElemTy, ArrayType::Normal, 0);
143950b70dcSNandor Licker 
144950b70dcSNandor Licker   // Dedup blocks since they are immutable and pointers cannot be compared.
145950b70dcSNandor Licker   auto It = DummyParams.find(PD);
146950b70dcSNandor Licker   if (It != DummyParams.end())
147950b70dcSNandor Licker     return It->second;
148950b70dcSNandor Licker 
149950b70dcSNandor Licker   if (auto Idx = createGlobal(PD, Ty, /*isStatic=*/true, /*isExtern=*/true)) {
150950b70dcSNandor Licker     DummyParams[PD] = *Idx;
151950b70dcSNandor Licker     return Idx;
152950b70dcSNandor Licker   }
153950b70dcSNandor Licker   return {};
154950b70dcSNandor Licker }
155950b70dcSNandor Licker 
createGlobal(const ValueDecl * VD)156950b70dcSNandor Licker llvm::Optional<unsigned> Program::createGlobal(const ValueDecl *VD) {
157950b70dcSNandor Licker   bool IsStatic, IsExtern;
158950b70dcSNandor Licker   if (auto *Var = dyn_cast<VarDecl>(VD)) {
159950b70dcSNandor Licker     IsStatic = !Var->hasLocalStorage();
160950b70dcSNandor Licker     IsExtern = !Var->getAnyInitializer();
161950b70dcSNandor Licker   } else {
162950b70dcSNandor Licker     IsStatic = false;
163950b70dcSNandor Licker     IsExtern = true;
164950b70dcSNandor Licker   }
165950b70dcSNandor Licker   if (auto Idx = createGlobal(VD, VD->getType(), IsStatic, IsExtern)) {
166950b70dcSNandor Licker     for (const Decl *P = VD; P; P = P->getPreviousDecl())
167950b70dcSNandor Licker       GlobalIndices[P] = *Idx;
168950b70dcSNandor Licker     return *Idx;
169950b70dcSNandor Licker   }
170950b70dcSNandor Licker   return {};
171950b70dcSNandor Licker }
172950b70dcSNandor Licker 
createGlobal(const Expr * E)173950b70dcSNandor Licker llvm::Optional<unsigned> Program::createGlobal(const Expr *E) {
174950b70dcSNandor Licker   return createGlobal(E, E->getType(), /*isStatic=*/true, /*isExtern=*/false);
175950b70dcSNandor Licker }
176950b70dcSNandor Licker 
createGlobal(const DeclTy & D,QualType Ty,bool IsStatic,bool IsExtern)177950b70dcSNandor Licker llvm::Optional<unsigned> Program::createGlobal(const DeclTy &D, QualType Ty,
178950b70dcSNandor Licker                                                bool IsStatic, bool IsExtern) {
179950b70dcSNandor Licker   // Create a descriptor for the global.
180950b70dcSNandor Licker   Descriptor *Desc;
181950b70dcSNandor Licker   const bool IsConst = Ty.isConstQualified();
182950b70dcSNandor Licker   const bool IsTemporary = D.dyn_cast<const Expr *>();
183950b70dcSNandor Licker   if (auto T = Ctx.classify(Ty)) {
184950b70dcSNandor Licker     Desc = createDescriptor(D, *T, IsConst, IsTemporary);
185950b70dcSNandor Licker   } else {
186950b70dcSNandor Licker     Desc = createDescriptor(D, Ty.getTypePtr(), IsConst, IsTemporary);
187950b70dcSNandor Licker   }
188950b70dcSNandor Licker   if (!Desc)
189950b70dcSNandor Licker     return {};
190950b70dcSNandor Licker 
191950b70dcSNandor Licker   // Allocate a block for storage.
192950b70dcSNandor Licker   unsigned I = Globals.size();
193950b70dcSNandor Licker 
194950b70dcSNandor Licker   auto *G = new (Allocator, Desc->getAllocSize())
195950b70dcSNandor Licker       Global(getCurrentDecl(), Desc, IsStatic, IsExtern);
196950b70dcSNandor Licker   G->block()->invokeCtor();
197950b70dcSNandor Licker 
198950b70dcSNandor Licker   Globals.push_back(G);
199950b70dcSNandor Licker 
200950b70dcSNandor Licker   return I;
201950b70dcSNandor Licker }
202950b70dcSNandor Licker 
getFunction(const FunctionDecl * F)203950b70dcSNandor Licker Function *Program::getFunction(const FunctionDecl *F) {
204950b70dcSNandor Licker   F = F->getDefinition();
205950b70dcSNandor Licker   auto It = Funcs.find(F);
206950b70dcSNandor Licker   return It == Funcs.end() ? nullptr : It->second.get();
207950b70dcSNandor Licker }
208950b70dcSNandor Licker 
getOrCreateFunction(const FunctionDecl * F)209950b70dcSNandor Licker llvm::Expected<Function *> Program::getOrCreateFunction(const FunctionDecl *F) {
210950b70dcSNandor Licker   if (Function *Func = getFunction(F)) {
211950b70dcSNandor Licker     return Func;
212950b70dcSNandor Licker   }
213950b70dcSNandor Licker 
214950b70dcSNandor Licker   // Try to compile the function if it wasn't compiled yet.
215950b70dcSNandor Licker   if (const FunctionDecl *FD = F->getDefinition())
216950b70dcSNandor Licker     return ByteCodeStmtGen<ByteCodeEmitter>(Ctx, *this).compileFunc(FD);
217950b70dcSNandor Licker 
218950b70dcSNandor Licker   // A relocation which traps if not resolved.
219950b70dcSNandor Licker   return nullptr;
220950b70dcSNandor Licker }
221950b70dcSNandor Licker 
getOrCreateRecord(const RecordDecl * RD)222950b70dcSNandor Licker Record *Program::getOrCreateRecord(const RecordDecl *RD) {
223950b70dcSNandor Licker   // Use the actual definition as a key.
224950b70dcSNandor Licker   RD = RD->getDefinition();
225950b70dcSNandor Licker   if (!RD)
226950b70dcSNandor Licker     return nullptr;
227950b70dcSNandor Licker 
228950b70dcSNandor Licker   // Deduplicate records.
229950b70dcSNandor Licker   auto It = Records.find(RD);
230950b70dcSNandor Licker   if (It != Records.end()) {
231950b70dcSNandor Licker     return It->second;
232950b70dcSNandor Licker   }
233950b70dcSNandor Licker 
234950b70dcSNandor Licker   // Number of bytes required by fields and base classes.
235950b70dcSNandor Licker   unsigned Size = 0;
236950b70dcSNandor Licker   // Number of bytes required by virtual base.
237950b70dcSNandor Licker   unsigned VirtSize = 0;
238950b70dcSNandor Licker 
239950b70dcSNandor Licker   // Helper to get a base descriptor.
240950b70dcSNandor Licker   auto GetBaseDesc = [this](const RecordDecl *BD, Record *BR) -> Descriptor * {
241950b70dcSNandor Licker     if (!BR)
242950b70dcSNandor Licker       return nullptr;
243950b70dcSNandor Licker     return allocateDescriptor(BD, BR, /*isConst=*/false,
244950b70dcSNandor Licker                               /*isTemporary=*/false,
245950b70dcSNandor Licker                               /*isMutable=*/false);
246950b70dcSNandor Licker   };
247950b70dcSNandor Licker 
248950b70dcSNandor Licker   // Reserve space for base classes.
249950b70dcSNandor Licker   Record::BaseList Bases;
250950b70dcSNandor Licker   Record::VirtualBaseList VirtBases;
251950b70dcSNandor Licker   if (auto *CD = dyn_cast<CXXRecordDecl>(RD)) {
252950b70dcSNandor Licker     for (const CXXBaseSpecifier &Spec : CD->bases()) {
253950b70dcSNandor Licker       if (Spec.isVirtual())
254950b70dcSNandor Licker         continue;
255950b70dcSNandor Licker 
2561cd399c9SSimon Pilgrim       const RecordDecl *BD = Spec.getType()->castAs<RecordType>()->getDecl();
257950b70dcSNandor Licker       Record *BR = getOrCreateRecord(BD);
258950b70dcSNandor Licker       if (Descriptor *Desc = GetBaseDesc(BD, BR)) {
259950b70dcSNandor Licker         Size += align(sizeof(InlineDescriptor));
260950b70dcSNandor Licker         Bases.push_back({BD, Size, Desc, BR});
261950b70dcSNandor Licker         Size += align(BR->getSize());
262950b70dcSNandor Licker         continue;
263950b70dcSNandor Licker       }
264950b70dcSNandor Licker       return nullptr;
265950b70dcSNandor Licker     }
266950b70dcSNandor Licker 
267950b70dcSNandor Licker     for (const CXXBaseSpecifier &Spec : CD->vbases()) {
2681cd399c9SSimon Pilgrim       const RecordDecl *BD = Spec.getType()->castAs<RecordType>()->getDecl();
269950b70dcSNandor Licker       Record *BR = getOrCreateRecord(BD);
270950b70dcSNandor Licker 
271950b70dcSNandor Licker       if (Descriptor *Desc = GetBaseDesc(BD, BR)) {
272950b70dcSNandor Licker         VirtSize += align(sizeof(InlineDescriptor));
273950b70dcSNandor Licker         VirtBases.push_back({BD, VirtSize, Desc, BR});
274950b70dcSNandor Licker         VirtSize += align(BR->getSize());
275950b70dcSNandor Licker         continue;
276950b70dcSNandor Licker       }
277950b70dcSNandor Licker       return nullptr;
278950b70dcSNandor Licker     }
279950b70dcSNandor Licker   }
280950b70dcSNandor Licker 
281950b70dcSNandor Licker   // Reserve space for fields.
282950b70dcSNandor Licker   Record::FieldList Fields;
283950b70dcSNandor Licker   for (const FieldDecl *FD : RD->fields()) {
284950b70dcSNandor Licker     // Reserve space for the field's descriptor and the offset.
285950b70dcSNandor Licker     Size += align(sizeof(InlineDescriptor));
286950b70dcSNandor Licker 
287950b70dcSNandor Licker     // Classify the field and add its metadata.
288950b70dcSNandor Licker     QualType FT = FD->getType();
289950b70dcSNandor Licker     const bool IsConst = FT.isConstQualified();
290950b70dcSNandor Licker     const bool IsMutable = FD->isMutable();
291950b70dcSNandor Licker     Descriptor *Desc;
292950b70dcSNandor Licker     if (llvm::Optional<PrimType> T = Ctx.classify(FT)) {
293950b70dcSNandor Licker       Desc = createDescriptor(FD, *T, IsConst, /*isTemporary=*/false,
294950b70dcSNandor Licker                               IsMutable);
295950b70dcSNandor Licker     } else {
296950b70dcSNandor Licker       Desc = createDescriptor(FD, FT.getTypePtr(), IsConst,
297950b70dcSNandor Licker                               /*isTemporary=*/false, IsMutable);
298950b70dcSNandor Licker     }
299950b70dcSNandor Licker     if (!Desc)
300950b70dcSNandor Licker       return nullptr;
301950b70dcSNandor Licker     Fields.push_back({FD, Size, Desc});
302950b70dcSNandor Licker     Size += align(Desc->getAllocSize());
303950b70dcSNandor Licker   }
304950b70dcSNandor Licker 
305950b70dcSNandor Licker   Record *R = new (Allocator) Record(RD, std::move(Bases), std::move(Fields),
306950b70dcSNandor Licker                                      std::move(VirtBases), VirtSize, Size);
307950b70dcSNandor Licker   Records.insert({RD, R});
308950b70dcSNandor Licker   return R;
309950b70dcSNandor Licker }
310950b70dcSNandor Licker 
createDescriptor(const DeclTy & D,const Type * Ty,bool IsConst,bool IsTemporary,bool IsMutable)311950b70dcSNandor Licker Descriptor *Program::createDescriptor(const DeclTy &D, const Type *Ty,
312950b70dcSNandor Licker                                       bool IsConst, bool IsTemporary,
313950b70dcSNandor Licker                                       bool IsMutable) {
314950b70dcSNandor Licker   // Classes and structures.
315950b70dcSNandor Licker   if (auto *RT = Ty->getAs<RecordType>()) {
316950b70dcSNandor Licker     if (auto *Record = getOrCreateRecord(RT->getDecl()))
317950b70dcSNandor Licker       return allocateDescriptor(D, Record, IsConst, IsTemporary, IsMutable);
318950b70dcSNandor Licker   }
319950b70dcSNandor Licker 
320950b70dcSNandor Licker   // Arrays.
321950b70dcSNandor Licker   if (auto ArrayType = Ty->getAsArrayTypeUnsafe()) {
322950b70dcSNandor Licker     QualType ElemTy = ArrayType->getElementType();
323950b70dcSNandor Licker     // Array of well-known bounds.
324950b70dcSNandor Licker     if (auto CAT = dyn_cast<ConstantArrayType>(ArrayType)) {
325950b70dcSNandor Licker       size_t NumElems = CAT->getSize().getZExtValue();
326950b70dcSNandor Licker       if (llvm::Optional<PrimType> T = Ctx.classify(ElemTy)) {
327950b70dcSNandor Licker         // Arrays of primitives.
328950b70dcSNandor Licker         unsigned ElemSize = primSize(*T);
329950b70dcSNandor Licker         if (std::numeric_limits<unsigned>::max() / ElemSize <= NumElems) {
330950b70dcSNandor Licker           return {};
331950b70dcSNandor Licker         }
332950b70dcSNandor Licker         return allocateDescriptor(D, *T, NumElems, IsConst, IsTemporary,
333950b70dcSNandor Licker                                   IsMutable);
334950b70dcSNandor Licker       } else {
335950b70dcSNandor Licker         // Arrays of composites. In this case, the array is a list of pointers,
336950b70dcSNandor Licker         // followed by the actual elements.
337950b70dcSNandor Licker         Descriptor *Desc =
338950b70dcSNandor Licker             createDescriptor(D, ElemTy.getTypePtr(), IsConst, IsTemporary);
339950b70dcSNandor Licker         if (!Desc)
340950b70dcSNandor Licker           return nullptr;
341950b70dcSNandor Licker         InterpSize ElemSize = Desc->getAllocSize() + sizeof(InlineDescriptor);
342950b70dcSNandor Licker         if (std::numeric_limits<unsigned>::max() / ElemSize <= NumElems)
343950b70dcSNandor Licker           return {};
344950b70dcSNandor Licker         return allocateDescriptor(D, Desc, NumElems, IsConst, IsTemporary,
345950b70dcSNandor Licker                                   IsMutable);
346950b70dcSNandor Licker       }
347950b70dcSNandor Licker     }
348950b70dcSNandor Licker 
349950b70dcSNandor Licker     // Array of unknown bounds - cannot be accessed and pointer arithmetic
350950b70dcSNandor Licker     // is forbidden on pointers to such objects.
351950b70dcSNandor Licker     if (isa<IncompleteArrayType>(ArrayType)) {
352950b70dcSNandor Licker       if (llvm::Optional<PrimType> T = Ctx.classify(ElemTy)) {
353950b70dcSNandor Licker         return allocateDescriptor(D, *T, IsTemporary,
354950b70dcSNandor Licker                                   Descriptor::UnknownSize{});
355950b70dcSNandor Licker       } else {
356950b70dcSNandor Licker         Descriptor *Desc =
357950b70dcSNandor Licker             createDescriptor(D, ElemTy.getTypePtr(), IsConst, IsTemporary);
358950b70dcSNandor Licker         if (!Desc)
359950b70dcSNandor Licker           return nullptr;
360950b70dcSNandor Licker         return allocateDescriptor(D, Desc, IsTemporary,
361950b70dcSNandor Licker                                   Descriptor::UnknownSize{});
362950b70dcSNandor Licker       }
363950b70dcSNandor Licker     }
364950b70dcSNandor Licker   }
365950b70dcSNandor Licker 
366950b70dcSNandor Licker   // Atomic types.
367950b70dcSNandor Licker   if (auto *AT = Ty->getAs<AtomicType>()) {
368950b70dcSNandor Licker     const Type *InnerTy = AT->getValueType().getTypePtr();
369950b70dcSNandor Licker     return createDescriptor(D, InnerTy, IsConst, IsTemporary, IsMutable);
370950b70dcSNandor Licker   }
371950b70dcSNandor Licker 
372950b70dcSNandor Licker   // Complex types - represented as arrays of elements.
373950b70dcSNandor Licker   if (auto *CT = Ty->getAs<ComplexType>()) {
374950b70dcSNandor Licker     PrimType ElemTy = *Ctx.classify(CT->getElementType());
375950b70dcSNandor Licker     return allocateDescriptor(D, ElemTy, 2, IsConst, IsTemporary, IsMutable);
376950b70dcSNandor Licker   }
377950b70dcSNandor Licker 
378950b70dcSNandor Licker   return nullptr;
379950b70dcSNandor Licker }
380