1a7dea167SDimitry Andric //===--- ByteCodeExprGen.cpp - Code generator for expressions ---*- C++ -*-===//
2a7dea167SDimitry Andric //
3a7dea167SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4a7dea167SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5a7dea167SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6a7dea167SDimitry Andric //
7a7dea167SDimitry Andric //===----------------------------------------------------------------------===//
8a7dea167SDimitry Andric 
9a7dea167SDimitry Andric #include "ByteCodeExprGen.h"
10a7dea167SDimitry Andric #include "ByteCodeEmitter.h"
11a7dea167SDimitry Andric #include "ByteCodeGenError.h"
12bdd1243dSDimitry Andric #include "ByteCodeStmtGen.h"
13a7dea167SDimitry Andric #include "Context.h"
14a7dea167SDimitry Andric #include "Function.h"
15a7dea167SDimitry Andric #include "PrimType.h"
16a7dea167SDimitry Andric #include "Program.h"
17a7dea167SDimitry Andric #include "State.h"
18a7dea167SDimitry Andric 
19a7dea167SDimitry Andric using namespace clang;
20a7dea167SDimitry Andric using namespace clang::interp;
21a7dea167SDimitry Andric 
22a7dea167SDimitry Andric using APSInt = llvm::APSInt;
23a7dea167SDimitry Andric 
24a7dea167SDimitry Andric namespace clang {
25a7dea167SDimitry Andric namespace interp {
26a7dea167SDimitry Andric 
27a7dea167SDimitry Andric /// Scope used to handle temporaries in toplevel variable declarations.
28a7dea167SDimitry Andric template <class Emitter> class DeclScope final : public LocalScope<Emitter> {
29a7dea167SDimitry Andric public:
30a7dea167SDimitry Andric   DeclScope(ByteCodeExprGen<Emitter> *Ctx, const VarDecl *VD)
31a7dea167SDimitry Andric       : LocalScope<Emitter>(Ctx), Scope(Ctx->P, VD) {}
32a7dea167SDimitry Andric 
33a7dea167SDimitry Andric   void addExtended(const Scope::Local &Local) override {
34a7dea167SDimitry Andric     return this->addLocal(Local);
35a7dea167SDimitry Andric   }
36a7dea167SDimitry Andric 
37a7dea167SDimitry Andric private:
38a7dea167SDimitry Andric   Program::DeclScope Scope;
39a7dea167SDimitry Andric };
40a7dea167SDimitry Andric 
41a7dea167SDimitry Andric /// Scope used to handle initialization methods.
42a7dea167SDimitry Andric template <class Emitter> class OptionScope {
43a7dea167SDimitry Andric public:
44a7dea167SDimitry Andric   /// Root constructor, compiling or discarding primitives.
45a7dea167SDimitry Andric   OptionScope(ByteCodeExprGen<Emitter> *Ctx, bool NewDiscardResult)
46bdd1243dSDimitry Andric       : Ctx(Ctx), OldDiscardResult(Ctx->DiscardResult) {
47a7dea167SDimitry Andric     Ctx->DiscardResult = NewDiscardResult;
48a7dea167SDimitry Andric   }
49a7dea167SDimitry Andric 
50bdd1243dSDimitry Andric   ~OptionScope() { Ctx->DiscardResult = OldDiscardResult; }
51a7dea167SDimitry Andric 
52a7dea167SDimitry Andric private:
53a7dea167SDimitry Andric   /// Parent context.
54a7dea167SDimitry Andric   ByteCodeExprGen<Emitter> *Ctx;
55a7dea167SDimitry Andric   /// Old discard flag to restore.
56a7dea167SDimitry Andric   bool OldDiscardResult;
57a7dea167SDimitry Andric };
58a7dea167SDimitry Andric 
59a7dea167SDimitry Andric } // namespace interp
60a7dea167SDimitry Andric } // namespace clang
61a7dea167SDimitry Andric 
62a7dea167SDimitry Andric template <class Emitter>
63a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCastExpr(const CastExpr *CE) {
64a7dea167SDimitry Andric   auto *SubExpr = CE->getSubExpr();
65a7dea167SDimitry Andric   switch (CE->getCastKind()) {
66a7dea167SDimitry Andric 
67a7dea167SDimitry Andric   case CK_LValueToRValue: {
68a7dea167SDimitry Andric     return dereference(
69a7dea167SDimitry Andric         CE->getSubExpr(), DerefKind::Read,
70a7dea167SDimitry Andric         [](PrimType) {
71a7dea167SDimitry Andric           // Value loaded - nothing to do here.
72a7dea167SDimitry Andric           return true;
73a7dea167SDimitry Andric         },
74a7dea167SDimitry Andric         [this, CE](PrimType T) {
75a7dea167SDimitry Andric           // Pointer on stack - dereference it.
76a7dea167SDimitry Andric           if (!this->emitLoadPop(T, CE))
77a7dea167SDimitry Andric             return false;
78a7dea167SDimitry Andric           return DiscardResult ? this->emitPop(T, CE) : true;
79a7dea167SDimitry Andric         });
80a7dea167SDimitry Andric   }
81a7dea167SDimitry Andric 
82bdd1243dSDimitry Andric   case CK_UncheckedDerivedToBase:
83bdd1243dSDimitry Andric   case CK_DerivedToBase: {
84bdd1243dSDimitry Andric     if (!this->visit(SubExpr))
85bdd1243dSDimitry Andric       return false;
86bdd1243dSDimitry Andric 
87bdd1243dSDimitry Andric     const CXXRecordDecl *FromDecl = getRecordDecl(SubExpr);
88bdd1243dSDimitry Andric     assert(FromDecl);
89bdd1243dSDimitry Andric     const CXXRecordDecl *ToDecl = getRecordDecl(CE);
90bdd1243dSDimitry Andric     assert(ToDecl);
91bdd1243dSDimitry Andric     const Record *R = getRecord(FromDecl);
92bdd1243dSDimitry Andric     const Record::Base *ToBase = R->getBase(ToDecl);
93bdd1243dSDimitry Andric     assert(ToBase);
94bdd1243dSDimitry Andric 
95bdd1243dSDimitry Andric     return this->emitGetPtrBase(ToBase->Offset, CE);
96bdd1243dSDimitry Andric   }
97bdd1243dSDimitry Andric 
98a7dea167SDimitry Andric   case CK_ArrayToPointerDecay:
99a7dea167SDimitry Andric   case CK_AtomicToNonAtomic:
100a7dea167SDimitry Andric   case CK_ConstructorConversion:
101a7dea167SDimitry Andric   case CK_FunctionToPointerDecay:
102a7dea167SDimitry Andric   case CK_NonAtomicToAtomic:
103a7dea167SDimitry Andric   case CK_NoOp:
104a7dea167SDimitry Andric   case CK_UserDefinedConversion:
105bdd1243dSDimitry Andric   case CK_NullToPointer:
106bdd1243dSDimitry Andric     return this->visit(SubExpr);
107bdd1243dSDimitry Andric 
108bdd1243dSDimitry Andric   case CK_IntegralToBoolean:
109bdd1243dSDimitry Andric   case CK_IntegralCast: {
110bdd1243dSDimitry Andric     std::optional<PrimType> FromT = classify(SubExpr->getType());
111bdd1243dSDimitry Andric     std::optional<PrimType> ToT = classify(CE->getType());
112bdd1243dSDimitry Andric     if (!FromT || !ToT)
113bdd1243dSDimitry Andric       return false;
114bdd1243dSDimitry Andric 
115bdd1243dSDimitry Andric     if (!this->visit(SubExpr))
116bdd1243dSDimitry Andric       return false;
117bdd1243dSDimitry Andric 
118bdd1243dSDimitry Andric     // TODO: Emit this only if FromT != ToT.
119bdd1243dSDimitry Andric     return this->emitCast(*FromT, *ToT, CE);
120bdd1243dSDimitry Andric   }
121a7dea167SDimitry Andric 
122a7dea167SDimitry Andric   case CK_ToVoid:
123a7dea167SDimitry Andric     return discard(SubExpr);
124a7dea167SDimitry Andric 
125bdd1243dSDimitry Andric   default:
126bdd1243dSDimitry Andric     assert(false && "Cast not implemented");
127a7dea167SDimitry Andric   }
128bdd1243dSDimitry Andric   llvm_unreachable("Unhandled clang::CastKind enum");
129a7dea167SDimitry Andric }
130a7dea167SDimitry Andric 
131a7dea167SDimitry Andric template <class Emitter>
132a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitIntegerLiteral(const IntegerLiteral *LE) {
133a7dea167SDimitry Andric   if (DiscardResult)
134a7dea167SDimitry Andric     return true;
135a7dea167SDimitry Andric 
136bdd1243dSDimitry Andric   return this->emitConst(LE->getValue(), LE);
137a7dea167SDimitry Andric }
138a7dea167SDimitry Andric 
139a7dea167SDimitry Andric template <class Emitter>
140a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitParenExpr(const ParenExpr *PE) {
141bdd1243dSDimitry Andric   return this->visit(PE->getSubExpr());
142a7dea167SDimitry Andric }
143a7dea167SDimitry Andric 
144a7dea167SDimitry Andric template <class Emitter>
145a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitBinaryOperator(const BinaryOperator *BO) {
146a7dea167SDimitry Andric   const Expr *LHS = BO->getLHS();
147a7dea167SDimitry Andric   const Expr *RHS = BO->getRHS();
148a7dea167SDimitry Andric 
149a7dea167SDimitry Andric   // Deal with operations which have composite or void types.
150a7dea167SDimitry Andric   switch (BO->getOpcode()) {
151a7dea167SDimitry Andric   case BO_Comma:
152a7dea167SDimitry Andric     if (!discard(LHS))
153a7dea167SDimitry Andric       return false;
154bdd1243dSDimitry Andric     if (!this->visit(RHS))
155a7dea167SDimitry Andric       return false;
156a7dea167SDimitry Andric     return true;
157a7dea167SDimitry Andric   default:
158a7dea167SDimitry Andric     break;
159a7dea167SDimitry Andric   }
160a7dea167SDimitry Andric 
161a7dea167SDimitry Andric   // Typecheck the args.
162bdd1243dSDimitry Andric   std::optional<PrimType> LT = classify(LHS->getType());
163bdd1243dSDimitry Andric   std::optional<PrimType> RT = classify(RHS->getType());
164bdd1243dSDimitry Andric   std::optional<PrimType> T = classify(BO->getType());
165bdd1243dSDimitry Andric   if (!LT || !RT || !T) {
166a7dea167SDimitry Andric     return this->bail(BO);
167a7dea167SDimitry Andric   }
168a7dea167SDimitry Andric 
169a7dea167SDimitry Andric   auto Discard = [this, T, BO](bool Result) {
170a7dea167SDimitry Andric     if (!Result)
171a7dea167SDimitry Andric       return false;
172a7dea167SDimitry Andric     return DiscardResult ? this->emitPop(*T, BO) : true;
173a7dea167SDimitry Andric   };
174a7dea167SDimitry Andric 
175bdd1243dSDimitry Andric   // Pointer arithmetic special case.
176bdd1243dSDimitry Andric   if (BO->getOpcode() == BO_Add || BO->getOpcode() == BO_Sub) {
177bdd1243dSDimitry Andric     if (*T == PT_Ptr || (*LT == PT_Ptr && *RT == PT_Ptr))
178bdd1243dSDimitry Andric       return this->VisitPointerArithBinOp(BO);
179bdd1243dSDimitry Andric   }
180bdd1243dSDimitry Andric 
181bdd1243dSDimitry Andric   if (!visit(LHS) || !visit(RHS))
182bdd1243dSDimitry Andric     return false;
183bdd1243dSDimitry Andric 
184a7dea167SDimitry Andric   switch (BO->getOpcode()) {
185a7dea167SDimitry Andric   case BO_EQ:
186a7dea167SDimitry Andric     return Discard(this->emitEQ(*LT, BO));
187a7dea167SDimitry Andric   case BO_NE:
188a7dea167SDimitry Andric     return Discard(this->emitNE(*LT, BO));
189a7dea167SDimitry Andric   case BO_LT:
190a7dea167SDimitry Andric     return Discard(this->emitLT(*LT, BO));
191a7dea167SDimitry Andric   case BO_LE:
192a7dea167SDimitry Andric     return Discard(this->emitLE(*LT, BO));
193a7dea167SDimitry Andric   case BO_GT:
194a7dea167SDimitry Andric     return Discard(this->emitGT(*LT, BO));
195a7dea167SDimitry Andric   case BO_GE:
196a7dea167SDimitry Andric     return Discard(this->emitGE(*LT, BO));
197a7dea167SDimitry Andric   case BO_Sub:
198a7dea167SDimitry Andric     return Discard(this->emitSub(*T, BO));
199a7dea167SDimitry Andric   case BO_Add:
200a7dea167SDimitry Andric     return Discard(this->emitAdd(*T, BO));
201a7dea167SDimitry Andric   case BO_Mul:
202a7dea167SDimitry Andric     return Discard(this->emitMul(*T, BO));
203bdd1243dSDimitry Andric   case BO_Rem:
204bdd1243dSDimitry Andric     return Discard(this->emitRem(*T, BO));
205bdd1243dSDimitry Andric   case BO_Div:
206bdd1243dSDimitry Andric     return Discard(this->emitDiv(*T, BO));
207bdd1243dSDimitry Andric   case BO_Assign:
208bdd1243dSDimitry Andric     if (DiscardResult)
209bdd1243dSDimitry Andric       return this->emitStorePop(*T, BO);
210bdd1243dSDimitry Andric     return this->emitStore(*T, BO);
211bdd1243dSDimitry Andric   case BO_And:
212bdd1243dSDimitry Andric     return Discard(this->emitBitAnd(*T, BO));
213bdd1243dSDimitry Andric   case BO_Or:
214bdd1243dSDimitry Andric     return Discard(this->emitBitOr(*T, BO));
215bdd1243dSDimitry Andric   case BO_Shl:
216bdd1243dSDimitry Andric     return Discard(this->emitShl(*LT, *RT, BO));
217bdd1243dSDimitry Andric   case BO_Shr:
218bdd1243dSDimitry Andric     return Discard(this->emitShr(*LT, *RT, BO));
219bdd1243dSDimitry Andric   case BO_Xor:
220bdd1243dSDimitry Andric     return Discard(this->emitBitXor(*T, BO));
221bdd1243dSDimitry Andric   case BO_LAnd:
222bdd1243dSDimitry Andric   case BO_LOr:
223a7dea167SDimitry Andric   default:
224a7dea167SDimitry Andric     return this->bail(BO);
225a7dea167SDimitry Andric   }
226bdd1243dSDimitry Andric 
227bdd1243dSDimitry Andric   llvm_unreachable("Unhandled binary op");
228a7dea167SDimitry Andric }
229a7dea167SDimitry Andric 
230bdd1243dSDimitry Andric /// Perform addition/subtraction of a pointer and an integer or
231bdd1243dSDimitry Andric /// subtraction of two pointers.
232bdd1243dSDimitry Andric template <class Emitter>
233bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitPointerArithBinOp(const BinaryOperator *E) {
234bdd1243dSDimitry Andric   BinaryOperatorKind Op = E->getOpcode();
235bdd1243dSDimitry Andric   const Expr *LHS = E->getLHS();
236bdd1243dSDimitry Andric   const Expr *RHS = E->getRHS();
237bdd1243dSDimitry Andric 
238bdd1243dSDimitry Andric   if ((Op != BO_Add && Op != BO_Sub) ||
239bdd1243dSDimitry Andric       (!LHS->getType()->isPointerType() && !RHS->getType()->isPointerType()))
240bdd1243dSDimitry Andric     return false;
241bdd1243dSDimitry Andric 
242bdd1243dSDimitry Andric   std::optional<PrimType> LT = classify(LHS);
243bdd1243dSDimitry Andric   std::optional<PrimType> RT = classify(RHS);
244bdd1243dSDimitry Andric 
245bdd1243dSDimitry Andric   if (!LT || !RT)
246bdd1243dSDimitry Andric     return false;
247bdd1243dSDimitry Andric 
248bdd1243dSDimitry Andric   if (LHS->getType()->isPointerType() && RHS->getType()->isPointerType()) {
249bdd1243dSDimitry Andric     if (Op != BO_Sub)
250bdd1243dSDimitry Andric       return false;
251bdd1243dSDimitry Andric 
252bdd1243dSDimitry Andric     assert(E->getType()->isIntegerType());
253bdd1243dSDimitry Andric     if (!visit(RHS) || !visit(LHS))
254bdd1243dSDimitry Andric       return false;
255bdd1243dSDimitry Andric 
256bdd1243dSDimitry Andric     return this->emitSubPtr(classifyPrim(E->getType()), E);
257bdd1243dSDimitry Andric   }
258bdd1243dSDimitry Andric 
259bdd1243dSDimitry Andric   PrimType OffsetType;
260bdd1243dSDimitry Andric   if (LHS->getType()->isIntegerType()) {
261bdd1243dSDimitry Andric     if (!visit(RHS) || !visit(LHS))
262bdd1243dSDimitry Andric       return false;
263bdd1243dSDimitry Andric     OffsetType = *LT;
264bdd1243dSDimitry Andric   } else if (RHS->getType()->isIntegerType()) {
265bdd1243dSDimitry Andric     if (!visit(LHS) || !visit(RHS))
266bdd1243dSDimitry Andric       return false;
267bdd1243dSDimitry Andric     OffsetType = *RT;
268bdd1243dSDimitry Andric   } else {
269bdd1243dSDimitry Andric     return false;
270bdd1243dSDimitry Andric   }
271bdd1243dSDimitry Andric 
272bdd1243dSDimitry Andric   if (Op == BO_Add)
273bdd1243dSDimitry Andric     return this->emitAddOffset(OffsetType, E);
274bdd1243dSDimitry Andric   else if (Op == BO_Sub)
275bdd1243dSDimitry Andric     return this->emitSubOffset(OffsetType, E);
276bdd1243dSDimitry Andric 
277bdd1243dSDimitry Andric   return this->bail(E);
278a7dea167SDimitry Andric }
279a7dea167SDimitry Andric 
280a7dea167SDimitry Andric template <class Emitter>
281bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E) {
282bdd1243dSDimitry Andric   if (std::optional<PrimType> T = classify(E))
283bdd1243dSDimitry Andric     return this->emitZero(*T, E);
284bdd1243dSDimitry Andric 
285bdd1243dSDimitry Andric   return false;
286bdd1243dSDimitry Andric }
287bdd1243dSDimitry Andric 
288bdd1243dSDimitry Andric template <class Emitter>
289bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitArraySubscriptExpr(
290bdd1243dSDimitry Andric     const ArraySubscriptExpr *E) {
291bdd1243dSDimitry Andric   const Expr *Base = E->getBase();
292bdd1243dSDimitry Andric   const Expr *Index = E->getIdx();
293bdd1243dSDimitry Andric   PrimType IndexT = classifyPrim(Index->getType());
294bdd1243dSDimitry Andric 
295bdd1243dSDimitry Andric   // Take pointer of LHS, add offset from RHS, narrow result.
296bdd1243dSDimitry Andric   // What's left on the stack after this is a pointer.
297bdd1243dSDimitry Andric   if (!this->visit(Base))
298bdd1243dSDimitry Andric     return false;
299bdd1243dSDimitry Andric 
300bdd1243dSDimitry Andric   if (!this->visit(Index))
301bdd1243dSDimitry Andric     return false;
302bdd1243dSDimitry Andric 
303bdd1243dSDimitry Andric   if (!this->emitAddOffset(IndexT, E))
304bdd1243dSDimitry Andric     return false;
305bdd1243dSDimitry Andric 
306bdd1243dSDimitry Andric   if (!this->emitNarrowPtr(E))
307bdd1243dSDimitry Andric     return false;
308bdd1243dSDimitry Andric 
309bdd1243dSDimitry Andric   if (DiscardResult)
310bdd1243dSDimitry Andric     return this->emitPopPtr(E);
311bdd1243dSDimitry Andric 
312bdd1243dSDimitry Andric   return true;
313bdd1243dSDimitry Andric }
314bdd1243dSDimitry Andric 
315bdd1243dSDimitry Andric template <class Emitter>
316bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitInitListExpr(const InitListExpr *E) {
317bdd1243dSDimitry Andric   for (const Expr *Init : E->inits()) {
318bdd1243dSDimitry Andric     if (!this->visit(Init))
319bdd1243dSDimitry Andric       return false;
320bdd1243dSDimitry Andric   }
321bdd1243dSDimitry Andric   return true;
322bdd1243dSDimitry Andric }
323bdd1243dSDimitry Andric 
324bdd1243dSDimitry Andric template <class Emitter>
325bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitSubstNonTypeTemplateParmExpr(
326bdd1243dSDimitry Andric     const SubstNonTypeTemplateParmExpr *E) {
327bdd1243dSDimitry Andric   return this->visit(E->getReplacement());
328bdd1243dSDimitry Andric }
329bdd1243dSDimitry Andric 
330bdd1243dSDimitry Andric template <class Emitter>
331bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitConstantExpr(const ConstantExpr *E) {
332bdd1243dSDimitry Andric   // TODO: Check if the ConstantExpr already has a value set and if so,
333bdd1243dSDimitry Andric   //   use that instead of evaluating it again.
334bdd1243dSDimitry Andric   return this->visit(E->getSubExpr());
335bdd1243dSDimitry Andric }
336bdd1243dSDimitry Andric 
337bdd1243dSDimitry Andric static CharUnits AlignOfType(QualType T, const ASTContext &ASTCtx,
338bdd1243dSDimitry Andric                              UnaryExprOrTypeTrait Kind) {
339bdd1243dSDimitry Andric   bool AlignOfReturnsPreferred =
340bdd1243dSDimitry Andric       ASTCtx.getLangOpts().getClangABICompat() <= LangOptions::ClangABI::Ver7;
341bdd1243dSDimitry Andric 
342bdd1243dSDimitry Andric   // C++ [expr.alignof]p3:
343bdd1243dSDimitry Andric   //     When alignof is applied to a reference type, the result is the
344bdd1243dSDimitry Andric   //     alignment of the referenced type.
345bdd1243dSDimitry Andric   if (const auto *Ref = T->getAs<ReferenceType>())
346bdd1243dSDimitry Andric     T = Ref->getPointeeType();
347bdd1243dSDimitry Andric 
348bdd1243dSDimitry Andric   // __alignof is defined to return the preferred alignment.
349bdd1243dSDimitry Andric   // Before 8, clang returned the preferred alignment for alignof and
350bdd1243dSDimitry Andric   // _Alignof as well.
351bdd1243dSDimitry Andric   if (Kind == UETT_PreferredAlignOf || AlignOfReturnsPreferred)
352bdd1243dSDimitry Andric     return ASTCtx.toCharUnitsFromBits(ASTCtx.getPreferredTypeAlign(T));
353bdd1243dSDimitry Andric 
354bdd1243dSDimitry Andric   return ASTCtx.getTypeAlignInChars(T);
355bdd1243dSDimitry Andric }
356bdd1243dSDimitry Andric 
357bdd1243dSDimitry Andric template <class Emitter>
358bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitUnaryExprOrTypeTraitExpr(
359bdd1243dSDimitry Andric     const UnaryExprOrTypeTraitExpr *E) {
360bdd1243dSDimitry Andric   UnaryExprOrTypeTrait Kind = E->getKind();
361bdd1243dSDimitry Andric   ASTContext &ASTCtx = Ctx.getASTContext();
362bdd1243dSDimitry Andric 
363bdd1243dSDimitry Andric   if (Kind == UETT_SizeOf) {
364bdd1243dSDimitry Andric     QualType ArgType = E->getTypeOfArgument();
365bdd1243dSDimitry Andric     CharUnits Size;
366bdd1243dSDimitry Andric     if (ArgType->isVoidType() || ArgType->isFunctionType())
367bdd1243dSDimitry Andric       Size = CharUnits::One();
368bdd1243dSDimitry Andric     else {
369bdd1243dSDimitry Andric       if (ArgType->isDependentType() || !ArgType->isConstantSizeType())
370bdd1243dSDimitry Andric         return false;
371bdd1243dSDimitry Andric 
372bdd1243dSDimitry Andric       Size = ASTCtx.getTypeSizeInChars(ArgType);
373bdd1243dSDimitry Andric     }
374bdd1243dSDimitry Andric 
375bdd1243dSDimitry Andric     return this->emitConst(Size.getQuantity(), E);
376bdd1243dSDimitry Andric   }
377bdd1243dSDimitry Andric 
378bdd1243dSDimitry Andric   if (Kind == UETT_AlignOf || Kind == UETT_PreferredAlignOf) {
379bdd1243dSDimitry Andric     CharUnits Size;
380bdd1243dSDimitry Andric 
381bdd1243dSDimitry Andric     if (E->isArgumentType()) {
382bdd1243dSDimitry Andric       QualType ArgType = E->getTypeOfArgument();
383bdd1243dSDimitry Andric 
384bdd1243dSDimitry Andric       Size = AlignOfType(ArgType, ASTCtx, Kind);
385bdd1243dSDimitry Andric     } else {
386bdd1243dSDimitry Andric       // Argument is an expression, not a type.
387bdd1243dSDimitry Andric       const Expr *Arg = E->getArgumentExpr()->IgnoreParens();
388bdd1243dSDimitry Andric 
389bdd1243dSDimitry Andric       // The kinds of expressions that we have special-case logic here for
390bdd1243dSDimitry Andric       // should be kept up to date with the special checks for those
391bdd1243dSDimitry Andric       // expressions in Sema.
392bdd1243dSDimitry Andric 
393bdd1243dSDimitry Andric       // alignof decl is always accepted, even if it doesn't make sense: we
394bdd1243dSDimitry Andric       // default to 1 in those cases.
395bdd1243dSDimitry Andric       if (const auto *DRE = dyn_cast<DeclRefExpr>(Arg))
396bdd1243dSDimitry Andric         Size = ASTCtx.getDeclAlign(DRE->getDecl(),
397bdd1243dSDimitry Andric                                    /*RefAsPointee*/ true);
398bdd1243dSDimitry Andric       else if (const auto *ME = dyn_cast<MemberExpr>(Arg))
399bdd1243dSDimitry Andric         Size = ASTCtx.getDeclAlign(ME->getMemberDecl(),
400bdd1243dSDimitry Andric                                    /*RefAsPointee*/ true);
401bdd1243dSDimitry Andric       else
402bdd1243dSDimitry Andric         Size = AlignOfType(Arg->getType(), ASTCtx, Kind);
403bdd1243dSDimitry Andric     }
404bdd1243dSDimitry Andric 
405bdd1243dSDimitry Andric     return this->emitConst(Size.getQuantity(), E);
406bdd1243dSDimitry Andric   }
407bdd1243dSDimitry Andric 
408bdd1243dSDimitry Andric   return false;
409bdd1243dSDimitry Andric }
410bdd1243dSDimitry Andric 
411bdd1243dSDimitry Andric template <class Emitter>
412bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitMemberExpr(const MemberExpr *E) {
413bdd1243dSDimitry Andric   if (DiscardResult)
414bdd1243dSDimitry Andric     return true;
415bdd1243dSDimitry Andric 
416bdd1243dSDimitry Andric   // 'Base.Member'
417bdd1243dSDimitry Andric   const Expr *Base = E->getBase();
418bdd1243dSDimitry Andric   const ValueDecl *Member = E->getMemberDecl();
419bdd1243dSDimitry Andric 
420bdd1243dSDimitry Andric   if (!this->visit(Base))
421bdd1243dSDimitry Andric     return false;
422bdd1243dSDimitry Andric 
423bdd1243dSDimitry Andric   // Base above gives us a pointer on the stack.
424bdd1243dSDimitry Andric   // TODO: Implement non-FieldDecl members.
425bdd1243dSDimitry Andric   if (const auto *FD = dyn_cast<FieldDecl>(Member)) {
426bdd1243dSDimitry Andric     const RecordDecl *RD = FD->getParent();
427bdd1243dSDimitry Andric     const Record *R = getRecord(RD);
428bdd1243dSDimitry Andric     const Record::Field *F = R->getField(FD);
429bdd1243dSDimitry Andric     // Leave a pointer to the field on the stack.
430bdd1243dSDimitry Andric     if (F->Decl->getType()->isReferenceType())
431bdd1243dSDimitry Andric       return this->emitGetFieldPop(PT_Ptr, F->Offset, E);
432bdd1243dSDimitry Andric     return this->emitGetPtrField(F->Offset, E);
433bdd1243dSDimitry Andric   }
434bdd1243dSDimitry Andric 
435bdd1243dSDimitry Andric   return false;
436bdd1243dSDimitry Andric }
437bdd1243dSDimitry Andric 
438bdd1243dSDimitry Andric template <class Emitter>
439bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitArrayInitIndexExpr(
440bdd1243dSDimitry Andric     const ArrayInitIndexExpr *E) {
441bdd1243dSDimitry Andric   // ArrayIndex might not be set if a ArrayInitIndexExpr is being evaluated
442bdd1243dSDimitry Andric   // stand-alone, e.g. via EvaluateAsInt().
443bdd1243dSDimitry Andric   if (!ArrayIndex)
444bdd1243dSDimitry Andric     return false;
445bdd1243dSDimitry Andric   return this->emitConst(*ArrayIndex, E);
446bdd1243dSDimitry Andric }
447bdd1243dSDimitry Andric 
448bdd1243dSDimitry Andric template <class Emitter>
449bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitOpaqueValueExpr(const OpaqueValueExpr *E) {
450bdd1243dSDimitry Andric   return this->visit(E->getSourceExpr());
451bdd1243dSDimitry Andric }
452bdd1243dSDimitry Andric 
453bdd1243dSDimitry Andric template <class Emitter>
454bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitAbstractConditionalOperator(
455bdd1243dSDimitry Andric     const AbstractConditionalOperator *E) {
456bdd1243dSDimitry Andric   const Expr *Condition = E->getCond();
457bdd1243dSDimitry Andric   const Expr *TrueExpr = E->getTrueExpr();
458bdd1243dSDimitry Andric   const Expr *FalseExpr = E->getFalseExpr();
459bdd1243dSDimitry Andric 
460bdd1243dSDimitry Andric   LabelTy LabelEnd = this->getLabel();   // Label after the operator.
461bdd1243dSDimitry Andric   LabelTy LabelFalse = this->getLabel(); // Label for the false expr.
462bdd1243dSDimitry Andric 
463bdd1243dSDimitry Andric   if (!this->visit(Condition))
464bdd1243dSDimitry Andric     return false;
465bdd1243dSDimitry Andric   if (!this->jumpFalse(LabelFalse))
466bdd1243dSDimitry Andric     return false;
467bdd1243dSDimitry Andric 
468bdd1243dSDimitry Andric   if (!this->visit(TrueExpr))
469bdd1243dSDimitry Andric     return false;
470bdd1243dSDimitry Andric   if (!this->jump(LabelEnd))
471bdd1243dSDimitry Andric     return false;
472bdd1243dSDimitry Andric 
473bdd1243dSDimitry Andric   this->emitLabel(LabelFalse);
474bdd1243dSDimitry Andric 
475bdd1243dSDimitry Andric   if (!this->visit(FalseExpr))
476bdd1243dSDimitry Andric     return false;
477bdd1243dSDimitry Andric 
478bdd1243dSDimitry Andric   this->fallthrough(LabelEnd);
479bdd1243dSDimitry Andric   this->emitLabel(LabelEnd);
480bdd1243dSDimitry Andric 
481bdd1243dSDimitry Andric   return true;
482bdd1243dSDimitry Andric }
483bdd1243dSDimitry Andric 
484bdd1243dSDimitry Andric template <class Emitter>
485bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitStringLiteral(const StringLiteral *E) {
486bdd1243dSDimitry Andric   unsigned StringIndex = P.createGlobalString(E);
487bdd1243dSDimitry Andric   return this->emitGetPtrGlobal(StringIndex, E);
488bdd1243dSDimitry Andric }
489bdd1243dSDimitry Andric 
490bdd1243dSDimitry Andric template <class Emitter>
491bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCharacterLiteral(
492bdd1243dSDimitry Andric     const CharacterLiteral *E) {
493bdd1243dSDimitry Andric   return this->emitConst(E->getValue(), E);
494bdd1243dSDimitry Andric }
495bdd1243dSDimitry Andric 
496bdd1243dSDimitry Andric template <class Emitter>
497bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCompoundAssignOperator(
498bdd1243dSDimitry Andric     const CompoundAssignOperator *E) {
499bdd1243dSDimitry Andric   const Expr *LHS = E->getLHS();
500bdd1243dSDimitry Andric   const Expr *RHS = E->getRHS();
501bdd1243dSDimitry Andric   std::optional<PrimType> LT = classify(E->getLHS()->getType());
502bdd1243dSDimitry Andric   std::optional<PrimType> RT = classify(E->getRHS()->getType());
503bdd1243dSDimitry Andric 
504bdd1243dSDimitry Andric   if (!LT || !RT)
505bdd1243dSDimitry Andric     return false;
506bdd1243dSDimitry Andric 
507bdd1243dSDimitry Andric   assert(!E->getType()->isPointerType() &&
508bdd1243dSDimitry Andric          "Support pointer arithmethic in compound assignment operators");
509bdd1243dSDimitry Andric 
510bdd1243dSDimitry Andric   // Get LHS pointer, load its value and get RHS value.
511bdd1243dSDimitry Andric   if (!visit(LHS))
512bdd1243dSDimitry Andric     return false;
513bdd1243dSDimitry Andric   if (!this->emitLoad(*LT, E))
514bdd1243dSDimitry Andric     return false;
515bdd1243dSDimitry Andric   if (!visit(RHS))
516bdd1243dSDimitry Andric     return false;
517bdd1243dSDimitry Andric 
518bdd1243dSDimitry Andric   // Perform operation.
519bdd1243dSDimitry Andric   switch (E->getOpcode()) {
520bdd1243dSDimitry Andric   case BO_AddAssign:
521bdd1243dSDimitry Andric     if (!this->emitAdd(*LT, E))
522bdd1243dSDimitry Andric       return false;
523bdd1243dSDimitry Andric     break;
524bdd1243dSDimitry Andric   case BO_SubAssign:
525bdd1243dSDimitry Andric     if (!this->emitSub(*LT, E))
526bdd1243dSDimitry Andric       return false;
527bdd1243dSDimitry Andric     break;
528bdd1243dSDimitry Andric 
529bdd1243dSDimitry Andric   case BO_MulAssign:
530bdd1243dSDimitry Andric   case BO_DivAssign:
531bdd1243dSDimitry Andric   case BO_RemAssign:
532bdd1243dSDimitry Andric   case BO_ShlAssign:
533bdd1243dSDimitry Andric     if (!this->emitShl(*LT, *RT, E))
534bdd1243dSDimitry Andric       return false;
535bdd1243dSDimitry Andric     break;
536bdd1243dSDimitry Andric   case BO_ShrAssign:
537bdd1243dSDimitry Andric     if (!this->emitShr(*LT, *RT, E))
538bdd1243dSDimitry Andric       return false;
539bdd1243dSDimitry Andric     break;
540bdd1243dSDimitry Andric   case BO_AndAssign:
541bdd1243dSDimitry Andric   case BO_XorAssign:
542bdd1243dSDimitry Andric   case BO_OrAssign:
543bdd1243dSDimitry Andric   default:
544bdd1243dSDimitry Andric     llvm_unreachable("Unimplemented compound assign operator");
545bdd1243dSDimitry Andric   }
546bdd1243dSDimitry Andric 
547bdd1243dSDimitry Andric   // And store the result in LHS.
548bdd1243dSDimitry Andric   if (DiscardResult)
549bdd1243dSDimitry Andric     return this->emitStorePop(*LT, E);
550bdd1243dSDimitry Andric   return this->emitStore(*LT, E);
551bdd1243dSDimitry Andric }
552bdd1243dSDimitry Andric 
553bdd1243dSDimitry Andric template <class Emitter> bool ByteCodeExprGen<Emitter>::discard(const Expr *E) {
55404eeddc0SDimitry Andric   OptionScope<Emitter> Scope(this, /*NewDiscardResult=*/true);
555a7dea167SDimitry Andric   return this->Visit(E);
556a7dea167SDimitry Andric }
557a7dea167SDimitry Andric 
558a7dea167SDimitry Andric template <class Emitter>
559a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::visit(const Expr *E) {
56004eeddc0SDimitry Andric   OptionScope<Emitter> Scope(this, /*NewDiscardResult=*/false);
561a7dea167SDimitry Andric   return this->Visit(E);
562a7dea167SDimitry Andric }
563a7dea167SDimitry Andric 
564a7dea167SDimitry Andric template <class Emitter>
565a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::visitBool(const Expr *E) {
566bdd1243dSDimitry Andric   if (std::optional<PrimType> T = classify(E->getType())) {
567a7dea167SDimitry Andric     return visit(E);
568a7dea167SDimitry Andric   } else {
569a7dea167SDimitry Andric     return this->bail(E);
570a7dea167SDimitry Andric   }
571a7dea167SDimitry Andric }
572a7dea167SDimitry Andric 
573a7dea167SDimitry Andric template <class Emitter>
574a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::visitZeroInitializer(PrimType T, const Expr *E) {
575a7dea167SDimitry Andric   switch (T) {
576a7dea167SDimitry Andric   case PT_Bool:
577a7dea167SDimitry Andric     return this->emitZeroBool(E);
578a7dea167SDimitry Andric   case PT_Sint8:
579a7dea167SDimitry Andric     return this->emitZeroSint8(E);
580a7dea167SDimitry Andric   case PT_Uint8:
581a7dea167SDimitry Andric     return this->emitZeroUint8(E);
582a7dea167SDimitry Andric   case PT_Sint16:
583a7dea167SDimitry Andric     return this->emitZeroSint16(E);
584a7dea167SDimitry Andric   case PT_Uint16:
585a7dea167SDimitry Andric     return this->emitZeroUint16(E);
586a7dea167SDimitry Andric   case PT_Sint32:
587a7dea167SDimitry Andric     return this->emitZeroSint32(E);
588a7dea167SDimitry Andric   case PT_Uint32:
589a7dea167SDimitry Andric     return this->emitZeroUint32(E);
590a7dea167SDimitry Andric   case PT_Sint64:
591a7dea167SDimitry Andric     return this->emitZeroSint64(E);
592a7dea167SDimitry Andric   case PT_Uint64:
593a7dea167SDimitry Andric     return this->emitZeroUint64(E);
594a7dea167SDimitry Andric   case PT_Ptr:
595a7dea167SDimitry Andric     return this->emitNullPtr(E);
596a7dea167SDimitry Andric   }
597a7dea167SDimitry Andric   llvm_unreachable("unknown primitive type");
598a7dea167SDimitry Andric }
599a7dea167SDimitry Andric 
600a7dea167SDimitry Andric template <class Emitter>
601a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::dereference(
602a7dea167SDimitry Andric     const Expr *LV, DerefKind AK, llvm::function_ref<bool(PrimType)> Direct,
603a7dea167SDimitry Andric     llvm::function_ref<bool(PrimType)> Indirect) {
604bdd1243dSDimitry Andric   if (std::optional<PrimType> T = classify(LV->getType())) {
605a7dea167SDimitry Andric     if (!LV->refersToBitField()) {
606a7dea167SDimitry Andric       // Only primitive, non bit-field types can be dereferenced directly.
607a7dea167SDimitry Andric       if (auto *DE = dyn_cast<DeclRefExpr>(LV)) {
608a7dea167SDimitry Andric         if (!DE->getDecl()->getType()->isReferenceType()) {
609a7dea167SDimitry Andric           if (auto *PD = dyn_cast<ParmVarDecl>(DE->getDecl()))
610a7dea167SDimitry Andric             return dereferenceParam(LV, *T, PD, AK, Direct, Indirect);
611a7dea167SDimitry Andric           if (auto *VD = dyn_cast<VarDecl>(DE->getDecl()))
612a7dea167SDimitry Andric             return dereferenceVar(LV, *T, VD, AK, Direct, Indirect);
613a7dea167SDimitry Andric         }
614a7dea167SDimitry Andric       }
615a7dea167SDimitry Andric     }
616a7dea167SDimitry Andric 
617a7dea167SDimitry Andric     if (!visit(LV))
618a7dea167SDimitry Andric       return false;
619a7dea167SDimitry Andric     return Indirect(*T);
620a7dea167SDimitry Andric   }
621a7dea167SDimitry Andric 
622a7dea167SDimitry Andric   return false;
623a7dea167SDimitry Andric }
624a7dea167SDimitry Andric 
625a7dea167SDimitry Andric template <class Emitter>
626a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::dereferenceParam(
627a7dea167SDimitry Andric     const Expr *LV, PrimType T, const ParmVarDecl *PD, DerefKind AK,
628a7dea167SDimitry Andric     llvm::function_ref<bool(PrimType)> Direct,
629a7dea167SDimitry Andric     llvm::function_ref<bool(PrimType)> Indirect) {
630a7dea167SDimitry Andric   auto It = this->Params.find(PD);
631a7dea167SDimitry Andric   if (It != this->Params.end()) {
632a7dea167SDimitry Andric     unsigned Idx = It->second;
633a7dea167SDimitry Andric     switch (AK) {
634a7dea167SDimitry Andric     case DerefKind::Read:
635a7dea167SDimitry Andric       return DiscardResult ? true : this->emitGetParam(T, Idx, LV);
636a7dea167SDimitry Andric 
637a7dea167SDimitry Andric     case DerefKind::Write:
638a7dea167SDimitry Andric       if (!Direct(T))
639a7dea167SDimitry Andric         return false;
640a7dea167SDimitry Andric       if (!this->emitSetParam(T, Idx, LV))
641a7dea167SDimitry Andric         return false;
642a7dea167SDimitry Andric       return DiscardResult ? true : this->emitGetPtrParam(Idx, LV);
643a7dea167SDimitry Andric 
644a7dea167SDimitry Andric     case DerefKind::ReadWrite:
645a7dea167SDimitry Andric       if (!this->emitGetParam(T, Idx, LV))
646a7dea167SDimitry Andric         return false;
647a7dea167SDimitry Andric       if (!Direct(T))
648a7dea167SDimitry Andric         return false;
649a7dea167SDimitry Andric       if (!this->emitSetParam(T, Idx, LV))
650a7dea167SDimitry Andric         return false;
651a7dea167SDimitry Andric       return DiscardResult ? true : this->emitGetPtrParam(Idx, LV);
652a7dea167SDimitry Andric     }
653a7dea167SDimitry Andric     return true;
654a7dea167SDimitry Andric   }
655a7dea167SDimitry Andric 
656a7dea167SDimitry Andric   // If the param is a pointer, we can dereference a dummy value.
657a7dea167SDimitry Andric   if (!DiscardResult && T == PT_Ptr && AK == DerefKind::Read) {
658a7dea167SDimitry Andric     if (auto Idx = P.getOrCreateDummy(PD))
659a7dea167SDimitry Andric       return this->emitGetPtrGlobal(*Idx, PD);
660a7dea167SDimitry Andric     return false;
661a7dea167SDimitry Andric   }
662a7dea167SDimitry Andric 
663a7dea167SDimitry Andric   // Value cannot be produced - try to emit pointer and do stuff with it.
664a7dea167SDimitry Andric   return visit(LV) && Indirect(T);
665a7dea167SDimitry Andric }
666a7dea167SDimitry Andric 
667a7dea167SDimitry Andric template <class Emitter>
668a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::dereferenceVar(
669a7dea167SDimitry Andric     const Expr *LV, PrimType T, const VarDecl *VD, DerefKind AK,
670a7dea167SDimitry Andric     llvm::function_ref<bool(PrimType)> Direct,
671a7dea167SDimitry Andric     llvm::function_ref<bool(PrimType)> Indirect) {
672a7dea167SDimitry Andric   auto It = Locals.find(VD);
673a7dea167SDimitry Andric   if (It != Locals.end()) {
674a7dea167SDimitry Andric     const auto &L = It->second;
675a7dea167SDimitry Andric     switch (AK) {
676a7dea167SDimitry Andric     case DerefKind::Read:
677a7dea167SDimitry Andric       if (!this->emitGetLocal(T, L.Offset, LV))
678a7dea167SDimitry Andric         return false;
679a7dea167SDimitry Andric       return DiscardResult ? this->emitPop(T, LV) : true;
680a7dea167SDimitry Andric 
681a7dea167SDimitry Andric     case DerefKind::Write:
682a7dea167SDimitry Andric       if (!Direct(T))
683a7dea167SDimitry Andric         return false;
684a7dea167SDimitry Andric       if (!this->emitSetLocal(T, L.Offset, LV))
685a7dea167SDimitry Andric         return false;
686a7dea167SDimitry Andric       return DiscardResult ? true : this->emitGetPtrLocal(L.Offset, LV);
687a7dea167SDimitry Andric 
688a7dea167SDimitry Andric     case DerefKind::ReadWrite:
689a7dea167SDimitry Andric       if (!this->emitGetLocal(T, L.Offset, LV))
690a7dea167SDimitry Andric         return false;
691a7dea167SDimitry Andric       if (!Direct(T))
692a7dea167SDimitry Andric         return false;
693a7dea167SDimitry Andric       if (!this->emitSetLocal(T, L.Offset, LV))
694a7dea167SDimitry Andric         return false;
695a7dea167SDimitry Andric       return DiscardResult ? true : this->emitGetPtrLocal(L.Offset, LV);
696a7dea167SDimitry Andric     }
697bdd1243dSDimitry Andric   } else if (auto Idx = P.getGlobal(VD)) {
698a7dea167SDimitry Andric     switch (AK) {
699a7dea167SDimitry Andric     case DerefKind::Read:
700a7dea167SDimitry Andric       if (!this->emitGetGlobal(T, *Idx, LV))
701a7dea167SDimitry Andric         return false;
702a7dea167SDimitry Andric       return DiscardResult ? this->emitPop(T, LV) : true;
703a7dea167SDimitry Andric 
704a7dea167SDimitry Andric     case DerefKind::Write:
705a7dea167SDimitry Andric       if (!Direct(T))
706a7dea167SDimitry Andric         return false;
707a7dea167SDimitry Andric       if (!this->emitSetGlobal(T, *Idx, LV))
708a7dea167SDimitry Andric         return false;
709a7dea167SDimitry Andric       return DiscardResult ? true : this->emitGetPtrGlobal(*Idx, LV);
710a7dea167SDimitry Andric 
711a7dea167SDimitry Andric     case DerefKind::ReadWrite:
712a7dea167SDimitry Andric       if (!this->emitGetGlobal(T, *Idx, LV))
713a7dea167SDimitry Andric         return false;
714a7dea167SDimitry Andric       if (!Direct(T))
715a7dea167SDimitry Andric         return false;
716a7dea167SDimitry Andric       if (!this->emitSetGlobal(T, *Idx, LV))
717a7dea167SDimitry Andric         return false;
718a7dea167SDimitry Andric       return DiscardResult ? true : this->emitGetPtrGlobal(*Idx, LV);
719a7dea167SDimitry Andric     }
720a7dea167SDimitry Andric   }
721a7dea167SDimitry Andric 
722a7dea167SDimitry Andric   // If the declaration is a constant value, emit it here even
723a7dea167SDimitry Andric   // though the declaration was not evaluated in the current scope.
724a7dea167SDimitry Andric   // The access mode can only be read in this case.
725a7dea167SDimitry Andric   if (!DiscardResult && AK == DerefKind::Read) {
726a7dea167SDimitry Andric     if (VD->hasLocalStorage() && VD->hasInit() && !VD->isConstexpr()) {
727a7dea167SDimitry Andric       QualType VT = VD->getType();
728a7dea167SDimitry Andric       if (VT.isConstQualified() && VT->isFundamentalType())
729bdd1243dSDimitry Andric         return this->visit(VD->getInit());
730a7dea167SDimitry Andric     }
731a7dea167SDimitry Andric   }
732a7dea167SDimitry Andric 
733a7dea167SDimitry Andric   // Value cannot be produced - try to emit pointer.
734a7dea167SDimitry Andric   return visit(LV) && Indirect(T);
735a7dea167SDimitry Andric }
736a7dea167SDimitry Andric 
737a7dea167SDimitry Andric template <class Emitter>
738bdd1243dSDimitry Andric template <typename T>
739bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::emitConst(T Value, const Expr *E) {
740bdd1243dSDimitry Andric   switch (classifyPrim(E->getType())) {
741a7dea167SDimitry Andric   case PT_Sint8:
742bdd1243dSDimitry Andric     return this->emitConstSint8(Value, E);
743a7dea167SDimitry Andric   case PT_Uint8:
744bdd1243dSDimitry Andric     return this->emitConstUint8(Value, E);
745a7dea167SDimitry Andric   case PT_Sint16:
746bdd1243dSDimitry Andric     return this->emitConstSint16(Value, E);
747a7dea167SDimitry Andric   case PT_Uint16:
748bdd1243dSDimitry Andric     return this->emitConstUint16(Value, E);
749a7dea167SDimitry Andric   case PT_Sint32:
750bdd1243dSDimitry Andric     return this->emitConstSint32(Value, E);
751a7dea167SDimitry Andric   case PT_Uint32:
752bdd1243dSDimitry Andric     return this->emitConstUint32(Value, E);
753a7dea167SDimitry Andric   case PT_Sint64:
754bdd1243dSDimitry Andric     return this->emitConstSint64(Value, E);
755a7dea167SDimitry Andric   case PT_Uint64:
756bdd1243dSDimitry Andric     return this->emitConstUint64(Value, E);
757a7dea167SDimitry Andric   case PT_Bool:
758bdd1243dSDimitry Andric     return this->emitConstBool(Value, E);
759a7dea167SDimitry Andric   case PT_Ptr:
760a7dea167SDimitry Andric     llvm_unreachable("Invalid integral type");
761a7dea167SDimitry Andric     break;
762a7dea167SDimitry Andric   }
763a7dea167SDimitry Andric   llvm_unreachable("unknown primitive type");
764a7dea167SDimitry Andric }
765a7dea167SDimitry Andric 
766a7dea167SDimitry Andric template <class Emitter>
767bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::emitConst(const APSInt &Value, const Expr *E) {
768bdd1243dSDimitry Andric   if (Value.isSigned())
769bdd1243dSDimitry Andric     return this->emitConst(Value.getSExtValue(), E);
770bdd1243dSDimitry Andric   return this->emitConst(Value.getZExtValue(), E);
771bdd1243dSDimitry Andric }
772bdd1243dSDimitry Andric 
773bdd1243dSDimitry Andric template <class Emitter>
774a7dea167SDimitry Andric unsigned ByteCodeExprGen<Emitter>::allocateLocalPrimitive(DeclTy &&Src,
775a7dea167SDimitry Andric                                                           PrimType Ty,
776a7dea167SDimitry Andric                                                           bool IsConst,
777a7dea167SDimitry Andric                                                           bool IsExtended) {
778bdd1243dSDimitry Andric   // Make sure we don't accidentally register the same decl twice.
779bdd1243dSDimitry Andric   if (const auto *VD =
780bdd1243dSDimitry Andric           dyn_cast_if_present<ValueDecl>(Src.dyn_cast<const Decl *>())) {
781bdd1243dSDimitry Andric     assert(!P.getGlobal(VD));
782bdd1243dSDimitry Andric     assert(Locals.find(VD) == Locals.end());
783bdd1243dSDimitry Andric   }
784bdd1243dSDimitry Andric 
785bdd1243dSDimitry Andric   // FIXME: There are cases where Src.is<Expr*>() is wrong, e.g.
786bdd1243dSDimitry Andric   //   (int){12} in C. Consider using Expr::isTemporaryObject() instead
787bdd1243dSDimitry Andric   //   or isa<MaterializeTemporaryExpr>().
788bdd1243dSDimitry Andric   Descriptor *D = P.createDescriptor(Src, Ty, Descriptor::InlineDescMD, IsConst,
789bdd1243dSDimitry Andric                                      Src.is<const Expr *>());
790a7dea167SDimitry Andric   Scope::Local Local = this->createLocal(D);
791a7dea167SDimitry Andric   if (auto *VD = dyn_cast_or_null<ValueDecl>(Src.dyn_cast<const Decl *>()))
792a7dea167SDimitry Andric     Locals.insert({VD, Local});
793a7dea167SDimitry Andric   VarScope->add(Local, IsExtended);
794a7dea167SDimitry Andric   return Local.Offset;
795a7dea167SDimitry Andric }
796a7dea167SDimitry Andric 
797a7dea167SDimitry Andric template <class Emitter>
798bdd1243dSDimitry Andric std::optional<unsigned>
799a7dea167SDimitry Andric ByteCodeExprGen<Emitter>::allocateLocal(DeclTy &&Src, bool IsExtended) {
800bdd1243dSDimitry Andric   // Make sure we don't accidentally register the same decl twice.
801bdd1243dSDimitry Andric   if (const auto *VD =
802bdd1243dSDimitry Andric           dyn_cast_if_present<ValueDecl>(Src.dyn_cast<const Decl *>())) {
803bdd1243dSDimitry Andric     assert(!P.getGlobal(VD));
804bdd1243dSDimitry Andric     assert(Locals.find(VD) == Locals.end());
805bdd1243dSDimitry Andric   }
806a7dea167SDimitry Andric 
807bdd1243dSDimitry Andric   QualType Ty;
808a7dea167SDimitry Andric   const ValueDecl *Key = nullptr;
809bdd1243dSDimitry Andric   const Expr *Init = nullptr;
810a7dea167SDimitry Andric   bool IsTemporary = false;
811bdd1243dSDimitry Andric   if (auto *VD = dyn_cast_if_present<ValueDecl>(Src.dyn_cast<const Decl *>())) {
812a7dea167SDimitry Andric     Key = VD;
813a7dea167SDimitry Andric     Ty = VD->getType();
814bdd1243dSDimitry Andric 
815bdd1243dSDimitry Andric     if (const auto *VarD = dyn_cast<VarDecl>(VD))
816bdd1243dSDimitry Andric       Init = VarD->getInit();
817a7dea167SDimitry Andric   }
818a7dea167SDimitry Andric   if (auto *E = Src.dyn_cast<const Expr *>()) {
819a7dea167SDimitry Andric     IsTemporary = true;
820a7dea167SDimitry Andric     Ty = E->getType();
821a7dea167SDimitry Andric   }
822a7dea167SDimitry Andric 
823bdd1243dSDimitry Andric   Descriptor *D = P.createDescriptor(
824bdd1243dSDimitry Andric       Src, Ty.getTypePtr(), Descriptor::InlineDescMD, Ty.isConstQualified(),
825bdd1243dSDimitry Andric       IsTemporary, /*IsMutable=*/false, Init);
826a7dea167SDimitry Andric   if (!D)
827a7dea167SDimitry Andric     return {};
828a7dea167SDimitry Andric 
829a7dea167SDimitry Andric   Scope::Local Local = this->createLocal(D);
830a7dea167SDimitry Andric   if (Key)
831a7dea167SDimitry Andric     Locals.insert({Key, Local});
832a7dea167SDimitry Andric   VarScope->add(Local, IsExtended);
833a7dea167SDimitry Andric   return Local.Offset;
834a7dea167SDimitry Andric }
835a7dea167SDimitry Andric 
836bdd1243dSDimitry Andric // NB: When calling this function, we have a pointer to the
837bdd1243dSDimitry Andric //   array-to-initialize on the stack.
838a7dea167SDimitry Andric template <class Emitter>
839bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::visitArrayInitializer(const Expr *Initializer) {
840bdd1243dSDimitry Andric   assert(Initializer->getType()->isArrayType());
841bdd1243dSDimitry Andric 
842bdd1243dSDimitry Andric   // TODO: Fillers?
843bdd1243dSDimitry Andric   if (const auto *InitList = dyn_cast<InitListExpr>(Initializer)) {
844bdd1243dSDimitry Andric     unsigned ElementIndex = 0;
845bdd1243dSDimitry Andric     for (const Expr *Init : InitList->inits()) {
846bdd1243dSDimitry Andric       if (std::optional<PrimType> T = classify(Init->getType())) {
847bdd1243dSDimitry Andric         // Visit the primitive element like normal.
848bdd1243dSDimitry Andric         if (!this->emitDupPtr(Init))
849bdd1243dSDimitry Andric           return false;
850bdd1243dSDimitry Andric         if (!this->visit(Init))
851bdd1243dSDimitry Andric           return false;
852bdd1243dSDimitry Andric         if (!this->emitInitElem(*T, ElementIndex, Init))
853bdd1243dSDimitry Andric           return false;
854bdd1243dSDimitry Andric       } else {
855bdd1243dSDimitry Andric         // Advance the pointer currently on the stack to the given
856bdd1243dSDimitry Andric         // dimension and narrow().
857bdd1243dSDimitry Andric         if (!this->emitDupPtr(Init))
858bdd1243dSDimitry Andric           return false;
859bdd1243dSDimitry Andric         if (!this->emitConstUint32(ElementIndex, Init))
860bdd1243dSDimitry Andric           return false;
861bdd1243dSDimitry Andric         if (!this->emitAddOffsetUint32(Init))
862bdd1243dSDimitry Andric           return false;
863bdd1243dSDimitry Andric         if (!this->emitNarrowPtr(Init))
864bdd1243dSDimitry Andric           return false;
865bdd1243dSDimitry Andric 
866bdd1243dSDimitry Andric         if (!visitInitializer(Init))
867bdd1243dSDimitry Andric           return false;
868bdd1243dSDimitry Andric       }
869bdd1243dSDimitry Andric         if (!this->emitPopPtr(Init))
870bdd1243dSDimitry Andric           return false;
871bdd1243dSDimitry Andric 
872bdd1243dSDimitry Andric       ++ElementIndex;
873bdd1243dSDimitry Andric     }
874bdd1243dSDimitry Andric     return true;
875bdd1243dSDimitry Andric   } else if (const auto *DIE = dyn_cast<CXXDefaultInitExpr>(Initializer)) {
876bdd1243dSDimitry Andric     return this->visitInitializer(DIE->getExpr());
877bdd1243dSDimitry Andric   } else if (const auto *AILE = dyn_cast<ArrayInitLoopExpr>(Initializer)) {
878bdd1243dSDimitry Andric     // TODO: This compiles to quite a lot of bytecode if the array is larger.
879bdd1243dSDimitry Andric     //   Investigate compiling this to a loop, or at least try to use
880bdd1243dSDimitry Andric     //   the AILE's Common expr.
881bdd1243dSDimitry Andric     const Expr *SubExpr = AILE->getSubExpr();
882bdd1243dSDimitry Andric     size_t Size = AILE->getArraySize().getZExtValue();
883bdd1243dSDimitry Andric     std::optional<PrimType> ElemT = classify(SubExpr->getType());
884bdd1243dSDimitry Andric 
885bdd1243dSDimitry Andric     // So, every iteration, we execute an assignment here
886bdd1243dSDimitry Andric     // where the LHS is on the stack (the target array)
887bdd1243dSDimitry Andric     // and the RHS is our SubExpr.
888bdd1243dSDimitry Andric     for (size_t I = 0; I != Size; ++I) {
889bdd1243dSDimitry Andric       ArrayIndexScope<Emitter> IndexScope(this, I);
890bdd1243dSDimitry Andric 
891bdd1243dSDimitry Andric       if (!this->emitDupPtr(SubExpr)) // LHS
892bdd1243dSDimitry Andric         return false;
893bdd1243dSDimitry Andric 
894bdd1243dSDimitry Andric       if (ElemT) {
895bdd1243dSDimitry Andric         if (!this->visit(SubExpr))
896bdd1243dSDimitry Andric           return false;
897bdd1243dSDimitry Andric         if (!this->emitInitElem(*ElemT, I, Initializer))
898bdd1243dSDimitry Andric           return false;
899bdd1243dSDimitry Andric       } else {
900bdd1243dSDimitry Andric         // Narrow to our array element and recurse into visitInitializer()
901bdd1243dSDimitry Andric         if (!this->emitConstUint64(I, SubExpr))
902bdd1243dSDimitry Andric           return false;
903bdd1243dSDimitry Andric 
904bdd1243dSDimitry Andric         if (!this->emitAddOffsetUint64(SubExpr))
905bdd1243dSDimitry Andric           return false;
906bdd1243dSDimitry Andric 
907bdd1243dSDimitry Andric         if (!this->emitNarrowPtr(SubExpr))
908bdd1243dSDimitry Andric           return false;
909bdd1243dSDimitry Andric 
910bdd1243dSDimitry Andric         if (!visitInitializer(SubExpr))
911bdd1243dSDimitry Andric           return false;
912bdd1243dSDimitry Andric       }
913bdd1243dSDimitry Andric 
914bdd1243dSDimitry Andric       if (!this->emitPopPtr(Initializer))
915bdd1243dSDimitry Andric         return false;
916bdd1243dSDimitry Andric     }
917bdd1243dSDimitry Andric     return true;
918bdd1243dSDimitry Andric   } else if (const auto *IVIE = dyn_cast<ImplicitValueInitExpr>(Initializer)) {
919bdd1243dSDimitry Andric     const ArrayType *AT = IVIE->getType()->getAsArrayTypeUnsafe();
920bdd1243dSDimitry Andric     assert(AT);
921bdd1243dSDimitry Andric     const auto *CAT = cast<ConstantArrayType>(AT);
922bdd1243dSDimitry Andric     size_t NumElems = CAT->getSize().getZExtValue();
923bdd1243dSDimitry Andric 
924bdd1243dSDimitry Andric     if (std::optional<PrimType> ElemT = classify(CAT->getElementType())) {
925bdd1243dSDimitry Andric       // TODO(perf): For int and bool types, we can probably just skip this
926bdd1243dSDimitry Andric       //   since we memset our Block*s to 0 and so we have the desired value
927bdd1243dSDimitry Andric       //   without this.
928bdd1243dSDimitry Andric       for (size_t I = 0; I != NumElems; ++I) {
929bdd1243dSDimitry Andric         if (!this->emitZero(*ElemT, Initializer))
930bdd1243dSDimitry Andric           return false;
931bdd1243dSDimitry Andric         if (!this->emitInitElem(*ElemT, I, Initializer))
932bdd1243dSDimitry Andric           return false;
933bdd1243dSDimitry Andric       }
934bdd1243dSDimitry Andric     } else {
935bdd1243dSDimitry Andric       assert(false && "default initializer for non-primitive type");
936bdd1243dSDimitry Andric     }
937bdd1243dSDimitry Andric 
938bdd1243dSDimitry Andric     return true;
939bdd1243dSDimitry Andric   } else if (const auto *Ctor = dyn_cast<CXXConstructExpr>(Initializer)) {
940bdd1243dSDimitry Andric     const ConstantArrayType *CAT =
941bdd1243dSDimitry Andric         Ctx.getASTContext().getAsConstantArrayType(Ctor->getType());
942bdd1243dSDimitry Andric     assert(CAT);
943bdd1243dSDimitry Andric     size_t NumElems = CAT->getSize().getZExtValue();
944bdd1243dSDimitry Andric     const Function *Func = getFunction(Ctor->getConstructor());
945bdd1243dSDimitry Andric     if (!Func || !Func->isConstexpr())
946bdd1243dSDimitry Andric       return false;
947bdd1243dSDimitry Andric 
948bdd1243dSDimitry Andric     // FIXME(perf): We're calling the constructor once per array element here,
949bdd1243dSDimitry Andric     //   in the old intepreter we had a special-case for trivial constructors.
950bdd1243dSDimitry Andric     for (size_t I = 0; I != NumElems; ++I) {
951bdd1243dSDimitry Andric       if (!this->emitDupPtr(Initializer))
952bdd1243dSDimitry Andric         return false;
953bdd1243dSDimitry Andric       if (!this->emitConstUint64(I, Initializer))
954bdd1243dSDimitry Andric         return false;
955bdd1243dSDimitry Andric       if (!this->emitAddOffsetUint64(Initializer))
956bdd1243dSDimitry Andric         return false;
957bdd1243dSDimitry Andric       if (!this->emitNarrowPtr(Initializer))
958bdd1243dSDimitry Andric         return false;
959bdd1243dSDimitry Andric 
960bdd1243dSDimitry Andric       // Constructor arguments.
961bdd1243dSDimitry Andric       for (const auto *Arg : Ctor->arguments()) {
962bdd1243dSDimitry Andric         if (!this->visit(Arg))
963bdd1243dSDimitry Andric           return false;
964bdd1243dSDimitry Andric       }
965bdd1243dSDimitry Andric 
966bdd1243dSDimitry Andric       if (!this->emitCall(Func, Initializer))
967bdd1243dSDimitry Andric         return false;
968bdd1243dSDimitry Andric     }
969bdd1243dSDimitry Andric     return true;
970bdd1243dSDimitry Andric   }
971bdd1243dSDimitry Andric 
972bdd1243dSDimitry Andric   assert(false && "Unknown expression for array initialization");
973bdd1243dSDimitry Andric   return false;
974a7dea167SDimitry Andric }
975a7dea167SDimitry Andric 
976a7dea167SDimitry Andric template <class Emitter>
977bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::visitRecordInitializer(const Expr *Initializer) {
978bdd1243dSDimitry Andric   Initializer = Initializer->IgnoreParenImpCasts();
979bdd1243dSDimitry Andric   assert(Initializer->getType()->isRecordType());
980bdd1243dSDimitry Andric 
981bdd1243dSDimitry Andric   if (const auto CtorExpr = dyn_cast<CXXConstructExpr>(Initializer)) {
982bdd1243dSDimitry Andric     const Function *Func = getFunction(CtorExpr->getConstructor());
983bdd1243dSDimitry Andric 
984bdd1243dSDimitry Andric     if (!Func || !Func->isConstexpr())
985bdd1243dSDimitry Andric       return false;
986bdd1243dSDimitry Andric 
987bdd1243dSDimitry Andric     // The This pointer is already on the stack because this is an initializer,
988bdd1243dSDimitry Andric     // but we need to dup() so the call() below has its own copy.
989bdd1243dSDimitry Andric     if (!this->emitDupPtr(Initializer))
990bdd1243dSDimitry Andric       return false;
991bdd1243dSDimitry Andric 
992bdd1243dSDimitry Andric     // Constructor arguments.
993bdd1243dSDimitry Andric     for (const auto *Arg : CtorExpr->arguments()) {
994bdd1243dSDimitry Andric       if (!this->visit(Arg))
995bdd1243dSDimitry Andric         return false;
996a7dea167SDimitry Andric     }
997bdd1243dSDimitry Andric 
998bdd1243dSDimitry Andric     return this->emitCall(Func, Initializer);
999bdd1243dSDimitry Andric   } else if (const auto *InitList = dyn_cast<InitListExpr>(Initializer)) {
1000bdd1243dSDimitry Andric     const Record *R = getRecord(InitList->getType());
1001bdd1243dSDimitry Andric 
1002bdd1243dSDimitry Andric     unsigned InitIndex = 0;
1003bdd1243dSDimitry Andric     for (const Expr *Init : InitList->inits()) {
1004bdd1243dSDimitry Andric       const Record::Field *FieldToInit = R->getField(InitIndex);
1005bdd1243dSDimitry Andric 
1006bdd1243dSDimitry Andric       if (!this->emitDupPtr(Initializer))
1007bdd1243dSDimitry Andric         return false;
1008bdd1243dSDimitry Andric 
1009bdd1243dSDimitry Andric       if (std::optional<PrimType> T = classify(Init)) {
1010bdd1243dSDimitry Andric         if (!this->visit(Init))
1011bdd1243dSDimitry Andric           return false;
1012bdd1243dSDimitry Andric 
1013bdd1243dSDimitry Andric         if (!this->emitInitField(*T, FieldToInit->Offset, Initializer))
1014bdd1243dSDimitry Andric           return false;
1015bdd1243dSDimitry Andric 
1016bdd1243dSDimitry Andric         if (!this->emitPopPtr(Initializer))
1017bdd1243dSDimitry Andric           return false;
1018bdd1243dSDimitry Andric       } else {
1019bdd1243dSDimitry Andric         // Non-primitive case. Get a pointer to the field-to-initialize
1020bdd1243dSDimitry Andric         // on the stack and recurse into visitInitializer().
1021bdd1243dSDimitry Andric         if (!this->emitGetPtrField(FieldToInit->Offset, Init))
1022bdd1243dSDimitry Andric           return false;
1023bdd1243dSDimitry Andric 
1024bdd1243dSDimitry Andric         if (!this->visitInitializer(Init))
1025bdd1243dSDimitry Andric           return false;
1026bdd1243dSDimitry Andric 
1027bdd1243dSDimitry Andric         if (!this->emitPopPtr(Initializer))
1028bdd1243dSDimitry Andric           return false;
1029bdd1243dSDimitry Andric       }
1030bdd1243dSDimitry Andric       ++InitIndex;
1031bdd1243dSDimitry Andric     }
1032bdd1243dSDimitry Andric 
1033bdd1243dSDimitry Andric     return true;
1034bdd1243dSDimitry Andric   } else if (const CallExpr *CE = dyn_cast<CallExpr>(Initializer)) {
1035bdd1243dSDimitry Andric     // RVO functions expect a pointer to initialize on the stack.
1036bdd1243dSDimitry Andric     // Dup our existing pointer so it has its own copy to use.
1037bdd1243dSDimitry Andric     if (!this->emitDupPtr(Initializer))
1038bdd1243dSDimitry Andric       return false;
1039bdd1243dSDimitry Andric 
1040bdd1243dSDimitry Andric     return this->VisitCallExpr(CE);
1041bdd1243dSDimitry Andric   } else if (const auto *DIE = dyn_cast<CXXDefaultInitExpr>(Initializer)) {
1042bdd1243dSDimitry Andric     return this->visitInitializer(DIE->getExpr());
1043bdd1243dSDimitry Andric   }
1044bdd1243dSDimitry Andric 
1045bdd1243dSDimitry Andric   return false;
1046a7dea167SDimitry Andric }
1047a7dea167SDimitry Andric 
1048a7dea167SDimitry Andric template <class Emitter>
1049bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::visitInitializer(const Expr *Initializer) {
1050bdd1243dSDimitry Andric   QualType InitializerType = Initializer->getType();
1051bdd1243dSDimitry Andric 
1052bdd1243dSDimitry Andric   if (InitializerType->isArrayType())
1053bdd1243dSDimitry Andric     return visitArrayInitializer(Initializer);
1054bdd1243dSDimitry Andric 
1055bdd1243dSDimitry Andric   if (InitializerType->isRecordType())
1056bdd1243dSDimitry Andric     return visitRecordInitializer(Initializer);
1057bdd1243dSDimitry Andric 
1058bdd1243dSDimitry Andric   // Otherwise, visit the expression like normal.
1059bdd1243dSDimitry Andric   return this->visit(Initializer);
1060a7dea167SDimitry Andric }
1061a7dea167SDimitry Andric 
1062a7dea167SDimitry Andric template <class Emitter>
1063a7dea167SDimitry Andric const RecordType *ByteCodeExprGen<Emitter>::getRecordTy(QualType Ty) {
1064753f127fSDimitry Andric   if (const PointerType *PT = dyn_cast<PointerType>(Ty))
1065a7dea167SDimitry Andric     return PT->getPointeeType()->getAs<RecordType>();
1066a7dea167SDimitry Andric   else
1067a7dea167SDimitry Andric     return Ty->getAs<RecordType>();
1068a7dea167SDimitry Andric }
1069a7dea167SDimitry Andric 
1070a7dea167SDimitry Andric template <class Emitter>
1071a7dea167SDimitry Andric Record *ByteCodeExprGen<Emitter>::getRecord(QualType Ty) {
1072a7dea167SDimitry Andric   if (auto *RecordTy = getRecordTy(Ty)) {
1073a7dea167SDimitry Andric     return getRecord(RecordTy->getDecl());
1074a7dea167SDimitry Andric   }
1075a7dea167SDimitry Andric   return nullptr;
1076a7dea167SDimitry Andric }
1077a7dea167SDimitry Andric 
1078a7dea167SDimitry Andric template <class Emitter>
1079a7dea167SDimitry Andric Record *ByteCodeExprGen<Emitter>::getRecord(const RecordDecl *RD) {
1080a7dea167SDimitry Andric   return P.getOrCreateRecord(RD);
1081a7dea167SDimitry Andric }
1082a7dea167SDimitry Andric 
1083a7dea167SDimitry Andric template <class Emitter>
1084bdd1243dSDimitry Andric const Function *ByteCodeExprGen<Emitter>::getFunction(const FunctionDecl *FD) {
1085bdd1243dSDimitry Andric   assert(FD);
1086bdd1243dSDimitry Andric   const Function *Func = P.getFunction(FD);
1087bdd1243dSDimitry Andric   bool IsBeingCompiled = Func && !Func->isFullyCompiled();
1088bdd1243dSDimitry Andric   bool WasNotDefined = Func && !Func->hasBody();
1089bdd1243dSDimitry Andric 
1090bdd1243dSDimitry Andric   if (IsBeingCompiled)
1091bdd1243dSDimitry Andric     return Func;
1092bdd1243dSDimitry Andric 
1093bdd1243dSDimitry Andric   if (!Func || WasNotDefined) {
1094bdd1243dSDimitry Andric     if (auto R = ByteCodeStmtGen<ByteCodeEmitter>(Ctx, P).compileFunc(FD))
1095bdd1243dSDimitry Andric       Func = *R;
1096bdd1243dSDimitry Andric     else {
1097bdd1243dSDimitry Andric       llvm::consumeError(R.takeError());
1098bdd1243dSDimitry Andric       return nullptr;
1099bdd1243dSDimitry Andric     }
1100bdd1243dSDimitry Andric   }
1101bdd1243dSDimitry Andric 
1102bdd1243dSDimitry Andric   return Func;
1103bdd1243dSDimitry Andric }
1104bdd1243dSDimitry Andric 
1105bdd1243dSDimitry Andric template <class Emitter>
1106a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::visitExpr(const Expr *Exp) {
1107a7dea167SDimitry Andric   ExprScope<Emitter> RootScope(this);
1108a7dea167SDimitry Andric   if (!visit(Exp))
1109a7dea167SDimitry Andric     return false;
1110a7dea167SDimitry Andric 
1111bdd1243dSDimitry Andric   if (std::optional<PrimType> T = classify(Exp))
1112a7dea167SDimitry Andric     return this->emitRet(*T, Exp);
1113a7dea167SDimitry Andric   else
1114a7dea167SDimitry Andric     return this->emitRetValue(Exp);
1115a7dea167SDimitry Andric }
1116a7dea167SDimitry Andric 
1117bdd1243dSDimitry Andric /// Toplevel visitDecl().
1118bdd1243dSDimitry Andric /// We get here from evaluateAsInitializer().
1119bdd1243dSDimitry Andric /// We need to evaluate the initializer and return its value.
1120a7dea167SDimitry Andric template <class Emitter>
1121a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::visitDecl(const VarDecl *VD) {
1122bdd1243dSDimitry Andric   std::optional<PrimType> VarT = classify(VD->getType());
1123a7dea167SDimitry Andric 
1124bdd1243dSDimitry Andric   // Create and initialize the variable.
1125bdd1243dSDimitry Andric   if (!this->visitVarDecl(VD))
1126a7dea167SDimitry Andric     return false;
1127a7dea167SDimitry Andric 
1128bdd1243dSDimitry Andric   // Get a pointer to the variable
1129bdd1243dSDimitry Andric   if (shouldBeGloballyIndexed(VD)) {
1130bdd1243dSDimitry Andric     auto GlobalIndex = P.getGlobal(VD);
1131bdd1243dSDimitry Andric     assert(GlobalIndex); // visitVarDecl() didn't return false.
1132bdd1243dSDimitry Andric     if (!this->emitGetPtrGlobal(*GlobalIndex, VD))
1133a7dea167SDimitry Andric       return false;
1134a7dea167SDimitry Andric   } else {
1135bdd1243dSDimitry Andric     auto Local = Locals.find(VD);
1136bdd1243dSDimitry Andric     assert(Local != Locals.end()); // Same here.
1137bdd1243dSDimitry Andric     if (!this->emitGetPtrLocal(Local->second.Offset, VD))
1138a7dea167SDimitry Andric       return false;
1139a7dea167SDimitry Andric   }
1140a7dea167SDimitry Andric 
1141bdd1243dSDimitry Andric   // Return the value
1142bdd1243dSDimitry Andric   if (VarT) {
1143bdd1243dSDimitry Andric     if (!this->emitLoadPop(*VarT, VD))
1144a7dea167SDimitry Andric       return false;
1145bdd1243dSDimitry Andric 
1146bdd1243dSDimitry Andric     return this->emitRet(*VarT, VD);
1147bdd1243dSDimitry Andric   }
1148bdd1243dSDimitry Andric 
1149a7dea167SDimitry Andric   return this->emitRetValue(VD);
1150a7dea167SDimitry Andric }
1151bdd1243dSDimitry Andric 
1152bdd1243dSDimitry Andric template <class Emitter>
1153bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::visitVarDecl(const VarDecl *VD) {
1154bdd1243dSDimitry Andric   const Expr *Init = VD->getInit();
1155bdd1243dSDimitry Andric   std::optional<PrimType> VarT = classify(VD->getType());
1156bdd1243dSDimitry Andric 
1157bdd1243dSDimitry Andric   if (shouldBeGloballyIndexed(VD)) {
1158bdd1243dSDimitry Andric     std::optional<unsigned> GlobalIndex = P.getOrCreateGlobal(VD, Init);
1159bdd1243dSDimitry Andric 
1160bdd1243dSDimitry Andric     if (!GlobalIndex)
1161bdd1243dSDimitry Andric       return this->bail(VD);
1162bdd1243dSDimitry Andric 
1163bdd1243dSDimitry Andric     assert(Init);
1164bdd1243dSDimitry Andric     {
1165bdd1243dSDimitry Andric       DeclScope<Emitter> LocalScope(this, VD);
1166bdd1243dSDimitry Andric 
1167bdd1243dSDimitry Andric       if (VarT) {
1168bdd1243dSDimitry Andric         if (!this->visit(Init))
1169bdd1243dSDimitry Andric           return false;
1170bdd1243dSDimitry Andric         return this->emitInitGlobal(*VarT, *GlobalIndex, VD);
1171bdd1243dSDimitry Andric       }
1172bdd1243dSDimitry Andric       return this->visitGlobalInitializer(Init, *GlobalIndex);
1173bdd1243dSDimitry Andric     }
1174bdd1243dSDimitry Andric   } else {
1175bdd1243dSDimitry Andric     VariableScope<Emitter> LocalScope(this);
1176bdd1243dSDimitry Andric     if (VarT) {
1177bdd1243dSDimitry Andric       unsigned Offset = this->allocateLocalPrimitive(
1178bdd1243dSDimitry Andric           VD, *VarT, VD->getType().isConstQualified());
1179bdd1243dSDimitry Andric       if (Init) {
1180bdd1243dSDimitry Andric         // Compile the initializer in its own scope.
1181bdd1243dSDimitry Andric         ExprScope<Emitter> Scope(this);
1182bdd1243dSDimitry Andric         if (!this->visit(Init))
1183bdd1243dSDimitry Andric           return false;
1184bdd1243dSDimitry Andric 
1185bdd1243dSDimitry Andric         return this->emitSetLocal(*VarT, Offset, VD);
1186bdd1243dSDimitry Andric       }
1187bdd1243dSDimitry Andric     } else {
1188bdd1243dSDimitry Andric       if (std::optional<unsigned> Offset = this->allocateLocal(VD)) {
1189bdd1243dSDimitry Andric         if (Init)
1190bdd1243dSDimitry Andric           return this->visitLocalInitializer(Init, *Offset);
1191bdd1243dSDimitry Andric       }
1192bdd1243dSDimitry Andric     }
1193bdd1243dSDimitry Andric     return true;
1194a7dea167SDimitry Andric   }
1195a7dea167SDimitry Andric 
1196bdd1243dSDimitry Andric   return false;
1197bdd1243dSDimitry Andric }
1198bdd1243dSDimitry Andric 
1199bdd1243dSDimitry Andric template <class Emitter>
1200bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCallExpr(const CallExpr *E) {
1201bdd1243dSDimitry Andric   assert(!E->getBuiltinCallee() && "Builtin functions aren't supported yet");
1202bdd1243dSDimitry Andric 
1203bdd1243dSDimitry Andric   const Decl *Callee = E->getCalleeDecl();
1204bdd1243dSDimitry Andric   if (const auto *FuncDecl = dyn_cast_or_null<FunctionDecl>(Callee)) {
1205bdd1243dSDimitry Andric     const Function *Func = getFunction(FuncDecl);
1206bdd1243dSDimitry Andric     if (!Func)
1207bdd1243dSDimitry Andric       return false;
1208bdd1243dSDimitry Andric     // If the function is being compiled right now, this is a recursive call.
1209bdd1243dSDimitry Andric     // In that case, the function can't be valid yet, even though it will be
1210bdd1243dSDimitry Andric     // later.
1211bdd1243dSDimitry Andric     // If the function is already fully compiled but not constexpr, it was
1212bdd1243dSDimitry Andric     // found to be faulty earlier on, so bail out.
1213bdd1243dSDimitry Andric     if (Func->isFullyCompiled() && !Func->isConstexpr())
1214bdd1243dSDimitry Andric       return false;
1215bdd1243dSDimitry Andric 
1216bdd1243dSDimitry Andric     QualType ReturnType = E->getCallReturnType(Ctx.getASTContext());
1217bdd1243dSDimitry Andric     std::optional<PrimType> T = classify(ReturnType);
1218bdd1243dSDimitry Andric 
1219bdd1243dSDimitry Andric     if (Func->hasRVO() && DiscardResult) {
1220bdd1243dSDimitry Andric       // If we need to discard the return value but the function returns its
1221bdd1243dSDimitry Andric       // value via an RVO pointer, we need to create one such pointer just
1222bdd1243dSDimitry Andric       // for this call.
1223bdd1243dSDimitry Andric       if (std::optional<unsigned> LocalIndex = allocateLocal(E)) {
1224bdd1243dSDimitry Andric         if (!this->emitGetPtrLocal(*LocalIndex, E))
1225bdd1243dSDimitry Andric           return false;
1226bdd1243dSDimitry Andric       }
1227bdd1243dSDimitry Andric     }
1228bdd1243dSDimitry Andric 
1229bdd1243dSDimitry Andric     // Put arguments on the stack.
1230bdd1243dSDimitry Andric     for (const auto *Arg : E->arguments()) {
1231bdd1243dSDimitry Andric       if (!this->visit(Arg))
1232bdd1243dSDimitry Andric         return false;
1233bdd1243dSDimitry Andric     }
1234bdd1243dSDimitry Andric 
1235bdd1243dSDimitry Andric     // In any case call the function. The return value will end up on the stack and
1236bdd1243dSDimitry Andric     // if the function has RVO, we already have the pointer on the stack to write
1237bdd1243dSDimitry Andric     // the result into.
1238bdd1243dSDimitry Andric     if (!this->emitCall(Func, E))
1239bdd1243dSDimitry Andric       return false;
1240bdd1243dSDimitry Andric 
1241bdd1243dSDimitry Andric     if (DiscardResult && !ReturnType->isVoidType() && T)
1242bdd1243dSDimitry Andric       return this->emitPop(*T, E);
1243bdd1243dSDimitry Andric 
1244bdd1243dSDimitry Andric     return true;
1245bdd1243dSDimitry Andric   } else {
1246bdd1243dSDimitry Andric     assert(false && "We don't support non-FunctionDecl callees right now.");
1247bdd1243dSDimitry Andric   }
1248bdd1243dSDimitry Andric 
1249bdd1243dSDimitry Andric   return false;
1250bdd1243dSDimitry Andric }
1251bdd1243dSDimitry Andric 
1252bdd1243dSDimitry Andric template <class Emitter>
1253bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCXXMemberCallExpr(
1254bdd1243dSDimitry Andric     const CXXMemberCallExpr *E) {
1255bdd1243dSDimitry Andric   // Get a This pointer on the stack.
1256bdd1243dSDimitry Andric   if (!this->visit(E->getImplicitObjectArgument()))
1257bdd1243dSDimitry Andric     return false;
1258bdd1243dSDimitry Andric 
1259bdd1243dSDimitry Andric   return VisitCallExpr(E);
1260bdd1243dSDimitry Andric }
1261bdd1243dSDimitry Andric 
1262bdd1243dSDimitry Andric template <class Emitter>
1263bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCXXDefaultInitExpr(
1264bdd1243dSDimitry Andric     const CXXDefaultInitExpr *E) {
1265bdd1243dSDimitry Andric   return this->visit(E->getExpr());
1266bdd1243dSDimitry Andric }
1267bdd1243dSDimitry Andric 
1268bdd1243dSDimitry Andric template <class Emitter>
1269bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCXXDefaultArgExpr(
1270bdd1243dSDimitry Andric     const CXXDefaultArgExpr *E) {
1271bdd1243dSDimitry Andric   return this->visit(E->getExpr());
1272bdd1243dSDimitry Andric }
1273bdd1243dSDimitry Andric 
1274bdd1243dSDimitry Andric template <class Emitter>
1275bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCXXBoolLiteralExpr(
1276bdd1243dSDimitry Andric     const CXXBoolLiteralExpr *E) {
1277bdd1243dSDimitry Andric   if (DiscardResult)
1278bdd1243dSDimitry Andric     return true;
1279bdd1243dSDimitry Andric 
1280bdd1243dSDimitry Andric   return this->emitConstBool(E->getValue(), E);
1281bdd1243dSDimitry Andric }
1282bdd1243dSDimitry Andric 
1283bdd1243dSDimitry Andric template <class Emitter>
1284bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCXXNullPtrLiteralExpr(
1285bdd1243dSDimitry Andric     const CXXNullPtrLiteralExpr *E) {
1286bdd1243dSDimitry Andric   if (DiscardResult)
1287bdd1243dSDimitry Andric     return true;
1288bdd1243dSDimitry Andric 
1289bdd1243dSDimitry Andric   return this->emitNullPtr(E);
1290bdd1243dSDimitry Andric }
1291bdd1243dSDimitry Andric 
1292bdd1243dSDimitry Andric template <class Emitter>
1293bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCXXThisExpr(const CXXThisExpr *E) {
1294bdd1243dSDimitry Andric   if (DiscardResult)
1295bdd1243dSDimitry Andric     return true;
1296bdd1243dSDimitry Andric   return this->emitThis(E);
1297bdd1243dSDimitry Andric }
1298bdd1243dSDimitry Andric 
1299bdd1243dSDimitry Andric template <class Emitter>
1300bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitUnaryOperator(const UnaryOperator *E) {
1301bdd1243dSDimitry Andric   const Expr *SubExpr = E->getSubExpr();
1302bdd1243dSDimitry Andric   std::optional<PrimType> T = classify(SubExpr->getType());
1303bdd1243dSDimitry Andric 
1304bdd1243dSDimitry Andric   // TODO: Support pointers for inc/dec operators.
1305bdd1243dSDimitry Andric   switch (E->getOpcode()) {
1306bdd1243dSDimitry Andric   case UO_PostInc: { // x++
1307bdd1243dSDimitry Andric     if (!this->visit(SubExpr))
1308bdd1243dSDimitry Andric       return false;
1309bdd1243dSDimitry Andric 
1310bdd1243dSDimitry Andric     return DiscardResult ? this->emitIncPop(*T, E) : this->emitInc(*T, E);
1311bdd1243dSDimitry Andric   }
1312bdd1243dSDimitry Andric   case UO_PostDec: { // x--
1313bdd1243dSDimitry Andric     if (!this->visit(SubExpr))
1314bdd1243dSDimitry Andric       return false;
1315bdd1243dSDimitry Andric 
1316bdd1243dSDimitry Andric     return DiscardResult ? this->emitDecPop(*T, E) : this->emitDec(*T, E);
1317bdd1243dSDimitry Andric   }
1318bdd1243dSDimitry Andric   case UO_PreInc: { // ++x
1319bdd1243dSDimitry Andric     if (!this->visit(SubExpr))
1320bdd1243dSDimitry Andric       return false;
1321bdd1243dSDimitry Andric 
1322bdd1243dSDimitry Andric     // Post-inc and pre-inc are the same if the value is to be discarded.
1323bdd1243dSDimitry Andric     if (DiscardResult)
1324bdd1243dSDimitry Andric       return this->emitIncPop(*T, E);
1325bdd1243dSDimitry Andric 
1326bdd1243dSDimitry Andric     this->emitLoad(*T, E);
1327bdd1243dSDimitry Andric     this->emitConst(1, E);
1328bdd1243dSDimitry Andric     this->emitAdd(*T, E);
1329bdd1243dSDimitry Andric     return this->emitStore(*T, E);
1330bdd1243dSDimitry Andric   }
1331bdd1243dSDimitry Andric   case UO_PreDec: { // --x
1332bdd1243dSDimitry Andric     if (!this->visit(SubExpr))
1333bdd1243dSDimitry Andric       return false;
1334bdd1243dSDimitry Andric 
1335bdd1243dSDimitry Andric     // Post-dec and pre-dec are the same if the value is to be discarded.
1336bdd1243dSDimitry Andric     if (DiscardResult)
1337bdd1243dSDimitry Andric       return this->emitDecPop(*T, E);
1338bdd1243dSDimitry Andric 
1339bdd1243dSDimitry Andric     this->emitLoad(*T, E);
1340bdd1243dSDimitry Andric     this->emitConst(1, E);
1341bdd1243dSDimitry Andric     this->emitSub(*T, E);
1342bdd1243dSDimitry Andric     return this->emitStore(*T, E);
1343bdd1243dSDimitry Andric   }
1344bdd1243dSDimitry Andric   case UO_LNot: // !x
1345bdd1243dSDimitry Andric     if (!this->visit(SubExpr))
1346bdd1243dSDimitry Andric       return false;
1347bdd1243dSDimitry Andric     // The Inv doesn't change anything, so skip it if we don't need the result.
1348bdd1243dSDimitry Andric     return DiscardResult ? this->emitPop(*T, E) : this->emitInvBool(E);
1349bdd1243dSDimitry Andric   case UO_Minus: // -x
1350bdd1243dSDimitry Andric     if (!this->visit(SubExpr))
1351bdd1243dSDimitry Andric       return false;
1352bdd1243dSDimitry Andric     return DiscardResult ? this->emitPop(*T, E) : this->emitNeg(*T, E);
1353bdd1243dSDimitry Andric   case UO_Plus:  // +x
1354bdd1243dSDimitry Andric     if (!this->visit(SubExpr)) // noop
1355bdd1243dSDimitry Andric       return false;
1356bdd1243dSDimitry Andric     return DiscardResult ? this->emitPop(*T, E) : true;
1357bdd1243dSDimitry Andric   case UO_AddrOf: // &x
1358bdd1243dSDimitry Andric     // We should already have a pointer when we get here.
1359bdd1243dSDimitry Andric     if (!this->visit(SubExpr))
1360bdd1243dSDimitry Andric       return false;
1361bdd1243dSDimitry Andric     return DiscardResult ? this->emitPop(*T, E) : true;
1362bdd1243dSDimitry Andric   case UO_Deref:  // *x
1363bdd1243dSDimitry Andric     return dereference(
1364bdd1243dSDimitry Andric         SubExpr, DerefKind::Read,
1365bdd1243dSDimitry Andric         [](PrimType) {
1366bdd1243dSDimitry Andric           llvm_unreachable("Dereferencing requires a pointer");
1367bdd1243dSDimitry Andric           return false;
1368bdd1243dSDimitry Andric         },
1369bdd1243dSDimitry Andric         [this, E](PrimType T) {
1370bdd1243dSDimitry Andric           return DiscardResult ? this->emitPop(T, E) : true;
1371bdd1243dSDimitry Andric         });
1372bdd1243dSDimitry Andric   case UO_Not:    // ~x
1373bdd1243dSDimitry Andric     if (!this->visit(SubExpr))
1374bdd1243dSDimitry Andric       return false;
1375bdd1243dSDimitry Andric     return DiscardResult ? this->emitPop(*T, E) : this->emitComp(*T, E);
1376bdd1243dSDimitry Andric   case UO_Real:   // __real x
1377bdd1243dSDimitry Andric   case UO_Imag:   // __imag x
1378bdd1243dSDimitry Andric   case UO_Extension:
1379bdd1243dSDimitry Andric   case UO_Coawait:
1380bdd1243dSDimitry Andric     assert(false && "Unhandled opcode");
1381bdd1243dSDimitry Andric   }
1382bdd1243dSDimitry Andric 
1383bdd1243dSDimitry Andric   return false;
1384bdd1243dSDimitry Andric }
1385bdd1243dSDimitry Andric 
1386bdd1243dSDimitry Andric template <class Emitter>
1387bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitDeclRefExpr(const DeclRefExpr *E) {
1388bdd1243dSDimitry Andric   const auto *Decl = E->getDecl();
1389bdd1243dSDimitry Andric   // References are implemented via pointers, so when we see a DeclRefExpr
1390bdd1243dSDimitry Andric   // pointing to a reference, we need to get its value directly (i.e. the
1391bdd1243dSDimitry Andric   // pointer to the actual value) instead of a pointer to the pointer to the
1392bdd1243dSDimitry Andric   // value.
1393bdd1243dSDimitry Andric   bool IsReference = Decl->getType()->isReferenceType();
1394bdd1243dSDimitry Andric 
1395bdd1243dSDimitry Andric   if (auto It = Locals.find(Decl); It != Locals.end()) {
1396bdd1243dSDimitry Andric     const unsigned Offset = It->second.Offset;
1397bdd1243dSDimitry Andric 
1398bdd1243dSDimitry Andric     if (IsReference)
1399bdd1243dSDimitry Andric       return this->emitGetLocal(PT_Ptr, Offset, E);
1400bdd1243dSDimitry Andric     return this->emitGetPtrLocal(Offset, E);
1401bdd1243dSDimitry Andric   } else if (auto GlobalIndex = P.getGlobal(Decl)) {
1402bdd1243dSDimitry Andric     if (IsReference)
1403bdd1243dSDimitry Andric       return this->emitGetGlobal(PT_Ptr, *GlobalIndex, E);
1404bdd1243dSDimitry Andric 
1405bdd1243dSDimitry Andric     return this->emitGetPtrGlobal(*GlobalIndex, E);
1406bdd1243dSDimitry Andric   } else if (const auto *PVD = dyn_cast<ParmVarDecl>(Decl)) {
1407bdd1243dSDimitry Andric     if (auto It = this->Params.find(PVD); It != this->Params.end()) {
1408bdd1243dSDimitry Andric       if (IsReference)
1409bdd1243dSDimitry Andric         return this->emitGetParam(PT_Ptr, It->second, E);
1410bdd1243dSDimitry Andric       return this->emitGetPtrParam(It->second, E);
1411bdd1243dSDimitry Andric     }
1412bdd1243dSDimitry Andric   } else if (const auto *ECD = dyn_cast<EnumConstantDecl>(Decl)) {
1413bdd1243dSDimitry Andric     return this->emitConst(ECD->getInitVal(), E);
1414bdd1243dSDimitry Andric   }
1415bdd1243dSDimitry Andric 
1416bdd1243dSDimitry Andric   return false;
1417a7dea167SDimitry Andric }
1418a7dea167SDimitry Andric 
1419a7dea167SDimitry Andric template <class Emitter>
1420a7dea167SDimitry Andric void ByteCodeExprGen<Emitter>::emitCleanup() {
1421a7dea167SDimitry Andric   for (VariableScope<Emitter> *C = VarScope; C; C = C->getParent())
1422a7dea167SDimitry Andric     C->emitDestruction();
1423a7dea167SDimitry Andric }
1424a7dea167SDimitry Andric 
1425a7dea167SDimitry Andric namespace clang {
1426a7dea167SDimitry Andric namespace interp {
1427a7dea167SDimitry Andric 
1428a7dea167SDimitry Andric template class ByteCodeExprGen<ByteCodeEmitter>;
1429a7dea167SDimitry Andric template class ByteCodeExprGen<EvalEmitter>;
1430a7dea167SDimitry Andric 
1431a7dea167SDimitry Andric } // namespace interp
1432a7dea167SDimitry Andric } // namespace clang
1433