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