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"
14*fe013be4SDimitry Andric #include "Floating.h"
15a7dea167SDimitry Andric #include "Function.h"
16a7dea167SDimitry Andric #include "PrimType.h"
17a7dea167SDimitry Andric #include "Program.h"
18a7dea167SDimitry Andric #include "State.h"
19a7dea167SDimitry Andric 
20a7dea167SDimitry Andric using namespace clang;
21a7dea167SDimitry Andric using namespace clang::interp;
22a7dea167SDimitry Andric 
23a7dea167SDimitry Andric using APSInt = llvm::APSInt;
24a7dea167SDimitry Andric 
25a7dea167SDimitry Andric namespace clang {
26a7dea167SDimitry Andric namespace interp {
27a7dea167SDimitry Andric 
28a7dea167SDimitry Andric /// Scope used to handle temporaries in toplevel variable declarations.
29*fe013be4SDimitry Andric template <class Emitter> class DeclScope final : public VariableScope<Emitter> {
30a7dea167SDimitry Andric public:
31*fe013be4SDimitry Andric   DeclScope(ByteCodeExprGen<Emitter> *Ctx, const ValueDecl *VD)
32*fe013be4SDimitry Andric       : VariableScope<Emitter>(Ctx), Scope(Ctx->P, VD) {}
33a7dea167SDimitry Andric 
34a7dea167SDimitry Andric   void addExtended(const Scope::Local &Local) override {
35a7dea167SDimitry Andric     return this->addLocal(Local);
36a7dea167SDimitry Andric   }
37a7dea167SDimitry Andric 
38a7dea167SDimitry Andric private:
39a7dea167SDimitry Andric   Program::DeclScope Scope;
40a7dea167SDimitry Andric };
41a7dea167SDimitry Andric 
42a7dea167SDimitry Andric /// Scope used to handle initialization methods.
43*fe013be4SDimitry Andric template <class Emitter> class OptionScope final {
44a7dea167SDimitry Andric public:
45a7dea167SDimitry Andric   /// Root constructor, compiling or discarding primitives.
46a7dea167SDimitry Andric   OptionScope(ByteCodeExprGen<Emitter> *Ctx, bool NewDiscardResult)
47bdd1243dSDimitry Andric       : Ctx(Ctx), OldDiscardResult(Ctx->DiscardResult) {
48a7dea167SDimitry Andric     Ctx->DiscardResult = NewDiscardResult;
49a7dea167SDimitry Andric   }
50a7dea167SDimitry Andric 
51bdd1243dSDimitry Andric   ~OptionScope() { Ctx->DiscardResult = OldDiscardResult; }
52a7dea167SDimitry Andric 
53a7dea167SDimitry Andric private:
54a7dea167SDimitry Andric   /// Parent context.
55a7dea167SDimitry Andric   ByteCodeExprGen<Emitter> *Ctx;
56a7dea167SDimitry Andric   /// Old discard flag to restore.
57a7dea167SDimitry Andric   bool OldDiscardResult;
58a7dea167SDimitry Andric };
59a7dea167SDimitry Andric 
60a7dea167SDimitry Andric } // namespace interp
61a7dea167SDimitry Andric } // namespace clang
62a7dea167SDimitry Andric 
63a7dea167SDimitry Andric template <class Emitter>
64a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCastExpr(const CastExpr *CE) {
65a7dea167SDimitry Andric   auto *SubExpr = CE->getSubExpr();
66a7dea167SDimitry Andric   switch (CE->getCastKind()) {
67a7dea167SDimitry Andric 
68a7dea167SDimitry Andric   case CK_LValueToRValue: {
69a7dea167SDimitry Andric     return dereference(
70*fe013be4SDimitry Andric         SubExpr, DerefKind::Read,
71a7dea167SDimitry Andric         [](PrimType) {
72a7dea167SDimitry Andric           // Value loaded - nothing to do here.
73a7dea167SDimitry Andric           return true;
74a7dea167SDimitry Andric         },
75a7dea167SDimitry Andric         [this, CE](PrimType T) {
76a7dea167SDimitry Andric           // Pointer on stack - dereference it.
77a7dea167SDimitry Andric           if (!this->emitLoadPop(T, CE))
78a7dea167SDimitry Andric             return false;
79a7dea167SDimitry Andric           return DiscardResult ? this->emitPop(T, CE) : true;
80a7dea167SDimitry Andric         });
81a7dea167SDimitry Andric   }
82a7dea167SDimitry Andric 
83bdd1243dSDimitry Andric   case CK_UncheckedDerivedToBase:
84bdd1243dSDimitry Andric   case CK_DerivedToBase: {
85bdd1243dSDimitry Andric     if (!this->visit(SubExpr))
86bdd1243dSDimitry Andric       return false;
87bdd1243dSDimitry Andric 
88*fe013be4SDimitry Andric     return this->emitDerivedToBaseCasts(getRecordTy(SubExpr->getType()),
89*fe013be4SDimitry Andric                                         getRecordTy(CE->getType()), CE);
90bdd1243dSDimitry Andric   }
91bdd1243dSDimitry Andric 
92*fe013be4SDimitry Andric   case CK_FloatingCast: {
93*fe013be4SDimitry Andric     if (!this->visit(SubExpr))
94*fe013be4SDimitry Andric       return false;
95*fe013be4SDimitry Andric     const auto *TargetSemantics = &Ctx.getFloatSemantics(CE->getType());
96*fe013be4SDimitry Andric     return this->emitCastFP(TargetSemantics, getRoundingMode(CE), CE);
97*fe013be4SDimitry Andric   }
98*fe013be4SDimitry Andric 
99*fe013be4SDimitry Andric   case CK_IntegralToFloating: {
100*fe013be4SDimitry Andric     std::optional<PrimType> FromT = classify(SubExpr->getType());
101*fe013be4SDimitry Andric     if (!FromT)
102*fe013be4SDimitry Andric       return false;
103*fe013be4SDimitry Andric 
104*fe013be4SDimitry Andric     if (!this->visit(SubExpr))
105*fe013be4SDimitry Andric       return false;
106*fe013be4SDimitry Andric 
107*fe013be4SDimitry Andric     const auto *TargetSemantics = &Ctx.getFloatSemantics(CE->getType());
108*fe013be4SDimitry Andric     llvm::RoundingMode RM = getRoundingMode(CE);
109*fe013be4SDimitry Andric     return this->emitCastIntegralFloating(*FromT, TargetSemantics, RM, CE);
110*fe013be4SDimitry Andric   }
111*fe013be4SDimitry Andric 
112*fe013be4SDimitry Andric   case CK_FloatingToBoolean:
113*fe013be4SDimitry Andric   case CK_FloatingToIntegral: {
114*fe013be4SDimitry Andric     std::optional<PrimType> ToT = classify(CE->getType());
115*fe013be4SDimitry Andric 
116*fe013be4SDimitry Andric     if (!ToT)
117*fe013be4SDimitry Andric       return false;
118*fe013be4SDimitry Andric 
119*fe013be4SDimitry Andric     if (!this->visit(SubExpr))
120*fe013be4SDimitry Andric       return false;
121*fe013be4SDimitry Andric 
122*fe013be4SDimitry Andric     return this->emitCastFloatingIntegral(*ToT, CE);
123*fe013be4SDimitry Andric   }
124*fe013be4SDimitry Andric 
125*fe013be4SDimitry Andric   case CK_NullToPointer:
126*fe013be4SDimitry Andric     if (DiscardResult)
127*fe013be4SDimitry Andric       return true;
128*fe013be4SDimitry Andric     return this->emitNull(classifyPrim(CE->getType()), CE);
129*fe013be4SDimitry Andric 
130a7dea167SDimitry Andric   case CK_ArrayToPointerDecay:
131a7dea167SDimitry Andric   case CK_AtomicToNonAtomic:
132a7dea167SDimitry Andric   case CK_ConstructorConversion:
133a7dea167SDimitry Andric   case CK_FunctionToPointerDecay:
134a7dea167SDimitry Andric   case CK_NonAtomicToAtomic:
135a7dea167SDimitry Andric   case CK_NoOp:
136a7dea167SDimitry Andric   case CK_UserDefinedConversion:
137bdd1243dSDimitry Andric     return this->visit(SubExpr);
138bdd1243dSDimitry Andric 
139bdd1243dSDimitry Andric   case CK_IntegralToBoolean:
140bdd1243dSDimitry Andric   case CK_IntegralCast: {
141bdd1243dSDimitry Andric     std::optional<PrimType> FromT = classify(SubExpr->getType());
142bdd1243dSDimitry Andric     std::optional<PrimType> ToT = classify(CE->getType());
143bdd1243dSDimitry Andric     if (!FromT || !ToT)
144bdd1243dSDimitry Andric       return false;
145bdd1243dSDimitry Andric 
146bdd1243dSDimitry Andric     if (!this->visit(SubExpr))
147bdd1243dSDimitry Andric       return false;
148bdd1243dSDimitry Andric 
149*fe013be4SDimitry Andric     if (FromT == ToT)
150*fe013be4SDimitry Andric       return true;
151*fe013be4SDimitry Andric 
152bdd1243dSDimitry Andric     return this->emitCast(*FromT, *ToT, CE);
153bdd1243dSDimitry Andric   }
154a7dea167SDimitry Andric 
155*fe013be4SDimitry Andric   case CK_PointerToBoolean: {
156*fe013be4SDimitry Andric     // Just emit p != nullptr for this.
157*fe013be4SDimitry Andric     if (!this->visit(SubExpr))
158*fe013be4SDimitry Andric       return false;
159*fe013be4SDimitry Andric 
160*fe013be4SDimitry Andric     if (!this->emitNullPtr(CE))
161*fe013be4SDimitry Andric       return false;
162*fe013be4SDimitry Andric 
163*fe013be4SDimitry Andric     return this->emitNEPtr(CE);
164*fe013be4SDimitry Andric   }
165*fe013be4SDimitry Andric 
166a7dea167SDimitry Andric   case CK_ToVoid:
167a7dea167SDimitry Andric     return discard(SubExpr);
168a7dea167SDimitry Andric 
169bdd1243dSDimitry Andric   default:
170bdd1243dSDimitry Andric     assert(false && "Cast not implemented");
171a7dea167SDimitry Andric   }
172bdd1243dSDimitry Andric   llvm_unreachable("Unhandled clang::CastKind enum");
173a7dea167SDimitry Andric }
174a7dea167SDimitry Andric 
175a7dea167SDimitry Andric template <class Emitter>
176a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitIntegerLiteral(const IntegerLiteral *LE) {
177a7dea167SDimitry Andric   if (DiscardResult)
178a7dea167SDimitry Andric     return true;
179a7dea167SDimitry Andric 
180bdd1243dSDimitry Andric   return this->emitConst(LE->getValue(), LE);
181a7dea167SDimitry Andric }
182a7dea167SDimitry Andric 
183a7dea167SDimitry Andric template <class Emitter>
184*fe013be4SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitFloatingLiteral(const FloatingLiteral *E) {
185*fe013be4SDimitry Andric   if (DiscardResult)
186*fe013be4SDimitry Andric     return true;
187*fe013be4SDimitry Andric 
188*fe013be4SDimitry Andric   return this->emitConstFloat(E->getValue(), E);
189*fe013be4SDimitry Andric }
190*fe013be4SDimitry Andric 
191*fe013be4SDimitry Andric template <class Emitter>
192a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitParenExpr(const ParenExpr *PE) {
193*fe013be4SDimitry Andric   const Expr *SubExpr = PE->getSubExpr();
194*fe013be4SDimitry Andric 
195*fe013be4SDimitry Andric   if (DiscardResult)
196*fe013be4SDimitry Andric     return this->discard(SubExpr);
197*fe013be4SDimitry Andric 
198*fe013be4SDimitry Andric   return this->visit(SubExpr);
199a7dea167SDimitry Andric }
200a7dea167SDimitry Andric 
201a7dea167SDimitry Andric template <class Emitter>
202a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitBinaryOperator(const BinaryOperator *BO) {
203*fe013be4SDimitry Andric   // Need short-circuiting for these.
204*fe013be4SDimitry Andric   if (BO->isLogicalOp())
205*fe013be4SDimitry Andric     return this->VisitLogicalBinOp(BO);
206*fe013be4SDimitry Andric 
207a7dea167SDimitry Andric   const Expr *LHS = BO->getLHS();
208a7dea167SDimitry Andric   const Expr *RHS = BO->getRHS();
209a7dea167SDimitry Andric 
210a7dea167SDimitry Andric   // Typecheck the args.
211bdd1243dSDimitry Andric   std::optional<PrimType> LT = classify(LHS->getType());
212bdd1243dSDimitry Andric   std::optional<PrimType> RT = classify(RHS->getType());
213bdd1243dSDimitry Andric   std::optional<PrimType> T = classify(BO->getType());
214bdd1243dSDimitry Andric   if (!LT || !RT || !T) {
215a7dea167SDimitry Andric     return this->bail(BO);
216a7dea167SDimitry Andric   }
217a7dea167SDimitry Andric 
218a7dea167SDimitry Andric   auto Discard = [this, T, BO](bool Result) {
219a7dea167SDimitry Andric     if (!Result)
220a7dea167SDimitry Andric       return false;
221a7dea167SDimitry Andric     return DiscardResult ? this->emitPop(*T, BO) : true;
222a7dea167SDimitry Andric   };
223a7dea167SDimitry Andric 
224*fe013be4SDimitry Andric   // Deal with operations which have composite or void types.
225*fe013be4SDimitry Andric   if (BO->isCommaOp()) {
226*fe013be4SDimitry Andric     if (!discard(LHS))
227*fe013be4SDimitry Andric       return false;
228*fe013be4SDimitry Andric     return Discard(this->visit(RHS));
229*fe013be4SDimitry Andric   }
230*fe013be4SDimitry Andric 
231bdd1243dSDimitry Andric   // Pointer arithmetic special case.
232bdd1243dSDimitry Andric   if (BO->getOpcode() == BO_Add || BO->getOpcode() == BO_Sub) {
233*fe013be4SDimitry Andric     if (T == PT_Ptr || (LT == PT_Ptr && RT == PT_Ptr))
234bdd1243dSDimitry Andric       return this->VisitPointerArithBinOp(BO);
235bdd1243dSDimitry Andric   }
236bdd1243dSDimitry Andric 
237bdd1243dSDimitry Andric   if (!visit(LHS) || !visit(RHS))
238bdd1243dSDimitry Andric     return false;
239bdd1243dSDimitry Andric 
240*fe013be4SDimitry Andric   // For languages such as C, cast the result of one
241*fe013be4SDimitry Andric   // of our comparision opcodes to T (which is usually int).
242*fe013be4SDimitry Andric   auto MaybeCastToBool = [this, T, BO](bool Result) {
243*fe013be4SDimitry Andric     if (!Result)
244*fe013be4SDimitry Andric       return false;
245*fe013be4SDimitry Andric     if (DiscardResult)
246*fe013be4SDimitry Andric       return this->emitPop(*T, BO);
247*fe013be4SDimitry Andric     if (T != PT_Bool)
248*fe013be4SDimitry Andric       return this->emitCast(PT_Bool, *T, BO);
249*fe013be4SDimitry Andric     return true;
250*fe013be4SDimitry Andric   };
251*fe013be4SDimitry Andric 
252a7dea167SDimitry Andric   switch (BO->getOpcode()) {
253a7dea167SDimitry Andric   case BO_EQ:
254*fe013be4SDimitry Andric     return MaybeCastToBool(this->emitEQ(*LT, BO));
255a7dea167SDimitry Andric   case BO_NE:
256*fe013be4SDimitry Andric     return MaybeCastToBool(this->emitNE(*LT, BO));
257a7dea167SDimitry Andric   case BO_LT:
258*fe013be4SDimitry Andric     return MaybeCastToBool(this->emitLT(*LT, BO));
259a7dea167SDimitry Andric   case BO_LE:
260*fe013be4SDimitry Andric     return MaybeCastToBool(this->emitLE(*LT, BO));
261a7dea167SDimitry Andric   case BO_GT:
262*fe013be4SDimitry Andric     return MaybeCastToBool(this->emitGT(*LT, BO));
263a7dea167SDimitry Andric   case BO_GE:
264*fe013be4SDimitry Andric     return MaybeCastToBool(this->emitGE(*LT, BO));
265a7dea167SDimitry Andric   case BO_Sub:
266*fe013be4SDimitry Andric     if (BO->getType()->isFloatingType())
267*fe013be4SDimitry Andric       return Discard(this->emitSubf(getRoundingMode(BO), BO));
268a7dea167SDimitry Andric     return Discard(this->emitSub(*T, BO));
269a7dea167SDimitry Andric   case BO_Add:
270*fe013be4SDimitry Andric     if (BO->getType()->isFloatingType())
271*fe013be4SDimitry Andric       return Discard(this->emitAddf(getRoundingMode(BO), BO));
272a7dea167SDimitry Andric     return Discard(this->emitAdd(*T, BO));
273a7dea167SDimitry Andric   case BO_Mul:
274*fe013be4SDimitry Andric     if (BO->getType()->isFloatingType())
275*fe013be4SDimitry Andric       return Discard(this->emitMulf(getRoundingMode(BO), BO));
276a7dea167SDimitry Andric     return Discard(this->emitMul(*T, BO));
277bdd1243dSDimitry Andric   case BO_Rem:
278bdd1243dSDimitry Andric     return Discard(this->emitRem(*T, BO));
279bdd1243dSDimitry Andric   case BO_Div:
280*fe013be4SDimitry Andric     if (BO->getType()->isFloatingType())
281*fe013be4SDimitry Andric       return Discard(this->emitDivf(getRoundingMode(BO), BO));
282bdd1243dSDimitry Andric     return Discard(this->emitDiv(*T, BO));
283bdd1243dSDimitry Andric   case BO_Assign:
284bdd1243dSDimitry Andric     if (DiscardResult)
285bdd1243dSDimitry Andric       return this->emitStorePop(*T, BO);
286bdd1243dSDimitry Andric     return this->emitStore(*T, BO);
287bdd1243dSDimitry Andric   case BO_And:
288bdd1243dSDimitry Andric     return Discard(this->emitBitAnd(*T, BO));
289bdd1243dSDimitry Andric   case BO_Or:
290bdd1243dSDimitry Andric     return Discard(this->emitBitOr(*T, BO));
291bdd1243dSDimitry Andric   case BO_Shl:
292bdd1243dSDimitry Andric     return Discard(this->emitShl(*LT, *RT, BO));
293bdd1243dSDimitry Andric   case BO_Shr:
294bdd1243dSDimitry Andric     return Discard(this->emitShr(*LT, *RT, BO));
295bdd1243dSDimitry Andric   case BO_Xor:
296bdd1243dSDimitry Andric     return Discard(this->emitBitXor(*T, BO));
297bdd1243dSDimitry Andric   case BO_LOr:
298*fe013be4SDimitry Andric   case BO_LAnd:
299*fe013be4SDimitry Andric     llvm_unreachable("Already handled earlier");
300a7dea167SDimitry Andric   default:
301a7dea167SDimitry Andric     return this->bail(BO);
302a7dea167SDimitry Andric   }
303bdd1243dSDimitry Andric 
304bdd1243dSDimitry Andric   llvm_unreachable("Unhandled binary op");
305a7dea167SDimitry Andric }
306a7dea167SDimitry Andric 
307bdd1243dSDimitry Andric /// Perform addition/subtraction of a pointer and an integer or
308bdd1243dSDimitry Andric /// subtraction of two pointers.
309bdd1243dSDimitry Andric template <class Emitter>
310bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitPointerArithBinOp(const BinaryOperator *E) {
311bdd1243dSDimitry Andric   BinaryOperatorKind Op = E->getOpcode();
312bdd1243dSDimitry Andric   const Expr *LHS = E->getLHS();
313bdd1243dSDimitry Andric   const Expr *RHS = E->getRHS();
314bdd1243dSDimitry Andric 
315bdd1243dSDimitry Andric   if ((Op != BO_Add && Op != BO_Sub) ||
316bdd1243dSDimitry Andric       (!LHS->getType()->isPointerType() && !RHS->getType()->isPointerType()))
317bdd1243dSDimitry Andric     return false;
318bdd1243dSDimitry Andric 
319bdd1243dSDimitry Andric   std::optional<PrimType> LT = classify(LHS);
320bdd1243dSDimitry Andric   std::optional<PrimType> RT = classify(RHS);
321bdd1243dSDimitry Andric 
322bdd1243dSDimitry Andric   if (!LT || !RT)
323bdd1243dSDimitry Andric     return false;
324bdd1243dSDimitry Andric 
325bdd1243dSDimitry Andric   if (LHS->getType()->isPointerType() && RHS->getType()->isPointerType()) {
326bdd1243dSDimitry Andric     if (Op != BO_Sub)
327bdd1243dSDimitry Andric       return false;
328bdd1243dSDimitry Andric 
329bdd1243dSDimitry Andric     assert(E->getType()->isIntegerType());
330bdd1243dSDimitry Andric     if (!visit(RHS) || !visit(LHS))
331bdd1243dSDimitry Andric       return false;
332bdd1243dSDimitry Andric 
333bdd1243dSDimitry Andric     return this->emitSubPtr(classifyPrim(E->getType()), E);
334bdd1243dSDimitry Andric   }
335bdd1243dSDimitry Andric 
336bdd1243dSDimitry Andric   PrimType OffsetType;
337bdd1243dSDimitry Andric   if (LHS->getType()->isIntegerType()) {
338bdd1243dSDimitry Andric     if (!visit(RHS) || !visit(LHS))
339bdd1243dSDimitry Andric       return false;
340bdd1243dSDimitry Andric     OffsetType = *LT;
341bdd1243dSDimitry Andric   } else if (RHS->getType()->isIntegerType()) {
342bdd1243dSDimitry Andric     if (!visit(LHS) || !visit(RHS))
343bdd1243dSDimitry Andric       return false;
344bdd1243dSDimitry Andric     OffsetType = *RT;
345bdd1243dSDimitry Andric   } else {
346bdd1243dSDimitry Andric     return false;
347bdd1243dSDimitry Andric   }
348bdd1243dSDimitry Andric 
349bdd1243dSDimitry Andric   if (Op == BO_Add)
350bdd1243dSDimitry Andric     return this->emitAddOffset(OffsetType, E);
351bdd1243dSDimitry Andric   else if (Op == BO_Sub)
352bdd1243dSDimitry Andric     return this->emitSubOffset(OffsetType, E);
353bdd1243dSDimitry Andric 
354bdd1243dSDimitry Andric   return this->bail(E);
355a7dea167SDimitry Andric }
356a7dea167SDimitry Andric 
357a7dea167SDimitry Andric template <class Emitter>
358*fe013be4SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitLogicalBinOp(const BinaryOperator *E) {
359*fe013be4SDimitry Andric   assert(E->isLogicalOp());
360*fe013be4SDimitry Andric   BinaryOperatorKind Op = E->getOpcode();
361*fe013be4SDimitry Andric   const Expr *LHS = E->getLHS();
362*fe013be4SDimitry Andric   const Expr *RHS = E->getRHS();
363bdd1243dSDimitry Andric 
364*fe013be4SDimitry Andric   if (Op == BO_LOr) {
365*fe013be4SDimitry Andric     // Logical OR. Visit LHS and only evaluate RHS if LHS was FALSE.
366*fe013be4SDimitry Andric     LabelTy LabelTrue = this->getLabel();
367*fe013be4SDimitry Andric     LabelTy LabelEnd = this->getLabel();
368*fe013be4SDimitry Andric 
369*fe013be4SDimitry Andric     if (!this->visit(LHS))
370bdd1243dSDimitry Andric       return false;
371*fe013be4SDimitry Andric     if (!this->jumpTrue(LabelTrue))
372*fe013be4SDimitry Andric       return false;
373*fe013be4SDimitry Andric 
374*fe013be4SDimitry Andric     if (!this->visit(RHS))
375*fe013be4SDimitry Andric       return false;
376*fe013be4SDimitry Andric     if (!this->jump(LabelEnd))
377*fe013be4SDimitry Andric       return false;
378*fe013be4SDimitry Andric 
379*fe013be4SDimitry Andric     this->emitLabel(LabelTrue);
380*fe013be4SDimitry Andric     this->emitConstBool(true, E);
381*fe013be4SDimitry Andric     this->fallthrough(LabelEnd);
382*fe013be4SDimitry Andric     this->emitLabel(LabelEnd);
383*fe013be4SDimitry Andric 
384*fe013be4SDimitry Andric     if (DiscardResult)
385*fe013be4SDimitry Andric       return this->emitPopBool(E);
386*fe013be4SDimitry Andric 
387*fe013be4SDimitry Andric     return true;
388*fe013be4SDimitry Andric   }
389*fe013be4SDimitry Andric 
390*fe013be4SDimitry Andric   // Logical AND.
391*fe013be4SDimitry Andric   // Visit LHS. Only visit RHS if LHS was TRUE.
392*fe013be4SDimitry Andric   LabelTy LabelFalse = this->getLabel();
393*fe013be4SDimitry Andric   LabelTy LabelEnd = this->getLabel();
394*fe013be4SDimitry Andric 
395*fe013be4SDimitry Andric   if (!this->visit(LHS))
396*fe013be4SDimitry Andric     return false;
397*fe013be4SDimitry Andric   if (!this->jumpFalse(LabelFalse))
398*fe013be4SDimitry Andric     return false;
399*fe013be4SDimitry Andric 
400*fe013be4SDimitry Andric   if (!this->visit(RHS))
401*fe013be4SDimitry Andric     return false;
402*fe013be4SDimitry Andric   if (!this->jump(LabelEnd))
403*fe013be4SDimitry Andric     return false;
404*fe013be4SDimitry Andric 
405*fe013be4SDimitry Andric   this->emitLabel(LabelFalse);
406*fe013be4SDimitry Andric   this->emitConstBool(false, E);
407*fe013be4SDimitry Andric   this->fallthrough(LabelEnd);
408*fe013be4SDimitry Andric   this->emitLabel(LabelEnd);
409*fe013be4SDimitry Andric 
410*fe013be4SDimitry Andric   if (DiscardResult)
411*fe013be4SDimitry Andric     return this->emitPopBool(E);
412*fe013be4SDimitry Andric 
413*fe013be4SDimitry Andric   return true;
414*fe013be4SDimitry Andric }
415*fe013be4SDimitry Andric 
416*fe013be4SDimitry Andric template <class Emitter>
417*fe013be4SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E) {
418*fe013be4SDimitry Andric   std::optional<PrimType> T = classify(E);
419*fe013be4SDimitry Andric 
420*fe013be4SDimitry Andric   if (!T)
421*fe013be4SDimitry Andric     return false;
422*fe013be4SDimitry Andric 
423*fe013be4SDimitry Andric   return this->visitZeroInitializer(E->getType(), E);
424bdd1243dSDimitry Andric }
425bdd1243dSDimitry Andric 
426bdd1243dSDimitry Andric template <class Emitter>
427bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitArraySubscriptExpr(
428bdd1243dSDimitry Andric     const ArraySubscriptExpr *E) {
429bdd1243dSDimitry Andric   const Expr *Base = E->getBase();
430bdd1243dSDimitry Andric   const Expr *Index = E->getIdx();
431bdd1243dSDimitry Andric   PrimType IndexT = classifyPrim(Index->getType());
432bdd1243dSDimitry Andric 
433*fe013be4SDimitry Andric   // Take pointer of LHS, add offset from RHS.
434bdd1243dSDimitry Andric   // What's left on the stack after this is a pointer.
435bdd1243dSDimitry Andric   if (!this->visit(Base))
436bdd1243dSDimitry Andric     return false;
437bdd1243dSDimitry Andric 
438bdd1243dSDimitry Andric   if (!this->visit(Index))
439bdd1243dSDimitry Andric     return false;
440bdd1243dSDimitry Andric 
441*fe013be4SDimitry Andric   if (!this->emitArrayElemPtrPop(IndexT, E))
442bdd1243dSDimitry Andric     return false;
443bdd1243dSDimitry Andric 
444bdd1243dSDimitry Andric   if (DiscardResult)
445bdd1243dSDimitry Andric     return this->emitPopPtr(E);
446bdd1243dSDimitry Andric 
447bdd1243dSDimitry Andric   return true;
448bdd1243dSDimitry Andric }
449bdd1243dSDimitry Andric 
450bdd1243dSDimitry Andric template <class Emitter>
451bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitInitListExpr(const InitListExpr *E) {
452bdd1243dSDimitry Andric   for (const Expr *Init : E->inits()) {
453bdd1243dSDimitry Andric     if (!this->visit(Init))
454bdd1243dSDimitry Andric       return false;
455bdd1243dSDimitry Andric   }
456bdd1243dSDimitry Andric   return true;
457bdd1243dSDimitry Andric }
458bdd1243dSDimitry Andric 
459bdd1243dSDimitry Andric template <class Emitter>
460bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitSubstNonTypeTemplateParmExpr(
461bdd1243dSDimitry Andric     const SubstNonTypeTemplateParmExpr *E) {
462bdd1243dSDimitry Andric   return this->visit(E->getReplacement());
463bdd1243dSDimitry Andric }
464bdd1243dSDimitry Andric 
465bdd1243dSDimitry Andric template <class Emitter>
466bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitConstantExpr(const ConstantExpr *E) {
467bdd1243dSDimitry Andric   // TODO: Check if the ConstantExpr already has a value set and if so,
468bdd1243dSDimitry Andric   //   use that instead of evaluating it again.
469bdd1243dSDimitry Andric   return this->visit(E->getSubExpr());
470bdd1243dSDimitry Andric }
471bdd1243dSDimitry Andric 
472bdd1243dSDimitry Andric static CharUnits AlignOfType(QualType T, const ASTContext &ASTCtx,
473bdd1243dSDimitry Andric                              UnaryExprOrTypeTrait Kind) {
474bdd1243dSDimitry Andric   bool AlignOfReturnsPreferred =
475bdd1243dSDimitry Andric       ASTCtx.getLangOpts().getClangABICompat() <= LangOptions::ClangABI::Ver7;
476bdd1243dSDimitry Andric 
477bdd1243dSDimitry Andric   // C++ [expr.alignof]p3:
478bdd1243dSDimitry Andric   //     When alignof is applied to a reference type, the result is the
479bdd1243dSDimitry Andric   //     alignment of the referenced type.
480bdd1243dSDimitry Andric   if (const auto *Ref = T->getAs<ReferenceType>())
481bdd1243dSDimitry Andric     T = Ref->getPointeeType();
482bdd1243dSDimitry Andric 
483bdd1243dSDimitry Andric   // __alignof is defined to return the preferred alignment.
484bdd1243dSDimitry Andric   // Before 8, clang returned the preferred alignment for alignof and
485bdd1243dSDimitry Andric   // _Alignof as well.
486bdd1243dSDimitry Andric   if (Kind == UETT_PreferredAlignOf || AlignOfReturnsPreferred)
487bdd1243dSDimitry Andric     return ASTCtx.toCharUnitsFromBits(ASTCtx.getPreferredTypeAlign(T));
488bdd1243dSDimitry Andric 
489bdd1243dSDimitry Andric   return ASTCtx.getTypeAlignInChars(T);
490bdd1243dSDimitry Andric }
491bdd1243dSDimitry Andric 
492bdd1243dSDimitry Andric template <class Emitter>
493bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitUnaryExprOrTypeTraitExpr(
494bdd1243dSDimitry Andric     const UnaryExprOrTypeTraitExpr *E) {
495bdd1243dSDimitry Andric   UnaryExprOrTypeTrait Kind = E->getKind();
496bdd1243dSDimitry Andric   ASTContext &ASTCtx = Ctx.getASTContext();
497bdd1243dSDimitry Andric 
498bdd1243dSDimitry Andric   if (Kind == UETT_SizeOf) {
499bdd1243dSDimitry Andric     QualType ArgType = E->getTypeOfArgument();
500bdd1243dSDimitry Andric     CharUnits Size;
501bdd1243dSDimitry Andric     if (ArgType->isVoidType() || ArgType->isFunctionType())
502bdd1243dSDimitry Andric       Size = CharUnits::One();
503bdd1243dSDimitry Andric     else {
504bdd1243dSDimitry Andric       if (ArgType->isDependentType() || !ArgType->isConstantSizeType())
505bdd1243dSDimitry Andric         return false;
506bdd1243dSDimitry Andric 
507bdd1243dSDimitry Andric       Size = ASTCtx.getTypeSizeInChars(ArgType);
508bdd1243dSDimitry Andric     }
509bdd1243dSDimitry Andric 
510bdd1243dSDimitry Andric     return this->emitConst(Size.getQuantity(), E);
511bdd1243dSDimitry Andric   }
512bdd1243dSDimitry Andric 
513bdd1243dSDimitry Andric   if (Kind == UETT_AlignOf || Kind == UETT_PreferredAlignOf) {
514bdd1243dSDimitry Andric     CharUnits Size;
515bdd1243dSDimitry Andric 
516bdd1243dSDimitry Andric     if (E->isArgumentType()) {
517bdd1243dSDimitry Andric       QualType ArgType = E->getTypeOfArgument();
518bdd1243dSDimitry Andric 
519bdd1243dSDimitry Andric       Size = AlignOfType(ArgType, ASTCtx, Kind);
520bdd1243dSDimitry Andric     } else {
521bdd1243dSDimitry Andric       // Argument is an expression, not a type.
522bdd1243dSDimitry Andric       const Expr *Arg = E->getArgumentExpr()->IgnoreParens();
523bdd1243dSDimitry Andric 
524bdd1243dSDimitry Andric       // The kinds of expressions that we have special-case logic here for
525bdd1243dSDimitry Andric       // should be kept up to date with the special checks for those
526bdd1243dSDimitry Andric       // expressions in Sema.
527bdd1243dSDimitry Andric 
528bdd1243dSDimitry Andric       // alignof decl is always accepted, even if it doesn't make sense: we
529bdd1243dSDimitry Andric       // default to 1 in those cases.
530bdd1243dSDimitry Andric       if (const auto *DRE = dyn_cast<DeclRefExpr>(Arg))
531bdd1243dSDimitry Andric         Size = ASTCtx.getDeclAlign(DRE->getDecl(),
532bdd1243dSDimitry Andric                                    /*RefAsPointee*/ true);
533bdd1243dSDimitry Andric       else if (const auto *ME = dyn_cast<MemberExpr>(Arg))
534bdd1243dSDimitry Andric         Size = ASTCtx.getDeclAlign(ME->getMemberDecl(),
535bdd1243dSDimitry Andric                                    /*RefAsPointee*/ true);
536bdd1243dSDimitry Andric       else
537bdd1243dSDimitry Andric         Size = AlignOfType(Arg->getType(), ASTCtx, Kind);
538bdd1243dSDimitry Andric     }
539bdd1243dSDimitry Andric 
540bdd1243dSDimitry Andric     return this->emitConst(Size.getQuantity(), E);
541bdd1243dSDimitry Andric   }
542bdd1243dSDimitry Andric 
543bdd1243dSDimitry Andric   return false;
544bdd1243dSDimitry Andric }
545bdd1243dSDimitry Andric 
546bdd1243dSDimitry Andric template <class Emitter>
547bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitMemberExpr(const MemberExpr *E) {
548bdd1243dSDimitry Andric   if (DiscardResult)
549bdd1243dSDimitry Andric     return true;
550bdd1243dSDimitry Andric 
551bdd1243dSDimitry Andric   // 'Base.Member'
552bdd1243dSDimitry Andric   const Expr *Base = E->getBase();
553bdd1243dSDimitry Andric   const ValueDecl *Member = E->getMemberDecl();
554bdd1243dSDimitry Andric 
555bdd1243dSDimitry Andric   if (!this->visit(Base))
556bdd1243dSDimitry Andric     return false;
557bdd1243dSDimitry Andric 
558bdd1243dSDimitry Andric   // Base above gives us a pointer on the stack.
559bdd1243dSDimitry Andric   // TODO: Implement non-FieldDecl members.
560bdd1243dSDimitry Andric   if (const auto *FD = dyn_cast<FieldDecl>(Member)) {
561bdd1243dSDimitry Andric     const RecordDecl *RD = FD->getParent();
562bdd1243dSDimitry Andric     const Record *R = getRecord(RD);
563bdd1243dSDimitry Andric     const Record::Field *F = R->getField(FD);
564bdd1243dSDimitry Andric     // Leave a pointer to the field on the stack.
565bdd1243dSDimitry Andric     if (F->Decl->getType()->isReferenceType())
566bdd1243dSDimitry Andric       return this->emitGetFieldPop(PT_Ptr, F->Offset, E);
567bdd1243dSDimitry Andric     return this->emitGetPtrField(F->Offset, E);
568bdd1243dSDimitry Andric   }
569bdd1243dSDimitry Andric 
570bdd1243dSDimitry Andric   return false;
571bdd1243dSDimitry Andric }
572bdd1243dSDimitry Andric 
573bdd1243dSDimitry Andric template <class Emitter>
574bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitArrayInitIndexExpr(
575bdd1243dSDimitry Andric     const ArrayInitIndexExpr *E) {
576bdd1243dSDimitry Andric   // ArrayIndex might not be set if a ArrayInitIndexExpr is being evaluated
577bdd1243dSDimitry Andric   // stand-alone, e.g. via EvaluateAsInt().
578bdd1243dSDimitry Andric   if (!ArrayIndex)
579bdd1243dSDimitry Andric     return false;
580bdd1243dSDimitry Andric   return this->emitConst(*ArrayIndex, E);
581bdd1243dSDimitry Andric }
582bdd1243dSDimitry Andric 
583bdd1243dSDimitry Andric template <class Emitter>
584bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitOpaqueValueExpr(const OpaqueValueExpr *E) {
585bdd1243dSDimitry Andric   return this->visit(E->getSourceExpr());
586bdd1243dSDimitry Andric }
587bdd1243dSDimitry Andric 
588bdd1243dSDimitry Andric template <class Emitter>
589bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitAbstractConditionalOperator(
590bdd1243dSDimitry Andric     const AbstractConditionalOperator *E) {
591*fe013be4SDimitry Andric   return this->visitConditional(
592*fe013be4SDimitry Andric       E, [this](const Expr *E) { return this->visit(E); });
593bdd1243dSDimitry Andric }
594bdd1243dSDimitry Andric 
595bdd1243dSDimitry Andric template <class Emitter>
596bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitStringLiteral(const StringLiteral *E) {
597bdd1243dSDimitry Andric   unsigned StringIndex = P.createGlobalString(E);
598bdd1243dSDimitry Andric   return this->emitGetPtrGlobal(StringIndex, E);
599bdd1243dSDimitry Andric }
600bdd1243dSDimitry Andric 
601bdd1243dSDimitry Andric template <class Emitter>
602bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCharacterLiteral(
603bdd1243dSDimitry Andric     const CharacterLiteral *E) {
604bdd1243dSDimitry Andric   return this->emitConst(E->getValue(), E);
605bdd1243dSDimitry Andric }
606bdd1243dSDimitry Andric 
607bdd1243dSDimitry Andric template <class Emitter>
608*fe013be4SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitFloatCompoundAssignOperator(
609bdd1243dSDimitry Andric     const CompoundAssignOperator *E) {
610*fe013be4SDimitry Andric   assert(E->getType()->isFloatingType());
611*fe013be4SDimitry Andric 
612bdd1243dSDimitry Andric   const Expr *LHS = E->getLHS();
613bdd1243dSDimitry Andric   const Expr *RHS = E->getRHS();
614*fe013be4SDimitry Andric   llvm::RoundingMode RM = getRoundingMode(E);
615*fe013be4SDimitry Andric   QualType LHSComputationType = E->getComputationLHSType();
616*fe013be4SDimitry Andric   QualType ResultType = E->getComputationResultType();
617*fe013be4SDimitry Andric   std::optional<PrimType> LT = classify(LHSComputationType);
618*fe013be4SDimitry Andric   std::optional<PrimType> RT = classify(ResultType);
619bdd1243dSDimitry Andric 
620bdd1243dSDimitry Andric   if (!LT || !RT)
621bdd1243dSDimitry Andric     return false;
622bdd1243dSDimitry Andric 
623*fe013be4SDimitry Andric   // C++17 onwards require that we evaluate the RHS first.
624*fe013be4SDimitry Andric   // Compute RHS and save it in a temporary variable so we can
625*fe013be4SDimitry Andric   // load it again later.
626*fe013be4SDimitry Andric   if (!visit(RHS))
627*fe013be4SDimitry Andric     return false;
628bdd1243dSDimitry Andric 
629*fe013be4SDimitry Andric   unsigned TempOffset = this->allocateLocalPrimitive(E, *RT, /*IsConst=*/true);
630*fe013be4SDimitry Andric   if (!this->emitSetLocal(*RT, TempOffset, E))
631*fe013be4SDimitry Andric     return false;
632*fe013be4SDimitry Andric 
633*fe013be4SDimitry Andric   // First, visit LHS.
634bdd1243dSDimitry Andric   if (!visit(LHS))
635bdd1243dSDimitry Andric     return false;
636bdd1243dSDimitry Andric   if (!this->emitLoad(*LT, E))
637bdd1243dSDimitry Andric     return false;
638*fe013be4SDimitry Andric 
639*fe013be4SDimitry Andric   // If necessary, convert LHS to its computation type.
640*fe013be4SDimitry Andric   if (LHS->getType() != LHSComputationType) {
641*fe013be4SDimitry Andric     const auto *TargetSemantics = &Ctx.getFloatSemantics(LHSComputationType);
642*fe013be4SDimitry Andric 
643*fe013be4SDimitry Andric     if (!this->emitCastFP(TargetSemantics, RM, E))
644*fe013be4SDimitry Andric       return false;
645*fe013be4SDimitry Andric   }
646*fe013be4SDimitry Andric 
647*fe013be4SDimitry Andric   // Now load RHS.
648*fe013be4SDimitry Andric   if (!this->emitGetLocal(*RT, TempOffset, E))
649bdd1243dSDimitry Andric     return false;
650bdd1243dSDimitry Andric 
651bdd1243dSDimitry Andric   switch (E->getOpcode()) {
652bdd1243dSDimitry Andric   case BO_AddAssign:
653*fe013be4SDimitry Andric     if (!this->emitAddf(RM, E))
654bdd1243dSDimitry Andric       return false;
655bdd1243dSDimitry Andric     break;
656bdd1243dSDimitry Andric   case BO_SubAssign:
657*fe013be4SDimitry Andric     if (!this->emitSubf(RM, E))
658bdd1243dSDimitry Andric       return false;
659bdd1243dSDimitry Andric     break;
660bdd1243dSDimitry Andric   case BO_MulAssign:
661*fe013be4SDimitry Andric     if (!this->emitMulf(RM, E))
662*fe013be4SDimitry Andric       return false;
663*fe013be4SDimitry Andric     break;
664bdd1243dSDimitry Andric   case BO_DivAssign:
665*fe013be4SDimitry Andric     if (!this->emitDivf(RM, E))
666bdd1243dSDimitry Andric       return false;
667bdd1243dSDimitry Andric     break;
668bdd1243dSDimitry Andric   default:
669*fe013be4SDimitry Andric     return false;
670bdd1243dSDimitry Andric   }
671bdd1243dSDimitry Andric 
672*fe013be4SDimitry Andric   // If necessary, convert result to LHS's type.
673*fe013be4SDimitry Andric   if (LHS->getType() != ResultType) {
674*fe013be4SDimitry Andric     const auto *TargetSemantics = &Ctx.getFloatSemantics(LHS->getType());
675*fe013be4SDimitry Andric 
676*fe013be4SDimitry Andric     if (!this->emitCastFP(TargetSemantics, RM, E))
677*fe013be4SDimitry Andric       return false;
678*fe013be4SDimitry Andric   }
679*fe013be4SDimitry Andric 
680bdd1243dSDimitry Andric   if (DiscardResult)
681bdd1243dSDimitry Andric     return this->emitStorePop(*LT, E);
682bdd1243dSDimitry Andric   return this->emitStore(*LT, E);
683bdd1243dSDimitry Andric }
684bdd1243dSDimitry Andric 
685*fe013be4SDimitry Andric template <class Emitter>
686*fe013be4SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitPointerCompoundAssignOperator(
687*fe013be4SDimitry Andric     const CompoundAssignOperator *E) {
688*fe013be4SDimitry Andric   BinaryOperatorKind Op = E->getOpcode();
689*fe013be4SDimitry Andric   const Expr *LHS = E->getLHS();
690*fe013be4SDimitry Andric   const Expr *RHS = E->getRHS();
691*fe013be4SDimitry Andric   std::optional<PrimType> LT = classify(LHS->getType());
692*fe013be4SDimitry Andric   std::optional<PrimType> RT = classify(RHS->getType());
693*fe013be4SDimitry Andric 
694*fe013be4SDimitry Andric   if (Op != BO_AddAssign && Op != BO_SubAssign)
695*fe013be4SDimitry Andric     return false;
696*fe013be4SDimitry Andric 
697*fe013be4SDimitry Andric   if (!LT || !RT)
698*fe013be4SDimitry Andric     return false;
699*fe013be4SDimitry Andric   assert(*LT == PT_Ptr);
700*fe013be4SDimitry Andric 
701*fe013be4SDimitry Andric   if (!visit(LHS))
702*fe013be4SDimitry Andric     return false;
703*fe013be4SDimitry Andric 
704*fe013be4SDimitry Andric   if (!this->emitLoadPtr(LHS))
705*fe013be4SDimitry Andric     return false;
706*fe013be4SDimitry Andric 
707*fe013be4SDimitry Andric   if (!visit(RHS))
708*fe013be4SDimitry Andric     return false;
709*fe013be4SDimitry Andric 
710*fe013be4SDimitry Andric   if (Op == BO_AddAssign)
711*fe013be4SDimitry Andric     this->emitAddOffset(*RT, E);
712*fe013be4SDimitry Andric   else
713*fe013be4SDimitry Andric     this->emitSubOffset(*RT, E);
714*fe013be4SDimitry Andric 
715*fe013be4SDimitry Andric   if (DiscardResult)
716*fe013be4SDimitry Andric     return this->emitStorePopPtr(E);
717*fe013be4SDimitry Andric   return this->emitStorePtr(E);
718*fe013be4SDimitry Andric }
719*fe013be4SDimitry Andric 
720*fe013be4SDimitry Andric template <class Emitter>
721*fe013be4SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCompoundAssignOperator(
722*fe013be4SDimitry Andric     const CompoundAssignOperator *E) {
723*fe013be4SDimitry Andric 
724*fe013be4SDimitry Andric   // Handle floating point operations separately here, since they
725*fe013be4SDimitry Andric   // require special care.
726*fe013be4SDimitry Andric   if (E->getType()->isFloatingType())
727*fe013be4SDimitry Andric     return VisitFloatCompoundAssignOperator(E);
728*fe013be4SDimitry Andric 
729*fe013be4SDimitry Andric   if (E->getType()->isPointerType())
730*fe013be4SDimitry Andric     return VisitPointerCompoundAssignOperator(E);
731*fe013be4SDimitry Andric 
732*fe013be4SDimitry Andric   const Expr *LHS = E->getLHS();
733*fe013be4SDimitry Andric   const Expr *RHS = E->getRHS();
734*fe013be4SDimitry Andric   std::optional<PrimType> LHSComputationT =
735*fe013be4SDimitry Andric       classify(E->getComputationLHSType());
736*fe013be4SDimitry Andric   std::optional<PrimType> LT = classify(LHS->getType());
737*fe013be4SDimitry Andric   std::optional<PrimType> RT = classify(E->getComputationResultType());
738*fe013be4SDimitry Andric   std::optional<PrimType> ResultT = classify(E->getType());
739*fe013be4SDimitry Andric 
740*fe013be4SDimitry Andric   if (!LT || !RT || !ResultT || !LHSComputationT)
741*fe013be4SDimitry Andric     return false;
742*fe013be4SDimitry Andric 
743*fe013be4SDimitry Andric   assert(!E->getType()->isPointerType() && "Handled above");
744*fe013be4SDimitry Andric   assert(!E->getType()->isFloatingType() && "Handled above");
745*fe013be4SDimitry Andric 
746*fe013be4SDimitry Andric   // C++17 onwards require that we evaluate the RHS first.
747*fe013be4SDimitry Andric   // Compute RHS and save it in a temporary variable so we can
748*fe013be4SDimitry Andric   // load it again later.
749*fe013be4SDimitry Andric   // FIXME: Compound assignments are unsequenced in C, so we might
750*fe013be4SDimitry Andric   //   have to figure out how to reject them.
751*fe013be4SDimitry Andric   if (!visit(RHS))
752*fe013be4SDimitry Andric     return false;
753*fe013be4SDimitry Andric 
754*fe013be4SDimitry Andric   unsigned TempOffset = this->allocateLocalPrimitive(E, *RT, /*IsConst=*/true);
755*fe013be4SDimitry Andric 
756*fe013be4SDimitry Andric   if (!this->emitSetLocal(*RT, TempOffset, E))
757*fe013be4SDimitry Andric     return false;
758*fe013be4SDimitry Andric 
759*fe013be4SDimitry Andric   // Get LHS pointer, load its value and cast it to the
760*fe013be4SDimitry Andric   // computation type if necessary.
761*fe013be4SDimitry Andric   if (!visit(LHS))
762*fe013be4SDimitry Andric     return false;
763*fe013be4SDimitry Andric   if (!this->emitLoad(*LT, E))
764*fe013be4SDimitry Andric     return false;
765*fe013be4SDimitry Andric   if (*LT != *LHSComputationT) {
766*fe013be4SDimitry Andric     if (!this->emitCast(*LT, *LHSComputationT, E))
767*fe013be4SDimitry Andric       return false;
768*fe013be4SDimitry Andric   }
769*fe013be4SDimitry Andric 
770*fe013be4SDimitry Andric   // Get the RHS value on the stack.
771*fe013be4SDimitry Andric   if (!this->emitGetLocal(*RT, TempOffset, E))
772*fe013be4SDimitry Andric     return false;
773*fe013be4SDimitry Andric 
774*fe013be4SDimitry Andric   // Perform operation.
775*fe013be4SDimitry Andric   switch (E->getOpcode()) {
776*fe013be4SDimitry Andric   case BO_AddAssign:
777*fe013be4SDimitry Andric     if (!this->emitAdd(*LHSComputationT, E))
778*fe013be4SDimitry Andric       return false;
779*fe013be4SDimitry Andric     break;
780*fe013be4SDimitry Andric   case BO_SubAssign:
781*fe013be4SDimitry Andric     if (!this->emitSub(*LHSComputationT, E))
782*fe013be4SDimitry Andric       return false;
783*fe013be4SDimitry Andric     break;
784*fe013be4SDimitry Andric   case BO_MulAssign:
785*fe013be4SDimitry Andric     if (!this->emitMul(*LHSComputationT, E))
786*fe013be4SDimitry Andric       return false;
787*fe013be4SDimitry Andric     break;
788*fe013be4SDimitry Andric   case BO_DivAssign:
789*fe013be4SDimitry Andric     if (!this->emitDiv(*LHSComputationT, E))
790*fe013be4SDimitry Andric       return false;
791*fe013be4SDimitry Andric     break;
792*fe013be4SDimitry Andric   case BO_RemAssign:
793*fe013be4SDimitry Andric     if (!this->emitRem(*LHSComputationT, E))
794*fe013be4SDimitry Andric       return false;
795*fe013be4SDimitry Andric     break;
796*fe013be4SDimitry Andric   case BO_ShlAssign:
797*fe013be4SDimitry Andric     if (!this->emitShl(*LHSComputationT, *RT, E))
798*fe013be4SDimitry Andric       return false;
799*fe013be4SDimitry Andric     break;
800*fe013be4SDimitry Andric   case BO_ShrAssign:
801*fe013be4SDimitry Andric     if (!this->emitShr(*LHSComputationT, *RT, E))
802*fe013be4SDimitry Andric       return false;
803*fe013be4SDimitry Andric     break;
804*fe013be4SDimitry Andric   case BO_AndAssign:
805*fe013be4SDimitry Andric     if (!this->emitBitAnd(*LHSComputationT, E))
806*fe013be4SDimitry Andric       return false;
807*fe013be4SDimitry Andric     break;
808*fe013be4SDimitry Andric   case BO_XorAssign:
809*fe013be4SDimitry Andric     if (!this->emitBitXor(*LHSComputationT, E))
810*fe013be4SDimitry Andric       return false;
811*fe013be4SDimitry Andric     break;
812*fe013be4SDimitry Andric   case BO_OrAssign:
813*fe013be4SDimitry Andric     if (!this->emitBitOr(*LHSComputationT, E))
814*fe013be4SDimitry Andric       return false;
815*fe013be4SDimitry Andric     break;
816*fe013be4SDimitry Andric   default:
817*fe013be4SDimitry Andric     llvm_unreachable("Unimplemented compound assign operator");
818*fe013be4SDimitry Andric   }
819*fe013be4SDimitry Andric 
820*fe013be4SDimitry Andric   // And now cast from LHSComputationT to ResultT.
821*fe013be4SDimitry Andric   if (*ResultT != *LHSComputationT) {
822*fe013be4SDimitry Andric     if (!this->emitCast(*LHSComputationT, *ResultT, E))
823*fe013be4SDimitry Andric       return false;
824*fe013be4SDimitry Andric   }
825*fe013be4SDimitry Andric 
826*fe013be4SDimitry Andric   // And store the result in LHS.
827*fe013be4SDimitry Andric   if (DiscardResult)
828*fe013be4SDimitry Andric     return this->emitStorePop(*ResultT, E);
829*fe013be4SDimitry Andric   return this->emitStore(*ResultT, E);
830*fe013be4SDimitry Andric }
831*fe013be4SDimitry Andric 
832*fe013be4SDimitry Andric template <class Emitter>
833*fe013be4SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitExprWithCleanups(
834*fe013be4SDimitry Andric     const ExprWithCleanups *E) {
835*fe013be4SDimitry Andric   const Expr *SubExpr = E->getSubExpr();
836*fe013be4SDimitry Andric 
837*fe013be4SDimitry Andric   assert(E->getNumObjects() == 0 && "TODO: Implement cleanups");
838*fe013be4SDimitry Andric   if (DiscardResult)
839*fe013be4SDimitry Andric     return this->discard(SubExpr);
840*fe013be4SDimitry Andric 
841*fe013be4SDimitry Andric   return this->visit(SubExpr);
842*fe013be4SDimitry Andric }
843*fe013be4SDimitry Andric 
844*fe013be4SDimitry Andric template <class Emitter>
845*fe013be4SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitMaterializeTemporaryExpr(
846*fe013be4SDimitry Andric     const MaterializeTemporaryExpr *E) {
847*fe013be4SDimitry Andric   const Expr *SubExpr = E->getSubExpr();
848*fe013be4SDimitry Andric   std::optional<PrimType> SubExprT = classify(SubExpr);
849*fe013be4SDimitry Andric 
850*fe013be4SDimitry Andric   if (E->getStorageDuration() == SD_Static) {
851*fe013be4SDimitry Andric     if (std::optional<unsigned> GlobalIndex = P.createGlobal(E)) {
852*fe013be4SDimitry Andric       const LifetimeExtendedTemporaryDecl *TempDecl =
853*fe013be4SDimitry Andric           E->getLifetimeExtendedTemporaryDecl();
854*fe013be4SDimitry Andric 
855*fe013be4SDimitry Andric       if (!this->visitInitializer(SubExpr))
856*fe013be4SDimitry Andric         return false;
857*fe013be4SDimitry Andric 
858*fe013be4SDimitry Andric       if (!this->emitInitGlobalTemp(*SubExprT, *GlobalIndex, TempDecl, E))
859*fe013be4SDimitry Andric         return false;
860*fe013be4SDimitry Andric       return this->emitGetPtrGlobal(*GlobalIndex, E);
861*fe013be4SDimitry Andric     }
862*fe013be4SDimitry Andric 
863*fe013be4SDimitry Andric     return false;
864*fe013be4SDimitry Andric   }
865*fe013be4SDimitry Andric 
866*fe013be4SDimitry Andric   // For everyhing else, use local variables.
867*fe013be4SDimitry Andric   if (SubExprT) {
868*fe013be4SDimitry Andric     if (std::optional<unsigned> LocalIndex = allocateLocalPrimitive(
869*fe013be4SDimitry Andric             SubExpr, *SubExprT, /*IsConst=*/true, /*IsExtended=*/true)) {
870*fe013be4SDimitry Andric       if (!this->visitInitializer(SubExpr))
871*fe013be4SDimitry Andric         return false;
872*fe013be4SDimitry Andric       this->emitSetLocal(*SubExprT, *LocalIndex, E);
873*fe013be4SDimitry Andric       return this->emitGetPtrLocal(*LocalIndex, E);
874*fe013be4SDimitry Andric     }
875*fe013be4SDimitry Andric   } else {
876*fe013be4SDimitry Andric     if (std::optional<unsigned> LocalIndex =
877*fe013be4SDimitry Andric             allocateLocal(SubExpr, /*IsExtended=*/true)) {
878*fe013be4SDimitry Andric       if (!this->emitGetPtrLocal(*LocalIndex, E))
879*fe013be4SDimitry Andric         return false;
880*fe013be4SDimitry Andric       return this->visitInitializer(SubExpr);
881*fe013be4SDimitry Andric     }
882*fe013be4SDimitry Andric   }
883*fe013be4SDimitry Andric   return false;
884*fe013be4SDimitry Andric }
885*fe013be4SDimitry Andric 
886*fe013be4SDimitry Andric template <class Emitter>
887*fe013be4SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCompoundLiteralExpr(
888*fe013be4SDimitry Andric     const CompoundLiteralExpr *E) {
889*fe013be4SDimitry Andric   std::optional<PrimType> T = classify(E->getType());
890*fe013be4SDimitry Andric   const Expr *Init = E->getInitializer();
891*fe013be4SDimitry Andric   if (E->isFileScope()) {
892*fe013be4SDimitry Andric     if (std::optional<unsigned> GlobalIndex = P.createGlobal(E)) {
893*fe013be4SDimitry Andric       if (classify(E->getType()))
894*fe013be4SDimitry Andric         return this->visit(Init);
895*fe013be4SDimitry Andric       if (!this->emitGetPtrGlobal(*GlobalIndex, E))
896*fe013be4SDimitry Andric         return false;
897*fe013be4SDimitry Andric       return this->visitInitializer(Init);
898*fe013be4SDimitry Andric     }
899*fe013be4SDimitry Andric   }
900*fe013be4SDimitry Andric 
901*fe013be4SDimitry Andric   // Otherwise, use a local variable.
902*fe013be4SDimitry Andric   if (T) {
903*fe013be4SDimitry Andric     // For primitive types, we just visit the initializer.
904*fe013be4SDimitry Andric     return this->visit(Init);
905*fe013be4SDimitry Andric   } else {
906*fe013be4SDimitry Andric     if (std::optional<unsigned> LocalIndex = allocateLocal(Init)) {
907*fe013be4SDimitry Andric       if (!this->emitGetPtrLocal(*LocalIndex, E))
908*fe013be4SDimitry Andric         return false;
909*fe013be4SDimitry Andric       return this->visitInitializer(Init);
910*fe013be4SDimitry Andric     }
911*fe013be4SDimitry Andric   }
912*fe013be4SDimitry Andric 
913*fe013be4SDimitry Andric   return false;
914*fe013be4SDimitry Andric }
915*fe013be4SDimitry Andric 
916*fe013be4SDimitry Andric template <class Emitter>
917*fe013be4SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitTypeTraitExpr(const TypeTraitExpr *E) {
918*fe013be4SDimitry Andric   return this->emitConstBool(E->getValue(), E);
919*fe013be4SDimitry Andric }
920*fe013be4SDimitry Andric 
921*fe013be4SDimitry Andric template <class Emitter>
922*fe013be4SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitLambdaExpr(const LambdaExpr *E) {
923*fe013be4SDimitry Andric   // XXX We assume here that a pointer-to-initialize is on the stack.
924*fe013be4SDimitry Andric 
925*fe013be4SDimitry Andric   const Record *R = P.getOrCreateRecord(E->getLambdaClass());
926*fe013be4SDimitry Andric 
927*fe013be4SDimitry Andric   auto *CaptureInitIt = E->capture_init_begin();
928*fe013be4SDimitry Andric   // Initialize all fields (which represent lambda captures) of the
929*fe013be4SDimitry Andric   // record with their initializers.
930*fe013be4SDimitry Andric   for (const Record::Field &F : R->fields()) {
931*fe013be4SDimitry Andric     const Expr *Init = *CaptureInitIt;
932*fe013be4SDimitry Andric     ++CaptureInitIt;
933*fe013be4SDimitry Andric 
934*fe013be4SDimitry Andric     if (std::optional<PrimType> T = classify(Init)) {
935*fe013be4SDimitry Andric       if (!this->visit(Init))
936*fe013be4SDimitry Andric         return false;
937*fe013be4SDimitry Andric 
938*fe013be4SDimitry Andric       if (!this->emitSetField(*T, F.Offset, E))
939*fe013be4SDimitry Andric         return false;
940*fe013be4SDimitry Andric     } else {
941*fe013be4SDimitry Andric       if (!this->emitDupPtr(E))
942*fe013be4SDimitry Andric         return false;
943*fe013be4SDimitry Andric 
944*fe013be4SDimitry Andric       if (!this->emitGetPtrField(F.Offset, E))
945*fe013be4SDimitry Andric         return false;
946*fe013be4SDimitry Andric 
947*fe013be4SDimitry Andric       if (!this->visitInitializer(Init))
948*fe013be4SDimitry Andric         return false;
949*fe013be4SDimitry Andric 
950*fe013be4SDimitry Andric       if (!this->emitPopPtr(E))
951*fe013be4SDimitry Andric         return false;
952*fe013be4SDimitry Andric     }
953*fe013be4SDimitry Andric   }
954*fe013be4SDimitry Andric 
955*fe013be4SDimitry Andric   return true;
956*fe013be4SDimitry Andric }
957*fe013be4SDimitry Andric 
958*fe013be4SDimitry Andric template <class Emitter>
959*fe013be4SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitPredefinedExpr(const PredefinedExpr *E) {
960*fe013be4SDimitry Andric   if (DiscardResult)
961*fe013be4SDimitry Andric     return true;
962*fe013be4SDimitry Andric 
963*fe013be4SDimitry Andric   return this->visit(E->getFunctionName());
964*fe013be4SDimitry Andric }
965*fe013be4SDimitry Andric 
966bdd1243dSDimitry Andric template <class Emitter> bool ByteCodeExprGen<Emitter>::discard(const Expr *E) {
967*fe013be4SDimitry Andric   if (E->containsErrors())
968*fe013be4SDimitry Andric     return false;
969*fe013be4SDimitry Andric 
97004eeddc0SDimitry Andric   OptionScope<Emitter> Scope(this, /*NewDiscardResult=*/true);
971a7dea167SDimitry Andric   return this->Visit(E);
972a7dea167SDimitry Andric }
973a7dea167SDimitry Andric 
974a7dea167SDimitry Andric template <class Emitter>
975a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::visit(const Expr *E) {
976*fe013be4SDimitry Andric   if (E->containsErrors())
977*fe013be4SDimitry Andric     return false;
978*fe013be4SDimitry Andric 
97904eeddc0SDimitry Andric   OptionScope<Emitter> Scope(this, /*NewDiscardResult=*/false);
980a7dea167SDimitry Andric   return this->Visit(E);
981a7dea167SDimitry Andric }
982a7dea167SDimitry Andric 
983a7dea167SDimitry Andric template <class Emitter>
984a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::visitBool(const Expr *E) {
985bdd1243dSDimitry Andric   if (std::optional<PrimType> T = classify(E->getType())) {
986a7dea167SDimitry Andric     return visit(E);
987a7dea167SDimitry Andric   } else {
988a7dea167SDimitry Andric     return this->bail(E);
989a7dea167SDimitry Andric   }
990a7dea167SDimitry Andric }
991a7dea167SDimitry Andric 
992*fe013be4SDimitry Andric /// Visit a conditional operator, i.e. `A ? B : C`.
993*fe013be4SDimitry Andric /// \V determines what function to call for the B and C expressions.
994a7dea167SDimitry Andric template <class Emitter>
995*fe013be4SDimitry Andric bool ByteCodeExprGen<Emitter>::visitConditional(
996*fe013be4SDimitry Andric     const AbstractConditionalOperator *E,
997*fe013be4SDimitry Andric     llvm::function_ref<bool(const Expr *)> V) {
998*fe013be4SDimitry Andric 
999*fe013be4SDimitry Andric   const Expr *Condition = E->getCond();
1000*fe013be4SDimitry Andric   const Expr *TrueExpr = E->getTrueExpr();
1001*fe013be4SDimitry Andric   const Expr *FalseExpr = E->getFalseExpr();
1002*fe013be4SDimitry Andric 
1003*fe013be4SDimitry Andric   LabelTy LabelEnd = this->getLabel();   // Label after the operator.
1004*fe013be4SDimitry Andric   LabelTy LabelFalse = this->getLabel(); // Label for the false expr.
1005*fe013be4SDimitry Andric 
1006*fe013be4SDimitry Andric   if (!this->visit(Condition))
1007*fe013be4SDimitry Andric     return false;
1008*fe013be4SDimitry Andric 
1009*fe013be4SDimitry Andric   // C special case: Convert to bool because our jump ops need that.
1010*fe013be4SDimitry Andric   // TODO: We probably want this to be done in visitBool().
1011*fe013be4SDimitry Andric   if (std::optional<PrimType> CondT = classify(Condition->getType());
1012*fe013be4SDimitry Andric       CondT && CondT != PT_Bool) {
1013*fe013be4SDimitry Andric     if (!this->emitCast(*CondT, PT_Bool, E))
1014*fe013be4SDimitry Andric       return false;
1015*fe013be4SDimitry Andric   }
1016*fe013be4SDimitry Andric 
1017*fe013be4SDimitry Andric   if (!this->jumpFalse(LabelFalse))
1018*fe013be4SDimitry Andric     return false;
1019*fe013be4SDimitry Andric 
1020*fe013be4SDimitry Andric   if (!V(TrueExpr))
1021*fe013be4SDimitry Andric     return false;
1022*fe013be4SDimitry Andric   if (!this->jump(LabelEnd))
1023*fe013be4SDimitry Andric     return false;
1024*fe013be4SDimitry Andric 
1025*fe013be4SDimitry Andric   this->emitLabel(LabelFalse);
1026*fe013be4SDimitry Andric 
1027*fe013be4SDimitry Andric   if (!V(FalseExpr))
1028*fe013be4SDimitry Andric     return false;
1029*fe013be4SDimitry Andric 
1030*fe013be4SDimitry Andric   this->fallthrough(LabelEnd);
1031*fe013be4SDimitry Andric   this->emitLabel(LabelEnd);
1032*fe013be4SDimitry Andric 
1033*fe013be4SDimitry Andric   return true;
1034*fe013be4SDimitry Andric }
1035*fe013be4SDimitry Andric 
1036*fe013be4SDimitry Andric template <class Emitter>
1037*fe013be4SDimitry Andric bool ByteCodeExprGen<Emitter>::visitZeroInitializer(QualType QT,
1038*fe013be4SDimitry Andric                                                     const Expr *E) {
1039*fe013be4SDimitry Andric   // FIXME: We need the QualType to get the float semantics, but that means we
1040*fe013be4SDimitry Andric   //   classify it over and over again in array situations.
1041*fe013be4SDimitry Andric   PrimType T = classifyPrim(QT);
1042*fe013be4SDimitry Andric 
1043a7dea167SDimitry Andric   switch (T) {
1044a7dea167SDimitry Andric   case PT_Bool:
1045a7dea167SDimitry Andric     return this->emitZeroBool(E);
1046a7dea167SDimitry Andric   case PT_Sint8:
1047a7dea167SDimitry Andric     return this->emitZeroSint8(E);
1048a7dea167SDimitry Andric   case PT_Uint8:
1049a7dea167SDimitry Andric     return this->emitZeroUint8(E);
1050a7dea167SDimitry Andric   case PT_Sint16:
1051a7dea167SDimitry Andric     return this->emitZeroSint16(E);
1052a7dea167SDimitry Andric   case PT_Uint16:
1053a7dea167SDimitry Andric     return this->emitZeroUint16(E);
1054a7dea167SDimitry Andric   case PT_Sint32:
1055a7dea167SDimitry Andric     return this->emitZeroSint32(E);
1056a7dea167SDimitry Andric   case PT_Uint32:
1057a7dea167SDimitry Andric     return this->emitZeroUint32(E);
1058a7dea167SDimitry Andric   case PT_Sint64:
1059a7dea167SDimitry Andric     return this->emitZeroSint64(E);
1060a7dea167SDimitry Andric   case PT_Uint64:
1061a7dea167SDimitry Andric     return this->emitZeroUint64(E);
1062a7dea167SDimitry Andric   case PT_Ptr:
1063a7dea167SDimitry Andric     return this->emitNullPtr(E);
1064*fe013be4SDimitry Andric   case PT_FnPtr:
1065*fe013be4SDimitry Andric     return this->emitNullFnPtr(E);
1066*fe013be4SDimitry Andric   case PT_Float: {
1067*fe013be4SDimitry Andric     return this->emitConstFloat(APFloat::getZero(Ctx.getFloatSemantics(QT)), E);
1068*fe013be4SDimitry Andric   }
1069a7dea167SDimitry Andric   }
1070a7dea167SDimitry Andric   llvm_unreachable("unknown primitive type");
1071a7dea167SDimitry Andric }
1072a7dea167SDimitry Andric 
1073a7dea167SDimitry Andric template <class Emitter>
1074a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::dereference(
1075a7dea167SDimitry Andric     const Expr *LV, DerefKind AK, llvm::function_ref<bool(PrimType)> Direct,
1076a7dea167SDimitry Andric     llvm::function_ref<bool(PrimType)> Indirect) {
1077bdd1243dSDimitry Andric   if (std::optional<PrimType> T = classify(LV->getType())) {
1078a7dea167SDimitry Andric     if (!LV->refersToBitField()) {
1079a7dea167SDimitry Andric       // Only primitive, non bit-field types can be dereferenced directly.
1080*fe013be4SDimitry Andric       if (const auto *DE = dyn_cast<DeclRefExpr>(LV)) {
1081a7dea167SDimitry Andric         if (!DE->getDecl()->getType()->isReferenceType()) {
1082*fe013be4SDimitry Andric           if (const auto *PD = dyn_cast<ParmVarDecl>(DE->getDecl()))
1083a7dea167SDimitry Andric             return dereferenceParam(LV, *T, PD, AK, Direct, Indirect);
1084*fe013be4SDimitry Andric           if (const auto *VD = dyn_cast<VarDecl>(DE->getDecl()))
1085a7dea167SDimitry Andric             return dereferenceVar(LV, *T, VD, AK, Direct, Indirect);
1086a7dea167SDimitry Andric         }
1087a7dea167SDimitry Andric       }
1088a7dea167SDimitry Andric     }
1089a7dea167SDimitry Andric 
1090a7dea167SDimitry Andric     if (!visit(LV))
1091a7dea167SDimitry Andric       return false;
1092a7dea167SDimitry Andric     return Indirect(*T);
1093a7dea167SDimitry Andric   }
1094a7dea167SDimitry Andric 
1095a7dea167SDimitry Andric   return false;
1096a7dea167SDimitry Andric }
1097a7dea167SDimitry Andric 
1098a7dea167SDimitry Andric template <class Emitter>
1099a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::dereferenceParam(
1100a7dea167SDimitry Andric     const Expr *LV, PrimType T, const ParmVarDecl *PD, DerefKind AK,
1101a7dea167SDimitry Andric     llvm::function_ref<bool(PrimType)> Direct,
1102a7dea167SDimitry Andric     llvm::function_ref<bool(PrimType)> Indirect) {
1103a7dea167SDimitry Andric   auto It = this->Params.find(PD);
1104a7dea167SDimitry Andric   if (It != this->Params.end()) {
1105a7dea167SDimitry Andric     unsigned Idx = It->second;
1106a7dea167SDimitry Andric     switch (AK) {
1107a7dea167SDimitry Andric     case DerefKind::Read:
1108a7dea167SDimitry Andric       return DiscardResult ? true : this->emitGetParam(T, Idx, LV);
1109a7dea167SDimitry Andric 
1110a7dea167SDimitry Andric     case DerefKind::Write:
1111a7dea167SDimitry Andric       if (!Direct(T))
1112a7dea167SDimitry Andric         return false;
1113a7dea167SDimitry Andric       if (!this->emitSetParam(T, Idx, LV))
1114a7dea167SDimitry Andric         return false;
1115a7dea167SDimitry Andric       return DiscardResult ? true : this->emitGetPtrParam(Idx, LV);
1116a7dea167SDimitry Andric 
1117a7dea167SDimitry Andric     case DerefKind::ReadWrite:
1118a7dea167SDimitry Andric       if (!this->emitGetParam(T, Idx, LV))
1119a7dea167SDimitry Andric         return false;
1120a7dea167SDimitry Andric       if (!Direct(T))
1121a7dea167SDimitry Andric         return false;
1122a7dea167SDimitry Andric       if (!this->emitSetParam(T, Idx, LV))
1123a7dea167SDimitry Andric         return false;
1124a7dea167SDimitry Andric       return DiscardResult ? true : this->emitGetPtrParam(Idx, LV);
1125a7dea167SDimitry Andric     }
1126a7dea167SDimitry Andric     return true;
1127a7dea167SDimitry Andric   }
1128a7dea167SDimitry Andric 
1129a7dea167SDimitry Andric   // If the param is a pointer, we can dereference a dummy value.
1130a7dea167SDimitry Andric   if (!DiscardResult && T == PT_Ptr && AK == DerefKind::Read) {
1131a7dea167SDimitry Andric     if (auto Idx = P.getOrCreateDummy(PD))
1132a7dea167SDimitry Andric       return this->emitGetPtrGlobal(*Idx, PD);
1133a7dea167SDimitry Andric     return false;
1134a7dea167SDimitry Andric   }
1135a7dea167SDimitry Andric 
1136a7dea167SDimitry Andric   // Value cannot be produced - try to emit pointer and do stuff with it.
1137a7dea167SDimitry Andric   return visit(LV) && Indirect(T);
1138a7dea167SDimitry Andric }
1139a7dea167SDimitry Andric 
1140a7dea167SDimitry Andric template <class Emitter>
1141a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::dereferenceVar(
1142a7dea167SDimitry Andric     const Expr *LV, PrimType T, const VarDecl *VD, DerefKind AK,
1143a7dea167SDimitry Andric     llvm::function_ref<bool(PrimType)> Direct,
1144a7dea167SDimitry Andric     llvm::function_ref<bool(PrimType)> Indirect) {
1145a7dea167SDimitry Andric   auto It = Locals.find(VD);
1146a7dea167SDimitry Andric   if (It != Locals.end()) {
1147a7dea167SDimitry Andric     const auto &L = It->second;
1148a7dea167SDimitry Andric     switch (AK) {
1149a7dea167SDimitry Andric     case DerefKind::Read:
1150a7dea167SDimitry Andric       if (!this->emitGetLocal(T, L.Offset, LV))
1151a7dea167SDimitry Andric         return false;
1152a7dea167SDimitry Andric       return DiscardResult ? this->emitPop(T, LV) : true;
1153a7dea167SDimitry Andric 
1154a7dea167SDimitry Andric     case DerefKind::Write:
1155a7dea167SDimitry Andric       if (!Direct(T))
1156a7dea167SDimitry Andric         return false;
1157a7dea167SDimitry Andric       if (!this->emitSetLocal(T, L.Offset, LV))
1158a7dea167SDimitry Andric         return false;
1159a7dea167SDimitry Andric       return DiscardResult ? true : this->emitGetPtrLocal(L.Offset, LV);
1160a7dea167SDimitry Andric 
1161a7dea167SDimitry Andric     case DerefKind::ReadWrite:
1162a7dea167SDimitry Andric       if (!this->emitGetLocal(T, L.Offset, LV))
1163a7dea167SDimitry Andric         return false;
1164a7dea167SDimitry Andric       if (!Direct(T))
1165a7dea167SDimitry Andric         return false;
1166a7dea167SDimitry Andric       if (!this->emitSetLocal(T, L.Offset, LV))
1167a7dea167SDimitry Andric         return false;
1168a7dea167SDimitry Andric       return DiscardResult ? true : this->emitGetPtrLocal(L.Offset, LV);
1169a7dea167SDimitry Andric     }
1170bdd1243dSDimitry Andric   } else if (auto Idx = P.getGlobal(VD)) {
1171a7dea167SDimitry Andric     switch (AK) {
1172a7dea167SDimitry Andric     case DerefKind::Read:
1173a7dea167SDimitry Andric       if (!this->emitGetGlobal(T, *Idx, LV))
1174a7dea167SDimitry Andric         return false;
1175a7dea167SDimitry Andric       return DiscardResult ? this->emitPop(T, LV) : true;
1176a7dea167SDimitry Andric 
1177a7dea167SDimitry Andric     case DerefKind::Write:
1178a7dea167SDimitry Andric       if (!Direct(T))
1179a7dea167SDimitry Andric         return false;
1180a7dea167SDimitry Andric       if (!this->emitSetGlobal(T, *Idx, LV))
1181a7dea167SDimitry Andric         return false;
1182a7dea167SDimitry Andric       return DiscardResult ? true : this->emitGetPtrGlobal(*Idx, LV);
1183a7dea167SDimitry Andric 
1184a7dea167SDimitry Andric     case DerefKind::ReadWrite:
1185a7dea167SDimitry Andric       if (!this->emitGetGlobal(T, *Idx, LV))
1186a7dea167SDimitry Andric         return false;
1187a7dea167SDimitry Andric       if (!Direct(T))
1188a7dea167SDimitry Andric         return false;
1189a7dea167SDimitry Andric       if (!this->emitSetGlobal(T, *Idx, LV))
1190a7dea167SDimitry Andric         return false;
1191a7dea167SDimitry Andric       return DiscardResult ? true : this->emitGetPtrGlobal(*Idx, LV);
1192a7dea167SDimitry Andric     }
1193a7dea167SDimitry Andric   }
1194a7dea167SDimitry Andric 
1195a7dea167SDimitry Andric   // If the declaration is a constant value, emit it here even
1196a7dea167SDimitry Andric   // though the declaration was not evaluated in the current scope.
1197a7dea167SDimitry Andric   // The access mode can only be read in this case.
1198a7dea167SDimitry Andric   if (!DiscardResult && AK == DerefKind::Read) {
1199a7dea167SDimitry Andric     if (VD->hasLocalStorage() && VD->hasInit() && !VD->isConstexpr()) {
1200a7dea167SDimitry Andric       QualType VT = VD->getType();
1201a7dea167SDimitry Andric       if (VT.isConstQualified() && VT->isFundamentalType())
1202bdd1243dSDimitry Andric         return this->visit(VD->getInit());
1203a7dea167SDimitry Andric     }
1204a7dea167SDimitry Andric   }
1205a7dea167SDimitry Andric 
1206a7dea167SDimitry Andric   // Value cannot be produced - try to emit pointer.
1207a7dea167SDimitry Andric   return visit(LV) && Indirect(T);
1208a7dea167SDimitry Andric }
1209a7dea167SDimitry Andric 
1210a7dea167SDimitry Andric template <class Emitter>
1211bdd1243dSDimitry Andric template <typename T>
1212bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::emitConst(T Value, const Expr *E) {
1213bdd1243dSDimitry Andric   switch (classifyPrim(E->getType())) {
1214a7dea167SDimitry Andric   case PT_Sint8:
1215bdd1243dSDimitry Andric     return this->emitConstSint8(Value, E);
1216a7dea167SDimitry Andric   case PT_Uint8:
1217bdd1243dSDimitry Andric     return this->emitConstUint8(Value, E);
1218a7dea167SDimitry Andric   case PT_Sint16:
1219bdd1243dSDimitry Andric     return this->emitConstSint16(Value, E);
1220a7dea167SDimitry Andric   case PT_Uint16:
1221bdd1243dSDimitry Andric     return this->emitConstUint16(Value, E);
1222a7dea167SDimitry Andric   case PT_Sint32:
1223bdd1243dSDimitry Andric     return this->emitConstSint32(Value, E);
1224a7dea167SDimitry Andric   case PT_Uint32:
1225bdd1243dSDimitry Andric     return this->emitConstUint32(Value, E);
1226a7dea167SDimitry Andric   case PT_Sint64:
1227bdd1243dSDimitry Andric     return this->emitConstSint64(Value, E);
1228a7dea167SDimitry Andric   case PT_Uint64:
1229bdd1243dSDimitry Andric     return this->emitConstUint64(Value, E);
1230a7dea167SDimitry Andric   case PT_Bool:
1231bdd1243dSDimitry Andric     return this->emitConstBool(Value, E);
1232a7dea167SDimitry Andric   case PT_Ptr:
1233*fe013be4SDimitry Andric   case PT_FnPtr:
1234*fe013be4SDimitry Andric   case PT_Float:
1235a7dea167SDimitry Andric     llvm_unreachable("Invalid integral type");
1236a7dea167SDimitry Andric     break;
1237a7dea167SDimitry Andric   }
1238a7dea167SDimitry Andric   llvm_unreachable("unknown primitive type");
1239a7dea167SDimitry Andric }
1240a7dea167SDimitry Andric 
1241a7dea167SDimitry Andric template <class Emitter>
1242bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::emitConst(const APSInt &Value, const Expr *E) {
1243bdd1243dSDimitry Andric   if (Value.isSigned())
1244bdd1243dSDimitry Andric     return this->emitConst(Value.getSExtValue(), E);
1245bdd1243dSDimitry Andric   return this->emitConst(Value.getZExtValue(), E);
1246bdd1243dSDimitry Andric }
1247bdd1243dSDimitry Andric 
1248bdd1243dSDimitry Andric template <class Emitter>
1249a7dea167SDimitry Andric unsigned ByteCodeExprGen<Emitter>::allocateLocalPrimitive(DeclTy &&Src,
1250a7dea167SDimitry Andric                                                           PrimType Ty,
1251a7dea167SDimitry Andric                                                           bool IsConst,
1252a7dea167SDimitry Andric                                                           bool IsExtended) {
1253bdd1243dSDimitry Andric   // Make sure we don't accidentally register the same decl twice.
1254bdd1243dSDimitry Andric   if (const auto *VD =
1255bdd1243dSDimitry Andric           dyn_cast_if_present<ValueDecl>(Src.dyn_cast<const Decl *>())) {
1256bdd1243dSDimitry Andric     assert(!P.getGlobal(VD));
1257*fe013be4SDimitry Andric     assert(!Locals.contains(VD));
1258bdd1243dSDimitry Andric   }
1259bdd1243dSDimitry Andric 
1260bdd1243dSDimitry Andric   // FIXME: There are cases where Src.is<Expr*>() is wrong, e.g.
1261bdd1243dSDimitry Andric   //   (int){12} in C. Consider using Expr::isTemporaryObject() instead
1262bdd1243dSDimitry Andric   //   or isa<MaterializeTemporaryExpr>().
1263bdd1243dSDimitry Andric   Descriptor *D = P.createDescriptor(Src, Ty, Descriptor::InlineDescMD, IsConst,
1264bdd1243dSDimitry Andric                                      Src.is<const Expr *>());
1265a7dea167SDimitry Andric   Scope::Local Local = this->createLocal(D);
1266*fe013be4SDimitry Andric   if (auto *VD = dyn_cast_if_present<ValueDecl>(Src.dyn_cast<const Decl *>()))
1267a7dea167SDimitry Andric     Locals.insert({VD, Local});
1268a7dea167SDimitry Andric   VarScope->add(Local, IsExtended);
1269a7dea167SDimitry Andric   return Local.Offset;
1270a7dea167SDimitry Andric }
1271a7dea167SDimitry Andric 
1272a7dea167SDimitry Andric template <class Emitter>
1273bdd1243dSDimitry Andric std::optional<unsigned>
1274a7dea167SDimitry Andric ByteCodeExprGen<Emitter>::allocateLocal(DeclTy &&Src, bool IsExtended) {
1275bdd1243dSDimitry Andric   // Make sure we don't accidentally register the same decl twice.
1276bdd1243dSDimitry Andric   if (const auto *VD =
1277bdd1243dSDimitry Andric           dyn_cast_if_present<ValueDecl>(Src.dyn_cast<const Decl *>())) {
1278bdd1243dSDimitry Andric     assert(!P.getGlobal(VD));
1279*fe013be4SDimitry Andric     assert(!Locals.contains(VD));
1280bdd1243dSDimitry Andric   }
1281a7dea167SDimitry Andric 
1282bdd1243dSDimitry Andric   QualType Ty;
1283a7dea167SDimitry Andric   const ValueDecl *Key = nullptr;
1284bdd1243dSDimitry Andric   const Expr *Init = nullptr;
1285a7dea167SDimitry Andric   bool IsTemporary = false;
1286bdd1243dSDimitry Andric   if (auto *VD = dyn_cast_if_present<ValueDecl>(Src.dyn_cast<const Decl *>())) {
1287a7dea167SDimitry Andric     Key = VD;
1288a7dea167SDimitry Andric     Ty = VD->getType();
1289bdd1243dSDimitry Andric 
1290bdd1243dSDimitry Andric     if (const auto *VarD = dyn_cast<VarDecl>(VD))
1291bdd1243dSDimitry Andric       Init = VarD->getInit();
1292a7dea167SDimitry Andric   }
1293a7dea167SDimitry Andric   if (auto *E = Src.dyn_cast<const Expr *>()) {
1294a7dea167SDimitry Andric     IsTemporary = true;
1295a7dea167SDimitry Andric     Ty = E->getType();
1296a7dea167SDimitry Andric   }
1297a7dea167SDimitry Andric 
1298bdd1243dSDimitry Andric   Descriptor *D = P.createDescriptor(
1299bdd1243dSDimitry Andric       Src, Ty.getTypePtr(), Descriptor::InlineDescMD, Ty.isConstQualified(),
1300bdd1243dSDimitry Andric       IsTemporary, /*IsMutable=*/false, Init);
1301a7dea167SDimitry Andric   if (!D)
1302a7dea167SDimitry Andric     return {};
1303a7dea167SDimitry Andric 
1304a7dea167SDimitry Andric   Scope::Local Local = this->createLocal(D);
1305a7dea167SDimitry Andric   if (Key)
1306a7dea167SDimitry Andric     Locals.insert({Key, Local});
1307a7dea167SDimitry Andric   VarScope->add(Local, IsExtended);
1308a7dea167SDimitry Andric   return Local.Offset;
1309a7dea167SDimitry Andric }
1310a7dea167SDimitry Andric 
1311bdd1243dSDimitry Andric // NB: When calling this function, we have a pointer to the
1312bdd1243dSDimitry Andric //   array-to-initialize on the stack.
1313a7dea167SDimitry Andric template <class Emitter>
1314bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::visitArrayInitializer(const Expr *Initializer) {
1315bdd1243dSDimitry Andric   assert(Initializer->getType()->isArrayType());
1316bdd1243dSDimitry Andric 
1317bdd1243dSDimitry Andric   // TODO: Fillers?
1318bdd1243dSDimitry Andric   if (const auto *InitList = dyn_cast<InitListExpr>(Initializer)) {
1319bdd1243dSDimitry Andric     unsigned ElementIndex = 0;
1320bdd1243dSDimitry Andric     for (const Expr *Init : InitList->inits()) {
1321bdd1243dSDimitry Andric       if (std::optional<PrimType> T = classify(Init->getType())) {
1322bdd1243dSDimitry Andric         // Visit the primitive element like normal.
1323bdd1243dSDimitry Andric         if (!this->visit(Init))
1324bdd1243dSDimitry Andric           return false;
1325bdd1243dSDimitry Andric         if (!this->emitInitElem(*T, ElementIndex, Init))
1326bdd1243dSDimitry Andric           return false;
1327bdd1243dSDimitry Andric       } else {
1328bdd1243dSDimitry Andric         // Advance the pointer currently on the stack to the given
1329*fe013be4SDimitry Andric         // dimension.
1330bdd1243dSDimitry Andric         if (!this->emitConstUint32(ElementIndex, Init))
1331bdd1243dSDimitry Andric           return false;
1332*fe013be4SDimitry Andric         if (!this->emitArrayElemPtrUint32(Init))
1333bdd1243dSDimitry Andric           return false;
1334bdd1243dSDimitry Andric         if (!visitInitializer(Init))
1335bdd1243dSDimitry Andric           return false;
1336bdd1243dSDimitry Andric         if (!this->emitPopPtr(Init))
1337bdd1243dSDimitry Andric           return false;
1338*fe013be4SDimitry Andric       }
1339bdd1243dSDimitry Andric 
1340bdd1243dSDimitry Andric       ++ElementIndex;
1341bdd1243dSDimitry Andric     }
1342bdd1243dSDimitry Andric     return true;
1343bdd1243dSDimitry Andric   } else if (const auto *DIE = dyn_cast<CXXDefaultInitExpr>(Initializer)) {
1344bdd1243dSDimitry Andric     return this->visitInitializer(DIE->getExpr());
1345bdd1243dSDimitry Andric   } else if (const auto *AILE = dyn_cast<ArrayInitLoopExpr>(Initializer)) {
1346bdd1243dSDimitry Andric     // TODO: This compiles to quite a lot of bytecode if the array is larger.
1347bdd1243dSDimitry Andric     //   Investigate compiling this to a loop, or at least try to use
1348bdd1243dSDimitry Andric     //   the AILE's Common expr.
1349bdd1243dSDimitry Andric     const Expr *SubExpr = AILE->getSubExpr();
1350bdd1243dSDimitry Andric     size_t Size = AILE->getArraySize().getZExtValue();
1351bdd1243dSDimitry Andric     std::optional<PrimType> ElemT = classify(SubExpr->getType());
1352bdd1243dSDimitry Andric 
1353bdd1243dSDimitry Andric     // So, every iteration, we execute an assignment here
1354bdd1243dSDimitry Andric     // where the LHS is on the stack (the target array)
1355bdd1243dSDimitry Andric     // and the RHS is our SubExpr.
1356bdd1243dSDimitry Andric     for (size_t I = 0; I != Size; ++I) {
1357bdd1243dSDimitry Andric       ArrayIndexScope<Emitter> IndexScope(this, I);
1358bdd1243dSDimitry Andric 
1359bdd1243dSDimitry Andric       if (ElemT) {
1360bdd1243dSDimitry Andric         if (!this->visit(SubExpr))
1361bdd1243dSDimitry Andric           return false;
1362bdd1243dSDimitry Andric         if (!this->emitInitElem(*ElemT, I, Initializer))
1363bdd1243dSDimitry Andric           return false;
1364bdd1243dSDimitry Andric       } else {
1365*fe013be4SDimitry Andric         // Get to our array element and recurse into visitInitializer()
1366bdd1243dSDimitry Andric         if (!this->emitConstUint64(I, SubExpr))
1367bdd1243dSDimitry Andric           return false;
1368*fe013be4SDimitry Andric         if (!this->emitArrayElemPtrUint64(SubExpr))
1369bdd1243dSDimitry Andric           return false;
1370bdd1243dSDimitry Andric         if (!visitInitializer(SubExpr))
1371bdd1243dSDimitry Andric           return false;
1372bdd1243dSDimitry Andric         if (!this->emitPopPtr(Initializer))
1373bdd1243dSDimitry Andric           return false;
1374bdd1243dSDimitry Andric       }
1375*fe013be4SDimitry Andric     }
1376bdd1243dSDimitry Andric     return true;
1377bdd1243dSDimitry Andric   } else if (const auto *IVIE = dyn_cast<ImplicitValueInitExpr>(Initializer)) {
1378bdd1243dSDimitry Andric     const ArrayType *AT = IVIE->getType()->getAsArrayTypeUnsafe();
1379bdd1243dSDimitry Andric     assert(AT);
1380bdd1243dSDimitry Andric     const auto *CAT = cast<ConstantArrayType>(AT);
1381bdd1243dSDimitry Andric     size_t NumElems = CAT->getSize().getZExtValue();
1382bdd1243dSDimitry Andric 
1383bdd1243dSDimitry Andric     if (std::optional<PrimType> ElemT = classify(CAT->getElementType())) {
1384bdd1243dSDimitry Andric       // TODO(perf): For int and bool types, we can probably just skip this
1385bdd1243dSDimitry Andric       //   since we memset our Block*s to 0 and so we have the desired value
1386bdd1243dSDimitry Andric       //   without this.
1387bdd1243dSDimitry Andric       for (size_t I = 0; I != NumElems; ++I) {
1388*fe013be4SDimitry Andric         if (!this->visitZeroInitializer(CAT->getElementType(), Initializer))
1389bdd1243dSDimitry Andric           return false;
1390bdd1243dSDimitry Andric         if (!this->emitInitElem(*ElemT, I, Initializer))
1391bdd1243dSDimitry Andric           return false;
1392bdd1243dSDimitry Andric       }
1393bdd1243dSDimitry Andric     } else {
1394bdd1243dSDimitry Andric       assert(false && "default initializer for non-primitive type");
1395bdd1243dSDimitry Andric     }
1396bdd1243dSDimitry Andric 
1397bdd1243dSDimitry Andric     return true;
1398bdd1243dSDimitry Andric   } else if (const auto *Ctor = dyn_cast<CXXConstructExpr>(Initializer)) {
1399bdd1243dSDimitry Andric     const ConstantArrayType *CAT =
1400bdd1243dSDimitry Andric         Ctx.getASTContext().getAsConstantArrayType(Ctor->getType());
1401bdd1243dSDimitry Andric     assert(CAT);
1402bdd1243dSDimitry Andric     size_t NumElems = CAT->getSize().getZExtValue();
1403bdd1243dSDimitry Andric     const Function *Func = getFunction(Ctor->getConstructor());
1404bdd1243dSDimitry Andric     if (!Func || !Func->isConstexpr())
1405bdd1243dSDimitry Andric       return false;
1406bdd1243dSDimitry Andric 
1407bdd1243dSDimitry Andric     // FIXME(perf): We're calling the constructor once per array element here,
1408bdd1243dSDimitry Andric     //   in the old intepreter we had a special-case for trivial constructors.
1409bdd1243dSDimitry Andric     for (size_t I = 0; I != NumElems; ++I) {
1410bdd1243dSDimitry Andric       if (!this->emitConstUint64(I, Initializer))
1411bdd1243dSDimitry Andric         return false;
1412*fe013be4SDimitry Andric       if (!this->emitArrayElemPtrUint64(Initializer))
1413bdd1243dSDimitry Andric         return false;
1414bdd1243dSDimitry Andric 
1415bdd1243dSDimitry Andric       // Constructor arguments.
1416bdd1243dSDimitry Andric       for (const auto *Arg : Ctor->arguments()) {
1417bdd1243dSDimitry Andric         if (!this->visit(Arg))
1418bdd1243dSDimitry Andric           return false;
1419bdd1243dSDimitry Andric       }
1420bdd1243dSDimitry Andric 
1421bdd1243dSDimitry Andric       if (!this->emitCall(Func, Initializer))
1422bdd1243dSDimitry Andric         return false;
1423bdd1243dSDimitry Andric     }
1424bdd1243dSDimitry Andric     return true;
1425*fe013be4SDimitry Andric   } else if (const auto *SL = dyn_cast<StringLiteral>(Initializer)) {
1426*fe013be4SDimitry Andric     const ConstantArrayType *CAT =
1427*fe013be4SDimitry Andric         Ctx.getASTContext().getAsConstantArrayType(SL->getType());
1428*fe013be4SDimitry Andric     assert(CAT && "a string literal that's not a constant array?");
1429*fe013be4SDimitry Andric 
1430*fe013be4SDimitry Andric     // If the initializer string is too long, a diagnostic has already been
1431*fe013be4SDimitry Andric     // emitted. Read only the array length from the string literal.
1432*fe013be4SDimitry Andric     unsigned N =
1433*fe013be4SDimitry Andric         std::min(unsigned(CAT->getSize().getZExtValue()), SL->getLength());
1434*fe013be4SDimitry Andric     size_t CharWidth = SL->getCharByteWidth();
1435*fe013be4SDimitry Andric 
1436*fe013be4SDimitry Andric     for (unsigned I = 0; I != N; ++I) {
1437*fe013be4SDimitry Andric       uint32_t CodeUnit = SL->getCodeUnit(I);
1438*fe013be4SDimitry Andric 
1439*fe013be4SDimitry Andric       if (CharWidth == 1) {
1440*fe013be4SDimitry Andric         this->emitConstSint8(CodeUnit, SL);
1441*fe013be4SDimitry Andric         this->emitInitElemSint8(I, SL);
1442*fe013be4SDimitry Andric       } else if (CharWidth == 2) {
1443*fe013be4SDimitry Andric         this->emitConstUint16(CodeUnit, SL);
1444*fe013be4SDimitry Andric         this->emitInitElemUint16(I, SL);
1445*fe013be4SDimitry Andric       } else if (CharWidth == 4) {
1446*fe013be4SDimitry Andric         this->emitConstUint32(CodeUnit, SL);
1447*fe013be4SDimitry Andric         this->emitInitElemUint32(I, SL);
1448*fe013be4SDimitry Andric       } else {
1449*fe013be4SDimitry Andric         llvm_unreachable("unsupported character width");
1450*fe013be4SDimitry Andric       }
1451*fe013be4SDimitry Andric     }
1452*fe013be4SDimitry Andric     return true;
1453*fe013be4SDimitry Andric   } else if (const auto *CLE = dyn_cast<CompoundLiteralExpr>(Initializer)) {
1454*fe013be4SDimitry Andric     return visitInitializer(CLE->getInitializer());
1455*fe013be4SDimitry Andric   } else if (const auto *EWC = dyn_cast<ExprWithCleanups>(Initializer)) {
1456*fe013be4SDimitry Andric     return visitInitializer(EWC->getSubExpr());
1457bdd1243dSDimitry Andric   }
1458bdd1243dSDimitry Andric 
1459bdd1243dSDimitry Andric   assert(false && "Unknown expression for array initialization");
1460bdd1243dSDimitry Andric   return false;
1461a7dea167SDimitry Andric }
1462a7dea167SDimitry Andric 
1463a7dea167SDimitry Andric template <class Emitter>
1464bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::visitRecordInitializer(const Expr *Initializer) {
1465bdd1243dSDimitry Andric   Initializer = Initializer->IgnoreParenImpCasts();
1466bdd1243dSDimitry Andric   assert(Initializer->getType()->isRecordType());
1467bdd1243dSDimitry Andric 
1468bdd1243dSDimitry Andric   if (const auto CtorExpr = dyn_cast<CXXConstructExpr>(Initializer)) {
1469bdd1243dSDimitry Andric     const Function *Func = getFunction(CtorExpr->getConstructor());
1470bdd1243dSDimitry Andric 
1471*fe013be4SDimitry Andric     if (!Func)
1472bdd1243dSDimitry Andric       return false;
1473bdd1243dSDimitry Andric 
1474bdd1243dSDimitry Andric     // The This pointer is already on the stack because this is an initializer,
1475bdd1243dSDimitry Andric     // but we need to dup() so the call() below has its own copy.
1476bdd1243dSDimitry Andric     if (!this->emitDupPtr(Initializer))
1477bdd1243dSDimitry Andric       return false;
1478bdd1243dSDimitry Andric 
1479bdd1243dSDimitry Andric     // Constructor arguments.
1480bdd1243dSDimitry Andric     for (const auto *Arg : CtorExpr->arguments()) {
1481bdd1243dSDimitry Andric       if (!this->visit(Arg))
1482bdd1243dSDimitry Andric         return false;
1483a7dea167SDimitry Andric     }
1484bdd1243dSDimitry Andric 
1485bdd1243dSDimitry Andric     return this->emitCall(Func, Initializer);
1486bdd1243dSDimitry Andric   } else if (const auto *InitList = dyn_cast<InitListExpr>(Initializer)) {
1487bdd1243dSDimitry Andric     const Record *R = getRecord(InitList->getType());
1488bdd1243dSDimitry Andric 
1489bdd1243dSDimitry Andric     unsigned InitIndex = 0;
1490bdd1243dSDimitry Andric     for (const Expr *Init : InitList->inits()) {
1491bdd1243dSDimitry Andric 
1492bdd1243dSDimitry Andric       if (!this->emitDupPtr(Initializer))
1493bdd1243dSDimitry Andric         return false;
1494bdd1243dSDimitry Andric 
1495bdd1243dSDimitry Andric       if (std::optional<PrimType> T = classify(Init)) {
1496*fe013be4SDimitry Andric         const Record::Field *FieldToInit = R->getField(InitIndex);
1497bdd1243dSDimitry Andric         if (!this->visit(Init))
1498bdd1243dSDimitry Andric           return false;
1499bdd1243dSDimitry Andric 
1500bdd1243dSDimitry Andric         if (!this->emitInitField(*T, FieldToInit->Offset, Initializer))
1501bdd1243dSDimitry Andric           return false;
1502bdd1243dSDimitry Andric 
1503bdd1243dSDimitry Andric         if (!this->emitPopPtr(Initializer))
1504bdd1243dSDimitry Andric           return false;
1505*fe013be4SDimitry Andric         ++InitIndex;
1506bdd1243dSDimitry Andric       } else {
1507*fe013be4SDimitry Andric         // Initializer for a direct base class.
1508*fe013be4SDimitry Andric         if (const Record::Base *B = R->getBase(Init->getType())) {
1509*fe013be4SDimitry Andric           if (!this->emitGetPtrBasePop(B->Offset, Init))
1510*fe013be4SDimitry Andric             return false;
1511*fe013be4SDimitry Andric 
1512*fe013be4SDimitry Andric           if (!this->visitInitializer(Init))
1513*fe013be4SDimitry Andric             return false;
1514*fe013be4SDimitry Andric 
1515*fe013be4SDimitry Andric           if (!this->emitPopPtr(Initializer))
1516*fe013be4SDimitry Andric             return false;
1517*fe013be4SDimitry Andric           // Base initializers don't increase InitIndex, since they don't count
1518*fe013be4SDimitry Andric           // into the Record's fields.
1519*fe013be4SDimitry Andric         } else {
1520*fe013be4SDimitry Andric           const Record::Field *FieldToInit = R->getField(InitIndex);
1521bdd1243dSDimitry Andric           // Non-primitive case. Get a pointer to the field-to-initialize
1522bdd1243dSDimitry Andric           // on the stack and recurse into visitInitializer().
1523bdd1243dSDimitry Andric           if (!this->emitGetPtrField(FieldToInit->Offset, Init))
1524bdd1243dSDimitry Andric             return false;
1525bdd1243dSDimitry Andric 
1526bdd1243dSDimitry Andric           if (!this->visitInitializer(Init))
1527bdd1243dSDimitry Andric             return false;
1528bdd1243dSDimitry Andric 
1529bdd1243dSDimitry Andric           if (!this->emitPopPtr(Initializer))
1530bdd1243dSDimitry Andric             return false;
1531bdd1243dSDimitry Andric           ++InitIndex;
1532bdd1243dSDimitry Andric         }
1533*fe013be4SDimitry Andric       }
1534*fe013be4SDimitry Andric     }
1535bdd1243dSDimitry Andric 
1536bdd1243dSDimitry Andric     return true;
1537bdd1243dSDimitry Andric   } else if (const CallExpr *CE = dyn_cast<CallExpr>(Initializer)) {
1538bdd1243dSDimitry Andric     // RVO functions expect a pointer to initialize on the stack.
1539bdd1243dSDimitry Andric     // Dup our existing pointer so it has its own copy to use.
1540bdd1243dSDimitry Andric     if (!this->emitDupPtr(Initializer))
1541bdd1243dSDimitry Andric       return false;
1542bdd1243dSDimitry Andric 
1543*fe013be4SDimitry Andric     return this->visit(CE);
1544bdd1243dSDimitry Andric   } else if (const auto *DIE = dyn_cast<CXXDefaultInitExpr>(Initializer)) {
1545bdd1243dSDimitry Andric     return this->visitInitializer(DIE->getExpr());
1546*fe013be4SDimitry Andric   } else if (const auto *CE = dyn_cast<CastExpr>(Initializer)) {
1547*fe013be4SDimitry Andric     return this->visitInitializer(CE->getSubExpr());
1548*fe013be4SDimitry Andric   } else if (const auto *CE = dyn_cast<CXXBindTemporaryExpr>(Initializer)) {
1549*fe013be4SDimitry Andric     return this->visitInitializer(CE->getSubExpr());
1550*fe013be4SDimitry Andric   } else if (const auto *ACO =
1551*fe013be4SDimitry Andric                  dyn_cast<AbstractConditionalOperator>(Initializer)) {
1552*fe013be4SDimitry Andric     return this->visitConditional(
1553*fe013be4SDimitry Andric         ACO, [this](const Expr *E) { return this->visitRecordInitializer(E); });
1554*fe013be4SDimitry Andric   } else if (const auto *LE = dyn_cast<LambdaExpr>(Initializer)) {
1555*fe013be4SDimitry Andric     return this->VisitLambdaExpr(LE);
1556bdd1243dSDimitry Andric   }
1557bdd1243dSDimitry Andric 
1558bdd1243dSDimitry Andric   return false;
1559a7dea167SDimitry Andric }
1560a7dea167SDimitry Andric 
1561a7dea167SDimitry Andric template <class Emitter>
1562bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::visitInitializer(const Expr *Initializer) {
1563bdd1243dSDimitry Andric   QualType InitializerType = Initializer->getType();
1564bdd1243dSDimitry Andric 
1565bdd1243dSDimitry Andric   if (InitializerType->isArrayType())
1566bdd1243dSDimitry Andric     return visitArrayInitializer(Initializer);
1567bdd1243dSDimitry Andric 
1568bdd1243dSDimitry Andric   if (InitializerType->isRecordType())
1569bdd1243dSDimitry Andric     return visitRecordInitializer(Initializer);
1570bdd1243dSDimitry Andric 
1571bdd1243dSDimitry Andric   // Otherwise, visit the expression like normal.
1572bdd1243dSDimitry Andric   return this->visit(Initializer);
1573a7dea167SDimitry Andric }
1574a7dea167SDimitry Andric 
1575a7dea167SDimitry Andric template <class Emitter>
1576a7dea167SDimitry Andric const RecordType *ByteCodeExprGen<Emitter>::getRecordTy(QualType Ty) {
1577753f127fSDimitry Andric   if (const PointerType *PT = dyn_cast<PointerType>(Ty))
1578a7dea167SDimitry Andric     return PT->getPointeeType()->getAs<RecordType>();
1579a7dea167SDimitry Andric   else
1580a7dea167SDimitry Andric     return Ty->getAs<RecordType>();
1581a7dea167SDimitry Andric }
1582a7dea167SDimitry Andric 
1583a7dea167SDimitry Andric template <class Emitter>
1584a7dea167SDimitry Andric Record *ByteCodeExprGen<Emitter>::getRecord(QualType Ty) {
1585a7dea167SDimitry Andric   if (auto *RecordTy = getRecordTy(Ty)) {
1586a7dea167SDimitry Andric     return getRecord(RecordTy->getDecl());
1587a7dea167SDimitry Andric   }
1588a7dea167SDimitry Andric   return nullptr;
1589a7dea167SDimitry Andric }
1590a7dea167SDimitry Andric 
1591a7dea167SDimitry Andric template <class Emitter>
1592a7dea167SDimitry Andric Record *ByteCodeExprGen<Emitter>::getRecord(const RecordDecl *RD) {
1593a7dea167SDimitry Andric   return P.getOrCreateRecord(RD);
1594a7dea167SDimitry Andric }
1595a7dea167SDimitry Andric 
1596a7dea167SDimitry Andric template <class Emitter>
1597bdd1243dSDimitry Andric const Function *ByteCodeExprGen<Emitter>::getFunction(const FunctionDecl *FD) {
1598bdd1243dSDimitry Andric   assert(FD);
1599bdd1243dSDimitry Andric   const Function *Func = P.getFunction(FD);
1600bdd1243dSDimitry Andric   bool IsBeingCompiled = Func && !Func->isFullyCompiled();
1601*fe013be4SDimitry Andric   bool WasNotDefined = Func && !Func->isConstexpr() && !Func->hasBody();
1602bdd1243dSDimitry Andric 
1603bdd1243dSDimitry Andric   if (IsBeingCompiled)
1604bdd1243dSDimitry Andric     return Func;
1605bdd1243dSDimitry Andric 
1606bdd1243dSDimitry Andric   if (!Func || WasNotDefined) {
1607bdd1243dSDimitry Andric     if (auto R = ByteCodeStmtGen<ByteCodeEmitter>(Ctx, P).compileFunc(FD))
1608bdd1243dSDimitry Andric       Func = *R;
1609bdd1243dSDimitry Andric     else {
1610bdd1243dSDimitry Andric       llvm::consumeError(R.takeError());
1611bdd1243dSDimitry Andric       return nullptr;
1612bdd1243dSDimitry Andric     }
1613bdd1243dSDimitry Andric   }
1614bdd1243dSDimitry Andric 
1615bdd1243dSDimitry Andric   return Func;
1616bdd1243dSDimitry Andric }
1617bdd1243dSDimitry Andric 
1618bdd1243dSDimitry Andric template <class Emitter>
1619a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::visitExpr(const Expr *Exp) {
1620a7dea167SDimitry Andric   ExprScope<Emitter> RootScope(this);
1621a7dea167SDimitry Andric   if (!visit(Exp))
1622a7dea167SDimitry Andric     return false;
1623a7dea167SDimitry Andric 
1624bdd1243dSDimitry Andric   if (std::optional<PrimType> T = classify(Exp))
1625a7dea167SDimitry Andric     return this->emitRet(*T, Exp);
1626a7dea167SDimitry Andric   else
1627a7dea167SDimitry Andric     return this->emitRetValue(Exp);
1628a7dea167SDimitry Andric }
1629a7dea167SDimitry Andric 
1630bdd1243dSDimitry Andric /// Toplevel visitDecl().
1631bdd1243dSDimitry Andric /// We get here from evaluateAsInitializer().
1632bdd1243dSDimitry Andric /// We need to evaluate the initializer and return its value.
1633a7dea167SDimitry Andric template <class Emitter>
1634a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::visitDecl(const VarDecl *VD) {
1635*fe013be4SDimitry Andric   assert(!VD->isInvalidDecl() && "Trying to constant evaluate an invalid decl");
1636a7dea167SDimitry Andric 
1637bdd1243dSDimitry Andric   // Create and initialize the variable.
1638bdd1243dSDimitry Andric   if (!this->visitVarDecl(VD))
1639a7dea167SDimitry Andric     return false;
1640a7dea167SDimitry Andric 
1641bdd1243dSDimitry Andric   // Get a pointer to the variable
1642*fe013be4SDimitry Andric   if (Context::shouldBeGloballyIndexed(VD)) {
1643bdd1243dSDimitry Andric     auto GlobalIndex = P.getGlobal(VD);
1644bdd1243dSDimitry Andric     assert(GlobalIndex); // visitVarDecl() didn't return false.
1645bdd1243dSDimitry Andric     if (!this->emitGetPtrGlobal(*GlobalIndex, VD))
1646a7dea167SDimitry Andric       return false;
1647a7dea167SDimitry Andric   } else {
1648bdd1243dSDimitry Andric     auto Local = Locals.find(VD);
1649bdd1243dSDimitry Andric     assert(Local != Locals.end()); // Same here.
1650bdd1243dSDimitry Andric     if (!this->emitGetPtrLocal(Local->second.Offset, VD))
1651a7dea167SDimitry Andric       return false;
1652a7dea167SDimitry Andric   }
1653a7dea167SDimitry Andric 
1654bdd1243dSDimitry Andric   // Return the value
1655*fe013be4SDimitry Andric   if (std::optional<PrimType> VarT = classify(VD->getType())) {
1656bdd1243dSDimitry Andric     if (!this->emitLoadPop(*VarT, VD))
1657a7dea167SDimitry Andric       return false;
1658bdd1243dSDimitry Andric 
1659bdd1243dSDimitry Andric     return this->emitRet(*VarT, VD);
1660bdd1243dSDimitry Andric   }
1661bdd1243dSDimitry Andric 
1662a7dea167SDimitry Andric   return this->emitRetValue(VD);
1663a7dea167SDimitry Andric }
1664bdd1243dSDimitry Andric 
1665bdd1243dSDimitry Andric template <class Emitter>
1666bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::visitVarDecl(const VarDecl *VD) {
1667*fe013be4SDimitry Andric   // We don't know what to do with these, so just return false.
1668*fe013be4SDimitry Andric   if (VD->getType().isNull())
1669*fe013be4SDimitry Andric     return false;
1670*fe013be4SDimitry Andric 
1671bdd1243dSDimitry Andric   const Expr *Init = VD->getInit();
1672bdd1243dSDimitry Andric   std::optional<PrimType> VarT = classify(VD->getType());
1673bdd1243dSDimitry Andric 
1674*fe013be4SDimitry Andric   if (Context::shouldBeGloballyIndexed(VD)) {
1675*fe013be4SDimitry Andric     // We've already seen and initialized this global.
1676*fe013be4SDimitry Andric     if (P.getGlobal(VD))
1677*fe013be4SDimitry Andric       return true;
1678*fe013be4SDimitry Andric 
1679*fe013be4SDimitry Andric     std::optional<unsigned> GlobalIndex = P.createGlobal(VD, Init);
1680bdd1243dSDimitry Andric 
1681bdd1243dSDimitry Andric     if (!GlobalIndex)
1682bdd1243dSDimitry Andric       return this->bail(VD);
1683bdd1243dSDimitry Andric 
1684bdd1243dSDimitry Andric     assert(Init);
1685bdd1243dSDimitry Andric     {
1686bdd1243dSDimitry Andric       DeclScope<Emitter> LocalScope(this, VD);
1687bdd1243dSDimitry Andric 
1688bdd1243dSDimitry Andric       if (VarT) {
1689bdd1243dSDimitry Andric         if (!this->visit(Init))
1690bdd1243dSDimitry Andric           return false;
1691bdd1243dSDimitry Andric         return this->emitInitGlobal(*VarT, *GlobalIndex, VD);
1692bdd1243dSDimitry Andric       }
1693bdd1243dSDimitry Andric       return this->visitGlobalInitializer(Init, *GlobalIndex);
1694bdd1243dSDimitry Andric     }
1695bdd1243dSDimitry Andric   } else {
1696bdd1243dSDimitry Andric     VariableScope<Emitter> LocalScope(this);
1697bdd1243dSDimitry Andric     if (VarT) {
1698bdd1243dSDimitry Andric       unsigned Offset = this->allocateLocalPrimitive(
1699bdd1243dSDimitry Andric           VD, *VarT, VD->getType().isConstQualified());
1700bdd1243dSDimitry Andric       if (Init) {
1701bdd1243dSDimitry Andric         // Compile the initializer in its own scope.
1702bdd1243dSDimitry Andric         ExprScope<Emitter> Scope(this);
1703bdd1243dSDimitry Andric         if (!this->visit(Init))
1704bdd1243dSDimitry Andric           return false;
1705bdd1243dSDimitry Andric 
1706bdd1243dSDimitry Andric         return this->emitSetLocal(*VarT, Offset, VD);
1707bdd1243dSDimitry Andric       }
1708bdd1243dSDimitry Andric     } else {
1709bdd1243dSDimitry Andric       if (std::optional<unsigned> Offset = this->allocateLocal(VD)) {
1710bdd1243dSDimitry Andric         if (Init)
1711bdd1243dSDimitry Andric           return this->visitLocalInitializer(Init, *Offset);
1712bdd1243dSDimitry Andric       }
1713bdd1243dSDimitry Andric     }
1714bdd1243dSDimitry Andric     return true;
1715a7dea167SDimitry Andric   }
1716a7dea167SDimitry Andric 
1717bdd1243dSDimitry Andric   return false;
1718bdd1243dSDimitry Andric }
1719bdd1243dSDimitry Andric 
1720bdd1243dSDimitry Andric template <class Emitter>
1721*fe013be4SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitBuiltinCallExpr(const CallExpr *E) {
1722*fe013be4SDimitry Andric   const Function *Func = getFunction(E->getDirectCallee());
1723bdd1243dSDimitry Andric   if (!Func)
1724bdd1243dSDimitry Andric     return false;
1725*fe013be4SDimitry Andric 
1726*fe013be4SDimitry Andric   // Put arguments on the stack.
1727*fe013be4SDimitry Andric   for (const auto *Arg : E->arguments()) {
1728*fe013be4SDimitry Andric     if (!this->visit(Arg))
1729*fe013be4SDimitry Andric       return false;
1730*fe013be4SDimitry Andric   }
1731*fe013be4SDimitry Andric 
1732*fe013be4SDimitry Andric   if (!this->emitCallBI(Func, E))
1733bdd1243dSDimitry Andric     return false;
1734bdd1243dSDimitry Andric 
1735bdd1243dSDimitry Andric   QualType ReturnType = E->getCallReturnType(Ctx.getASTContext());
1736*fe013be4SDimitry Andric   if (DiscardResult && !ReturnType->isVoidType()) {
1737*fe013be4SDimitry Andric     PrimType T = classifyPrim(ReturnType);
1738*fe013be4SDimitry Andric     return this->emitPop(T, E);
1739*fe013be4SDimitry Andric   }
1740bdd1243dSDimitry Andric 
1741*fe013be4SDimitry Andric   return true;
1742*fe013be4SDimitry Andric }
1743*fe013be4SDimitry Andric 
1744*fe013be4SDimitry Andric template <class Emitter>
1745*fe013be4SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCallExpr(const CallExpr *E) {
1746*fe013be4SDimitry Andric   if (E->getBuiltinCallee())
1747*fe013be4SDimitry Andric     return VisitBuiltinCallExpr(E);
1748*fe013be4SDimitry Andric 
1749*fe013be4SDimitry Andric   QualType ReturnType = E->getCallReturnType(Ctx.getASTContext());
1750*fe013be4SDimitry Andric   std::optional<PrimType> T = classify(ReturnType);
1751*fe013be4SDimitry Andric   bool HasRVO = !ReturnType->isVoidType() && !T;
1752*fe013be4SDimitry Andric 
1753*fe013be4SDimitry Andric   if (HasRVO && DiscardResult) {
1754bdd1243dSDimitry Andric     // If we need to discard the return value but the function returns its
1755bdd1243dSDimitry Andric     // value via an RVO pointer, we need to create one such pointer just
1756bdd1243dSDimitry Andric     // for this call.
1757bdd1243dSDimitry Andric     if (std::optional<unsigned> LocalIndex = allocateLocal(E)) {
1758bdd1243dSDimitry Andric       if (!this->emitGetPtrLocal(*LocalIndex, E))
1759bdd1243dSDimitry Andric         return false;
1760bdd1243dSDimitry Andric     }
1761bdd1243dSDimitry Andric   }
1762bdd1243dSDimitry Andric 
1763bdd1243dSDimitry Andric   // Put arguments on the stack.
1764bdd1243dSDimitry Andric   for (const auto *Arg : E->arguments()) {
1765bdd1243dSDimitry Andric     if (!this->visit(Arg))
1766bdd1243dSDimitry Andric       return false;
1767bdd1243dSDimitry Andric   }
1768bdd1243dSDimitry Andric 
1769*fe013be4SDimitry Andric   if (const FunctionDecl *FuncDecl = E->getDirectCallee()) {
1770*fe013be4SDimitry Andric     const Function *Func = getFunction(FuncDecl);
1771*fe013be4SDimitry Andric     if (!Func)
1772*fe013be4SDimitry Andric       return false;
1773*fe013be4SDimitry Andric     // If the function is being compiled right now, this is a recursive call.
1774*fe013be4SDimitry Andric     // In that case, the function can't be valid yet, even though it will be
1775*fe013be4SDimitry Andric     // later.
1776*fe013be4SDimitry Andric     // If the function is already fully compiled but not constexpr, it was
1777*fe013be4SDimitry Andric     // found to be faulty earlier on, so bail out.
1778*fe013be4SDimitry Andric     if (Func->isFullyCompiled() && !Func->isConstexpr())
1779bdd1243dSDimitry Andric       return false;
1780bdd1243dSDimitry Andric 
1781*fe013be4SDimitry Andric     assert(HasRVO == Func->hasRVO());
1782*fe013be4SDimitry Andric 
1783*fe013be4SDimitry Andric     bool HasQualifier = false;
1784*fe013be4SDimitry Andric     if (const auto *ME = dyn_cast<MemberExpr>(E->getCallee()))
1785*fe013be4SDimitry Andric       HasQualifier = ME->hasQualifier();
1786*fe013be4SDimitry Andric 
1787*fe013be4SDimitry Andric     bool IsVirtual = false;
1788*fe013be4SDimitry Andric     if (const auto *MD = dyn_cast<CXXMethodDecl>(FuncDecl))
1789*fe013be4SDimitry Andric       IsVirtual = MD->isVirtual();
1790*fe013be4SDimitry Andric 
1791*fe013be4SDimitry Andric     // In any case call the function. The return value will end up on the stack
1792*fe013be4SDimitry Andric     // and if the function has RVO, we already have the pointer on the stack to
1793*fe013be4SDimitry Andric     // write the result into.
1794*fe013be4SDimitry Andric     if (IsVirtual && !HasQualifier) {
1795*fe013be4SDimitry Andric       if (!this->emitCallVirt(Func, E))
1796*fe013be4SDimitry Andric         return false;
1797*fe013be4SDimitry Andric     } else {
1798*fe013be4SDimitry Andric       if (!this->emitCall(Func, E))
1799*fe013be4SDimitry Andric         return false;
1800*fe013be4SDimitry Andric     }
1801*fe013be4SDimitry Andric   } else {
1802*fe013be4SDimitry Andric     // Indirect call. Visit the callee, which will leave a FunctionPointer on
1803*fe013be4SDimitry Andric     // the stack. Cleanup of the returned value if necessary will be done after
1804*fe013be4SDimitry Andric     // the function call completed.
1805*fe013be4SDimitry Andric     if (!this->visit(E->getCallee()))
1806*fe013be4SDimitry Andric       return false;
1807*fe013be4SDimitry Andric 
1808*fe013be4SDimitry Andric     if (!this->emitCallPtr(E))
1809*fe013be4SDimitry Andric       return false;
1810*fe013be4SDimitry Andric   }
1811*fe013be4SDimitry Andric 
1812*fe013be4SDimitry Andric   // Cleanup for discarded return values.
1813bdd1243dSDimitry Andric   if (DiscardResult && !ReturnType->isVoidType() && T)
1814bdd1243dSDimitry Andric     return this->emitPop(*T, E);
1815bdd1243dSDimitry Andric 
1816bdd1243dSDimitry Andric   return true;
1817bdd1243dSDimitry Andric }
1818bdd1243dSDimitry Andric 
1819bdd1243dSDimitry Andric template <class Emitter>
1820bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCXXMemberCallExpr(
1821bdd1243dSDimitry Andric     const CXXMemberCallExpr *E) {
1822bdd1243dSDimitry Andric   // Get a This pointer on the stack.
1823bdd1243dSDimitry Andric   if (!this->visit(E->getImplicitObjectArgument()))
1824bdd1243dSDimitry Andric     return false;
1825bdd1243dSDimitry Andric 
1826bdd1243dSDimitry Andric   return VisitCallExpr(E);
1827bdd1243dSDimitry Andric }
1828bdd1243dSDimitry Andric 
1829bdd1243dSDimitry Andric template <class Emitter>
1830bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCXXDefaultInitExpr(
1831bdd1243dSDimitry Andric     const CXXDefaultInitExpr *E) {
1832*fe013be4SDimitry Andric   assert(classify(E->getType()));
1833bdd1243dSDimitry Andric   return this->visit(E->getExpr());
1834bdd1243dSDimitry Andric }
1835bdd1243dSDimitry Andric 
1836bdd1243dSDimitry Andric template <class Emitter>
1837bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCXXDefaultArgExpr(
1838bdd1243dSDimitry Andric     const CXXDefaultArgExpr *E) {
1839bdd1243dSDimitry Andric   return this->visit(E->getExpr());
1840bdd1243dSDimitry Andric }
1841bdd1243dSDimitry Andric 
1842bdd1243dSDimitry Andric template <class Emitter>
1843bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCXXBoolLiteralExpr(
1844bdd1243dSDimitry Andric     const CXXBoolLiteralExpr *E) {
1845bdd1243dSDimitry Andric   if (DiscardResult)
1846bdd1243dSDimitry Andric     return true;
1847bdd1243dSDimitry Andric 
1848bdd1243dSDimitry Andric   return this->emitConstBool(E->getValue(), E);
1849bdd1243dSDimitry Andric }
1850bdd1243dSDimitry Andric 
1851bdd1243dSDimitry Andric template <class Emitter>
1852bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCXXNullPtrLiteralExpr(
1853bdd1243dSDimitry Andric     const CXXNullPtrLiteralExpr *E) {
1854bdd1243dSDimitry Andric   if (DiscardResult)
1855bdd1243dSDimitry Andric     return true;
1856bdd1243dSDimitry Andric 
1857bdd1243dSDimitry Andric   return this->emitNullPtr(E);
1858bdd1243dSDimitry Andric }
1859bdd1243dSDimitry Andric 
1860bdd1243dSDimitry Andric template <class Emitter>
1861bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCXXThisExpr(const CXXThisExpr *E) {
1862bdd1243dSDimitry Andric   if (DiscardResult)
1863bdd1243dSDimitry Andric     return true;
1864bdd1243dSDimitry Andric   return this->emitThis(E);
1865bdd1243dSDimitry Andric }
1866bdd1243dSDimitry Andric 
1867bdd1243dSDimitry Andric template <class Emitter>
1868bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitUnaryOperator(const UnaryOperator *E) {
1869bdd1243dSDimitry Andric   const Expr *SubExpr = E->getSubExpr();
1870bdd1243dSDimitry Andric   std::optional<PrimType> T = classify(SubExpr->getType());
1871bdd1243dSDimitry Andric 
1872bdd1243dSDimitry Andric   switch (E->getOpcode()) {
1873bdd1243dSDimitry Andric   case UO_PostInc: { // x++
1874bdd1243dSDimitry Andric     if (!this->visit(SubExpr))
1875bdd1243dSDimitry Andric       return false;
1876bdd1243dSDimitry Andric 
1877*fe013be4SDimitry Andric     if (T == PT_Ptr) {
1878*fe013be4SDimitry Andric       if (!this->emitIncPtr(E))
1879*fe013be4SDimitry Andric         return false;
1880*fe013be4SDimitry Andric 
1881*fe013be4SDimitry Andric       return DiscardResult ? this->emitPopPtr(E) : true;
1882*fe013be4SDimitry Andric     }
1883*fe013be4SDimitry Andric 
1884*fe013be4SDimitry Andric     if (T == PT_Float) {
1885*fe013be4SDimitry Andric       return DiscardResult ? this->emitIncfPop(getRoundingMode(E), E)
1886*fe013be4SDimitry Andric                            : this->emitIncf(getRoundingMode(E), E);
1887*fe013be4SDimitry Andric     }
1888*fe013be4SDimitry Andric 
1889bdd1243dSDimitry Andric     return DiscardResult ? this->emitIncPop(*T, E) : this->emitInc(*T, E);
1890bdd1243dSDimitry Andric   }
1891bdd1243dSDimitry Andric   case UO_PostDec: { // x--
1892bdd1243dSDimitry Andric     if (!this->visit(SubExpr))
1893bdd1243dSDimitry Andric       return false;
1894bdd1243dSDimitry Andric 
1895*fe013be4SDimitry Andric     if (T == PT_Ptr) {
1896*fe013be4SDimitry Andric       if (!this->emitDecPtr(E))
1897*fe013be4SDimitry Andric         return false;
1898*fe013be4SDimitry Andric 
1899*fe013be4SDimitry Andric       return DiscardResult ? this->emitPopPtr(E) : true;
1900*fe013be4SDimitry Andric     }
1901*fe013be4SDimitry Andric 
1902*fe013be4SDimitry Andric     if (T == PT_Float) {
1903*fe013be4SDimitry Andric       return DiscardResult ? this->emitDecfPop(getRoundingMode(E), E)
1904*fe013be4SDimitry Andric                            : this->emitDecf(getRoundingMode(E), E);
1905*fe013be4SDimitry Andric     }
1906*fe013be4SDimitry Andric 
1907bdd1243dSDimitry Andric     return DiscardResult ? this->emitDecPop(*T, E) : this->emitDec(*T, E);
1908bdd1243dSDimitry Andric   }
1909bdd1243dSDimitry Andric   case UO_PreInc: { // ++x
1910bdd1243dSDimitry Andric     if (!this->visit(SubExpr))
1911bdd1243dSDimitry Andric       return false;
1912bdd1243dSDimitry Andric 
1913*fe013be4SDimitry Andric     if (T == PT_Ptr) {
1914*fe013be4SDimitry Andric       this->emitLoadPtr(E);
1915*fe013be4SDimitry Andric       this->emitConstUint8(1, E);
1916*fe013be4SDimitry Andric       this->emitAddOffsetUint8(E);
1917*fe013be4SDimitry Andric       return DiscardResult ? this->emitStorePopPtr(E) : this->emitStorePtr(E);
1918*fe013be4SDimitry Andric     }
1919bdd1243dSDimitry Andric 
1920*fe013be4SDimitry Andric     // Post-inc and pre-inc are the same if the value is to be discarded.
1921*fe013be4SDimitry Andric     if (DiscardResult) {
1922*fe013be4SDimitry Andric       if (T == PT_Float)
1923*fe013be4SDimitry Andric         return this->emitIncfPop(getRoundingMode(E), E);
1924*fe013be4SDimitry Andric       return this->emitIncPop(*T, E);
1925*fe013be4SDimitry Andric     }
1926*fe013be4SDimitry Andric 
1927*fe013be4SDimitry Andric     if (T == PT_Float) {
1928*fe013be4SDimitry Andric       const auto &TargetSemantics = Ctx.getFloatSemantics(E->getType());
1929*fe013be4SDimitry Andric       this->emitLoadFloat(E);
1930*fe013be4SDimitry Andric       this->emitConstFloat(llvm::APFloat(TargetSemantics, 1), E);
1931*fe013be4SDimitry Andric       this->emitAddf(getRoundingMode(E), E);
1932*fe013be4SDimitry Andric       return this->emitStoreFloat(E);
1933*fe013be4SDimitry Andric     }
1934bdd1243dSDimitry Andric     this->emitLoad(*T, E);
1935bdd1243dSDimitry Andric     this->emitConst(1, E);
1936bdd1243dSDimitry Andric     this->emitAdd(*T, E);
1937bdd1243dSDimitry Andric     return this->emitStore(*T, E);
1938bdd1243dSDimitry Andric   }
1939bdd1243dSDimitry Andric   case UO_PreDec: { // --x
1940bdd1243dSDimitry Andric     if (!this->visit(SubExpr))
1941bdd1243dSDimitry Andric       return false;
1942bdd1243dSDimitry Andric 
1943*fe013be4SDimitry Andric     if (T == PT_Ptr) {
1944*fe013be4SDimitry Andric       this->emitLoadPtr(E);
1945*fe013be4SDimitry Andric       this->emitConstUint8(1, E);
1946*fe013be4SDimitry Andric       this->emitSubOffsetUint8(E);
1947*fe013be4SDimitry Andric       return DiscardResult ? this->emitStorePopPtr(E) : this->emitStorePtr(E);
1948*fe013be4SDimitry Andric     }
1949bdd1243dSDimitry Andric 
1950*fe013be4SDimitry Andric     // Post-dec and pre-dec are the same if the value is to be discarded.
1951*fe013be4SDimitry Andric     if (DiscardResult) {
1952*fe013be4SDimitry Andric       if (T == PT_Float)
1953*fe013be4SDimitry Andric         return this->emitDecfPop(getRoundingMode(E), E);
1954*fe013be4SDimitry Andric       return this->emitDecPop(*T, E);
1955*fe013be4SDimitry Andric     }
1956*fe013be4SDimitry Andric 
1957*fe013be4SDimitry Andric     if (T == PT_Float) {
1958*fe013be4SDimitry Andric       const auto &TargetSemantics = Ctx.getFloatSemantics(E->getType());
1959*fe013be4SDimitry Andric       this->emitLoadFloat(E);
1960*fe013be4SDimitry Andric       this->emitConstFloat(llvm::APFloat(TargetSemantics, 1), E);
1961*fe013be4SDimitry Andric       this->emitSubf(getRoundingMode(E), E);
1962*fe013be4SDimitry Andric       return this->emitStoreFloat(E);
1963*fe013be4SDimitry Andric     }
1964bdd1243dSDimitry Andric     this->emitLoad(*T, E);
1965bdd1243dSDimitry Andric     this->emitConst(1, E);
1966bdd1243dSDimitry Andric     this->emitSub(*T, E);
1967bdd1243dSDimitry Andric     return this->emitStore(*T, E);
1968bdd1243dSDimitry Andric   }
1969bdd1243dSDimitry Andric   case UO_LNot: // !x
1970bdd1243dSDimitry Andric     if (!this->visit(SubExpr))
1971bdd1243dSDimitry Andric       return false;
1972bdd1243dSDimitry Andric     // The Inv doesn't change anything, so skip it if we don't need the result.
1973bdd1243dSDimitry Andric     return DiscardResult ? this->emitPop(*T, E) : this->emitInvBool(E);
1974bdd1243dSDimitry Andric   case UO_Minus: // -x
1975bdd1243dSDimitry Andric     if (!this->visit(SubExpr))
1976bdd1243dSDimitry Andric       return false;
1977bdd1243dSDimitry Andric     return DiscardResult ? this->emitPop(*T, E) : this->emitNeg(*T, E);
1978bdd1243dSDimitry Andric   case UO_Plus:  // +x
1979bdd1243dSDimitry Andric     if (!this->visit(SubExpr)) // noop
1980bdd1243dSDimitry Andric       return false;
1981bdd1243dSDimitry Andric     return DiscardResult ? this->emitPop(*T, E) : true;
1982bdd1243dSDimitry Andric   case UO_AddrOf: // &x
1983bdd1243dSDimitry Andric     // We should already have a pointer when we get here.
1984bdd1243dSDimitry Andric     if (!this->visit(SubExpr))
1985bdd1243dSDimitry Andric       return false;
1986bdd1243dSDimitry Andric     return DiscardResult ? this->emitPop(*T, E) : true;
1987bdd1243dSDimitry Andric   case UO_Deref:  // *x
1988bdd1243dSDimitry Andric     return dereference(
1989bdd1243dSDimitry Andric         SubExpr, DerefKind::Read,
1990bdd1243dSDimitry Andric         [](PrimType) {
1991bdd1243dSDimitry Andric           llvm_unreachable("Dereferencing requires a pointer");
1992bdd1243dSDimitry Andric           return false;
1993bdd1243dSDimitry Andric         },
1994bdd1243dSDimitry Andric         [this, E](PrimType T) {
1995bdd1243dSDimitry Andric           return DiscardResult ? this->emitPop(T, E) : true;
1996bdd1243dSDimitry Andric         });
1997bdd1243dSDimitry Andric   case UO_Not:    // ~x
1998bdd1243dSDimitry Andric     if (!this->visit(SubExpr))
1999bdd1243dSDimitry Andric       return false;
2000bdd1243dSDimitry Andric     return DiscardResult ? this->emitPop(*T, E) : this->emitComp(*T, E);
2001bdd1243dSDimitry Andric   case UO_Real:   // __real x
2002bdd1243dSDimitry Andric   case UO_Imag:   // __imag x
2003bdd1243dSDimitry Andric   case UO_Extension:
2004bdd1243dSDimitry Andric   case UO_Coawait:
2005bdd1243dSDimitry Andric     assert(false && "Unhandled opcode");
2006bdd1243dSDimitry Andric   }
2007bdd1243dSDimitry Andric 
2008bdd1243dSDimitry Andric   return false;
2009bdd1243dSDimitry Andric }
2010bdd1243dSDimitry Andric 
2011bdd1243dSDimitry Andric template <class Emitter>
2012bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitDeclRefExpr(const DeclRefExpr *E) {
2013*fe013be4SDimitry Andric   if (DiscardResult)
2014*fe013be4SDimitry Andric     return true;
2015*fe013be4SDimitry Andric 
2016*fe013be4SDimitry Andric   const auto *D = E->getDecl();
2017*fe013be4SDimitry Andric 
2018*fe013be4SDimitry Andric   if (const auto *ECD = dyn_cast<EnumConstantDecl>(D)) {
2019*fe013be4SDimitry Andric     return this->emitConst(ECD->getInitVal(), E);
2020*fe013be4SDimitry Andric   } else if (const auto *BD = dyn_cast<BindingDecl>(D)) {
2021*fe013be4SDimitry Andric     return this->visit(BD->getBinding());
2022*fe013be4SDimitry Andric   } else if (const auto *FuncDecl = dyn_cast<FunctionDecl>(D)) {
2023*fe013be4SDimitry Andric     const Function *F = getFunction(FuncDecl);
2024*fe013be4SDimitry Andric     return F && this->emitGetFnPtr(F, E);
2025*fe013be4SDimitry Andric   }
2026*fe013be4SDimitry Andric 
2027bdd1243dSDimitry Andric   // References are implemented via pointers, so when we see a DeclRefExpr
2028bdd1243dSDimitry Andric   // pointing to a reference, we need to get its value directly (i.e. the
2029bdd1243dSDimitry Andric   // pointer to the actual value) instead of a pointer to the pointer to the
2030bdd1243dSDimitry Andric   // value.
2031*fe013be4SDimitry Andric   bool IsReference = D->getType()->isReferenceType();
2032bdd1243dSDimitry Andric 
2033*fe013be4SDimitry Andric   // Check for local/global variables and parameters.
2034*fe013be4SDimitry Andric   if (auto It = Locals.find(D); It != Locals.end()) {
2035bdd1243dSDimitry Andric     const unsigned Offset = It->second.Offset;
2036bdd1243dSDimitry Andric 
2037bdd1243dSDimitry Andric     if (IsReference)
2038bdd1243dSDimitry Andric       return this->emitGetLocal(PT_Ptr, Offset, E);
2039bdd1243dSDimitry Andric     return this->emitGetPtrLocal(Offset, E);
2040*fe013be4SDimitry Andric   } else if (auto GlobalIndex = P.getGlobal(D)) {
2041bdd1243dSDimitry Andric     if (IsReference)
2042*fe013be4SDimitry Andric       return this->emitGetGlobalPtr(*GlobalIndex, E);
2043bdd1243dSDimitry Andric 
2044bdd1243dSDimitry Andric     return this->emitGetPtrGlobal(*GlobalIndex, E);
2045*fe013be4SDimitry Andric   } else if (const auto *PVD = dyn_cast<ParmVarDecl>(D)) {
2046bdd1243dSDimitry Andric     if (auto It = this->Params.find(PVD); It != this->Params.end()) {
2047bdd1243dSDimitry Andric       if (IsReference)
2048*fe013be4SDimitry Andric         return this->emitGetParamPtr(It->second, E);
2049bdd1243dSDimitry Andric       return this->emitGetPtrParam(It->second, E);
2050bdd1243dSDimitry Andric     }
2051*fe013be4SDimitry Andric   }
2052*fe013be4SDimitry Andric 
2053*fe013be4SDimitry Andric   // Handle lambda captures.
2054*fe013be4SDimitry Andric   if (auto It = this->LambdaCaptures.find(D);
2055*fe013be4SDimitry Andric       It != this->LambdaCaptures.end()) {
2056*fe013be4SDimitry Andric     auto [Offset, IsReference] = It->second;
2057*fe013be4SDimitry Andric 
2058*fe013be4SDimitry Andric     if (IsReference)
2059*fe013be4SDimitry Andric       return this->emitGetThisFieldPtr(Offset, E);
2060*fe013be4SDimitry Andric     return this->emitGetPtrThisField(Offset, E);
2061bdd1243dSDimitry Andric   }
2062bdd1243dSDimitry Andric 
2063bdd1243dSDimitry Andric   return false;
2064a7dea167SDimitry Andric }
2065a7dea167SDimitry Andric 
2066a7dea167SDimitry Andric template <class Emitter>
2067a7dea167SDimitry Andric void ByteCodeExprGen<Emitter>::emitCleanup() {
2068a7dea167SDimitry Andric   for (VariableScope<Emitter> *C = VarScope; C; C = C->getParent())
2069a7dea167SDimitry Andric     C->emitDestruction();
2070a7dea167SDimitry Andric }
2071a7dea167SDimitry Andric 
2072*fe013be4SDimitry Andric template <class Emitter>
2073*fe013be4SDimitry Andric bool ByteCodeExprGen<Emitter>::emitDerivedToBaseCasts(
2074*fe013be4SDimitry Andric     const RecordType *DerivedType, const RecordType *BaseType, const Expr *E) {
2075*fe013be4SDimitry Andric   // Pointer of derived type is already on the stack.
2076*fe013be4SDimitry Andric   const auto *FinalDecl = cast<CXXRecordDecl>(BaseType->getDecl());
2077*fe013be4SDimitry Andric   const RecordDecl *CurDecl = DerivedType->getDecl();
2078*fe013be4SDimitry Andric   const Record *CurRecord = getRecord(CurDecl);
2079*fe013be4SDimitry Andric   assert(CurDecl && FinalDecl);
2080*fe013be4SDimitry Andric   for (;;) {
2081*fe013be4SDimitry Andric     assert(CurRecord->getNumBases() > 0);
2082*fe013be4SDimitry Andric     // One level up
2083*fe013be4SDimitry Andric     for (const Record::Base &B : CurRecord->bases()) {
2084*fe013be4SDimitry Andric       const auto *BaseDecl = cast<CXXRecordDecl>(B.Decl);
2085*fe013be4SDimitry Andric 
2086*fe013be4SDimitry Andric       if (BaseDecl == FinalDecl || BaseDecl->isDerivedFrom(FinalDecl)) {
2087*fe013be4SDimitry Andric         // This decl will lead us to the final decl, so emit a base cast.
2088*fe013be4SDimitry Andric         if (!this->emitGetPtrBasePop(B.Offset, E))
2089*fe013be4SDimitry Andric           return false;
2090*fe013be4SDimitry Andric 
2091*fe013be4SDimitry Andric         CurRecord = B.R;
2092*fe013be4SDimitry Andric         CurDecl = BaseDecl;
2093*fe013be4SDimitry Andric         break;
2094*fe013be4SDimitry Andric       }
2095*fe013be4SDimitry Andric     }
2096*fe013be4SDimitry Andric     if (CurDecl == FinalDecl)
2097*fe013be4SDimitry Andric       return true;
2098*fe013be4SDimitry Andric   }
2099*fe013be4SDimitry Andric 
2100*fe013be4SDimitry Andric   llvm_unreachable("Couldn't find the base class?");
2101*fe013be4SDimitry Andric   return false;
2102*fe013be4SDimitry Andric }
2103*fe013be4SDimitry Andric 
2104*fe013be4SDimitry Andric /// When calling this, we have a pointer of the local-to-destroy
2105*fe013be4SDimitry Andric /// on the stack.
2106*fe013be4SDimitry Andric /// Emit destruction of record types (or arrays of record types).
2107*fe013be4SDimitry Andric /// FIXME: Handle virtual destructors.
2108*fe013be4SDimitry Andric template <class Emitter>
2109*fe013be4SDimitry Andric bool ByteCodeExprGen<Emitter>::emitRecordDestruction(const Descriptor *Desc) {
2110*fe013be4SDimitry Andric   assert(Desc);
2111*fe013be4SDimitry Andric   assert(!Desc->isPrimitive());
2112*fe013be4SDimitry Andric   assert(!Desc->isPrimitiveArray());
2113*fe013be4SDimitry Andric 
2114*fe013be4SDimitry Andric   // Arrays.
2115*fe013be4SDimitry Andric   if (Desc->isArray()) {
2116*fe013be4SDimitry Andric     const Descriptor *ElemDesc = Desc->ElemDesc;
2117*fe013be4SDimitry Andric     const Record *ElemRecord = ElemDesc->ElemRecord;
2118*fe013be4SDimitry Andric     assert(ElemRecord); // This is not a primitive array.
2119*fe013be4SDimitry Andric 
2120*fe013be4SDimitry Andric     if (const CXXDestructorDecl *Dtor = ElemRecord->getDestructor();
2121*fe013be4SDimitry Andric         Dtor && !Dtor->isTrivial()) {
2122*fe013be4SDimitry Andric       for (ssize_t I = Desc->getNumElems() - 1; I >= 0; --I) {
2123*fe013be4SDimitry Andric         if (!this->emitConstUint64(I, SourceInfo{}))
2124*fe013be4SDimitry Andric           return false;
2125*fe013be4SDimitry Andric         if (!this->emitArrayElemPtrUint64(SourceInfo{}))
2126*fe013be4SDimitry Andric           return false;
2127*fe013be4SDimitry Andric         if (!this->emitRecordDestruction(Desc->ElemDesc))
2128*fe013be4SDimitry Andric           return false;
2129*fe013be4SDimitry Andric       }
2130*fe013be4SDimitry Andric     }
2131*fe013be4SDimitry Andric     return this->emitPopPtr(SourceInfo{});
2132*fe013be4SDimitry Andric   }
2133*fe013be4SDimitry Andric 
2134*fe013be4SDimitry Andric   const Record *R = Desc->ElemRecord;
2135*fe013be4SDimitry Andric   assert(R);
2136*fe013be4SDimitry Andric   // First, destroy all fields.
2137*fe013be4SDimitry Andric   for (const Record::Field &Field : llvm::reverse(R->fields())) {
2138*fe013be4SDimitry Andric     const Descriptor *D = Field.Desc;
2139*fe013be4SDimitry Andric     if (!D->isPrimitive() && !D->isPrimitiveArray()) {
2140*fe013be4SDimitry Andric       if (!this->emitDupPtr(SourceInfo{}))
2141*fe013be4SDimitry Andric         return false;
2142*fe013be4SDimitry Andric       if (!this->emitGetPtrField(Field.Offset, SourceInfo{}))
2143*fe013be4SDimitry Andric         return false;
2144*fe013be4SDimitry Andric       if (!this->emitRecordDestruction(D))
2145*fe013be4SDimitry Andric         return false;
2146*fe013be4SDimitry Andric     }
2147*fe013be4SDimitry Andric   }
2148*fe013be4SDimitry Andric 
2149*fe013be4SDimitry Andric   // FIXME: Unions need to be handled differently here. We don't want to
2150*fe013be4SDimitry Andric   //   call the destructor of its members.
2151*fe013be4SDimitry Andric 
2152*fe013be4SDimitry Andric   // Now emit the destructor and recurse into base classes.
2153*fe013be4SDimitry Andric   if (const CXXDestructorDecl *Dtor = R->getDestructor();
2154*fe013be4SDimitry Andric       Dtor && !Dtor->isTrivial()) {
2155*fe013be4SDimitry Andric     const Function *DtorFunc = getFunction(Dtor);
2156*fe013be4SDimitry Andric     if (DtorFunc && DtorFunc->isConstexpr()) {
2157*fe013be4SDimitry Andric       assert(DtorFunc->hasThisPointer());
2158*fe013be4SDimitry Andric       assert(DtorFunc->getNumParams() == 1);
2159*fe013be4SDimitry Andric       if (!this->emitDupPtr(SourceInfo{}))
2160*fe013be4SDimitry Andric         return false;
2161*fe013be4SDimitry Andric       if (!this->emitCall(DtorFunc, SourceInfo{}))
2162*fe013be4SDimitry Andric         return false;
2163*fe013be4SDimitry Andric     }
2164*fe013be4SDimitry Andric   }
2165*fe013be4SDimitry Andric 
2166*fe013be4SDimitry Andric   for (const Record::Base &Base : llvm::reverse(R->bases())) {
2167*fe013be4SDimitry Andric     if (!this->emitGetPtrBase(Base.Offset, SourceInfo{}))
2168*fe013be4SDimitry Andric       return false;
2169*fe013be4SDimitry Andric     if (!this->emitRecordDestruction(Base.Desc))
2170*fe013be4SDimitry Andric       return false;
2171*fe013be4SDimitry Andric   }
2172*fe013be4SDimitry Andric   // FIXME: Virtual bases.
2173*fe013be4SDimitry Andric 
2174*fe013be4SDimitry Andric   // Remove the instance pointer.
2175*fe013be4SDimitry Andric   return this->emitPopPtr(SourceInfo{});
2176*fe013be4SDimitry Andric }
2177*fe013be4SDimitry Andric 
2178a7dea167SDimitry Andric namespace clang {
2179a7dea167SDimitry Andric namespace interp {
2180a7dea167SDimitry Andric 
2181a7dea167SDimitry Andric template class ByteCodeExprGen<ByteCodeEmitter>;
2182a7dea167SDimitry Andric template class ByteCodeExprGen<EvalEmitter>;
2183a7dea167SDimitry Andric 
2184a7dea167SDimitry Andric } // namespace interp
2185a7dea167SDimitry Andric } // namespace clang
2186