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"
14fe013be4SDimitry Andric #include "Floating.h"
15a7dea167SDimitry Andric #include "Function.h"
16a7dea167SDimitry Andric #include "PrimType.h"
17a7dea167SDimitry Andric #include "Program.h"
18a7dea167SDimitry Andric 
19a7dea167SDimitry Andric using namespace clang;
20a7dea167SDimitry Andric using namespace clang::interp;
21a7dea167SDimitry Andric 
22a7dea167SDimitry Andric using APSInt = llvm::APSInt;
23a7dea167SDimitry Andric 
24a7dea167SDimitry Andric namespace clang {
25a7dea167SDimitry Andric namespace interp {
26a7dea167SDimitry Andric 
27a7dea167SDimitry Andric /// Scope used to handle temporaries in toplevel variable declarations.
28fe013be4SDimitry Andric template <class Emitter> class DeclScope final : public VariableScope<Emitter> {
29a7dea167SDimitry Andric public:
30fe013be4SDimitry Andric   DeclScope(ByteCodeExprGen<Emitter> *Ctx, const ValueDecl *VD)
31*c9157d92SDimitry Andric       : VariableScope<Emitter>(Ctx), Scope(Ctx->P, VD),
32*c9157d92SDimitry Andric         OldGlobalDecl(Ctx->GlobalDecl) {
33*c9157d92SDimitry Andric     Ctx->GlobalDecl = Context::shouldBeGloballyIndexed(VD);
34*c9157d92SDimitry Andric   }
35a7dea167SDimitry Andric 
36a7dea167SDimitry Andric   void addExtended(const Scope::Local &Local) override {
37a7dea167SDimitry Andric     return this->addLocal(Local);
38a7dea167SDimitry Andric   }
39a7dea167SDimitry Andric 
40*c9157d92SDimitry Andric   ~DeclScope() { this->Ctx->GlobalDecl = OldGlobalDecl; }
41*c9157d92SDimitry Andric 
42a7dea167SDimitry Andric private:
43a7dea167SDimitry Andric   Program::DeclScope Scope;
44*c9157d92SDimitry Andric   bool OldGlobalDecl;
45a7dea167SDimitry Andric };
46a7dea167SDimitry Andric 
47a7dea167SDimitry Andric /// Scope used to handle initialization methods.
48fe013be4SDimitry Andric template <class Emitter> class OptionScope final {
49a7dea167SDimitry Andric public:
50a7dea167SDimitry Andric   /// Root constructor, compiling or discarding primitives.
51*c9157d92SDimitry Andric   OptionScope(ByteCodeExprGen<Emitter> *Ctx, bool NewDiscardResult,
52*c9157d92SDimitry Andric               bool NewInitializing)
53*c9157d92SDimitry Andric       : Ctx(Ctx), OldDiscardResult(Ctx->DiscardResult),
54*c9157d92SDimitry Andric         OldInitializing(Ctx->Initializing) {
55a7dea167SDimitry Andric     Ctx->DiscardResult = NewDiscardResult;
56*c9157d92SDimitry Andric     Ctx->Initializing = NewInitializing;
57a7dea167SDimitry Andric   }
58a7dea167SDimitry Andric 
59*c9157d92SDimitry Andric   ~OptionScope() {
60*c9157d92SDimitry Andric     Ctx->DiscardResult = OldDiscardResult;
61*c9157d92SDimitry Andric     Ctx->Initializing = OldInitializing;
62*c9157d92SDimitry Andric   }
63a7dea167SDimitry Andric 
64a7dea167SDimitry Andric private:
65a7dea167SDimitry Andric   /// Parent context.
66a7dea167SDimitry Andric   ByteCodeExprGen<Emitter> *Ctx;
67a7dea167SDimitry Andric   /// Old discard flag to restore.
68a7dea167SDimitry Andric   bool OldDiscardResult;
69*c9157d92SDimitry Andric   bool OldInitializing;
70a7dea167SDimitry Andric };
71a7dea167SDimitry Andric 
72a7dea167SDimitry Andric } // namespace interp
73a7dea167SDimitry Andric } // namespace clang
74a7dea167SDimitry Andric 
75a7dea167SDimitry Andric template <class Emitter>
76a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCastExpr(const CastExpr *CE) {
77*c9157d92SDimitry Andric   const Expr *SubExpr = CE->getSubExpr();
78a7dea167SDimitry Andric   switch (CE->getCastKind()) {
79a7dea167SDimitry Andric 
80a7dea167SDimitry Andric   case CK_LValueToRValue: {
81a7dea167SDimitry Andric     return dereference(
82fe013be4SDimitry Andric         SubExpr, DerefKind::Read,
83a7dea167SDimitry Andric         [](PrimType) {
84a7dea167SDimitry Andric           // Value loaded - nothing to do here.
85a7dea167SDimitry Andric           return true;
86a7dea167SDimitry Andric         },
87a7dea167SDimitry Andric         [this, CE](PrimType T) {
88a7dea167SDimitry Andric           // Pointer on stack - dereference it.
89a7dea167SDimitry Andric           if (!this->emitLoadPop(T, CE))
90a7dea167SDimitry Andric             return false;
91a7dea167SDimitry Andric           return DiscardResult ? this->emitPop(T, CE) : true;
92a7dea167SDimitry Andric         });
93a7dea167SDimitry Andric   }
94a7dea167SDimitry Andric 
95bdd1243dSDimitry Andric   case CK_UncheckedDerivedToBase:
96bdd1243dSDimitry Andric   case CK_DerivedToBase: {
97bdd1243dSDimitry Andric     if (!this->visit(SubExpr))
98bdd1243dSDimitry Andric       return false;
99bdd1243dSDimitry Andric 
100*c9157d92SDimitry Andric     unsigned DerivedOffset = collectBaseOffset(getRecordTy(CE->getType()),
101*c9157d92SDimitry Andric                                                getRecordTy(SubExpr->getType()));
102*c9157d92SDimitry Andric 
103*c9157d92SDimitry Andric     return this->emitGetPtrBasePop(DerivedOffset, CE);
104*c9157d92SDimitry Andric   }
105*c9157d92SDimitry Andric 
106*c9157d92SDimitry Andric   case CK_BaseToDerived: {
107*c9157d92SDimitry Andric     if (!this->visit(SubExpr))
108*c9157d92SDimitry Andric       return false;
109*c9157d92SDimitry Andric 
110*c9157d92SDimitry Andric     unsigned DerivedOffset = collectBaseOffset(getRecordTy(SubExpr->getType()),
111*c9157d92SDimitry Andric                                                getRecordTy(CE->getType()));
112*c9157d92SDimitry Andric 
113*c9157d92SDimitry Andric     return this->emitGetPtrDerivedPop(DerivedOffset, CE);
114bdd1243dSDimitry Andric   }
115bdd1243dSDimitry Andric 
116fe013be4SDimitry Andric   case CK_FloatingCast: {
117fe013be4SDimitry Andric     if (!this->visit(SubExpr))
118fe013be4SDimitry Andric       return false;
119fe013be4SDimitry Andric     const auto *TargetSemantics = &Ctx.getFloatSemantics(CE->getType());
120fe013be4SDimitry Andric     return this->emitCastFP(TargetSemantics, getRoundingMode(CE), CE);
121fe013be4SDimitry Andric   }
122fe013be4SDimitry Andric 
123fe013be4SDimitry Andric   case CK_IntegralToFloating: {
124fe013be4SDimitry Andric     std::optional<PrimType> FromT = classify(SubExpr->getType());
125fe013be4SDimitry Andric     if (!FromT)
126fe013be4SDimitry Andric       return false;
127fe013be4SDimitry Andric 
128fe013be4SDimitry Andric     if (!this->visit(SubExpr))
129fe013be4SDimitry Andric       return false;
130fe013be4SDimitry Andric 
131fe013be4SDimitry Andric     const auto *TargetSemantics = &Ctx.getFloatSemantics(CE->getType());
132fe013be4SDimitry Andric     llvm::RoundingMode RM = getRoundingMode(CE);
133fe013be4SDimitry Andric     return this->emitCastIntegralFloating(*FromT, TargetSemantics, RM, CE);
134fe013be4SDimitry Andric   }
135fe013be4SDimitry Andric 
136fe013be4SDimitry Andric   case CK_FloatingToBoolean:
137fe013be4SDimitry Andric   case CK_FloatingToIntegral: {
138fe013be4SDimitry Andric     std::optional<PrimType> ToT = classify(CE->getType());
139fe013be4SDimitry Andric 
140fe013be4SDimitry Andric     if (!ToT)
141fe013be4SDimitry Andric       return false;
142fe013be4SDimitry Andric 
143fe013be4SDimitry Andric     if (!this->visit(SubExpr))
144fe013be4SDimitry Andric       return false;
145fe013be4SDimitry Andric 
146*c9157d92SDimitry Andric     if (ToT == PT_IntAP)
147*c9157d92SDimitry Andric       return this->emitCastFloatingIntegralAP(Ctx.getBitWidth(CE->getType()),
148*c9157d92SDimitry Andric                                               CE);
149*c9157d92SDimitry Andric     if (ToT == PT_IntAPS)
150*c9157d92SDimitry Andric       return this->emitCastFloatingIntegralAPS(Ctx.getBitWidth(CE->getType()),
151*c9157d92SDimitry Andric                                                CE);
152*c9157d92SDimitry Andric 
153fe013be4SDimitry Andric     return this->emitCastFloatingIntegral(*ToT, CE);
154fe013be4SDimitry Andric   }
155fe013be4SDimitry Andric 
156fe013be4SDimitry Andric   case CK_NullToPointer:
157fe013be4SDimitry Andric     if (DiscardResult)
158fe013be4SDimitry Andric       return true;
159fe013be4SDimitry Andric     return this->emitNull(classifyPrim(CE->getType()), CE);
160fe013be4SDimitry Andric 
161*c9157d92SDimitry Andric   case CK_PointerToIntegral: {
162*c9157d92SDimitry Andric     // TODO: Discard handling.
163*c9157d92SDimitry Andric     if (!this->visit(SubExpr))
164*c9157d92SDimitry Andric       return false;
165*c9157d92SDimitry Andric 
166*c9157d92SDimitry Andric     PrimType T = classifyPrim(CE->getType());
167*c9157d92SDimitry Andric     return this->emitCastPointerIntegral(T, CE);
168*c9157d92SDimitry Andric   }
169*c9157d92SDimitry Andric 
170*c9157d92SDimitry Andric   case CK_ArrayToPointerDecay: {
171*c9157d92SDimitry Andric     if (!this->visit(SubExpr))
172*c9157d92SDimitry Andric       return false;
173*c9157d92SDimitry Andric     if (!this->emitArrayDecay(CE))
174*c9157d92SDimitry Andric       return false;
175*c9157d92SDimitry Andric     if (DiscardResult)
176*c9157d92SDimitry Andric       return this->emitPopPtr(CE);
177*c9157d92SDimitry Andric     return true;
178*c9157d92SDimitry Andric   }
179*c9157d92SDimitry Andric 
180a7dea167SDimitry Andric   case CK_AtomicToNonAtomic:
181a7dea167SDimitry Andric   case CK_ConstructorConversion:
182a7dea167SDimitry Andric   case CK_FunctionToPointerDecay:
183a7dea167SDimitry Andric   case CK_NonAtomicToAtomic:
184a7dea167SDimitry Andric   case CK_NoOp:
185a7dea167SDimitry Andric   case CK_UserDefinedConversion:
186*c9157d92SDimitry Andric   case CK_BitCast:
187*c9157d92SDimitry Andric     return this->delegate(SubExpr);
188bdd1243dSDimitry Andric 
189bdd1243dSDimitry Andric   case CK_IntegralToBoolean:
190bdd1243dSDimitry Andric   case CK_IntegralCast: {
191*c9157d92SDimitry Andric     if (DiscardResult)
192*c9157d92SDimitry Andric       return this->discard(SubExpr);
193bdd1243dSDimitry Andric     std::optional<PrimType> FromT = classify(SubExpr->getType());
194bdd1243dSDimitry Andric     std::optional<PrimType> ToT = classify(CE->getType());
195*c9157d92SDimitry Andric 
196bdd1243dSDimitry Andric     if (!FromT || !ToT)
197bdd1243dSDimitry Andric       return false;
198bdd1243dSDimitry Andric 
199bdd1243dSDimitry Andric     if (!this->visit(SubExpr))
200bdd1243dSDimitry Andric       return false;
201bdd1243dSDimitry Andric 
202*c9157d92SDimitry Andric     if (ToT == PT_IntAP)
203*c9157d92SDimitry Andric       return this->emitCastAP(*FromT, Ctx.getBitWidth(CE->getType()), CE);
204*c9157d92SDimitry Andric     if (ToT == PT_IntAPS)
205*c9157d92SDimitry Andric       return this->emitCastAPS(*FromT, Ctx.getBitWidth(CE->getType()), CE);
206*c9157d92SDimitry Andric 
207fe013be4SDimitry Andric     if (FromT == ToT)
208fe013be4SDimitry Andric       return true;
209bdd1243dSDimitry Andric     return this->emitCast(*FromT, *ToT, CE);
210bdd1243dSDimitry Andric   }
211a7dea167SDimitry Andric 
212fe013be4SDimitry Andric   case CK_PointerToBoolean: {
213*c9157d92SDimitry Andric     PrimType PtrT = classifyPrim(SubExpr->getType());
214*c9157d92SDimitry Andric 
215fe013be4SDimitry Andric     // Just emit p != nullptr for this.
216fe013be4SDimitry Andric     if (!this->visit(SubExpr))
217fe013be4SDimitry Andric       return false;
218fe013be4SDimitry Andric 
219*c9157d92SDimitry Andric     if (!this->emitNull(PtrT, CE))
220fe013be4SDimitry Andric       return false;
221fe013be4SDimitry Andric 
222*c9157d92SDimitry Andric     return this->emitNE(PtrT, CE);
223*c9157d92SDimitry Andric   }
224*c9157d92SDimitry Andric 
225*c9157d92SDimitry Andric   case CK_IntegralComplexToBoolean:
226*c9157d92SDimitry Andric   case CK_FloatingComplexToBoolean: {
227*c9157d92SDimitry Andric     std::optional<PrimType> ElemT =
228*c9157d92SDimitry Andric         classifyComplexElementType(SubExpr->getType());
229*c9157d92SDimitry Andric     if (!ElemT)
230*c9157d92SDimitry Andric       return false;
231*c9157d92SDimitry Andric     // We emit the expression (__real(E) != 0 || __imag(E) != 0)
232*c9157d92SDimitry Andric     // for us, that means (bool)E[0] || (bool)E[1]
233*c9157d92SDimitry Andric     if (!this->visit(SubExpr))
234*c9157d92SDimitry Andric       return false;
235*c9157d92SDimitry Andric     if (!this->emitConstUint8(0, CE))
236*c9157d92SDimitry Andric       return false;
237*c9157d92SDimitry Andric     if (!this->emitArrayElemPtrUint8(CE))
238*c9157d92SDimitry Andric       return false;
239*c9157d92SDimitry Andric     if (!this->emitLoadPop(*ElemT, CE))
240*c9157d92SDimitry Andric       return false;
241*c9157d92SDimitry Andric     if (*ElemT == PT_Float) {
242*c9157d92SDimitry Andric       if (!this->emitCastFloatingIntegral(PT_Bool, CE))
243*c9157d92SDimitry Andric         return false;
244*c9157d92SDimitry Andric     } else {
245*c9157d92SDimitry Andric       if (!this->emitCast(*ElemT, PT_Bool, CE))
246*c9157d92SDimitry Andric         return false;
247*c9157d92SDimitry Andric     }
248*c9157d92SDimitry Andric 
249*c9157d92SDimitry Andric     // We now have the bool value of E[0] on the stack.
250*c9157d92SDimitry Andric     LabelTy LabelTrue = this->getLabel();
251*c9157d92SDimitry Andric     if (!this->jumpTrue(LabelTrue))
252*c9157d92SDimitry Andric       return false;
253*c9157d92SDimitry Andric 
254*c9157d92SDimitry Andric     if (!this->emitConstUint8(1, CE))
255*c9157d92SDimitry Andric       return false;
256*c9157d92SDimitry Andric     if (!this->emitArrayElemPtrPopUint8(CE))
257*c9157d92SDimitry Andric       return false;
258*c9157d92SDimitry Andric     if (!this->emitLoadPop(*ElemT, CE))
259*c9157d92SDimitry Andric       return false;
260*c9157d92SDimitry Andric     if (*ElemT == PT_Float) {
261*c9157d92SDimitry Andric       if (!this->emitCastFloatingIntegral(PT_Bool, CE))
262*c9157d92SDimitry Andric         return false;
263*c9157d92SDimitry Andric     } else {
264*c9157d92SDimitry Andric       if (!this->emitCast(*ElemT, PT_Bool, CE))
265*c9157d92SDimitry Andric         return false;
266*c9157d92SDimitry Andric     }
267*c9157d92SDimitry Andric     // Leave the boolean value of E[1] on the stack.
268*c9157d92SDimitry Andric     LabelTy EndLabel = this->getLabel();
269*c9157d92SDimitry Andric     this->jump(EndLabel);
270*c9157d92SDimitry Andric 
271*c9157d92SDimitry Andric     this->emitLabel(LabelTrue);
272*c9157d92SDimitry Andric     if (!this->emitPopPtr(CE))
273*c9157d92SDimitry Andric       return false;
274*c9157d92SDimitry Andric     if (!this->emitConstBool(true, CE))
275*c9157d92SDimitry Andric       return false;
276*c9157d92SDimitry Andric 
277*c9157d92SDimitry Andric     this->fallthrough(EndLabel);
278*c9157d92SDimitry Andric     this->emitLabel(EndLabel);
279*c9157d92SDimitry Andric 
280*c9157d92SDimitry Andric     return true;
281fe013be4SDimitry Andric   }
282fe013be4SDimitry Andric 
283a7dea167SDimitry Andric   case CK_ToVoid:
284a7dea167SDimitry Andric     return discard(SubExpr);
285a7dea167SDimitry Andric 
286bdd1243dSDimitry Andric   default:
287bdd1243dSDimitry Andric     assert(false && "Cast not implemented");
288a7dea167SDimitry Andric   }
289bdd1243dSDimitry Andric   llvm_unreachable("Unhandled clang::CastKind enum");
290a7dea167SDimitry Andric }
291a7dea167SDimitry Andric 
292a7dea167SDimitry Andric template <class Emitter>
293a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitIntegerLiteral(const IntegerLiteral *LE) {
294a7dea167SDimitry Andric   if (DiscardResult)
295a7dea167SDimitry Andric     return true;
296a7dea167SDimitry Andric 
297bdd1243dSDimitry Andric   return this->emitConst(LE->getValue(), LE);
298a7dea167SDimitry Andric }
299a7dea167SDimitry Andric 
300a7dea167SDimitry Andric template <class Emitter>
301fe013be4SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitFloatingLiteral(const FloatingLiteral *E) {
302fe013be4SDimitry Andric   if (DiscardResult)
303fe013be4SDimitry Andric     return true;
304fe013be4SDimitry Andric 
305fe013be4SDimitry Andric   return this->emitConstFloat(E->getValue(), E);
306fe013be4SDimitry Andric }
307fe013be4SDimitry Andric 
308fe013be4SDimitry Andric template <class Emitter>
309*c9157d92SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitParenExpr(const ParenExpr *E) {
310*c9157d92SDimitry Andric   return this->delegate(E->getSubExpr());
311a7dea167SDimitry Andric }
312a7dea167SDimitry Andric 
313a7dea167SDimitry Andric template <class Emitter>
314a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitBinaryOperator(const BinaryOperator *BO) {
315fe013be4SDimitry Andric   // Need short-circuiting for these.
316fe013be4SDimitry Andric   if (BO->isLogicalOp())
317fe013be4SDimitry Andric     return this->VisitLogicalBinOp(BO);
318fe013be4SDimitry Andric 
319*c9157d92SDimitry Andric   if (BO->getType()->isAnyComplexType())
320*c9157d92SDimitry Andric     return this->VisitComplexBinOp(BO);
321*c9157d92SDimitry Andric 
322a7dea167SDimitry Andric   const Expr *LHS = BO->getLHS();
323a7dea167SDimitry Andric   const Expr *RHS = BO->getRHS();
324a7dea167SDimitry Andric 
325*c9157d92SDimitry Andric   if (BO->isPtrMemOp())
326*c9157d92SDimitry Andric     return this->visit(RHS);
327*c9157d92SDimitry Andric 
328a7dea167SDimitry Andric   // Typecheck the args.
329bdd1243dSDimitry Andric   std::optional<PrimType> LT = classify(LHS->getType());
330bdd1243dSDimitry Andric   std::optional<PrimType> RT = classify(RHS->getType());
331bdd1243dSDimitry Andric   std::optional<PrimType> T = classify(BO->getType());
332a7dea167SDimitry Andric 
333fe013be4SDimitry Andric   // Deal with operations which have composite or void types.
334fe013be4SDimitry Andric   if (BO->isCommaOp()) {
335*c9157d92SDimitry Andric     if (!this->discard(LHS))
336fe013be4SDimitry Andric       return false;
337*c9157d92SDimitry Andric     if (RHS->getType()->isVoidType())
338*c9157d92SDimitry Andric       return this->discard(RHS);
339*c9157d92SDimitry Andric 
340*c9157d92SDimitry Andric     return this->delegate(RHS);
341fe013be4SDimitry Andric   }
342fe013be4SDimitry Andric 
343*c9157d92SDimitry Andric   // Special case for C++'s three-way/spaceship operator <=>, which
344*c9157d92SDimitry Andric   // returns a std::{strong,weak,partial}_ordering (which is a class, so doesn't
345*c9157d92SDimitry Andric   // have a PrimType).
346*c9157d92SDimitry Andric   if (!T) {
347*c9157d92SDimitry Andric     if (DiscardResult)
348*c9157d92SDimitry Andric       return true;
349*c9157d92SDimitry Andric     const ComparisonCategoryInfo *CmpInfo =
350*c9157d92SDimitry Andric         Ctx.getASTContext().CompCategories.lookupInfoForType(BO->getType());
351*c9157d92SDimitry Andric     assert(CmpInfo);
352*c9157d92SDimitry Andric 
353*c9157d92SDimitry Andric     // We need a temporary variable holding our return value.
354*c9157d92SDimitry Andric     if (!Initializing) {
355*c9157d92SDimitry Andric       std::optional<unsigned> ResultIndex = this->allocateLocal(BO, false);
356*c9157d92SDimitry Andric       if (!this->emitGetPtrLocal(*ResultIndex, BO))
357*c9157d92SDimitry Andric         return false;
358*c9157d92SDimitry Andric     }
359*c9157d92SDimitry Andric 
360*c9157d92SDimitry Andric     if (!visit(LHS) || !visit(RHS))
361*c9157d92SDimitry Andric       return false;
362*c9157d92SDimitry Andric 
363*c9157d92SDimitry Andric     return this->emitCMP3(*LT, CmpInfo, BO);
364*c9157d92SDimitry Andric   }
365*c9157d92SDimitry Andric 
366*c9157d92SDimitry Andric   if (!LT || !RT || !T)
367*c9157d92SDimitry Andric     return this->bail(BO);
368*c9157d92SDimitry Andric 
369bdd1243dSDimitry Andric   // Pointer arithmetic special case.
370bdd1243dSDimitry Andric   if (BO->getOpcode() == BO_Add || BO->getOpcode() == BO_Sub) {
371fe013be4SDimitry Andric     if (T == PT_Ptr || (LT == PT_Ptr && RT == PT_Ptr))
372bdd1243dSDimitry Andric       return this->VisitPointerArithBinOp(BO);
373bdd1243dSDimitry Andric   }
374bdd1243dSDimitry Andric 
375bdd1243dSDimitry Andric   if (!visit(LHS) || !visit(RHS))
376bdd1243dSDimitry Andric     return false;
377bdd1243dSDimitry Andric 
378fe013be4SDimitry Andric   // For languages such as C, cast the result of one
379fe013be4SDimitry Andric   // of our comparision opcodes to T (which is usually int).
380fe013be4SDimitry Andric   auto MaybeCastToBool = [this, T, BO](bool Result) {
381fe013be4SDimitry Andric     if (!Result)
382fe013be4SDimitry Andric       return false;
383fe013be4SDimitry Andric     if (DiscardResult)
384fe013be4SDimitry Andric       return this->emitPop(*T, BO);
385fe013be4SDimitry Andric     if (T != PT_Bool)
386fe013be4SDimitry Andric       return this->emitCast(PT_Bool, *T, BO);
387fe013be4SDimitry Andric     return true;
388fe013be4SDimitry Andric   };
389fe013be4SDimitry Andric 
390*c9157d92SDimitry Andric   auto Discard = [this, T, BO](bool Result) {
391*c9157d92SDimitry Andric     if (!Result)
392*c9157d92SDimitry Andric       return false;
393*c9157d92SDimitry Andric     return DiscardResult ? this->emitPop(*T, BO) : true;
394*c9157d92SDimitry Andric   };
395*c9157d92SDimitry Andric 
396a7dea167SDimitry Andric   switch (BO->getOpcode()) {
397a7dea167SDimitry Andric   case BO_EQ:
398fe013be4SDimitry Andric     return MaybeCastToBool(this->emitEQ(*LT, BO));
399a7dea167SDimitry Andric   case BO_NE:
400fe013be4SDimitry Andric     return MaybeCastToBool(this->emitNE(*LT, BO));
401a7dea167SDimitry Andric   case BO_LT:
402fe013be4SDimitry Andric     return MaybeCastToBool(this->emitLT(*LT, BO));
403a7dea167SDimitry Andric   case BO_LE:
404fe013be4SDimitry Andric     return MaybeCastToBool(this->emitLE(*LT, BO));
405a7dea167SDimitry Andric   case BO_GT:
406fe013be4SDimitry Andric     return MaybeCastToBool(this->emitGT(*LT, BO));
407a7dea167SDimitry Andric   case BO_GE:
408fe013be4SDimitry Andric     return MaybeCastToBool(this->emitGE(*LT, BO));
409a7dea167SDimitry Andric   case BO_Sub:
410fe013be4SDimitry Andric     if (BO->getType()->isFloatingType())
411fe013be4SDimitry Andric       return Discard(this->emitSubf(getRoundingMode(BO), BO));
412a7dea167SDimitry Andric     return Discard(this->emitSub(*T, BO));
413a7dea167SDimitry Andric   case BO_Add:
414fe013be4SDimitry Andric     if (BO->getType()->isFloatingType())
415fe013be4SDimitry Andric       return Discard(this->emitAddf(getRoundingMode(BO), BO));
416a7dea167SDimitry Andric     return Discard(this->emitAdd(*T, BO));
417a7dea167SDimitry Andric   case BO_Mul:
418fe013be4SDimitry Andric     if (BO->getType()->isFloatingType())
419fe013be4SDimitry Andric       return Discard(this->emitMulf(getRoundingMode(BO), BO));
420a7dea167SDimitry Andric     return Discard(this->emitMul(*T, BO));
421bdd1243dSDimitry Andric   case BO_Rem:
422bdd1243dSDimitry Andric     return Discard(this->emitRem(*T, BO));
423bdd1243dSDimitry Andric   case BO_Div:
424fe013be4SDimitry Andric     if (BO->getType()->isFloatingType())
425fe013be4SDimitry Andric       return Discard(this->emitDivf(getRoundingMode(BO), BO));
426bdd1243dSDimitry Andric     return Discard(this->emitDiv(*T, BO));
427bdd1243dSDimitry Andric   case BO_Assign:
428bdd1243dSDimitry Andric     if (DiscardResult)
429*c9157d92SDimitry Andric       return LHS->refersToBitField() ? this->emitStoreBitFieldPop(*T, BO)
430*c9157d92SDimitry Andric                                      : this->emitStorePop(*T, BO);
431*c9157d92SDimitry Andric     return LHS->refersToBitField() ? this->emitStoreBitField(*T, BO)
432*c9157d92SDimitry Andric                                    : this->emitStore(*T, BO);
433bdd1243dSDimitry Andric   case BO_And:
434bdd1243dSDimitry Andric     return Discard(this->emitBitAnd(*T, BO));
435bdd1243dSDimitry Andric   case BO_Or:
436bdd1243dSDimitry Andric     return Discard(this->emitBitOr(*T, BO));
437bdd1243dSDimitry Andric   case BO_Shl:
438bdd1243dSDimitry Andric     return Discard(this->emitShl(*LT, *RT, BO));
439bdd1243dSDimitry Andric   case BO_Shr:
440bdd1243dSDimitry Andric     return Discard(this->emitShr(*LT, *RT, BO));
441bdd1243dSDimitry Andric   case BO_Xor:
442bdd1243dSDimitry Andric     return Discard(this->emitBitXor(*T, BO));
443bdd1243dSDimitry Andric   case BO_LOr:
444fe013be4SDimitry Andric   case BO_LAnd:
445fe013be4SDimitry Andric     llvm_unreachable("Already handled earlier");
446a7dea167SDimitry Andric   default:
447a7dea167SDimitry Andric     return this->bail(BO);
448a7dea167SDimitry Andric   }
449bdd1243dSDimitry Andric 
450bdd1243dSDimitry Andric   llvm_unreachable("Unhandled binary op");
451a7dea167SDimitry Andric }
452a7dea167SDimitry Andric 
453bdd1243dSDimitry Andric /// Perform addition/subtraction of a pointer and an integer or
454bdd1243dSDimitry Andric /// subtraction of two pointers.
455bdd1243dSDimitry Andric template <class Emitter>
456bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitPointerArithBinOp(const BinaryOperator *E) {
457bdd1243dSDimitry Andric   BinaryOperatorKind Op = E->getOpcode();
458bdd1243dSDimitry Andric   const Expr *LHS = E->getLHS();
459bdd1243dSDimitry Andric   const Expr *RHS = E->getRHS();
460bdd1243dSDimitry Andric 
461bdd1243dSDimitry Andric   if ((Op != BO_Add && Op != BO_Sub) ||
462bdd1243dSDimitry Andric       (!LHS->getType()->isPointerType() && !RHS->getType()->isPointerType()))
463bdd1243dSDimitry Andric     return false;
464bdd1243dSDimitry Andric 
465bdd1243dSDimitry Andric   std::optional<PrimType> LT = classify(LHS);
466bdd1243dSDimitry Andric   std::optional<PrimType> RT = classify(RHS);
467bdd1243dSDimitry Andric 
468bdd1243dSDimitry Andric   if (!LT || !RT)
469bdd1243dSDimitry Andric     return false;
470bdd1243dSDimitry Andric 
471bdd1243dSDimitry Andric   if (LHS->getType()->isPointerType() && RHS->getType()->isPointerType()) {
472bdd1243dSDimitry Andric     if (Op != BO_Sub)
473bdd1243dSDimitry Andric       return false;
474bdd1243dSDimitry Andric 
475bdd1243dSDimitry Andric     assert(E->getType()->isIntegerType());
476bdd1243dSDimitry Andric     if (!visit(RHS) || !visit(LHS))
477bdd1243dSDimitry Andric       return false;
478bdd1243dSDimitry Andric 
479bdd1243dSDimitry Andric     return this->emitSubPtr(classifyPrim(E->getType()), E);
480bdd1243dSDimitry Andric   }
481bdd1243dSDimitry Andric 
482bdd1243dSDimitry Andric   PrimType OffsetType;
483bdd1243dSDimitry Andric   if (LHS->getType()->isIntegerType()) {
484bdd1243dSDimitry Andric     if (!visit(RHS) || !visit(LHS))
485bdd1243dSDimitry Andric       return false;
486bdd1243dSDimitry Andric     OffsetType = *LT;
487bdd1243dSDimitry Andric   } else if (RHS->getType()->isIntegerType()) {
488bdd1243dSDimitry Andric     if (!visit(LHS) || !visit(RHS))
489bdd1243dSDimitry Andric       return false;
490bdd1243dSDimitry Andric     OffsetType = *RT;
491bdd1243dSDimitry Andric   } else {
492bdd1243dSDimitry Andric     return false;
493bdd1243dSDimitry Andric   }
494bdd1243dSDimitry Andric 
495bdd1243dSDimitry Andric   if (Op == BO_Add)
496bdd1243dSDimitry Andric     return this->emitAddOffset(OffsetType, E);
497bdd1243dSDimitry Andric   else if (Op == BO_Sub)
498bdd1243dSDimitry Andric     return this->emitSubOffset(OffsetType, E);
499bdd1243dSDimitry Andric 
500bdd1243dSDimitry Andric   return this->bail(E);
501a7dea167SDimitry Andric }
502a7dea167SDimitry Andric 
503a7dea167SDimitry Andric template <class Emitter>
504fe013be4SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitLogicalBinOp(const BinaryOperator *E) {
505fe013be4SDimitry Andric   assert(E->isLogicalOp());
506fe013be4SDimitry Andric   BinaryOperatorKind Op = E->getOpcode();
507fe013be4SDimitry Andric   const Expr *LHS = E->getLHS();
508fe013be4SDimitry Andric   const Expr *RHS = E->getRHS();
509*c9157d92SDimitry Andric   std::optional<PrimType> T = classify(E->getType());
510bdd1243dSDimitry Andric 
511fe013be4SDimitry Andric   if (Op == BO_LOr) {
512fe013be4SDimitry Andric     // Logical OR. Visit LHS and only evaluate RHS if LHS was FALSE.
513fe013be4SDimitry Andric     LabelTy LabelTrue = this->getLabel();
514fe013be4SDimitry Andric     LabelTy LabelEnd = this->getLabel();
515fe013be4SDimitry Andric 
516*c9157d92SDimitry Andric     if (!this->visitBool(LHS))
517bdd1243dSDimitry Andric       return false;
518fe013be4SDimitry Andric     if (!this->jumpTrue(LabelTrue))
519fe013be4SDimitry Andric       return false;
520fe013be4SDimitry Andric 
521*c9157d92SDimitry Andric     if (!this->visitBool(RHS))
522fe013be4SDimitry Andric       return false;
523fe013be4SDimitry Andric     if (!this->jump(LabelEnd))
524fe013be4SDimitry Andric       return false;
525fe013be4SDimitry Andric 
526fe013be4SDimitry Andric     this->emitLabel(LabelTrue);
527fe013be4SDimitry Andric     this->emitConstBool(true, E);
528fe013be4SDimitry Andric     this->fallthrough(LabelEnd);
529fe013be4SDimitry Andric     this->emitLabel(LabelEnd);
530fe013be4SDimitry Andric 
531*c9157d92SDimitry Andric   } else {
532*c9157d92SDimitry Andric     assert(Op == BO_LAnd);
533fe013be4SDimitry Andric     // Logical AND.
534fe013be4SDimitry Andric     // Visit LHS. Only visit RHS if LHS was TRUE.
535fe013be4SDimitry Andric     LabelTy LabelFalse = this->getLabel();
536fe013be4SDimitry Andric     LabelTy LabelEnd = this->getLabel();
537fe013be4SDimitry Andric 
538*c9157d92SDimitry Andric     if (!this->visitBool(LHS))
539fe013be4SDimitry Andric       return false;
540fe013be4SDimitry Andric     if (!this->jumpFalse(LabelFalse))
541fe013be4SDimitry Andric       return false;
542fe013be4SDimitry Andric 
543*c9157d92SDimitry Andric     if (!this->visitBool(RHS))
544fe013be4SDimitry Andric       return false;
545fe013be4SDimitry Andric     if (!this->jump(LabelEnd))
546fe013be4SDimitry Andric       return false;
547fe013be4SDimitry Andric 
548fe013be4SDimitry Andric     this->emitLabel(LabelFalse);
549fe013be4SDimitry Andric     this->emitConstBool(false, E);
550fe013be4SDimitry Andric     this->fallthrough(LabelEnd);
551fe013be4SDimitry Andric     this->emitLabel(LabelEnd);
552*c9157d92SDimitry Andric   }
553fe013be4SDimitry Andric 
554fe013be4SDimitry Andric   if (DiscardResult)
555fe013be4SDimitry Andric     return this->emitPopBool(E);
556fe013be4SDimitry Andric 
557*c9157d92SDimitry Andric   // For C, cast back to integer type.
558*c9157d92SDimitry Andric   assert(T);
559*c9157d92SDimitry Andric   if (T != PT_Bool)
560*c9157d92SDimitry Andric     return this->emitCast(PT_Bool, *T, E);
561*c9157d92SDimitry Andric   return true;
562*c9157d92SDimitry Andric }
563*c9157d92SDimitry Andric 
564*c9157d92SDimitry Andric template <class Emitter>
565*c9157d92SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitComplexBinOp(const BinaryOperator *E) {
566*c9157d92SDimitry Andric   assert(Initializing);
567*c9157d92SDimitry Andric 
568*c9157d92SDimitry Andric   const Expr *LHS = E->getLHS();
569*c9157d92SDimitry Andric   const Expr *RHS = E->getRHS();
570*c9157d92SDimitry Andric   PrimType LHSElemT = *this->classifyComplexElementType(LHS->getType());
571*c9157d92SDimitry Andric   PrimType RHSElemT = *this->classifyComplexElementType(RHS->getType());
572*c9157d92SDimitry Andric 
573*c9157d92SDimitry Andric   unsigned LHSOffset = this->allocateLocalPrimitive(LHS, PT_Ptr, true, false);
574*c9157d92SDimitry Andric   unsigned RHSOffset = this->allocateLocalPrimitive(RHS, PT_Ptr, true, false);
575*c9157d92SDimitry Andric   unsigned ResultOffset = ~0u;
576*c9157d92SDimitry Andric   if (!this->DiscardResult)
577*c9157d92SDimitry Andric     ResultOffset = this->allocateLocalPrimitive(E, PT_Ptr, true, false);
578*c9157d92SDimitry Andric 
579*c9157d92SDimitry Andric   assert(LHSElemT == RHSElemT);
580*c9157d92SDimitry Andric 
581*c9157d92SDimitry Andric   // Save result pointer in ResultOffset
582*c9157d92SDimitry Andric   if (!this->DiscardResult) {
583*c9157d92SDimitry Andric     if (!this->emitDupPtr(E))
584*c9157d92SDimitry Andric       return false;
585*c9157d92SDimitry Andric     if (!this->emitSetLocal(PT_Ptr, ResultOffset, E))
586*c9157d92SDimitry Andric       return false;
587*c9157d92SDimitry Andric   }
588*c9157d92SDimitry Andric 
589*c9157d92SDimitry Andric   // Evaluate LHS and save value to LHSOffset.
590*c9157d92SDimitry Andric   if (!this->visit(LHS))
591*c9157d92SDimitry Andric     return false;
592*c9157d92SDimitry Andric   if (!this->emitSetLocal(PT_Ptr, LHSOffset, E))
593*c9157d92SDimitry Andric     return false;
594*c9157d92SDimitry Andric 
595*c9157d92SDimitry Andric   // Same with RHS.
596*c9157d92SDimitry Andric   if (!this->visit(RHS))
597*c9157d92SDimitry Andric     return false;
598*c9157d92SDimitry Andric   if (!this->emitSetLocal(PT_Ptr, RHSOffset, E))
599*c9157d92SDimitry Andric     return false;
600*c9157d92SDimitry Andric 
601*c9157d92SDimitry Andric   // Now we can get pointers to the LHS and RHS from the offsets above.
602*c9157d92SDimitry Andric   BinaryOperatorKind Op = E->getOpcode();
603*c9157d92SDimitry Andric   for (unsigned ElemIndex = 0; ElemIndex != 2; ++ElemIndex) {
604*c9157d92SDimitry Andric     // Result pointer for the store later.
605*c9157d92SDimitry Andric     if (!this->DiscardResult) {
606*c9157d92SDimitry Andric       if (!this->emitGetLocal(PT_Ptr, ResultOffset, E))
607*c9157d92SDimitry Andric         return false;
608*c9157d92SDimitry Andric     }
609*c9157d92SDimitry Andric 
610*c9157d92SDimitry Andric     if (!this->emitGetLocal(PT_Ptr, LHSOffset, E))
611*c9157d92SDimitry Andric       return false;
612*c9157d92SDimitry Andric     if (!this->emitConstUint8(ElemIndex, E))
613*c9157d92SDimitry Andric       return false;
614*c9157d92SDimitry Andric     if (!this->emitArrayElemPtrPopUint8(E))
615*c9157d92SDimitry Andric       return false;
616*c9157d92SDimitry Andric     if (!this->emitLoadPop(LHSElemT, E))
617*c9157d92SDimitry Andric       return false;
618*c9157d92SDimitry Andric 
619*c9157d92SDimitry Andric     if (!this->emitGetLocal(PT_Ptr, RHSOffset, E))
620*c9157d92SDimitry Andric       return false;
621*c9157d92SDimitry Andric     if (!this->emitConstUint8(ElemIndex, E))
622*c9157d92SDimitry Andric       return false;
623*c9157d92SDimitry Andric     if (!this->emitArrayElemPtrPopUint8(E))
624*c9157d92SDimitry Andric       return false;
625*c9157d92SDimitry Andric     if (!this->emitLoadPop(RHSElemT, E))
626*c9157d92SDimitry Andric       return false;
627*c9157d92SDimitry Andric 
628*c9157d92SDimitry Andric     // The actual operation.
629*c9157d92SDimitry Andric     switch (Op) {
630*c9157d92SDimitry Andric     case BO_Add:
631*c9157d92SDimitry Andric       if (LHSElemT == PT_Float) {
632*c9157d92SDimitry Andric         if (!this->emitAddf(getRoundingMode(E), E))
633*c9157d92SDimitry Andric           return false;
634*c9157d92SDimitry Andric       } else {
635*c9157d92SDimitry Andric         if (!this->emitAdd(LHSElemT, E))
636*c9157d92SDimitry Andric           return false;
637*c9157d92SDimitry Andric       }
638*c9157d92SDimitry Andric       break;
639*c9157d92SDimitry Andric     case BO_Sub:
640*c9157d92SDimitry Andric       if (LHSElemT == PT_Float) {
641*c9157d92SDimitry Andric         if (!this->emitSubf(getRoundingMode(E), E))
642*c9157d92SDimitry Andric           return false;
643*c9157d92SDimitry Andric       } else {
644*c9157d92SDimitry Andric         if (!this->emitSub(LHSElemT, E))
645*c9157d92SDimitry Andric           return false;
646*c9157d92SDimitry Andric       }
647*c9157d92SDimitry Andric       break;
648*c9157d92SDimitry Andric 
649*c9157d92SDimitry Andric     default:
650*c9157d92SDimitry Andric       return false;
651*c9157d92SDimitry Andric     }
652*c9157d92SDimitry Andric 
653*c9157d92SDimitry Andric     if (!this->DiscardResult) {
654*c9157d92SDimitry Andric       // Initialize array element with the value we just computed.
655*c9157d92SDimitry Andric       if (!this->emitInitElemPop(LHSElemT, ElemIndex, E))
656*c9157d92SDimitry Andric         return false;
657*c9157d92SDimitry Andric     } else {
658*c9157d92SDimitry Andric       if (!this->emitPop(LHSElemT, E))
659*c9157d92SDimitry Andric         return false;
660*c9157d92SDimitry Andric     }
661*c9157d92SDimitry Andric   }
662fe013be4SDimitry Andric   return true;
663fe013be4SDimitry Andric }
664fe013be4SDimitry Andric 
665fe013be4SDimitry Andric template <class Emitter>
666fe013be4SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E) {
667*c9157d92SDimitry Andric   QualType QT = E->getType();
668fe013be4SDimitry Andric 
669*c9157d92SDimitry Andric   if (std::optional<PrimType> T = classify(QT))
670*c9157d92SDimitry Andric     return this->visitZeroInitializer(*T, QT, E);
671*c9157d92SDimitry Andric 
672*c9157d92SDimitry Andric   if (QT->isRecordType())
673fe013be4SDimitry Andric     return false;
674fe013be4SDimitry Andric 
675*c9157d92SDimitry Andric   if (QT->isIncompleteArrayType())
676*c9157d92SDimitry Andric     return true;
677*c9157d92SDimitry Andric 
678*c9157d92SDimitry Andric   if (QT->isArrayType()) {
679*c9157d92SDimitry Andric     const ArrayType *AT = QT->getAsArrayTypeUnsafe();
680*c9157d92SDimitry Andric     assert(AT);
681*c9157d92SDimitry Andric     const auto *CAT = cast<ConstantArrayType>(AT);
682*c9157d92SDimitry Andric     size_t NumElems = CAT->getSize().getZExtValue();
683*c9157d92SDimitry Andric     PrimType ElemT = classifyPrim(CAT->getElementType());
684*c9157d92SDimitry Andric 
685*c9157d92SDimitry Andric     for (size_t I = 0; I != NumElems; ++I) {
686*c9157d92SDimitry Andric       if (!this->visitZeroInitializer(ElemT, CAT->getElementType(), E))
687*c9157d92SDimitry Andric         return false;
688*c9157d92SDimitry Andric       if (!this->emitInitElem(ElemT, I, E))
689*c9157d92SDimitry Andric         return false;
690*c9157d92SDimitry Andric     }
691*c9157d92SDimitry Andric 
692*c9157d92SDimitry Andric     return true;
693*c9157d92SDimitry Andric   }
694*c9157d92SDimitry Andric 
695*c9157d92SDimitry Andric   return false;
696bdd1243dSDimitry Andric }
697bdd1243dSDimitry Andric 
698bdd1243dSDimitry Andric template <class Emitter>
699bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitArraySubscriptExpr(
700bdd1243dSDimitry Andric     const ArraySubscriptExpr *E) {
701bdd1243dSDimitry Andric   const Expr *Base = E->getBase();
702bdd1243dSDimitry Andric   const Expr *Index = E->getIdx();
703*c9157d92SDimitry Andric 
704*c9157d92SDimitry Andric   if (DiscardResult)
705*c9157d92SDimitry Andric     return this->discard(Base) && this->discard(Index);
706bdd1243dSDimitry Andric 
707fe013be4SDimitry Andric   // Take pointer of LHS, add offset from RHS.
708bdd1243dSDimitry Andric   // What's left on the stack after this is a pointer.
709bdd1243dSDimitry Andric   if (!this->visit(Base))
710bdd1243dSDimitry Andric     return false;
711bdd1243dSDimitry Andric 
712bdd1243dSDimitry Andric   if (!this->visit(Index))
713bdd1243dSDimitry Andric     return false;
714bdd1243dSDimitry Andric 
715*c9157d92SDimitry Andric   PrimType IndexT = classifyPrim(Index->getType());
716*c9157d92SDimitry Andric   return this->emitArrayElemPtrPop(IndexT, E);
717*c9157d92SDimitry Andric }
718*c9157d92SDimitry Andric 
719*c9157d92SDimitry Andric template <class Emitter>
720*c9157d92SDimitry Andric bool ByteCodeExprGen<Emitter>::visitInitList(ArrayRef<const Expr *> Inits,
721*c9157d92SDimitry Andric                                              const Expr *E) {
722*c9157d92SDimitry Andric   assert(E->getType()->isRecordType());
723*c9157d92SDimitry Andric   const Record *R = getRecord(E->getType());
724*c9157d92SDimitry Andric 
725*c9157d92SDimitry Andric   unsigned InitIndex = 0;
726*c9157d92SDimitry Andric   for (const Expr *Init : Inits) {
727*c9157d92SDimitry Andric     if (!this->emitDupPtr(E))
728bdd1243dSDimitry Andric       return false;
729bdd1243dSDimitry Andric 
730*c9157d92SDimitry Andric     if (std::optional<PrimType> T = classify(Init)) {
731*c9157d92SDimitry Andric       const Record::Field *FieldToInit = R->getField(InitIndex);
732*c9157d92SDimitry Andric       if (!this->visit(Init))
733*c9157d92SDimitry Andric         return false;
734bdd1243dSDimitry Andric 
735*c9157d92SDimitry Andric       if (FieldToInit->isBitField()) {
736*c9157d92SDimitry Andric         if (!this->emitInitBitField(*T, FieldToInit, E))
737*c9157d92SDimitry Andric           return false;
738*c9157d92SDimitry Andric       } else {
739*c9157d92SDimitry Andric         if (!this->emitInitField(*T, FieldToInit->Offset, E))
740*c9157d92SDimitry Andric           return false;
741*c9157d92SDimitry Andric       }
742*c9157d92SDimitry Andric 
743*c9157d92SDimitry Andric       if (!this->emitPopPtr(E))
744*c9157d92SDimitry Andric         return false;
745*c9157d92SDimitry Andric       ++InitIndex;
746*c9157d92SDimitry Andric     } else {
747*c9157d92SDimitry Andric       // Initializer for a direct base class.
748*c9157d92SDimitry Andric       if (const Record::Base *B = R->getBase(Init->getType())) {
749*c9157d92SDimitry Andric         if (!this->emitGetPtrBasePop(B->Offset, Init))
750*c9157d92SDimitry Andric           return false;
751*c9157d92SDimitry Andric 
752*c9157d92SDimitry Andric         if (!this->visitInitializer(Init))
753*c9157d92SDimitry Andric           return false;
754*c9157d92SDimitry Andric 
755*c9157d92SDimitry Andric         if (!this->emitInitPtrPop(E))
756*c9157d92SDimitry Andric           return false;
757*c9157d92SDimitry Andric         // Base initializers don't increase InitIndex, since they don't count
758*c9157d92SDimitry Andric         // into the Record's fields.
759*c9157d92SDimitry Andric       } else {
760*c9157d92SDimitry Andric         const Record::Field *FieldToInit = R->getField(InitIndex);
761*c9157d92SDimitry Andric         // Non-primitive case. Get a pointer to the field-to-initialize
762*c9157d92SDimitry Andric         // on the stack and recurse into visitInitializer().
763*c9157d92SDimitry Andric         if (!this->emitGetPtrField(FieldToInit->Offset, Init))
764*c9157d92SDimitry Andric           return false;
765*c9157d92SDimitry Andric 
766*c9157d92SDimitry Andric         if (!this->visitInitializer(Init))
767*c9157d92SDimitry Andric           return false;
768*c9157d92SDimitry Andric 
769*c9157d92SDimitry Andric         if (!this->emitPopPtr(E))
770*c9157d92SDimitry Andric           return false;
771*c9157d92SDimitry Andric         ++InitIndex;
772*c9157d92SDimitry Andric       }
773*c9157d92SDimitry Andric     }
774*c9157d92SDimitry Andric   }
775bdd1243dSDimitry Andric   return true;
776bdd1243dSDimitry Andric }
777bdd1243dSDimitry Andric 
778*c9157d92SDimitry Andric /// Pointer to the array(not the element!) must be on the stack when calling
779*c9157d92SDimitry Andric /// this.
780*c9157d92SDimitry Andric template <class Emitter>
781*c9157d92SDimitry Andric bool ByteCodeExprGen<Emitter>::visitArrayElemInit(unsigned ElemIndex,
782*c9157d92SDimitry Andric                                                   const Expr *Init) {
783*c9157d92SDimitry Andric   if (std::optional<PrimType> T = classify(Init->getType())) {
784*c9157d92SDimitry Andric     // Visit the primitive element like normal.
785*c9157d92SDimitry Andric     if (!this->visit(Init))
786*c9157d92SDimitry Andric       return false;
787*c9157d92SDimitry Andric     return this->emitInitElem(*T, ElemIndex, Init);
788*c9157d92SDimitry Andric   }
789*c9157d92SDimitry Andric 
790*c9157d92SDimitry Andric   // Advance the pointer currently on the stack to the given
791*c9157d92SDimitry Andric   // dimension.
792*c9157d92SDimitry Andric   if (!this->emitConstUint32(ElemIndex, Init))
793*c9157d92SDimitry Andric     return false;
794*c9157d92SDimitry Andric   if (!this->emitArrayElemPtrUint32(Init))
795*c9157d92SDimitry Andric     return false;
796*c9157d92SDimitry Andric   if (!this->visitInitializer(Init))
797*c9157d92SDimitry Andric     return false;
798*c9157d92SDimitry Andric   return this->emitPopPtr(Init);
799*c9157d92SDimitry Andric }
800*c9157d92SDimitry Andric 
801bdd1243dSDimitry Andric template <class Emitter>
802bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitInitListExpr(const InitListExpr *E) {
803*c9157d92SDimitry Andric   // Handle discarding first.
804*c9157d92SDimitry Andric   if (DiscardResult) {
805bdd1243dSDimitry Andric     for (const Expr *Init : E->inits()) {
806*c9157d92SDimitry Andric       if (!this->discard(Init))
807bdd1243dSDimitry Andric         return false;
808bdd1243dSDimitry Andric     }
809bdd1243dSDimitry Andric     return true;
810bdd1243dSDimitry Andric   }
811bdd1243dSDimitry Andric 
812*c9157d92SDimitry Andric   // Primitive values.
813*c9157d92SDimitry Andric   if (std::optional<PrimType> T = classify(E->getType())) {
814*c9157d92SDimitry Andric     assert(!DiscardResult);
815*c9157d92SDimitry Andric     if (E->getNumInits() == 0)
816*c9157d92SDimitry Andric       return this->visitZeroInitializer(*T, E->getType(), E);
817*c9157d92SDimitry Andric     assert(E->getNumInits() == 1);
818*c9157d92SDimitry Andric     return this->delegate(E->inits()[0]);
819*c9157d92SDimitry Andric   }
820*c9157d92SDimitry Andric 
821*c9157d92SDimitry Andric   QualType T = E->getType();
822*c9157d92SDimitry Andric   if (T->isRecordType())
823*c9157d92SDimitry Andric     return this->visitInitList(E->inits(), E);
824*c9157d92SDimitry Andric 
825*c9157d92SDimitry Andric   if (T->isArrayType()) {
826*c9157d92SDimitry Andric     // FIXME: Array fillers.
827*c9157d92SDimitry Andric     unsigned ElementIndex = 0;
828*c9157d92SDimitry Andric     for (const Expr *Init : E->inits()) {
829*c9157d92SDimitry Andric       if (!this->visitArrayElemInit(ElementIndex, Init))
830*c9157d92SDimitry Andric         return false;
831*c9157d92SDimitry Andric       ++ElementIndex;
832*c9157d92SDimitry Andric     }
833*c9157d92SDimitry Andric     return true;
834*c9157d92SDimitry Andric   }
835*c9157d92SDimitry Andric 
836*c9157d92SDimitry Andric   if (T->isAnyComplexType()) {
837*c9157d92SDimitry Andric     unsigned NumInits = E->getNumInits();
838*c9157d92SDimitry Andric     QualType ElemQT = E->getType()->getAs<ComplexType>()->getElementType();
839*c9157d92SDimitry Andric     PrimType ElemT = classifyPrim(ElemQT);
840*c9157d92SDimitry Andric     if (NumInits == 0) {
841*c9157d92SDimitry Andric       // Zero-initialize both elements.
842*c9157d92SDimitry Andric       for (unsigned I = 0; I < 2; ++I) {
843*c9157d92SDimitry Andric         if (!this->visitZeroInitializer(ElemT, ElemQT, E))
844*c9157d92SDimitry Andric           return false;
845*c9157d92SDimitry Andric         if (!this->emitInitElem(ElemT, I, E))
846*c9157d92SDimitry Andric           return false;
847*c9157d92SDimitry Andric       }
848*c9157d92SDimitry Andric     } else if (NumInits == 2) {
849*c9157d92SDimitry Andric       unsigned InitIndex = 0;
850*c9157d92SDimitry Andric       for (const Expr *Init : E->inits()) {
851*c9157d92SDimitry Andric         if (!this->visit(Init))
852*c9157d92SDimitry Andric           return false;
853*c9157d92SDimitry Andric 
854*c9157d92SDimitry Andric         if (!this->emitInitElem(ElemT, InitIndex, E))
855*c9157d92SDimitry Andric           return false;
856*c9157d92SDimitry Andric         ++InitIndex;
857*c9157d92SDimitry Andric       }
858*c9157d92SDimitry Andric     }
859*c9157d92SDimitry Andric     return true;
860*c9157d92SDimitry Andric   }
861*c9157d92SDimitry Andric 
862*c9157d92SDimitry Andric   return false;
863*c9157d92SDimitry Andric }
864*c9157d92SDimitry Andric 
865*c9157d92SDimitry Andric template <class Emitter>
866*c9157d92SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCXXParenListInitExpr(
867*c9157d92SDimitry Andric     const CXXParenListInitExpr *E) {
868*c9157d92SDimitry Andric   if (DiscardResult) {
869*c9157d92SDimitry Andric     for (const Expr *Init : E->getInitExprs()) {
870*c9157d92SDimitry Andric       if (!this->discard(Init))
871*c9157d92SDimitry Andric         return false;
872*c9157d92SDimitry Andric     }
873*c9157d92SDimitry Andric     return true;
874*c9157d92SDimitry Andric   }
875*c9157d92SDimitry Andric 
876*c9157d92SDimitry Andric   assert(E->getType()->isRecordType());
877*c9157d92SDimitry Andric   return this->visitInitList(E->getInitExprs(), E);
878*c9157d92SDimitry Andric }
879*c9157d92SDimitry Andric 
880bdd1243dSDimitry Andric template <class Emitter>
881bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitSubstNonTypeTemplateParmExpr(
882bdd1243dSDimitry Andric     const SubstNonTypeTemplateParmExpr *E) {
883*c9157d92SDimitry Andric   return this->delegate(E->getReplacement());
884bdd1243dSDimitry Andric }
885bdd1243dSDimitry Andric 
886bdd1243dSDimitry Andric template <class Emitter>
887bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitConstantExpr(const ConstantExpr *E) {
888*c9157d92SDimitry Andric   // Try to emit the APValue directly, without visiting the subexpr.
889*c9157d92SDimitry Andric   // This will only fail if we can't emit the APValue, so won't emit any
890*c9157d92SDimitry Andric   // diagnostics or any double values.
891*c9157d92SDimitry Andric   std::optional<PrimType> T = classify(E->getType());
892*c9157d92SDimitry Andric   if (T && E->hasAPValueResult() &&
893*c9157d92SDimitry Andric       this->visitAPValue(E->getAPValueResult(), *T, E))
894*c9157d92SDimitry Andric     return true;
895*c9157d92SDimitry Andric 
896*c9157d92SDimitry Andric   return this->delegate(E->getSubExpr());
897bdd1243dSDimitry Andric }
898bdd1243dSDimitry Andric 
899bdd1243dSDimitry Andric static CharUnits AlignOfType(QualType T, const ASTContext &ASTCtx,
900bdd1243dSDimitry Andric                              UnaryExprOrTypeTrait Kind) {
901bdd1243dSDimitry Andric   bool AlignOfReturnsPreferred =
902bdd1243dSDimitry Andric       ASTCtx.getLangOpts().getClangABICompat() <= LangOptions::ClangABI::Ver7;
903bdd1243dSDimitry Andric 
904bdd1243dSDimitry Andric   // C++ [expr.alignof]p3:
905bdd1243dSDimitry Andric   //     When alignof is applied to a reference type, the result is the
906bdd1243dSDimitry Andric   //     alignment of the referenced type.
907bdd1243dSDimitry Andric   if (const auto *Ref = T->getAs<ReferenceType>())
908bdd1243dSDimitry Andric     T = Ref->getPointeeType();
909bdd1243dSDimitry Andric 
910bdd1243dSDimitry Andric   // __alignof is defined to return the preferred alignment.
911bdd1243dSDimitry Andric   // Before 8, clang returned the preferred alignment for alignof and
912bdd1243dSDimitry Andric   // _Alignof as well.
913bdd1243dSDimitry Andric   if (Kind == UETT_PreferredAlignOf || AlignOfReturnsPreferred)
914bdd1243dSDimitry Andric     return ASTCtx.toCharUnitsFromBits(ASTCtx.getPreferredTypeAlign(T));
915bdd1243dSDimitry Andric 
916bdd1243dSDimitry Andric   return ASTCtx.getTypeAlignInChars(T);
917bdd1243dSDimitry Andric }
918bdd1243dSDimitry Andric 
919bdd1243dSDimitry Andric template <class Emitter>
920bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitUnaryExprOrTypeTraitExpr(
921bdd1243dSDimitry Andric     const UnaryExprOrTypeTraitExpr *E) {
922bdd1243dSDimitry Andric   UnaryExprOrTypeTrait Kind = E->getKind();
923bdd1243dSDimitry Andric   ASTContext &ASTCtx = Ctx.getASTContext();
924bdd1243dSDimitry Andric 
925bdd1243dSDimitry Andric   if (Kind == UETT_SizeOf) {
926bdd1243dSDimitry Andric     QualType ArgType = E->getTypeOfArgument();
927bdd1243dSDimitry Andric     CharUnits Size;
928bdd1243dSDimitry Andric     if (ArgType->isVoidType() || ArgType->isFunctionType())
929bdd1243dSDimitry Andric       Size = CharUnits::One();
930bdd1243dSDimitry Andric     else {
931bdd1243dSDimitry Andric       if (ArgType->isDependentType() || !ArgType->isConstantSizeType())
932bdd1243dSDimitry Andric         return false;
933bdd1243dSDimitry Andric 
934bdd1243dSDimitry Andric       Size = ASTCtx.getTypeSizeInChars(ArgType);
935bdd1243dSDimitry Andric     }
936bdd1243dSDimitry Andric 
937*c9157d92SDimitry Andric     if (DiscardResult)
938*c9157d92SDimitry Andric       return true;
939*c9157d92SDimitry Andric 
940bdd1243dSDimitry Andric     return this->emitConst(Size.getQuantity(), E);
941bdd1243dSDimitry Andric   }
942bdd1243dSDimitry Andric 
943bdd1243dSDimitry Andric   if (Kind == UETT_AlignOf || Kind == UETT_PreferredAlignOf) {
944bdd1243dSDimitry Andric     CharUnits Size;
945bdd1243dSDimitry Andric 
946bdd1243dSDimitry Andric     if (E->isArgumentType()) {
947bdd1243dSDimitry Andric       QualType ArgType = E->getTypeOfArgument();
948bdd1243dSDimitry Andric 
949bdd1243dSDimitry Andric       Size = AlignOfType(ArgType, ASTCtx, Kind);
950bdd1243dSDimitry Andric     } else {
951bdd1243dSDimitry Andric       // Argument is an expression, not a type.
952bdd1243dSDimitry Andric       const Expr *Arg = E->getArgumentExpr()->IgnoreParens();
953bdd1243dSDimitry Andric 
954bdd1243dSDimitry Andric       // The kinds of expressions that we have special-case logic here for
955bdd1243dSDimitry Andric       // should be kept up to date with the special checks for those
956bdd1243dSDimitry Andric       // expressions in Sema.
957bdd1243dSDimitry Andric 
958bdd1243dSDimitry Andric       // alignof decl is always accepted, even if it doesn't make sense: we
959bdd1243dSDimitry Andric       // default to 1 in those cases.
960bdd1243dSDimitry Andric       if (const auto *DRE = dyn_cast<DeclRefExpr>(Arg))
961bdd1243dSDimitry Andric         Size = ASTCtx.getDeclAlign(DRE->getDecl(),
962bdd1243dSDimitry Andric                                    /*RefAsPointee*/ true);
963bdd1243dSDimitry Andric       else if (const auto *ME = dyn_cast<MemberExpr>(Arg))
964bdd1243dSDimitry Andric         Size = ASTCtx.getDeclAlign(ME->getMemberDecl(),
965bdd1243dSDimitry Andric                                    /*RefAsPointee*/ true);
966bdd1243dSDimitry Andric       else
967bdd1243dSDimitry Andric         Size = AlignOfType(Arg->getType(), ASTCtx, Kind);
968bdd1243dSDimitry Andric     }
969bdd1243dSDimitry Andric 
970*c9157d92SDimitry Andric     if (DiscardResult)
971*c9157d92SDimitry Andric       return true;
972*c9157d92SDimitry Andric 
973bdd1243dSDimitry Andric     return this->emitConst(Size.getQuantity(), E);
974bdd1243dSDimitry Andric   }
975bdd1243dSDimitry Andric 
976bdd1243dSDimitry Andric   return false;
977bdd1243dSDimitry Andric }
978bdd1243dSDimitry Andric 
979bdd1243dSDimitry Andric template <class Emitter>
980bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitMemberExpr(const MemberExpr *E) {
981bdd1243dSDimitry Andric   // 'Base.Member'
982bdd1243dSDimitry Andric   const Expr *Base = E->getBase();
983*c9157d92SDimitry Andric 
984*c9157d92SDimitry Andric   if (DiscardResult)
985*c9157d92SDimitry Andric     return this->discard(Base);
986bdd1243dSDimitry Andric 
987bdd1243dSDimitry Andric   if (!this->visit(Base))
988bdd1243dSDimitry Andric     return false;
989bdd1243dSDimitry Andric 
990bdd1243dSDimitry Andric   // Base above gives us a pointer on the stack.
991bdd1243dSDimitry Andric   // TODO: Implement non-FieldDecl members.
992*c9157d92SDimitry Andric   const ValueDecl *Member = E->getMemberDecl();
993bdd1243dSDimitry Andric   if (const auto *FD = dyn_cast<FieldDecl>(Member)) {
994bdd1243dSDimitry Andric     const RecordDecl *RD = FD->getParent();
995bdd1243dSDimitry Andric     const Record *R = getRecord(RD);
996bdd1243dSDimitry Andric     const Record::Field *F = R->getField(FD);
997bdd1243dSDimitry Andric     // Leave a pointer to the field on the stack.
998bdd1243dSDimitry Andric     if (F->Decl->getType()->isReferenceType())
999bdd1243dSDimitry Andric       return this->emitGetFieldPop(PT_Ptr, F->Offset, E);
1000bdd1243dSDimitry Andric     return this->emitGetPtrField(F->Offset, E);
1001bdd1243dSDimitry Andric   }
1002bdd1243dSDimitry Andric 
1003bdd1243dSDimitry Andric   return false;
1004bdd1243dSDimitry Andric }
1005bdd1243dSDimitry Andric 
1006bdd1243dSDimitry Andric template <class Emitter>
1007bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitArrayInitIndexExpr(
1008bdd1243dSDimitry Andric     const ArrayInitIndexExpr *E) {
1009bdd1243dSDimitry Andric   // ArrayIndex might not be set if a ArrayInitIndexExpr is being evaluated
1010bdd1243dSDimitry Andric   // stand-alone, e.g. via EvaluateAsInt().
1011bdd1243dSDimitry Andric   if (!ArrayIndex)
1012bdd1243dSDimitry Andric     return false;
1013bdd1243dSDimitry Andric   return this->emitConst(*ArrayIndex, E);
1014bdd1243dSDimitry Andric }
1015bdd1243dSDimitry Andric 
1016bdd1243dSDimitry Andric template <class Emitter>
1017*c9157d92SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitArrayInitLoopExpr(
1018*c9157d92SDimitry Andric     const ArrayInitLoopExpr *E) {
1019*c9157d92SDimitry Andric   assert(Initializing);
1020*c9157d92SDimitry Andric   assert(!DiscardResult);
1021*c9157d92SDimitry Andric   // TODO: This compiles to quite a lot of bytecode if the array is larger.
1022*c9157d92SDimitry Andric   //   Investigate compiling this to a loop.
1023*c9157d92SDimitry Andric 
1024*c9157d92SDimitry Andric   const Expr *SubExpr = E->getSubExpr();
1025*c9157d92SDimitry Andric   const Expr *CommonExpr = E->getCommonExpr();
1026*c9157d92SDimitry Andric   size_t Size = E->getArraySize().getZExtValue();
1027*c9157d92SDimitry Andric 
1028*c9157d92SDimitry Andric   // If the common expression is an opaque expression, we visit it
1029*c9157d92SDimitry Andric   // here once so we have its value cached.
1030*c9157d92SDimitry Andric   // FIXME: This might be necessary (or useful) for all expressions.
1031*c9157d92SDimitry Andric   if (isa<OpaqueValueExpr>(CommonExpr)) {
1032*c9157d92SDimitry Andric     if (!this->discard(CommonExpr))
1033*c9157d92SDimitry Andric       return false;
1034*c9157d92SDimitry Andric   }
1035*c9157d92SDimitry Andric 
1036*c9157d92SDimitry Andric   // So, every iteration, we execute an assignment here
1037*c9157d92SDimitry Andric   // where the LHS is on the stack (the target array)
1038*c9157d92SDimitry Andric   // and the RHS is our SubExpr.
1039*c9157d92SDimitry Andric   for (size_t I = 0; I != Size; ++I) {
1040*c9157d92SDimitry Andric     ArrayIndexScope<Emitter> IndexScope(this, I);
1041*c9157d92SDimitry Andric     BlockScope<Emitter> BS(this);
1042*c9157d92SDimitry Andric 
1043*c9157d92SDimitry Andric     if (!this->visitArrayElemInit(I, SubExpr))
1044*c9157d92SDimitry Andric       return false;
1045*c9157d92SDimitry Andric   }
1046*c9157d92SDimitry Andric   return true;
1047*c9157d92SDimitry Andric }
1048*c9157d92SDimitry Andric 
1049*c9157d92SDimitry Andric template <class Emitter>
1050bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitOpaqueValueExpr(const OpaqueValueExpr *E) {
1051*c9157d92SDimitry Andric   if (Initializing)
1052*c9157d92SDimitry Andric     return this->visitInitializer(E->getSourceExpr());
1053*c9157d92SDimitry Andric 
1054*c9157d92SDimitry Andric   PrimType SubExprT = classify(E->getSourceExpr()).value_or(PT_Ptr);
1055*c9157d92SDimitry Andric   if (auto It = OpaqueExprs.find(E); It != OpaqueExprs.end())
1056*c9157d92SDimitry Andric     return this->emitGetLocal(SubExprT, It->second, E);
1057*c9157d92SDimitry Andric 
1058*c9157d92SDimitry Andric   if (!this->visit(E->getSourceExpr()))
1059*c9157d92SDimitry Andric     return false;
1060*c9157d92SDimitry Andric 
1061*c9157d92SDimitry Andric   // At this point we either have the evaluated source expression or a pointer
1062*c9157d92SDimitry Andric   // to an object on the stack. We want to create a local variable that stores
1063*c9157d92SDimitry Andric   // this value.
1064*c9157d92SDimitry Andric   std::optional<unsigned> LocalIndex =
1065*c9157d92SDimitry Andric       allocateLocalPrimitive(E, SubExprT, /*IsConst=*/true);
1066*c9157d92SDimitry Andric   if (!LocalIndex)
1067*c9157d92SDimitry Andric     return false;
1068*c9157d92SDimitry Andric   if (!this->emitSetLocal(SubExprT, *LocalIndex, E))
1069*c9157d92SDimitry Andric     return false;
1070*c9157d92SDimitry Andric 
1071*c9157d92SDimitry Andric   // Here the local variable is created but the value is removed from the stack,
1072*c9157d92SDimitry Andric   // so we put it back, because the caller might need it.
1073*c9157d92SDimitry Andric   if (!DiscardResult) {
1074*c9157d92SDimitry Andric     if (!this->emitGetLocal(SubExprT, *LocalIndex, E))
1075*c9157d92SDimitry Andric       return false;
1076*c9157d92SDimitry Andric   }
1077*c9157d92SDimitry Andric 
1078*c9157d92SDimitry Andric   // FIXME: Ideally the cached value should be cleaned up later.
1079*c9157d92SDimitry Andric   OpaqueExprs.insert({E, *LocalIndex});
1080*c9157d92SDimitry Andric 
1081*c9157d92SDimitry Andric   return true;
1082bdd1243dSDimitry Andric }
1083bdd1243dSDimitry Andric 
1084bdd1243dSDimitry Andric template <class Emitter>
1085bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitAbstractConditionalOperator(
1086bdd1243dSDimitry Andric     const AbstractConditionalOperator *E) {
1087*c9157d92SDimitry Andric   const Expr *Condition = E->getCond();
1088*c9157d92SDimitry Andric   const Expr *TrueExpr = E->getTrueExpr();
1089*c9157d92SDimitry Andric   const Expr *FalseExpr = E->getFalseExpr();
1090*c9157d92SDimitry Andric 
1091*c9157d92SDimitry Andric   LabelTy LabelEnd = this->getLabel();   // Label after the operator.
1092*c9157d92SDimitry Andric   LabelTy LabelFalse = this->getLabel(); // Label for the false expr.
1093*c9157d92SDimitry Andric 
1094*c9157d92SDimitry Andric   if (!this->visitBool(Condition))
1095*c9157d92SDimitry Andric     return false;
1096*c9157d92SDimitry Andric 
1097*c9157d92SDimitry Andric   if (!this->jumpFalse(LabelFalse))
1098*c9157d92SDimitry Andric     return false;
1099*c9157d92SDimitry Andric 
1100*c9157d92SDimitry Andric   if (!this->delegate(TrueExpr))
1101*c9157d92SDimitry Andric     return false;
1102*c9157d92SDimitry Andric   if (!this->jump(LabelEnd))
1103*c9157d92SDimitry Andric     return false;
1104*c9157d92SDimitry Andric 
1105*c9157d92SDimitry Andric   this->emitLabel(LabelFalse);
1106*c9157d92SDimitry Andric 
1107*c9157d92SDimitry Andric   if (!this->delegate(FalseExpr))
1108*c9157d92SDimitry Andric     return false;
1109*c9157d92SDimitry Andric 
1110*c9157d92SDimitry Andric   this->fallthrough(LabelEnd);
1111*c9157d92SDimitry Andric   this->emitLabel(LabelEnd);
1112*c9157d92SDimitry Andric 
1113*c9157d92SDimitry Andric   return true;
1114bdd1243dSDimitry Andric }
1115bdd1243dSDimitry Andric 
1116bdd1243dSDimitry Andric template <class Emitter>
1117bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitStringLiteral(const StringLiteral *E) {
1118*c9157d92SDimitry Andric   if (DiscardResult)
1119*c9157d92SDimitry Andric     return true;
1120*c9157d92SDimitry Andric 
1121*c9157d92SDimitry Andric   if (!Initializing) {
1122bdd1243dSDimitry Andric     unsigned StringIndex = P.createGlobalString(E);
1123bdd1243dSDimitry Andric     return this->emitGetPtrGlobal(StringIndex, E);
1124bdd1243dSDimitry Andric   }
1125bdd1243dSDimitry Andric 
1126*c9157d92SDimitry Andric   // We are initializing an array on the stack.
1127*c9157d92SDimitry Andric   const ConstantArrayType *CAT =
1128*c9157d92SDimitry Andric       Ctx.getASTContext().getAsConstantArrayType(E->getType());
1129*c9157d92SDimitry Andric   assert(CAT && "a string literal that's not a constant array?");
1130*c9157d92SDimitry Andric 
1131*c9157d92SDimitry Andric   // If the initializer string is too long, a diagnostic has already been
1132*c9157d92SDimitry Andric   // emitted. Read only the array length from the string literal.
1133*c9157d92SDimitry Andric   unsigned ArraySize = CAT->getSize().getZExtValue();
1134*c9157d92SDimitry Andric   unsigned N = std::min(ArraySize, E->getLength());
1135*c9157d92SDimitry Andric   size_t CharWidth = E->getCharByteWidth();
1136*c9157d92SDimitry Andric 
1137*c9157d92SDimitry Andric   for (unsigned I = 0; I != N; ++I) {
1138*c9157d92SDimitry Andric     uint32_t CodeUnit = E->getCodeUnit(I);
1139*c9157d92SDimitry Andric 
1140*c9157d92SDimitry Andric     if (CharWidth == 1) {
1141*c9157d92SDimitry Andric       this->emitConstSint8(CodeUnit, E);
1142*c9157d92SDimitry Andric       this->emitInitElemSint8(I, E);
1143*c9157d92SDimitry Andric     } else if (CharWidth == 2) {
1144*c9157d92SDimitry Andric       this->emitConstUint16(CodeUnit, E);
1145*c9157d92SDimitry Andric       this->emitInitElemUint16(I, E);
1146*c9157d92SDimitry Andric     } else if (CharWidth == 4) {
1147*c9157d92SDimitry Andric       this->emitConstUint32(CodeUnit, E);
1148*c9157d92SDimitry Andric       this->emitInitElemUint32(I, E);
1149*c9157d92SDimitry Andric     } else {
1150*c9157d92SDimitry Andric       llvm_unreachable("unsupported character width");
1151*c9157d92SDimitry Andric     }
1152*c9157d92SDimitry Andric   }
1153*c9157d92SDimitry Andric 
1154*c9157d92SDimitry Andric   // Fill up the rest of the char array with NUL bytes.
1155*c9157d92SDimitry Andric   for (unsigned I = N; I != ArraySize; ++I) {
1156*c9157d92SDimitry Andric     if (CharWidth == 1) {
1157*c9157d92SDimitry Andric       this->emitConstSint8(0, E);
1158*c9157d92SDimitry Andric       this->emitInitElemSint8(I, E);
1159*c9157d92SDimitry Andric     } else if (CharWidth == 2) {
1160*c9157d92SDimitry Andric       this->emitConstUint16(0, E);
1161*c9157d92SDimitry Andric       this->emitInitElemUint16(I, E);
1162*c9157d92SDimitry Andric     } else if (CharWidth == 4) {
1163*c9157d92SDimitry Andric       this->emitConstUint32(0, E);
1164*c9157d92SDimitry Andric       this->emitInitElemUint32(I, E);
1165*c9157d92SDimitry Andric     } else {
1166*c9157d92SDimitry Andric       llvm_unreachable("unsupported character width");
1167*c9157d92SDimitry Andric     }
1168*c9157d92SDimitry Andric   }
1169*c9157d92SDimitry Andric 
1170*c9157d92SDimitry Andric   return true;
1171*c9157d92SDimitry Andric }
1172*c9157d92SDimitry Andric 
1173bdd1243dSDimitry Andric template <class Emitter>
1174bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCharacterLiteral(
1175bdd1243dSDimitry Andric     const CharacterLiteral *E) {
1176*c9157d92SDimitry Andric   if (DiscardResult)
1177*c9157d92SDimitry Andric     return true;
1178bdd1243dSDimitry Andric   return this->emitConst(E->getValue(), E);
1179bdd1243dSDimitry Andric }
1180bdd1243dSDimitry Andric 
1181bdd1243dSDimitry Andric template <class Emitter>
1182fe013be4SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitFloatCompoundAssignOperator(
1183bdd1243dSDimitry Andric     const CompoundAssignOperator *E) {
1184fe013be4SDimitry Andric 
1185bdd1243dSDimitry Andric   const Expr *LHS = E->getLHS();
1186bdd1243dSDimitry Andric   const Expr *RHS = E->getRHS();
1187*c9157d92SDimitry Andric   QualType LHSType = LHS->getType();
1188fe013be4SDimitry Andric   QualType LHSComputationType = E->getComputationLHSType();
1189fe013be4SDimitry Andric   QualType ResultType = E->getComputationResultType();
1190fe013be4SDimitry Andric   std::optional<PrimType> LT = classify(LHSComputationType);
1191fe013be4SDimitry Andric   std::optional<PrimType> RT = classify(ResultType);
1192bdd1243dSDimitry Andric 
1193*c9157d92SDimitry Andric   assert(ResultType->isFloatingType());
1194*c9157d92SDimitry Andric 
1195bdd1243dSDimitry Andric   if (!LT || !RT)
1196bdd1243dSDimitry Andric     return false;
1197bdd1243dSDimitry Andric 
1198*c9157d92SDimitry Andric   PrimType LHST = classifyPrim(LHSType);
1199*c9157d92SDimitry Andric 
1200fe013be4SDimitry Andric   // C++17 onwards require that we evaluate the RHS first.
1201fe013be4SDimitry Andric   // Compute RHS and save it in a temporary variable so we can
1202fe013be4SDimitry Andric   // load it again later.
1203fe013be4SDimitry Andric   if (!visit(RHS))
1204fe013be4SDimitry Andric     return false;
1205bdd1243dSDimitry Andric 
1206fe013be4SDimitry Andric   unsigned TempOffset = this->allocateLocalPrimitive(E, *RT, /*IsConst=*/true);
1207fe013be4SDimitry Andric   if (!this->emitSetLocal(*RT, TempOffset, E))
1208fe013be4SDimitry Andric     return false;
1209fe013be4SDimitry Andric 
1210fe013be4SDimitry Andric   // First, visit LHS.
1211bdd1243dSDimitry Andric   if (!visit(LHS))
1212bdd1243dSDimitry Andric     return false;
1213*c9157d92SDimitry Andric   if (!this->emitLoad(LHST, E))
1214bdd1243dSDimitry Andric     return false;
1215fe013be4SDimitry Andric 
1216fe013be4SDimitry Andric   // If necessary, convert LHS to its computation type.
1217*c9157d92SDimitry Andric   if (!this->emitPrimCast(LHST, classifyPrim(LHSComputationType),
1218*c9157d92SDimitry Andric                           LHSComputationType, E))
1219fe013be4SDimitry Andric     return false;
1220fe013be4SDimitry Andric 
1221fe013be4SDimitry Andric   // Now load RHS.
1222fe013be4SDimitry Andric   if (!this->emitGetLocal(*RT, TempOffset, E))
1223bdd1243dSDimitry Andric     return false;
1224bdd1243dSDimitry Andric 
1225*c9157d92SDimitry Andric   llvm::RoundingMode RM = getRoundingMode(E);
1226bdd1243dSDimitry Andric   switch (E->getOpcode()) {
1227bdd1243dSDimitry Andric   case BO_AddAssign:
1228fe013be4SDimitry Andric     if (!this->emitAddf(RM, E))
1229bdd1243dSDimitry Andric       return false;
1230bdd1243dSDimitry Andric     break;
1231bdd1243dSDimitry Andric   case BO_SubAssign:
1232fe013be4SDimitry Andric     if (!this->emitSubf(RM, E))
1233bdd1243dSDimitry Andric       return false;
1234bdd1243dSDimitry Andric     break;
1235bdd1243dSDimitry Andric   case BO_MulAssign:
1236fe013be4SDimitry Andric     if (!this->emitMulf(RM, E))
1237fe013be4SDimitry Andric       return false;
1238fe013be4SDimitry Andric     break;
1239bdd1243dSDimitry Andric   case BO_DivAssign:
1240fe013be4SDimitry Andric     if (!this->emitDivf(RM, E))
1241bdd1243dSDimitry Andric       return false;
1242bdd1243dSDimitry Andric     break;
1243bdd1243dSDimitry Andric   default:
1244fe013be4SDimitry Andric     return false;
1245bdd1243dSDimitry Andric   }
1246bdd1243dSDimitry Andric 
1247*c9157d92SDimitry Andric   if (!this->emitPrimCast(classifyPrim(ResultType), LHST, LHS->getType(), E))
1248fe013be4SDimitry Andric     return false;
1249fe013be4SDimitry Andric 
1250bdd1243dSDimitry Andric   if (DiscardResult)
1251*c9157d92SDimitry Andric     return this->emitStorePop(LHST, E);
1252*c9157d92SDimitry Andric   return this->emitStore(LHST, E);
1253bdd1243dSDimitry Andric }
1254bdd1243dSDimitry Andric 
1255fe013be4SDimitry Andric template <class Emitter>
1256fe013be4SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitPointerCompoundAssignOperator(
1257fe013be4SDimitry Andric     const CompoundAssignOperator *E) {
1258fe013be4SDimitry Andric   BinaryOperatorKind Op = E->getOpcode();
1259fe013be4SDimitry Andric   const Expr *LHS = E->getLHS();
1260fe013be4SDimitry Andric   const Expr *RHS = E->getRHS();
1261fe013be4SDimitry Andric   std::optional<PrimType> LT = classify(LHS->getType());
1262fe013be4SDimitry Andric   std::optional<PrimType> RT = classify(RHS->getType());
1263fe013be4SDimitry Andric 
1264fe013be4SDimitry Andric   if (Op != BO_AddAssign && Op != BO_SubAssign)
1265fe013be4SDimitry Andric     return false;
1266fe013be4SDimitry Andric 
1267fe013be4SDimitry Andric   if (!LT || !RT)
1268fe013be4SDimitry Andric     return false;
1269fe013be4SDimitry Andric   assert(*LT == PT_Ptr);
1270fe013be4SDimitry Andric 
1271fe013be4SDimitry Andric   if (!visit(LHS))
1272fe013be4SDimitry Andric     return false;
1273fe013be4SDimitry Andric 
1274fe013be4SDimitry Andric   if (!this->emitLoadPtr(LHS))
1275fe013be4SDimitry Andric     return false;
1276fe013be4SDimitry Andric 
1277fe013be4SDimitry Andric   if (!visit(RHS))
1278fe013be4SDimitry Andric     return false;
1279fe013be4SDimitry Andric 
1280fe013be4SDimitry Andric   if (Op == BO_AddAssign)
1281fe013be4SDimitry Andric     this->emitAddOffset(*RT, E);
1282fe013be4SDimitry Andric   else
1283fe013be4SDimitry Andric     this->emitSubOffset(*RT, E);
1284fe013be4SDimitry Andric 
1285fe013be4SDimitry Andric   if (DiscardResult)
1286fe013be4SDimitry Andric     return this->emitStorePopPtr(E);
1287fe013be4SDimitry Andric   return this->emitStorePtr(E);
1288fe013be4SDimitry Andric }
1289fe013be4SDimitry Andric 
1290fe013be4SDimitry Andric template <class Emitter>
1291fe013be4SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCompoundAssignOperator(
1292fe013be4SDimitry Andric     const CompoundAssignOperator *E) {
1293fe013be4SDimitry Andric 
1294fe013be4SDimitry Andric   const Expr *LHS = E->getLHS();
1295fe013be4SDimitry Andric   const Expr *RHS = E->getRHS();
1296fe013be4SDimitry Andric   std::optional<PrimType> LHSComputationT =
1297fe013be4SDimitry Andric       classify(E->getComputationLHSType());
1298fe013be4SDimitry Andric   std::optional<PrimType> LT = classify(LHS->getType());
1299fe013be4SDimitry Andric   std::optional<PrimType> RT = classify(E->getComputationResultType());
1300fe013be4SDimitry Andric   std::optional<PrimType> ResultT = classify(E->getType());
1301fe013be4SDimitry Andric 
1302fe013be4SDimitry Andric   if (!LT || !RT || !ResultT || !LHSComputationT)
1303fe013be4SDimitry Andric     return false;
1304fe013be4SDimitry Andric 
1305*c9157d92SDimitry Andric   // Handle floating point operations separately here, since they
1306*c9157d92SDimitry Andric   // require special care.
1307*c9157d92SDimitry Andric 
1308*c9157d92SDimitry Andric   if (ResultT == PT_Float || RT == PT_Float)
1309*c9157d92SDimitry Andric     return VisitFloatCompoundAssignOperator(E);
1310*c9157d92SDimitry Andric 
1311*c9157d92SDimitry Andric   if (E->getType()->isPointerType())
1312*c9157d92SDimitry Andric     return VisitPointerCompoundAssignOperator(E);
1313*c9157d92SDimitry Andric 
1314fe013be4SDimitry Andric   assert(!E->getType()->isPointerType() && "Handled above");
1315fe013be4SDimitry Andric   assert(!E->getType()->isFloatingType() && "Handled above");
1316fe013be4SDimitry Andric 
1317fe013be4SDimitry Andric   // C++17 onwards require that we evaluate the RHS first.
1318fe013be4SDimitry Andric   // Compute RHS and save it in a temporary variable so we can
1319fe013be4SDimitry Andric   // load it again later.
1320fe013be4SDimitry Andric   // FIXME: Compound assignments are unsequenced in C, so we might
1321fe013be4SDimitry Andric   //   have to figure out how to reject them.
1322fe013be4SDimitry Andric   if (!visit(RHS))
1323fe013be4SDimitry Andric     return false;
1324fe013be4SDimitry Andric 
1325fe013be4SDimitry Andric   unsigned TempOffset = this->allocateLocalPrimitive(E, *RT, /*IsConst=*/true);
1326fe013be4SDimitry Andric 
1327fe013be4SDimitry Andric   if (!this->emitSetLocal(*RT, TempOffset, E))
1328fe013be4SDimitry Andric     return false;
1329fe013be4SDimitry Andric 
1330fe013be4SDimitry Andric   // Get LHS pointer, load its value and cast it to the
1331fe013be4SDimitry Andric   // computation type if necessary.
1332fe013be4SDimitry Andric   if (!visit(LHS))
1333fe013be4SDimitry Andric     return false;
1334fe013be4SDimitry Andric   if (!this->emitLoad(*LT, E))
1335fe013be4SDimitry Andric     return false;
1336fe013be4SDimitry Andric   if (*LT != *LHSComputationT) {
1337fe013be4SDimitry Andric     if (!this->emitCast(*LT, *LHSComputationT, E))
1338fe013be4SDimitry Andric       return false;
1339fe013be4SDimitry Andric   }
1340fe013be4SDimitry Andric 
1341fe013be4SDimitry Andric   // Get the RHS value on the stack.
1342fe013be4SDimitry Andric   if (!this->emitGetLocal(*RT, TempOffset, E))
1343fe013be4SDimitry Andric     return false;
1344fe013be4SDimitry Andric 
1345fe013be4SDimitry Andric   // Perform operation.
1346fe013be4SDimitry Andric   switch (E->getOpcode()) {
1347fe013be4SDimitry Andric   case BO_AddAssign:
1348fe013be4SDimitry Andric     if (!this->emitAdd(*LHSComputationT, E))
1349fe013be4SDimitry Andric       return false;
1350fe013be4SDimitry Andric     break;
1351fe013be4SDimitry Andric   case BO_SubAssign:
1352fe013be4SDimitry Andric     if (!this->emitSub(*LHSComputationT, E))
1353fe013be4SDimitry Andric       return false;
1354fe013be4SDimitry Andric     break;
1355fe013be4SDimitry Andric   case BO_MulAssign:
1356fe013be4SDimitry Andric     if (!this->emitMul(*LHSComputationT, E))
1357fe013be4SDimitry Andric       return false;
1358fe013be4SDimitry Andric     break;
1359fe013be4SDimitry Andric   case BO_DivAssign:
1360fe013be4SDimitry Andric     if (!this->emitDiv(*LHSComputationT, E))
1361fe013be4SDimitry Andric       return false;
1362fe013be4SDimitry Andric     break;
1363fe013be4SDimitry Andric   case BO_RemAssign:
1364fe013be4SDimitry Andric     if (!this->emitRem(*LHSComputationT, E))
1365fe013be4SDimitry Andric       return false;
1366fe013be4SDimitry Andric     break;
1367fe013be4SDimitry Andric   case BO_ShlAssign:
1368fe013be4SDimitry Andric     if (!this->emitShl(*LHSComputationT, *RT, E))
1369fe013be4SDimitry Andric       return false;
1370fe013be4SDimitry Andric     break;
1371fe013be4SDimitry Andric   case BO_ShrAssign:
1372fe013be4SDimitry Andric     if (!this->emitShr(*LHSComputationT, *RT, E))
1373fe013be4SDimitry Andric       return false;
1374fe013be4SDimitry Andric     break;
1375fe013be4SDimitry Andric   case BO_AndAssign:
1376fe013be4SDimitry Andric     if (!this->emitBitAnd(*LHSComputationT, E))
1377fe013be4SDimitry Andric       return false;
1378fe013be4SDimitry Andric     break;
1379fe013be4SDimitry Andric   case BO_XorAssign:
1380fe013be4SDimitry Andric     if (!this->emitBitXor(*LHSComputationT, E))
1381fe013be4SDimitry Andric       return false;
1382fe013be4SDimitry Andric     break;
1383fe013be4SDimitry Andric   case BO_OrAssign:
1384fe013be4SDimitry Andric     if (!this->emitBitOr(*LHSComputationT, E))
1385fe013be4SDimitry Andric       return false;
1386fe013be4SDimitry Andric     break;
1387fe013be4SDimitry Andric   default:
1388fe013be4SDimitry Andric     llvm_unreachable("Unimplemented compound assign operator");
1389fe013be4SDimitry Andric   }
1390fe013be4SDimitry Andric 
1391fe013be4SDimitry Andric   // And now cast from LHSComputationT to ResultT.
1392fe013be4SDimitry Andric   if (*ResultT != *LHSComputationT) {
1393fe013be4SDimitry Andric     if (!this->emitCast(*LHSComputationT, *ResultT, E))
1394fe013be4SDimitry Andric       return false;
1395fe013be4SDimitry Andric   }
1396fe013be4SDimitry Andric 
1397fe013be4SDimitry Andric   // And store the result in LHS.
1398*c9157d92SDimitry Andric   if (DiscardResult) {
1399*c9157d92SDimitry Andric     if (LHS->refersToBitField())
1400*c9157d92SDimitry Andric       return this->emitStoreBitFieldPop(*ResultT, E);
1401fe013be4SDimitry Andric     return this->emitStorePop(*ResultT, E);
1402*c9157d92SDimitry Andric   }
1403*c9157d92SDimitry Andric   if (LHS->refersToBitField())
1404*c9157d92SDimitry Andric     return this->emitStoreBitField(*ResultT, E);
1405fe013be4SDimitry Andric   return this->emitStore(*ResultT, E);
1406fe013be4SDimitry Andric }
1407fe013be4SDimitry Andric 
1408fe013be4SDimitry Andric template <class Emitter>
1409fe013be4SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitExprWithCleanups(
1410fe013be4SDimitry Andric     const ExprWithCleanups *E) {
1411fe013be4SDimitry Andric   const Expr *SubExpr = E->getSubExpr();
1412fe013be4SDimitry Andric 
1413fe013be4SDimitry Andric   assert(E->getNumObjects() == 0 && "TODO: Implement cleanups");
1414fe013be4SDimitry Andric 
1415*c9157d92SDimitry Andric   return this->delegate(SubExpr);
1416fe013be4SDimitry Andric }
1417fe013be4SDimitry Andric 
1418fe013be4SDimitry Andric template <class Emitter>
1419fe013be4SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitMaterializeTemporaryExpr(
1420fe013be4SDimitry Andric     const MaterializeTemporaryExpr *E) {
1421fe013be4SDimitry Andric   const Expr *SubExpr = E->getSubExpr();
1422fe013be4SDimitry Andric 
1423*c9157d92SDimitry Andric   if (Initializing) {
1424*c9157d92SDimitry Andric     // We already have a value, just initialize that.
1425*c9157d92SDimitry Andric     return this->visitInitializer(SubExpr);
1426*c9157d92SDimitry Andric   }
1427*c9157d92SDimitry Andric   // If we don't end up using the materialized temporary anyway, don't
1428*c9157d92SDimitry Andric   // bother creating it.
1429*c9157d92SDimitry Andric   if (DiscardResult)
1430*c9157d92SDimitry Andric     return this->discard(SubExpr);
1431*c9157d92SDimitry Andric 
1432*c9157d92SDimitry Andric   // When we're initializing a global variable *or* the storage duration of
1433*c9157d92SDimitry Andric   // the temporary is explicitly static, create a global variable.
1434*c9157d92SDimitry Andric   std::optional<PrimType> SubExprT = classify(SubExpr);
1435*c9157d92SDimitry Andric   bool IsStatic = E->getStorageDuration() == SD_Static;
1436*c9157d92SDimitry Andric   if (GlobalDecl || IsStatic) {
1437*c9157d92SDimitry Andric     std::optional<unsigned> GlobalIndex = P.createGlobal(E);
1438*c9157d92SDimitry Andric     if (!GlobalIndex)
1439*c9157d92SDimitry Andric       return false;
1440*c9157d92SDimitry Andric 
1441fe013be4SDimitry Andric     const LifetimeExtendedTemporaryDecl *TempDecl =
1442fe013be4SDimitry Andric         E->getLifetimeExtendedTemporaryDecl();
1443*c9157d92SDimitry Andric     if (IsStatic)
1444*c9157d92SDimitry Andric       assert(TempDecl);
1445fe013be4SDimitry Andric 
1446*c9157d92SDimitry Andric     if (SubExprT) {
1447*c9157d92SDimitry Andric       if (!this->visit(SubExpr))
1448fe013be4SDimitry Andric         return false;
1449*c9157d92SDimitry Andric       if (IsStatic) {
1450fe013be4SDimitry Andric         if (!this->emitInitGlobalTemp(*SubExprT, *GlobalIndex, TempDecl, E))
1451fe013be4SDimitry Andric           return false;
1452*c9157d92SDimitry Andric       } else {
1453*c9157d92SDimitry Andric         if (!this->emitInitGlobal(*SubExprT, *GlobalIndex, E))
1454*c9157d92SDimitry Andric           return false;
1455*c9157d92SDimitry Andric       }
1456fe013be4SDimitry Andric       return this->emitGetPtrGlobal(*GlobalIndex, E);
1457fe013be4SDimitry Andric     }
1458fe013be4SDimitry Andric 
1459*c9157d92SDimitry Andric     // Non-primitive values.
1460*c9157d92SDimitry Andric     if (!this->emitGetPtrGlobal(*GlobalIndex, E))
1461fe013be4SDimitry Andric       return false;
1462*c9157d92SDimitry Andric     if (!this->visitInitializer(SubExpr))
1463*c9157d92SDimitry Andric       return false;
1464*c9157d92SDimitry Andric     if (IsStatic)
1465*c9157d92SDimitry Andric       return this->emitInitGlobalTempComp(TempDecl, E);
1466*c9157d92SDimitry Andric     return true;
1467fe013be4SDimitry Andric   }
1468fe013be4SDimitry Andric 
1469fe013be4SDimitry Andric   // For everyhing else, use local variables.
1470fe013be4SDimitry Andric   if (SubExprT) {
1471fe013be4SDimitry Andric     if (std::optional<unsigned> LocalIndex = allocateLocalPrimitive(
1472fe013be4SDimitry Andric             SubExpr, *SubExprT, /*IsConst=*/true, /*IsExtended=*/true)) {
1473*c9157d92SDimitry Andric       if (!this->visit(SubExpr))
1474fe013be4SDimitry Andric         return false;
1475fe013be4SDimitry Andric       this->emitSetLocal(*SubExprT, *LocalIndex, E);
1476fe013be4SDimitry Andric       return this->emitGetPtrLocal(*LocalIndex, E);
1477fe013be4SDimitry Andric     }
1478fe013be4SDimitry Andric   } else {
1479fe013be4SDimitry Andric     if (std::optional<unsigned> LocalIndex =
1480fe013be4SDimitry Andric             allocateLocal(SubExpr, /*IsExtended=*/true)) {
1481fe013be4SDimitry Andric       if (!this->emitGetPtrLocal(*LocalIndex, E))
1482fe013be4SDimitry Andric         return false;
1483fe013be4SDimitry Andric       return this->visitInitializer(SubExpr);
1484fe013be4SDimitry Andric     }
1485fe013be4SDimitry Andric   }
1486fe013be4SDimitry Andric   return false;
1487fe013be4SDimitry Andric }
1488fe013be4SDimitry Andric 
1489fe013be4SDimitry Andric template <class Emitter>
1490*c9157d92SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCXXBindTemporaryExpr(
1491*c9157d92SDimitry Andric     const CXXBindTemporaryExpr *E) {
1492*c9157d92SDimitry Andric   return this->delegate(E->getSubExpr());
1493*c9157d92SDimitry Andric }
1494*c9157d92SDimitry Andric 
1495*c9157d92SDimitry Andric template <class Emitter>
1496fe013be4SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCompoundLiteralExpr(
1497fe013be4SDimitry Andric     const CompoundLiteralExpr *E) {
1498fe013be4SDimitry Andric   const Expr *Init = E->getInitializer();
1499*c9157d92SDimitry Andric   if (Initializing) {
1500*c9157d92SDimitry Andric     // We already have a value, just initialize that.
1501*c9157d92SDimitry Andric     return this->visitInitializer(Init);
1502*c9157d92SDimitry Andric   }
1503*c9157d92SDimitry Andric 
1504*c9157d92SDimitry Andric   std::optional<PrimType> T = classify(E->getType());
1505fe013be4SDimitry Andric   if (E->isFileScope()) {
1506fe013be4SDimitry Andric     if (std::optional<unsigned> GlobalIndex = P.createGlobal(E)) {
1507fe013be4SDimitry Andric       if (classify(E->getType()))
1508fe013be4SDimitry Andric         return this->visit(Init);
1509fe013be4SDimitry Andric       if (!this->emitGetPtrGlobal(*GlobalIndex, E))
1510fe013be4SDimitry Andric         return false;
1511fe013be4SDimitry Andric       return this->visitInitializer(Init);
1512fe013be4SDimitry Andric     }
1513fe013be4SDimitry Andric   }
1514fe013be4SDimitry Andric 
1515fe013be4SDimitry Andric   // Otherwise, use a local variable.
1516fe013be4SDimitry Andric   if (T) {
1517fe013be4SDimitry Andric     // For primitive types, we just visit the initializer.
1518*c9157d92SDimitry Andric     return this->delegate(Init);
1519fe013be4SDimitry Andric   } else {
1520fe013be4SDimitry Andric     if (std::optional<unsigned> LocalIndex = allocateLocal(Init)) {
1521fe013be4SDimitry Andric       if (!this->emitGetPtrLocal(*LocalIndex, E))
1522fe013be4SDimitry Andric         return false;
1523*c9157d92SDimitry Andric       if (!this->visitInitializer(Init))
1524*c9157d92SDimitry Andric         return false;
1525*c9157d92SDimitry Andric       if (DiscardResult)
1526*c9157d92SDimitry Andric         return this->emitPopPtr(E);
1527*c9157d92SDimitry Andric       return true;
1528fe013be4SDimitry Andric     }
1529fe013be4SDimitry Andric   }
1530fe013be4SDimitry Andric 
1531fe013be4SDimitry Andric   return false;
1532fe013be4SDimitry Andric }
1533fe013be4SDimitry Andric 
1534fe013be4SDimitry Andric template <class Emitter>
1535fe013be4SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitTypeTraitExpr(const TypeTraitExpr *E) {
1536*c9157d92SDimitry Andric   if (DiscardResult)
1537*c9157d92SDimitry Andric     return true;
1538fe013be4SDimitry Andric   return this->emitConstBool(E->getValue(), E);
1539fe013be4SDimitry Andric }
1540fe013be4SDimitry Andric 
1541fe013be4SDimitry Andric template <class Emitter>
1542fe013be4SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitLambdaExpr(const LambdaExpr *E) {
1543*c9157d92SDimitry Andric   assert(Initializing);
1544fe013be4SDimitry Andric   const Record *R = P.getOrCreateRecord(E->getLambdaClass());
1545fe013be4SDimitry Andric 
1546fe013be4SDimitry Andric   auto *CaptureInitIt = E->capture_init_begin();
1547fe013be4SDimitry Andric   // Initialize all fields (which represent lambda captures) of the
1548fe013be4SDimitry Andric   // record with their initializers.
1549fe013be4SDimitry Andric   for (const Record::Field &F : R->fields()) {
1550fe013be4SDimitry Andric     const Expr *Init = *CaptureInitIt;
1551fe013be4SDimitry Andric     ++CaptureInitIt;
1552fe013be4SDimitry Andric 
1553fe013be4SDimitry Andric     if (std::optional<PrimType> T = classify(Init)) {
1554fe013be4SDimitry Andric       if (!this->visit(Init))
1555fe013be4SDimitry Andric         return false;
1556fe013be4SDimitry Andric 
1557fe013be4SDimitry Andric       if (!this->emitSetField(*T, F.Offset, E))
1558fe013be4SDimitry Andric         return false;
1559fe013be4SDimitry Andric     } else {
1560fe013be4SDimitry Andric       if (!this->emitDupPtr(E))
1561fe013be4SDimitry Andric         return false;
1562fe013be4SDimitry Andric 
1563fe013be4SDimitry Andric       if (!this->emitGetPtrField(F.Offset, E))
1564fe013be4SDimitry Andric         return false;
1565fe013be4SDimitry Andric 
1566fe013be4SDimitry Andric       if (!this->visitInitializer(Init))
1567fe013be4SDimitry Andric         return false;
1568fe013be4SDimitry Andric 
1569fe013be4SDimitry Andric       if (!this->emitPopPtr(E))
1570fe013be4SDimitry Andric         return false;
1571fe013be4SDimitry Andric     }
1572fe013be4SDimitry Andric   }
1573fe013be4SDimitry Andric 
1574fe013be4SDimitry Andric   return true;
1575fe013be4SDimitry Andric }
1576fe013be4SDimitry Andric 
1577fe013be4SDimitry Andric template <class Emitter>
1578fe013be4SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitPredefinedExpr(const PredefinedExpr *E) {
1579fe013be4SDimitry Andric   if (DiscardResult)
1580fe013be4SDimitry Andric     return true;
1581fe013be4SDimitry Andric 
1582*c9157d92SDimitry Andric   assert(!Initializing);
1583fe013be4SDimitry Andric   return this->visit(E->getFunctionName());
1584fe013be4SDimitry Andric }
1585fe013be4SDimitry Andric 
1586*c9157d92SDimitry Andric template <class Emitter>
1587*c9157d92SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCXXThrowExpr(const CXXThrowExpr *E) {
1588*c9157d92SDimitry Andric   if (E->getSubExpr() && !this->discard(E->getSubExpr()))
1589*c9157d92SDimitry Andric     return false;
1590*c9157d92SDimitry Andric 
1591*c9157d92SDimitry Andric   return this->emitInvalid(E);
1592*c9157d92SDimitry Andric }
1593*c9157d92SDimitry Andric 
1594*c9157d92SDimitry Andric template <class Emitter>
1595*c9157d92SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCXXReinterpretCastExpr(
1596*c9157d92SDimitry Andric     const CXXReinterpretCastExpr *E) {
1597*c9157d92SDimitry Andric   if (!this->discard(E->getSubExpr()))
1598*c9157d92SDimitry Andric     return false;
1599*c9157d92SDimitry Andric 
1600*c9157d92SDimitry Andric   return this->emitInvalidCast(CastKind::Reinterpret, E);
1601*c9157d92SDimitry Andric }
1602*c9157d92SDimitry Andric 
1603*c9157d92SDimitry Andric template <class Emitter>
1604*c9157d92SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCXXNoexceptExpr(const CXXNoexceptExpr *E) {
1605*c9157d92SDimitry Andric   assert(E->getType()->isBooleanType());
1606*c9157d92SDimitry Andric 
1607*c9157d92SDimitry Andric   if (DiscardResult)
1608*c9157d92SDimitry Andric     return true;
1609*c9157d92SDimitry Andric   return this->emitConstBool(E->getValue(), E);
1610*c9157d92SDimitry Andric }
1611*c9157d92SDimitry Andric 
1612*c9157d92SDimitry Andric template <class Emitter>
1613*c9157d92SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCXXConstructExpr(
1614*c9157d92SDimitry Andric     const CXXConstructExpr *E) {
1615*c9157d92SDimitry Andric   QualType T = E->getType();
1616*c9157d92SDimitry Andric   assert(!classify(T));
1617*c9157d92SDimitry Andric 
1618*c9157d92SDimitry Andric   if (T->isRecordType()) {
1619*c9157d92SDimitry Andric     const CXXConstructorDecl *Ctor = E->getConstructor();
1620*c9157d92SDimitry Andric 
1621*c9157d92SDimitry Andric     // Trivial zero initialization.
1622*c9157d92SDimitry Andric     if (E->requiresZeroInitialization() && Ctor->isTrivial()) {
1623*c9157d92SDimitry Andric       const Record *R = getRecord(E->getType());
1624*c9157d92SDimitry Andric       return this->visitZeroRecordInitializer(R, E);
1625*c9157d92SDimitry Andric     }
1626*c9157d92SDimitry Andric 
1627*c9157d92SDimitry Andric     const Function *Func = getFunction(Ctor);
1628*c9157d92SDimitry Andric 
1629*c9157d92SDimitry Andric     if (!Func)
1630*c9157d92SDimitry Andric       return false;
1631*c9157d92SDimitry Andric 
1632*c9157d92SDimitry Andric     assert(Func->hasThisPointer());
1633*c9157d92SDimitry Andric     assert(!Func->hasRVO());
1634*c9157d92SDimitry Andric 
1635*c9157d92SDimitry Andric     // If we're discarding a construct expression, we still need
1636*c9157d92SDimitry Andric     // to allocate a variable and call the constructor and destructor.
1637*c9157d92SDimitry Andric     if (DiscardResult) {
1638*c9157d92SDimitry Andric       assert(!Initializing);
1639*c9157d92SDimitry Andric       std::optional<unsigned> LocalIndex =
1640*c9157d92SDimitry Andric           allocateLocal(E, /*IsExtended=*/true);
1641*c9157d92SDimitry Andric 
1642*c9157d92SDimitry Andric       if (!LocalIndex)
1643*c9157d92SDimitry Andric         return false;
1644*c9157d92SDimitry Andric 
1645*c9157d92SDimitry Andric       if (!this->emitGetPtrLocal(*LocalIndex, E))
1646*c9157d92SDimitry Andric         return false;
1647*c9157d92SDimitry Andric     }
1648*c9157d92SDimitry Andric 
1649*c9157d92SDimitry Andric     //  The This pointer is already on the stack because this is an initializer,
1650*c9157d92SDimitry Andric     //  but we need to dup() so the call() below has its own copy.
1651*c9157d92SDimitry Andric     if (!this->emitDupPtr(E))
1652*c9157d92SDimitry Andric       return false;
1653*c9157d92SDimitry Andric 
1654*c9157d92SDimitry Andric     // Constructor arguments.
1655*c9157d92SDimitry Andric     for (const auto *Arg : E->arguments()) {
1656*c9157d92SDimitry Andric       if (!this->visit(Arg))
1657*c9157d92SDimitry Andric         return false;
1658*c9157d92SDimitry Andric     }
1659*c9157d92SDimitry Andric 
1660*c9157d92SDimitry Andric     if (!this->emitCall(Func, E))
1661*c9157d92SDimitry Andric       return false;
1662*c9157d92SDimitry Andric 
1663*c9157d92SDimitry Andric     // Immediately call the destructor if we have to.
1664*c9157d92SDimitry Andric     if (DiscardResult) {
1665*c9157d92SDimitry Andric       if (!this->emitPopPtr(E))
1666*c9157d92SDimitry Andric         return false;
1667*c9157d92SDimitry Andric     }
1668*c9157d92SDimitry Andric     return true;
1669*c9157d92SDimitry Andric   }
1670*c9157d92SDimitry Andric 
1671*c9157d92SDimitry Andric   if (T->isArrayType()) {
1672*c9157d92SDimitry Andric     const ConstantArrayType *CAT =
1673*c9157d92SDimitry Andric         Ctx.getASTContext().getAsConstantArrayType(E->getType());
1674*c9157d92SDimitry Andric     assert(CAT);
1675*c9157d92SDimitry Andric     size_t NumElems = CAT->getSize().getZExtValue();
1676*c9157d92SDimitry Andric     const Function *Func = getFunction(E->getConstructor());
1677*c9157d92SDimitry Andric     if (!Func || !Func->isConstexpr())
1678*c9157d92SDimitry Andric       return false;
1679*c9157d92SDimitry Andric 
1680*c9157d92SDimitry Andric     // FIXME(perf): We're calling the constructor once per array element here,
1681*c9157d92SDimitry Andric     //   in the old intepreter we had a special-case for trivial constructors.
1682*c9157d92SDimitry Andric     for (size_t I = 0; I != NumElems; ++I) {
1683*c9157d92SDimitry Andric       if (!this->emitConstUint64(I, E))
1684*c9157d92SDimitry Andric         return false;
1685*c9157d92SDimitry Andric       if (!this->emitArrayElemPtrUint64(E))
1686*c9157d92SDimitry Andric         return false;
1687*c9157d92SDimitry Andric 
1688*c9157d92SDimitry Andric       // Constructor arguments.
1689*c9157d92SDimitry Andric       for (const auto *Arg : E->arguments()) {
1690*c9157d92SDimitry Andric         if (!this->visit(Arg))
1691*c9157d92SDimitry Andric           return false;
1692*c9157d92SDimitry Andric       }
1693*c9157d92SDimitry Andric 
1694*c9157d92SDimitry Andric       if (!this->emitCall(Func, E))
1695*c9157d92SDimitry Andric         return false;
1696*c9157d92SDimitry Andric     }
1697*c9157d92SDimitry Andric     return true;
1698*c9157d92SDimitry Andric   }
1699*c9157d92SDimitry Andric 
1700*c9157d92SDimitry Andric   return false;
1701*c9157d92SDimitry Andric }
1702*c9157d92SDimitry Andric 
1703*c9157d92SDimitry Andric template <class Emitter>
1704*c9157d92SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitSourceLocExpr(const SourceLocExpr *E) {
1705*c9157d92SDimitry Andric   if (DiscardResult)
1706*c9157d92SDimitry Andric     return true;
1707*c9157d92SDimitry Andric 
1708*c9157d92SDimitry Andric   const APValue Val =
1709*c9157d92SDimitry Andric       E->EvaluateInContext(Ctx.getASTContext(), SourceLocDefaultExpr);
1710*c9157d92SDimitry Andric 
1711*c9157d92SDimitry Andric   // Things like __builtin_LINE().
1712*c9157d92SDimitry Andric   if (E->getType()->isIntegerType()) {
1713*c9157d92SDimitry Andric     assert(Val.isInt());
1714*c9157d92SDimitry Andric     const APSInt &I = Val.getInt();
1715*c9157d92SDimitry Andric     return this->emitConst(I, E);
1716*c9157d92SDimitry Andric   }
1717*c9157d92SDimitry Andric   // Otherwise, the APValue is an LValue, with only one element.
1718*c9157d92SDimitry Andric   // Theoretically, we don't need the APValue at all of course.
1719*c9157d92SDimitry Andric   assert(E->getType()->isPointerType());
1720*c9157d92SDimitry Andric   assert(Val.isLValue());
1721*c9157d92SDimitry Andric   const APValue::LValueBase &Base = Val.getLValueBase();
1722*c9157d92SDimitry Andric   if (const Expr *LValueExpr = Base.dyn_cast<const Expr *>())
1723*c9157d92SDimitry Andric     return this->visit(LValueExpr);
1724*c9157d92SDimitry Andric 
1725*c9157d92SDimitry Andric   // Otherwise, we have a decl (which is the case for
1726*c9157d92SDimitry Andric   // __builtin_source_location).
1727*c9157d92SDimitry Andric   assert(Base.is<const ValueDecl *>());
1728*c9157d92SDimitry Andric   assert(Val.getLValuePath().size() == 0);
1729*c9157d92SDimitry Andric   const auto *BaseDecl = Base.dyn_cast<const ValueDecl *>();
1730*c9157d92SDimitry Andric   assert(BaseDecl);
1731*c9157d92SDimitry Andric 
1732*c9157d92SDimitry Andric   auto *UGCD = cast<UnnamedGlobalConstantDecl>(BaseDecl);
1733*c9157d92SDimitry Andric 
1734*c9157d92SDimitry Andric   std::optional<unsigned> GlobalIndex = P.getOrCreateGlobal(UGCD);
1735*c9157d92SDimitry Andric   if (!GlobalIndex)
1736*c9157d92SDimitry Andric     return false;
1737*c9157d92SDimitry Andric 
1738*c9157d92SDimitry Andric   if (!this->emitGetPtrGlobal(*GlobalIndex, E))
1739*c9157d92SDimitry Andric     return false;
1740*c9157d92SDimitry Andric 
1741*c9157d92SDimitry Andric   const Record *R = getRecord(E->getType());
1742*c9157d92SDimitry Andric   const APValue &V = UGCD->getValue();
1743*c9157d92SDimitry Andric   for (unsigned I = 0, N = R->getNumFields(); I != N; ++I) {
1744*c9157d92SDimitry Andric     const Record::Field *F = R->getField(I);
1745*c9157d92SDimitry Andric     const APValue &FieldValue = V.getStructField(I);
1746*c9157d92SDimitry Andric 
1747*c9157d92SDimitry Andric     PrimType FieldT = classifyPrim(F->Decl->getType());
1748*c9157d92SDimitry Andric 
1749*c9157d92SDimitry Andric     if (!this->visitAPValue(FieldValue, FieldT, E))
1750*c9157d92SDimitry Andric       return false;
1751*c9157d92SDimitry Andric     if (!this->emitInitField(FieldT, F->Offset, E))
1752*c9157d92SDimitry Andric       return false;
1753*c9157d92SDimitry Andric   }
1754*c9157d92SDimitry Andric 
1755*c9157d92SDimitry Andric   // Leave the pointer to the global on the stack.
1756*c9157d92SDimitry Andric   return true;
1757*c9157d92SDimitry Andric }
1758*c9157d92SDimitry Andric 
1759*c9157d92SDimitry Andric template <class Emitter>
1760*c9157d92SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitOffsetOfExpr(const OffsetOfExpr *E) {
1761*c9157d92SDimitry Andric   unsigned N = E->getNumComponents();
1762*c9157d92SDimitry Andric   if (N == 0)
1763*c9157d92SDimitry Andric     return false;
1764*c9157d92SDimitry Andric 
1765*c9157d92SDimitry Andric   for (unsigned I = 0; I != N; ++I) {
1766*c9157d92SDimitry Andric     const OffsetOfNode &Node = E->getComponent(I);
1767*c9157d92SDimitry Andric     if (Node.getKind() == OffsetOfNode::Array) {
1768*c9157d92SDimitry Andric       const Expr *ArrayIndexExpr = E->getIndexExpr(Node.getArrayExprIndex());
1769*c9157d92SDimitry Andric       PrimType IndexT = classifyPrim(ArrayIndexExpr->getType());
1770*c9157d92SDimitry Andric 
1771*c9157d92SDimitry Andric       if (DiscardResult) {
1772*c9157d92SDimitry Andric         if (!this->discard(ArrayIndexExpr))
1773*c9157d92SDimitry Andric           return false;
1774*c9157d92SDimitry Andric         continue;
1775*c9157d92SDimitry Andric       }
1776*c9157d92SDimitry Andric 
1777*c9157d92SDimitry Andric       if (!this->visit(ArrayIndexExpr))
1778*c9157d92SDimitry Andric         return false;
1779*c9157d92SDimitry Andric       // Cast to Sint64.
1780*c9157d92SDimitry Andric       if (IndexT != PT_Sint64) {
1781*c9157d92SDimitry Andric         if (!this->emitCast(IndexT, PT_Sint64, E))
1782*c9157d92SDimitry Andric           return false;
1783*c9157d92SDimitry Andric       }
1784*c9157d92SDimitry Andric     }
1785*c9157d92SDimitry Andric   }
1786*c9157d92SDimitry Andric 
1787*c9157d92SDimitry Andric   if (DiscardResult)
1788*c9157d92SDimitry Andric     return true;
1789*c9157d92SDimitry Andric 
1790*c9157d92SDimitry Andric   PrimType T = classifyPrim(E->getType());
1791*c9157d92SDimitry Andric   return this->emitOffsetOf(T, E, E);
1792*c9157d92SDimitry Andric }
1793*c9157d92SDimitry Andric 
1794*c9157d92SDimitry Andric template <class Emitter>
1795*c9157d92SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCXXScalarValueInitExpr(
1796*c9157d92SDimitry Andric     const CXXScalarValueInitExpr *E) {
1797*c9157d92SDimitry Andric   QualType Ty = E->getType();
1798*c9157d92SDimitry Andric 
1799*c9157d92SDimitry Andric   if (Ty->isVoidType())
1800*c9157d92SDimitry Andric     return true;
1801*c9157d92SDimitry Andric 
1802*c9157d92SDimitry Andric   return this->visitZeroInitializer(classifyPrim(Ty), Ty, E);
1803*c9157d92SDimitry Andric }
1804*c9157d92SDimitry Andric 
1805*c9157d92SDimitry Andric template <class Emitter>
1806*c9157d92SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitSizeOfPackExpr(const SizeOfPackExpr *E) {
1807*c9157d92SDimitry Andric   return this->emitConst(E->getPackLength(), E);
1808*c9157d92SDimitry Andric }
1809*c9157d92SDimitry Andric 
1810bdd1243dSDimitry Andric template <class Emitter> bool ByteCodeExprGen<Emitter>::discard(const Expr *E) {
1811fe013be4SDimitry Andric   if (E->containsErrors())
1812fe013be4SDimitry Andric     return false;
1813fe013be4SDimitry Andric 
1814*c9157d92SDimitry Andric   OptionScope<Emitter> Scope(this, /*NewDiscardResult=*/true,
1815*c9157d92SDimitry Andric                              /*NewInitializing=*/false);
1816a7dea167SDimitry Andric   return this->Visit(E);
1817a7dea167SDimitry Andric }
1818a7dea167SDimitry Andric 
1819a7dea167SDimitry Andric template <class Emitter>
1820*c9157d92SDimitry Andric bool ByteCodeExprGen<Emitter>::delegate(const Expr *E) {
1821fe013be4SDimitry Andric   if (E->containsErrors())
1822fe013be4SDimitry Andric     return false;
1823fe013be4SDimitry Andric 
1824*c9157d92SDimitry Andric   // We're basically doing:
1825*c9157d92SDimitry Andric   // OptionScope<Emitter> Scope(this, DicardResult, Initializing);
1826*c9157d92SDimitry Andric   // but that's unnecessary of course.
1827*c9157d92SDimitry Andric   return this->Visit(E);
1828*c9157d92SDimitry Andric }
1829*c9157d92SDimitry Andric 
1830*c9157d92SDimitry Andric template <class Emitter> bool ByteCodeExprGen<Emitter>::visit(const Expr *E) {
1831*c9157d92SDimitry Andric   if (E->containsErrors())
1832*c9157d92SDimitry Andric     return false;
1833*c9157d92SDimitry Andric 
1834*c9157d92SDimitry Andric   if (E->getType()->isVoidType())
1835*c9157d92SDimitry Andric     return this->discard(E);
1836*c9157d92SDimitry Andric 
1837*c9157d92SDimitry Andric   // Create local variable to hold the return value.
1838*c9157d92SDimitry Andric   if (!E->isGLValue() && !E->getType()->isAnyComplexType() &&
1839*c9157d92SDimitry Andric       !classify(E->getType())) {
1840*c9157d92SDimitry Andric     std::optional<unsigned> LocalIndex = allocateLocal(E, /*IsExtended=*/true);
1841*c9157d92SDimitry Andric     if (!LocalIndex)
1842*c9157d92SDimitry Andric       return false;
1843*c9157d92SDimitry Andric 
1844*c9157d92SDimitry Andric     if (!this->emitGetPtrLocal(*LocalIndex, E))
1845*c9157d92SDimitry Andric       return false;
1846*c9157d92SDimitry Andric     return this->visitInitializer(E);
1847*c9157d92SDimitry Andric   }
1848*c9157d92SDimitry Andric 
1849*c9157d92SDimitry Andric   //  Otherwise,we have a primitive return value, produce the value directly
1850*c9157d92SDimitry Andric   //  and push it on the stack.
1851*c9157d92SDimitry Andric   OptionScope<Emitter> Scope(this, /*NewDiscardResult=*/false,
1852*c9157d92SDimitry Andric                              /*NewInitializing=*/false);
1853*c9157d92SDimitry Andric   return this->Visit(E);
1854*c9157d92SDimitry Andric }
1855*c9157d92SDimitry Andric 
1856*c9157d92SDimitry Andric template <class Emitter>
1857*c9157d92SDimitry Andric bool ByteCodeExprGen<Emitter>::visitInitializer(const Expr *E) {
1858*c9157d92SDimitry Andric   assert(!classify(E->getType()));
1859*c9157d92SDimitry Andric 
1860*c9157d92SDimitry Andric   if (E->containsErrors())
1861*c9157d92SDimitry Andric     return false;
1862*c9157d92SDimitry Andric 
1863*c9157d92SDimitry Andric   OptionScope<Emitter> Scope(this, /*NewDiscardResult=*/false,
1864*c9157d92SDimitry Andric                              /*NewInitializing=*/true);
1865a7dea167SDimitry Andric   return this->Visit(E);
1866a7dea167SDimitry Andric }
1867a7dea167SDimitry Andric 
1868a7dea167SDimitry Andric template <class Emitter>
1869a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::visitBool(const Expr *E) {
1870*c9157d92SDimitry Andric   std::optional<PrimType> T = classify(E->getType());
1871*c9157d92SDimitry Andric   if (!T)
1872fe013be4SDimitry Andric     return false;
1873fe013be4SDimitry Andric 
1874*c9157d92SDimitry Andric   if (!this->visit(E))
1875fe013be4SDimitry Andric     return false;
1876fe013be4SDimitry Andric 
1877*c9157d92SDimitry Andric   if (T == PT_Bool)
1878fe013be4SDimitry Andric     return true;
1879*c9157d92SDimitry Andric 
1880*c9157d92SDimitry Andric   // Convert pointers to bool.
1881*c9157d92SDimitry Andric   if (T == PT_Ptr || T == PT_FnPtr) {
1882*c9157d92SDimitry Andric     if (!this->emitNull(*T, E))
1883*c9157d92SDimitry Andric       return false;
1884*c9157d92SDimitry Andric     return this->emitNE(*T, E);
1885*c9157d92SDimitry Andric   }
1886*c9157d92SDimitry Andric 
1887*c9157d92SDimitry Andric   // Or Floats.
1888*c9157d92SDimitry Andric   if (T == PT_Float)
1889*c9157d92SDimitry Andric     return this->emitCastFloatingIntegralBool(E);
1890*c9157d92SDimitry Andric 
1891*c9157d92SDimitry Andric   // Or anything else we can.
1892*c9157d92SDimitry Andric   return this->emitCast(*T, PT_Bool, E);
1893fe013be4SDimitry Andric }
1894fe013be4SDimitry Andric 
1895fe013be4SDimitry Andric template <class Emitter>
1896*c9157d92SDimitry Andric bool ByteCodeExprGen<Emitter>::visitZeroInitializer(PrimType T, QualType QT,
1897fe013be4SDimitry Andric                                                     const Expr *E) {
1898a7dea167SDimitry Andric   switch (T) {
1899a7dea167SDimitry Andric   case PT_Bool:
1900a7dea167SDimitry Andric     return this->emitZeroBool(E);
1901a7dea167SDimitry Andric   case PT_Sint8:
1902a7dea167SDimitry Andric     return this->emitZeroSint8(E);
1903a7dea167SDimitry Andric   case PT_Uint8:
1904a7dea167SDimitry Andric     return this->emitZeroUint8(E);
1905a7dea167SDimitry Andric   case PT_Sint16:
1906a7dea167SDimitry Andric     return this->emitZeroSint16(E);
1907a7dea167SDimitry Andric   case PT_Uint16:
1908a7dea167SDimitry Andric     return this->emitZeroUint16(E);
1909a7dea167SDimitry Andric   case PT_Sint32:
1910a7dea167SDimitry Andric     return this->emitZeroSint32(E);
1911a7dea167SDimitry Andric   case PT_Uint32:
1912a7dea167SDimitry Andric     return this->emitZeroUint32(E);
1913a7dea167SDimitry Andric   case PT_Sint64:
1914a7dea167SDimitry Andric     return this->emitZeroSint64(E);
1915a7dea167SDimitry Andric   case PT_Uint64:
1916a7dea167SDimitry Andric     return this->emitZeroUint64(E);
1917*c9157d92SDimitry Andric   case PT_IntAP:
1918*c9157d92SDimitry Andric     return this->emitZeroIntAP(Ctx.getBitWidth(QT), E);
1919*c9157d92SDimitry Andric   case PT_IntAPS:
1920*c9157d92SDimitry Andric     return this->emitZeroIntAPS(Ctx.getBitWidth(QT), E);
1921a7dea167SDimitry Andric   case PT_Ptr:
1922a7dea167SDimitry Andric     return this->emitNullPtr(E);
1923fe013be4SDimitry Andric   case PT_FnPtr:
1924fe013be4SDimitry Andric     return this->emitNullFnPtr(E);
1925fe013be4SDimitry Andric   case PT_Float: {
1926fe013be4SDimitry Andric     return this->emitConstFloat(APFloat::getZero(Ctx.getFloatSemantics(QT)), E);
1927fe013be4SDimitry Andric   }
1928a7dea167SDimitry Andric   }
1929a7dea167SDimitry Andric   llvm_unreachable("unknown primitive type");
1930a7dea167SDimitry Andric }
1931a7dea167SDimitry Andric 
1932a7dea167SDimitry Andric template <class Emitter>
1933*c9157d92SDimitry Andric bool ByteCodeExprGen<Emitter>::visitZeroRecordInitializer(const Record *R,
1934*c9157d92SDimitry Andric                                                           const Expr *E) {
1935*c9157d92SDimitry Andric   assert(E);
1936*c9157d92SDimitry Andric   assert(R);
1937*c9157d92SDimitry Andric   // Fields
1938*c9157d92SDimitry Andric   for (const Record::Field &Field : R->fields()) {
1939*c9157d92SDimitry Andric     const Descriptor *D = Field.Desc;
1940*c9157d92SDimitry Andric     if (D->isPrimitive()) {
1941*c9157d92SDimitry Andric       QualType QT = D->getType();
1942*c9157d92SDimitry Andric       PrimType T = classifyPrim(D->getType());
1943*c9157d92SDimitry Andric       if (!this->visitZeroInitializer(T, QT, E))
1944*c9157d92SDimitry Andric         return false;
1945*c9157d92SDimitry Andric       if (!this->emitInitField(T, Field.Offset, E))
1946*c9157d92SDimitry Andric         return false;
1947*c9157d92SDimitry Andric       continue;
1948*c9157d92SDimitry Andric     }
1949*c9157d92SDimitry Andric 
1950*c9157d92SDimitry Andric     // TODO: Add GetPtrFieldPop and get rid of this dup.
1951*c9157d92SDimitry Andric     if (!this->emitDupPtr(E))
1952*c9157d92SDimitry Andric       return false;
1953*c9157d92SDimitry Andric     if (!this->emitGetPtrField(Field.Offset, E))
1954*c9157d92SDimitry Andric       return false;
1955*c9157d92SDimitry Andric 
1956*c9157d92SDimitry Andric     if (D->isPrimitiveArray()) {
1957*c9157d92SDimitry Andric       QualType ET = D->getElemQualType();
1958*c9157d92SDimitry Andric       PrimType T = classifyPrim(ET);
1959*c9157d92SDimitry Andric       for (uint32_t I = 0, N = D->getNumElems(); I != N; ++I) {
1960*c9157d92SDimitry Andric         if (!this->visitZeroInitializer(T, ET, E))
1961*c9157d92SDimitry Andric           return false;
1962*c9157d92SDimitry Andric         if (!this->emitInitElem(T, I, E))
1963*c9157d92SDimitry Andric           return false;
1964*c9157d92SDimitry Andric       }
1965*c9157d92SDimitry Andric     } else if (D->isCompositeArray()) {
1966*c9157d92SDimitry Andric       const Record *ElemRecord = D->ElemDesc->ElemRecord;
1967*c9157d92SDimitry Andric       assert(D->ElemDesc->ElemRecord);
1968*c9157d92SDimitry Andric       for (uint32_t I = 0, N = D->getNumElems(); I != N; ++I) {
1969*c9157d92SDimitry Andric         if (!this->emitConstUint32(I, E))
1970*c9157d92SDimitry Andric           return false;
1971*c9157d92SDimitry Andric         if (!this->emitArrayElemPtr(PT_Uint32, E))
1972*c9157d92SDimitry Andric           return false;
1973*c9157d92SDimitry Andric         if (!this->visitZeroRecordInitializer(ElemRecord, E))
1974*c9157d92SDimitry Andric           return false;
1975*c9157d92SDimitry Andric         if (!this->emitPopPtr(E))
1976*c9157d92SDimitry Andric           return false;
1977*c9157d92SDimitry Andric       }
1978*c9157d92SDimitry Andric     } else if (D->isRecord()) {
1979*c9157d92SDimitry Andric       if (!this->visitZeroRecordInitializer(D->ElemRecord, E))
1980*c9157d92SDimitry Andric         return false;
1981*c9157d92SDimitry Andric     } else {
1982*c9157d92SDimitry Andric       assert(false);
1983*c9157d92SDimitry Andric     }
1984*c9157d92SDimitry Andric 
1985*c9157d92SDimitry Andric     if (!this->emitPopPtr(E))
1986*c9157d92SDimitry Andric       return false;
1987*c9157d92SDimitry Andric   }
1988*c9157d92SDimitry Andric 
1989*c9157d92SDimitry Andric   for (const Record::Base &B : R->bases()) {
1990*c9157d92SDimitry Andric     if (!this->emitGetPtrBase(B.Offset, E))
1991*c9157d92SDimitry Andric       return false;
1992*c9157d92SDimitry Andric     if (!this->visitZeroRecordInitializer(B.R, E))
1993*c9157d92SDimitry Andric       return false;
1994*c9157d92SDimitry Andric     if (!this->emitInitPtrPop(E))
1995*c9157d92SDimitry Andric       return false;
1996*c9157d92SDimitry Andric   }
1997*c9157d92SDimitry Andric 
1998*c9157d92SDimitry Andric   // FIXME: Virtual bases.
1999*c9157d92SDimitry Andric 
2000*c9157d92SDimitry Andric   return true;
2001*c9157d92SDimitry Andric }
2002*c9157d92SDimitry Andric 
2003*c9157d92SDimitry Andric template <class Emitter>
2004a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::dereference(
2005a7dea167SDimitry Andric     const Expr *LV, DerefKind AK, llvm::function_ref<bool(PrimType)> Direct,
2006a7dea167SDimitry Andric     llvm::function_ref<bool(PrimType)> Indirect) {
2007bdd1243dSDimitry Andric   if (std::optional<PrimType> T = classify(LV->getType())) {
2008a7dea167SDimitry Andric     if (!LV->refersToBitField()) {
2009a7dea167SDimitry Andric       // Only primitive, non bit-field types can be dereferenced directly.
2010fe013be4SDimitry Andric       if (const auto *DE = dyn_cast<DeclRefExpr>(LV)) {
2011a7dea167SDimitry Andric         if (!DE->getDecl()->getType()->isReferenceType()) {
2012fe013be4SDimitry Andric           if (const auto *PD = dyn_cast<ParmVarDecl>(DE->getDecl()))
2013a7dea167SDimitry Andric             return dereferenceParam(LV, *T, PD, AK, Direct, Indirect);
2014fe013be4SDimitry Andric           if (const auto *VD = dyn_cast<VarDecl>(DE->getDecl()))
2015a7dea167SDimitry Andric             return dereferenceVar(LV, *T, VD, AK, Direct, Indirect);
2016a7dea167SDimitry Andric         }
2017a7dea167SDimitry Andric       }
2018a7dea167SDimitry Andric     }
2019a7dea167SDimitry Andric 
2020a7dea167SDimitry Andric     if (!visit(LV))
2021a7dea167SDimitry Andric       return false;
2022a7dea167SDimitry Andric     return Indirect(*T);
2023a7dea167SDimitry Andric   }
2024a7dea167SDimitry Andric 
2025*c9157d92SDimitry Andric   if (LV->getType()->isAnyComplexType())
2026*c9157d92SDimitry Andric     return visit(LV);
2027*c9157d92SDimitry Andric 
2028a7dea167SDimitry Andric   return false;
2029a7dea167SDimitry Andric }
2030a7dea167SDimitry Andric 
2031a7dea167SDimitry Andric template <class Emitter>
2032a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::dereferenceParam(
2033a7dea167SDimitry Andric     const Expr *LV, PrimType T, const ParmVarDecl *PD, DerefKind AK,
2034a7dea167SDimitry Andric     llvm::function_ref<bool(PrimType)> Direct,
2035a7dea167SDimitry Andric     llvm::function_ref<bool(PrimType)> Indirect) {
2036a7dea167SDimitry Andric   auto It = this->Params.find(PD);
2037a7dea167SDimitry Andric   if (It != this->Params.end()) {
2038*c9157d92SDimitry Andric     unsigned Idx = It->second.Offset;
2039a7dea167SDimitry Andric     switch (AK) {
2040a7dea167SDimitry Andric     case DerefKind::Read:
2041a7dea167SDimitry Andric       return DiscardResult ? true : this->emitGetParam(T, Idx, LV);
2042a7dea167SDimitry Andric 
2043a7dea167SDimitry Andric     case DerefKind::Write:
2044a7dea167SDimitry Andric       if (!Direct(T))
2045a7dea167SDimitry Andric         return false;
2046a7dea167SDimitry Andric       if (!this->emitSetParam(T, Idx, LV))
2047a7dea167SDimitry Andric         return false;
2048a7dea167SDimitry Andric       return DiscardResult ? true : this->emitGetPtrParam(Idx, LV);
2049a7dea167SDimitry Andric 
2050a7dea167SDimitry Andric     case DerefKind::ReadWrite:
2051a7dea167SDimitry Andric       if (!this->emitGetParam(T, Idx, LV))
2052a7dea167SDimitry Andric         return false;
2053a7dea167SDimitry Andric       if (!Direct(T))
2054a7dea167SDimitry Andric         return false;
2055a7dea167SDimitry Andric       if (!this->emitSetParam(T, Idx, LV))
2056a7dea167SDimitry Andric         return false;
2057a7dea167SDimitry Andric       return DiscardResult ? true : this->emitGetPtrParam(Idx, LV);
2058a7dea167SDimitry Andric     }
2059a7dea167SDimitry Andric     return true;
2060a7dea167SDimitry Andric   }
2061a7dea167SDimitry Andric 
2062a7dea167SDimitry Andric   // If the param is a pointer, we can dereference a dummy value.
2063a7dea167SDimitry Andric   if (!DiscardResult && T == PT_Ptr && AK == DerefKind::Read) {
2064a7dea167SDimitry Andric     if (auto Idx = P.getOrCreateDummy(PD))
2065a7dea167SDimitry Andric       return this->emitGetPtrGlobal(*Idx, PD);
2066a7dea167SDimitry Andric     return false;
2067a7dea167SDimitry Andric   }
2068a7dea167SDimitry Andric 
2069a7dea167SDimitry Andric   // Value cannot be produced - try to emit pointer and do stuff with it.
2070a7dea167SDimitry Andric   return visit(LV) && Indirect(T);
2071a7dea167SDimitry Andric }
2072a7dea167SDimitry Andric 
2073a7dea167SDimitry Andric template <class Emitter>
2074a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::dereferenceVar(
2075a7dea167SDimitry Andric     const Expr *LV, PrimType T, const VarDecl *VD, DerefKind AK,
2076a7dea167SDimitry Andric     llvm::function_ref<bool(PrimType)> Direct,
2077a7dea167SDimitry Andric     llvm::function_ref<bool(PrimType)> Indirect) {
2078a7dea167SDimitry Andric   auto It = Locals.find(VD);
2079a7dea167SDimitry Andric   if (It != Locals.end()) {
2080a7dea167SDimitry Andric     const auto &L = It->second;
2081a7dea167SDimitry Andric     switch (AK) {
2082a7dea167SDimitry Andric     case DerefKind::Read:
2083a7dea167SDimitry Andric       if (!this->emitGetLocal(T, L.Offset, LV))
2084a7dea167SDimitry Andric         return false;
2085a7dea167SDimitry Andric       return DiscardResult ? this->emitPop(T, LV) : true;
2086a7dea167SDimitry Andric 
2087a7dea167SDimitry Andric     case DerefKind::Write:
2088a7dea167SDimitry Andric       if (!Direct(T))
2089a7dea167SDimitry Andric         return false;
2090a7dea167SDimitry Andric       if (!this->emitSetLocal(T, L.Offset, LV))
2091a7dea167SDimitry Andric         return false;
2092a7dea167SDimitry Andric       return DiscardResult ? true : this->emitGetPtrLocal(L.Offset, LV);
2093a7dea167SDimitry Andric 
2094a7dea167SDimitry Andric     case DerefKind::ReadWrite:
2095a7dea167SDimitry Andric       if (!this->emitGetLocal(T, L.Offset, LV))
2096a7dea167SDimitry Andric         return false;
2097a7dea167SDimitry Andric       if (!Direct(T))
2098a7dea167SDimitry Andric         return false;
2099a7dea167SDimitry Andric       if (!this->emitSetLocal(T, L.Offset, LV))
2100a7dea167SDimitry Andric         return false;
2101a7dea167SDimitry Andric       return DiscardResult ? true : this->emitGetPtrLocal(L.Offset, LV);
2102a7dea167SDimitry Andric     }
2103bdd1243dSDimitry Andric   } else if (auto Idx = P.getGlobal(VD)) {
2104a7dea167SDimitry Andric     switch (AK) {
2105a7dea167SDimitry Andric     case DerefKind::Read:
2106a7dea167SDimitry Andric       if (!this->emitGetGlobal(T, *Idx, LV))
2107a7dea167SDimitry Andric         return false;
2108a7dea167SDimitry Andric       return DiscardResult ? this->emitPop(T, LV) : true;
2109a7dea167SDimitry Andric 
2110a7dea167SDimitry Andric     case DerefKind::Write:
2111a7dea167SDimitry Andric       if (!Direct(T))
2112a7dea167SDimitry Andric         return false;
2113a7dea167SDimitry Andric       if (!this->emitSetGlobal(T, *Idx, LV))
2114a7dea167SDimitry Andric         return false;
2115a7dea167SDimitry Andric       return DiscardResult ? true : this->emitGetPtrGlobal(*Idx, LV);
2116a7dea167SDimitry Andric 
2117a7dea167SDimitry Andric     case DerefKind::ReadWrite:
2118a7dea167SDimitry Andric       if (!this->emitGetGlobal(T, *Idx, LV))
2119a7dea167SDimitry Andric         return false;
2120a7dea167SDimitry Andric       if (!Direct(T))
2121a7dea167SDimitry Andric         return false;
2122a7dea167SDimitry Andric       if (!this->emitSetGlobal(T, *Idx, LV))
2123a7dea167SDimitry Andric         return false;
2124a7dea167SDimitry Andric       return DiscardResult ? true : this->emitGetPtrGlobal(*Idx, LV);
2125a7dea167SDimitry Andric     }
2126a7dea167SDimitry Andric   }
2127a7dea167SDimitry Andric 
2128a7dea167SDimitry Andric   // If the declaration is a constant value, emit it here even
2129a7dea167SDimitry Andric   // though the declaration was not evaluated in the current scope.
2130a7dea167SDimitry Andric   // The access mode can only be read in this case.
2131a7dea167SDimitry Andric   if (!DiscardResult && AK == DerefKind::Read) {
2132a7dea167SDimitry Andric     if (VD->hasLocalStorage() && VD->hasInit() && !VD->isConstexpr()) {
2133a7dea167SDimitry Andric       QualType VT = VD->getType();
2134a7dea167SDimitry Andric       if (VT.isConstQualified() && VT->isFundamentalType())
2135bdd1243dSDimitry Andric         return this->visit(VD->getInit());
2136a7dea167SDimitry Andric     }
2137a7dea167SDimitry Andric   }
2138a7dea167SDimitry Andric 
2139a7dea167SDimitry Andric   // Value cannot be produced - try to emit pointer.
2140a7dea167SDimitry Andric   return visit(LV) && Indirect(T);
2141a7dea167SDimitry Andric }
2142a7dea167SDimitry Andric 
2143a7dea167SDimitry Andric template <class Emitter>
2144bdd1243dSDimitry Andric template <typename T>
2145*c9157d92SDimitry Andric bool ByteCodeExprGen<Emitter>::emitConst(T Value, PrimType Ty, const Expr *E) {
2146*c9157d92SDimitry Andric   switch (Ty) {
2147a7dea167SDimitry Andric   case PT_Sint8:
2148bdd1243dSDimitry Andric     return this->emitConstSint8(Value, E);
2149a7dea167SDimitry Andric   case PT_Uint8:
2150bdd1243dSDimitry Andric     return this->emitConstUint8(Value, E);
2151a7dea167SDimitry Andric   case PT_Sint16:
2152bdd1243dSDimitry Andric     return this->emitConstSint16(Value, E);
2153a7dea167SDimitry Andric   case PT_Uint16:
2154bdd1243dSDimitry Andric     return this->emitConstUint16(Value, E);
2155a7dea167SDimitry Andric   case PT_Sint32:
2156bdd1243dSDimitry Andric     return this->emitConstSint32(Value, E);
2157a7dea167SDimitry Andric   case PT_Uint32:
2158bdd1243dSDimitry Andric     return this->emitConstUint32(Value, E);
2159a7dea167SDimitry Andric   case PT_Sint64:
2160bdd1243dSDimitry Andric     return this->emitConstSint64(Value, E);
2161a7dea167SDimitry Andric   case PT_Uint64:
2162bdd1243dSDimitry Andric     return this->emitConstUint64(Value, E);
2163*c9157d92SDimitry Andric   case PT_IntAP:
2164*c9157d92SDimitry Andric   case PT_IntAPS:
2165*c9157d92SDimitry Andric     assert(false);
2166*c9157d92SDimitry Andric     return false;
2167a7dea167SDimitry Andric   case PT_Bool:
2168bdd1243dSDimitry Andric     return this->emitConstBool(Value, E);
2169a7dea167SDimitry Andric   case PT_Ptr:
2170fe013be4SDimitry Andric   case PT_FnPtr:
2171fe013be4SDimitry Andric   case PT_Float:
2172a7dea167SDimitry Andric     llvm_unreachable("Invalid integral type");
2173a7dea167SDimitry Andric     break;
2174a7dea167SDimitry Andric   }
2175a7dea167SDimitry Andric   llvm_unreachable("unknown primitive type");
2176a7dea167SDimitry Andric }
2177a7dea167SDimitry Andric 
2178a7dea167SDimitry Andric template <class Emitter>
2179*c9157d92SDimitry Andric template <typename T>
2180*c9157d92SDimitry Andric bool ByteCodeExprGen<Emitter>::emitConst(T Value, const Expr *E) {
2181*c9157d92SDimitry Andric   return this->emitConst(Value, classifyPrim(E->getType()), E);
2182*c9157d92SDimitry Andric }
2183*c9157d92SDimitry Andric 
2184*c9157d92SDimitry Andric template <class Emitter>
2185*c9157d92SDimitry Andric bool ByteCodeExprGen<Emitter>::emitConst(const APSInt &Value, PrimType Ty,
2186*c9157d92SDimitry Andric                                          const Expr *E) {
2187bdd1243dSDimitry Andric   if (Value.isSigned())
2188*c9157d92SDimitry Andric     return this->emitConst(Value.getSExtValue(), Ty, E);
2189*c9157d92SDimitry Andric   return this->emitConst(Value.getZExtValue(), Ty, E);
2190*c9157d92SDimitry Andric }
2191*c9157d92SDimitry Andric 
2192*c9157d92SDimitry Andric template <class Emitter>
2193*c9157d92SDimitry Andric bool ByteCodeExprGen<Emitter>::emitConst(const APSInt &Value, const Expr *E) {
2194*c9157d92SDimitry Andric   return this->emitConst(Value, classifyPrim(E->getType()), E);
2195bdd1243dSDimitry Andric }
2196bdd1243dSDimitry Andric 
2197bdd1243dSDimitry Andric template <class Emitter>
2198a7dea167SDimitry Andric unsigned ByteCodeExprGen<Emitter>::allocateLocalPrimitive(DeclTy &&Src,
2199a7dea167SDimitry Andric                                                           PrimType Ty,
2200a7dea167SDimitry Andric                                                           bool IsConst,
2201a7dea167SDimitry Andric                                                           bool IsExtended) {
2202bdd1243dSDimitry Andric   // Make sure we don't accidentally register the same decl twice.
2203bdd1243dSDimitry Andric   if (const auto *VD =
2204bdd1243dSDimitry Andric           dyn_cast_if_present<ValueDecl>(Src.dyn_cast<const Decl *>())) {
2205bdd1243dSDimitry Andric     assert(!P.getGlobal(VD));
2206fe013be4SDimitry Andric     assert(!Locals.contains(VD));
2207bdd1243dSDimitry Andric   }
2208bdd1243dSDimitry Andric 
2209bdd1243dSDimitry Andric   // FIXME: There are cases where Src.is<Expr*>() is wrong, e.g.
2210bdd1243dSDimitry Andric   //   (int){12} in C. Consider using Expr::isTemporaryObject() instead
2211bdd1243dSDimitry Andric   //   or isa<MaterializeTemporaryExpr>().
2212bdd1243dSDimitry Andric   Descriptor *D = P.createDescriptor(Src, Ty, Descriptor::InlineDescMD, IsConst,
2213bdd1243dSDimitry Andric                                      Src.is<const Expr *>());
2214a7dea167SDimitry Andric   Scope::Local Local = this->createLocal(D);
2215fe013be4SDimitry Andric   if (auto *VD = dyn_cast_if_present<ValueDecl>(Src.dyn_cast<const Decl *>()))
2216a7dea167SDimitry Andric     Locals.insert({VD, Local});
2217a7dea167SDimitry Andric   VarScope->add(Local, IsExtended);
2218a7dea167SDimitry Andric   return Local.Offset;
2219a7dea167SDimitry Andric }
2220a7dea167SDimitry Andric 
2221a7dea167SDimitry Andric template <class Emitter>
2222bdd1243dSDimitry Andric std::optional<unsigned>
2223a7dea167SDimitry Andric ByteCodeExprGen<Emitter>::allocateLocal(DeclTy &&Src, bool IsExtended) {
2224bdd1243dSDimitry Andric   // Make sure we don't accidentally register the same decl twice.
2225*c9157d92SDimitry Andric   if ([[maybe_unused]]  const auto *VD =
2226bdd1243dSDimitry Andric           dyn_cast_if_present<ValueDecl>(Src.dyn_cast<const Decl *>())) {
2227bdd1243dSDimitry Andric     assert(!P.getGlobal(VD));
2228fe013be4SDimitry Andric     assert(!Locals.contains(VD));
2229bdd1243dSDimitry Andric   }
2230a7dea167SDimitry Andric 
2231bdd1243dSDimitry Andric   QualType Ty;
2232a7dea167SDimitry Andric   const ValueDecl *Key = nullptr;
2233bdd1243dSDimitry Andric   const Expr *Init = nullptr;
2234a7dea167SDimitry Andric   bool IsTemporary = false;
2235bdd1243dSDimitry Andric   if (auto *VD = dyn_cast_if_present<ValueDecl>(Src.dyn_cast<const Decl *>())) {
2236a7dea167SDimitry Andric     Key = VD;
2237a7dea167SDimitry Andric     Ty = VD->getType();
2238bdd1243dSDimitry Andric 
2239bdd1243dSDimitry Andric     if (const auto *VarD = dyn_cast<VarDecl>(VD))
2240bdd1243dSDimitry Andric       Init = VarD->getInit();
2241a7dea167SDimitry Andric   }
2242a7dea167SDimitry Andric   if (auto *E = Src.dyn_cast<const Expr *>()) {
2243a7dea167SDimitry Andric     IsTemporary = true;
2244a7dea167SDimitry Andric     Ty = E->getType();
2245a7dea167SDimitry Andric   }
2246a7dea167SDimitry Andric 
2247bdd1243dSDimitry Andric   Descriptor *D = P.createDescriptor(
2248bdd1243dSDimitry Andric       Src, Ty.getTypePtr(), Descriptor::InlineDescMD, Ty.isConstQualified(),
2249bdd1243dSDimitry Andric       IsTemporary, /*IsMutable=*/false, Init);
2250a7dea167SDimitry Andric   if (!D)
2251a7dea167SDimitry Andric     return {};
2252a7dea167SDimitry Andric 
2253a7dea167SDimitry Andric   Scope::Local Local = this->createLocal(D);
2254a7dea167SDimitry Andric   if (Key)
2255a7dea167SDimitry Andric     Locals.insert({Key, Local});
2256a7dea167SDimitry Andric   VarScope->add(Local, IsExtended);
2257a7dea167SDimitry Andric   return Local.Offset;
2258a7dea167SDimitry Andric }
2259a7dea167SDimitry Andric 
2260a7dea167SDimitry Andric template <class Emitter>
2261a7dea167SDimitry Andric const RecordType *ByteCodeExprGen<Emitter>::getRecordTy(QualType Ty) {
2262753f127fSDimitry Andric   if (const PointerType *PT = dyn_cast<PointerType>(Ty))
2263a7dea167SDimitry Andric     return PT->getPointeeType()->getAs<RecordType>();
2264a7dea167SDimitry Andric   return Ty->getAs<RecordType>();
2265a7dea167SDimitry Andric }
2266a7dea167SDimitry Andric 
2267a7dea167SDimitry Andric template <class Emitter>
2268a7dea167SDimitry Andric Record *ByteCodeExprGen<Emitter>::getRecord(QualType Ty) {
2269*c9157d92SDimitry Andric   if (const auto *RecordTy = getRecordTy(Ty))
2270a7dea167SDimitry Andric     return getRecord(RecordTy->getDecl());
2271a7dea167SDimitry Andric   return nullptr;
2272a7dea167SDimitry Andric }
2273a7dea167SDimitry Andric 
2274a7dea167SDimitry Andric template <class Emitter>
2275a7dea167SDimitry Andric Record *ByteCodeExprGen<Emitter>::getRecord(const RecordDecl *RD) {
2276a7dea167SDimitry Andric   return P.getOrCreateRecord(RD);
2277a7dea167SDimitry Andric }
2278a7dea167SDimitry Andric 
2279a7dea167SDimitry Andric template <class Emitter>
2280bdd1243dSDimitry Andric const Function *ByteCodeExprGen<Emitter>::getFunction(const FunctionDecl *FD) {
2281*c9157d92SDimitry Andric   return Ctx.getOrCreateFunction(FD);
2282bdd1243dSDimitry Andric }
2283bdd1243dSDimitry Andric 
2284bdd1243dSDimitry Andric template <class Emitter>
2285*c9157d92SDimitry Andric bool ByteCodeExprGen<Emitter>::visitExpr(const Expr *E) {
2286a7dea167SDimitry Andric   ExprScope<Emitter> RootScope(this);
2287*c9157d92SDimitry Andric   // Void expressions.
2288*c9157d92SDimitry Andric   if (E->getType()->isVoidType()) {
2289*c9157d92SDimitry Andric     if (!visit(E))
2290*c9157d92SDimitry Andric       return false;
2291*c9157d92SDimitry Andric     return this->emitRetVoid(E);
2292*c9157d92SDimitry Andric   }
2293*c9157d92SDimitry Andric 
2294*c9157d92SDimitry Andric   // Expressions with a primitive return type.
2295*c9157d92SDimitry Andric   if (std::optional<PrimType> T = classify(E)) {
2296*c9157d92SDimitry Andric     if (!visit(E))
2297*c9157d92SDimitry Andric       return false;
2298*c9157d92SDimitry Andric     return this->emitRet(*T, E);
2299*c9157d92SDimitry Andric   }
2300*c9157d92SDimitry Andric 
2301*c9157d92SDimitry Andric   // Expressions with a composite return type.
2302*c9157d92SDimitry Andric   // For us, that means everything we don't
2303*c9157d92SDimitry Andric   // have a PrimType for.
2304*c9157d92SDimitry Andric   if (std::optional<unsigned> LocalOffset = this->allocateLocal(E)) {
2305*c9157d92SDimitry Andric     if (!this->visitLocalInitializer(E, *LocalOffset))
2306a7dea167SDimitry Andric       return false;
2307a7dea167SDimitry Andric 
2308*c9157d92SDimitry Andric     if (!this->emitGetPtrLocal(*LocalOffset, E))
2309*c9157d92SDimitry Andric       return false;
2310*c9157d92SDimitry Andric     return this->emitRetValue(E);
2311*c9157d92SDimitry Andric   }
2312*c9157d92SDimitry Andric 
2313*c9157d92SDimitry Andric   return false;
2314a7dea167SDimitry Andric }
2315a7dea167SDimitry Andric 
2316bdd1243dSDimitry Andric /// Toplevel visitDecl().
2317bdd1243dSDimitry Andric /// We get here from evaluateAsInitializer().
2318bdd1243dSDimitry Andric /// We need to evaluate the initializer and return its value.
2319a7dea167SDimitry Andric template <class Emitter>
2320a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::visitDecl(const VarDecl *VD) {
2321fe013be4SDimitry Andric   assert(!VD->isInvalidDecl() && "Trying to constant evaluate an invalid decl");
2322a7dea167SDimitry Andric 
2323bdd1243dSDimitry Andric   // Create and initialize the variable.
2324bdd1243dSDimitry Andric   if (!this->visitVarDecl(VD))
2325a7dea167SDimitry Andric     return false;
2326a7dea167SDimitry Andric 
2327*c9157d92SDimitry Andric   std::optional<PrimType> VarT = classify(VD->getType());
2328bdd1243dSDimitry Andric   // Get a pointer to the variable
2329fe013be4SDimitry Andric   if (Context::shouldBeGloballyIndexed(VD)) {
2330bdd1243dSDimitry Andric     auto GlobalIndex = P.getGlobal(VD);
2331bdd1243dSDimitry Andric     assert(GlobalIndex); // visitVarDecl() didn't return false.
2332*c9157d92SDimitry Andric     if (VarT) {
2333*c9157d92SDimitry Andric       if (!this->emitGetGlobal(*VarT, *GlobalIndex, VD))
2334*c9157d92SDimitry Andric         return false;
2335*c9157d92SDimitry Andric     } else {
2336bdd1243dSDimitry Andric       if (!this->emitGetPtrGlobal(*GlobalIndex, VD))
2337a7dea167SDimitry Andric         return false;
2338*c9157d92SDimitry Andric     }
2339a7dea167SDimitry Andric   } else {
2340bdd1243dSDimitry Andric     auto Local = Locals.find(VD);
2341bdd1243dSDimitry Andric     assert(Local != Locals.end()); // Same here.
2342*c9157d92SDimitry Andric     if (VarT) {
2343*c9157d92SDimitry Andric       if (!this->emitGetLocal(*VarT, Local->second.Offset, VD))
2344*c9157d92SDimitry Andric         return false;
2345*c9157d92SDimitry Andric     } else {
2346bdd1243dSDimitry Andric       if (!this->emitGetPtrLocal(Local->second.Offset, VD))
2347a7dea167SDimitry Andric         return false;
2348a7dea167SDimitry Andric     }
2349bdd1243dSDimitry Andric   }
2350bdd1243dSDimitry Andric 
2351*c9157d92SDimitry Andric   // Return the value
2352*c9157d92SDimitry Andric   if (VarT)
2353*c9157d92SDimitry Andric     return this->emitRet(*VarT, VD);
2354a7dea167SDimitry Andric   return this->emitRetValue(VD);
2355a7dea167SDimitry Andric }
2356bdd1243dSDimitry Andric 
2357bdd1243dSDimitry Andric template <class Emitter>
2358bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::visitVarDecl(const VarDecl *VD) {
2359fe013be4SDimitry Andric   // We don't know what to do with these, so just return false.
2360fe013be4SDimitry Andric   if (VD->getType().isNull())
2361fe013be4SDimitry Andric     return false;
2362fe013be4SDimitry Andric 
2363bdd1243dSDimitry Andric   const Expr *Init = VD->getInit();
2364bdd1243dSDimitry Andric   std::optional<PrimType> VarT = classify(VD->getType());
2365bdd1243dSDimitry Andric 
2366fe013be4SDimitry Andric   if (Context::shouldBeGloballyIndexed(VD)) {
2367fe013be4SDimitry Andric     // We've already seen and initialized this global.
2368fe013be4SDimitry Andric     if (P.getGlobal(VD))
2369fe013be4SDimitry Andric       return true;
2370fe013be4SDimitry Andric 
2371fe013be4SDimitry Andric     std::optional<unsigned> GlobalIndex = P.createGlobal(VD, Init);
2372bdd1243dSDimitry Andric 
2373bdd1243dSDimitry Andric     if (!GlobalIndex)
2374bdd1243dSDimitry Andric       return this->bail(VD);
2375bdd1243dSDimitry Andric 
2376bdd1243dSDimitry Andric     assert(Init);
2377bdd1243dSDimitry Andric     {
2378bdd1243dSDimitry Andric       DeclScope<Emitter> LocalScope(this, VD);
2379bdd1243dSDimitry Andric 
2380bdd1243dSDimitry Andric       if (VarT) {
2381bdd1243dSDimitry Andric         if (!this->visit(Init))
2382bdd1243dSDimitry Andric           return false;
2383bdd1243dSDimitry Andric         return this->emitInitGlobal(*VarT, *GlobalIndex, VD);
2384bdd1243dSDimitry Andric       }
2385bdd1243dSDimitry Andric       return this->visitGlobalInitializer(Init, *GlobalIndex);
2386bdd1243dSDimitry Andric     }
2387bdd1243dSDimitry Andric   } else {
2388bdd1243dSDimitry Andric     VariableScope<Emitter> LocalScope(this);
2389bdd1243dSDimitry Andric     if (VarT) {
2390bdd1243dSDimitry Andric       unsigned Offset = this->allocateLocalPrimitive(
2391bdd1243dSDimitry Andric           VD, *VarT, VD->getType().isConstQualified());
2392bdd1243dSDimitry Andric       if (Init) {
2393bdd1243dSDimitry Andric         // Compile the initializer in its own scope.
2394bdd1243dSDimitry Andric         ExprScope<Emitter> Scope(this);
2395bdd1243dSDimitry Andric         if (!this->visit(Init))
2396bdd1243dSDimitry Andric           return false;
2397bdd1243dSDimitry Andric 
2398bdd1243dSDimitry Andric         return this->emitSetLocal(*VarT, Offset, VD);
2399bdd1243dSDimitry Andric       }
2400bdd1243dSDimitry Andric     } else {
2401bdd1243dSDimitry Andric       if (std::optional<unsigned> Offset = this->allocateLocal(VD)) {
2402bdd1243dSDimitry Andric         if (Init)
2403bdd1243dSDimitry Andric           return this->visitLocalInitializer(Init, *Offset);
2404bdd1243dSDimitry Andric       }
2405bdd1243dSDimitry Andric     }
2406bdd1243dSDimitry Andric     return true;
2407a7dea167SDimitry Andric   }
2408a7dea167SDimitry Andric 
2409bdd1243dSDimitry Andric   return false;
2410bdd1243dSDimitry Andric }
2411bdd1243dSDimitry Andric 
2412bdd1243dSDimitry Andric template <class Emitter>
2413*c9157d92SDimitry Andric bool ByteCodeExprGen<Emitter>::visitAPValue(const APValue &Val,
2414*c9157d92SDimitry Andric                                             PrimType ValType, const Expr *E) {
2415*c9157d92SDimitry Andric   assert(!DiscardResult);
2416*c9157d92SDimitry Andric   if (Val.isInt())
2417*c9157d92SDimitry Andric     return this->emitConst(Val.getInt(), ValType, E);
2418*c9157d92SDimitry Andric 
2419*c9157d92SDimitry Andric   if (Val.isLValue()) {
2420*c9157d92SDimitry Andric     APValue::LValueBase Base = Val.getLValueBase();
2421*c9157d92SDimitry Andric     if (const Expr *BaseExpr = Base.dyn_cast<const Expr *>())
2422*c9157d92SDimitry Andric       return this->visit(BaseExpr);
2423*c9157d92SDimitry Andric   }
2424*c9157d92SDimitry Andric 
2425*c9157d92SDimitry Andric   return false;
2426*c9157d92SDimitry Andric }
2427*c9157d92SDimitry Andric 
2428*c9157d92SDimitry Andric template <class Emitter>
2429fe013be4SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitBuiltinCallExpr(const CallExpr *E) {
2430fe013be4SDimitry Andric   const Function *Func = getFunction(E->getDirectCallee());
2431bdd1243dSDimitry Andric   if (!Func)
2432bdd1243dSDimitry Andric     return false;
2433fe013be4SDimitry Andric 
2434*c9157d92SDimitry Andric   if (!Func->isUnevaluatedBuiltin()) {
2435fe013be4SDimitry Andric     // Put arguments on the stack.
2436fe013be4SDimitry Andric     for (const auto *Arg : E->arguments()) {
2437fe013be4SDimitry Andric       if (!this->visit(Arg))
2438fe013be4SDimitry Andric         return false;
2439fe013be4SDimitry Andric     }
2440*c9157d92SDimitry Andric   }
2441fe013be4SDimitry Andric 
2442*c9157d92SDimitry Andric   if (!this->emitCallBI(Func, E, E))
2443bdd1243dSDimitry Andric     return false;
2444bdd1243dSDimitry Andric 
2445bdd1243dSDimitry Andric   QualType ReturnType = E->getCallReturnType(Ctx.getASTContext());
2446fe013be4SDimitry Andric   if (DiscardResult && !ReturnType->isVoidType()) {
2447fe013be4SDimitry Andric     PrimType T = classifyPrim(ReturnType);
2448fe013be4SDimitry Andric     return this->emitPop(T, E);
2449fe013be4SDimitry Andric   }
2450bdd1243dSDimitry Andric 
2451fe013be4SDimitry Andric   return true;
2452fe013be4SDimitry Andric }
2453fe013be4SDimitry Andric 
2454fe013be4SDimitry Andric template <class Emitter>
2455fe013be4SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCallExpr(const CallExpr *E) {
2456fe013be4SDimitry Andric   if (E->getBuiltinCallee())
2457fe013be4SDimitry Andric     return VisitBuiltinCallExpr(E);
2458fe013be4SDimitry Andric 
2459fe013be4SDimitry Andric   QualType ReturnType = E->getCallReturnType(Ctx.getASTContext());
2460fe013be4SDimitry Andric   std::optional<PrimType> T = classify(ReturnType);
2461fe013be4SDimitry Andric   bool HasRVO = !ReturnType->isVoidType() && !T;
2462fe013be4SDimitry Andric 
2463*c9157d92SDimitry Andric   if (HasRVO) {
2464*c9157d92SDimitry Andric     if (DiscardResult) {
2465bdd1243dSDimitry Andric       // If we need to discard the return value but the function returns its
2466bdd1243dSDimitry Andric       // value via an RVO pointer, we need to create one such pointer just
2467bdd1243dSDimitry Andric       // for this call.
2468bdd1243dSDimitry Andric       if (std::optional<unsigned> LocalIndex = allocateLocal(E)) {
2469bdd1243dSDimitry Andric         if (!this->emitGetPtrLocal(*LocalIndex, E))
2470bdd1243dSDimitry Andric           return false;
2471bdd1243dSDimitry Andric       }
2472*c9157d92SDimitry Andric     } else {
2473*c9157d92SDimitry Andric       assert(Initializing);
2474*c9157d92SDimitry Andric       if (!this->emitDupPtr(E))
2475*c9157d92SDimitry Andric         return false;
2476*c9157d92SDimitry Andric     }
2477*c9157d92SDimitry Andric   }
2478*c9157d92SDimitry Andric 
2479*c9157d92SDimitry Andric   // Add the (optional, implicit) This pointer.
2480*c9157d92SDimitry Andric   if (const auto *MC = dyn_cast<CXXMemberCallExpr>(E)) {
2481*c9157d92SDimitry Andric     if (!this->visit(MC->getImplicitObjectArgument()))
2482*c9157d92SDimitry Andric       return false;
2483bdd1243dSDimitry Andric   }
2484bdd1243dSDimitry Andric 
2485bdd1243dSDimitry Andric   // Put arguments on the stack.
2486bdd1243dSDimitry Andric   for (const auto *Arg : E->arguments()) {
2487bdd1243dSDimitry Andric     if (!this->visit(Arg))
2488bdd1243dSDimitry Andric       return false;
2489bdd1243dSDimitry Andric   }
2490bdd1243dSDimitry Andric 
2491fe013be4SDimitry Andric   if (const FunctionDecl *FuncDecl = E->getDirectCallee()) {
2492fe013be4SDimitry Andric     const Function *Func = getFunction(FuncDecl);
2493fe013be4SDimitry Andric     if (!Func)
2494fe013be4SDimitry Andric       return false;
2495fe013be4SDimitry Andric     // If the function is being compiled right now, this is a recursive call.
2496fe013be4SDimitry Andric     // In that case, the function can't be valid yet, even though it will be
2497fe013be4SDimitry Andric     // later.
2498fe013be4SDimitry Andric     // If the function is already fully compiled but not constexpr, it was
2499fe013be4SDimitry Andric     // found to be faulty earlier on, so bail out.
2500fe013be4SDimitry Andric     if (Func->isFullyCompiled() && !Func->isConstexpr())
2501bdd1243dSDimitry Andric       return false;
2502bdd1243dSDimitry Andric 
2503fe013be4SDimitry Andric     assert(HasRVO == Func->hasRVO());
2504fe013be4SDimitry Andric 
2505fe013be4SDimitry Andric     bool HasQualifier = false;
2506fe013be4SDimitry Andric     if (const auto *ME = dyn_cast<MemberExpr>(E->getCallee()))
2507fe013be4SDimitry Andric       HasQualifier = ME->hasQualifier();
2508fe013be4SDimitry Andric 
2509fe013be4SDimitry Andric     bool IsVirtual = false;
2510fe013be4SDimitry Andric     if (const auto *MD = dyn_cast<CXXMethodDecl>(FuncDecl))
2511fe013be4SDimitry Andric       IsVirtual = MD->isVirtual();
2512fe013be4SDimitry Andric 
2513fe013be4SDimitry Andric     // In any case call the function. The return value will end up on the stack
2514fe013be4SDimitry Andric     // and if the function has RVO, we already have the pointer on the stack to
2515fe013be4SDimitry Andric     // write the result into.
2516fe013be4SDimitry Andric     if (IsVirtual && !HasQualifier) {
2517fe013be4SDimitry Andric       if (!this->emitCallVirt(Func, E))
2518fe013be4SDimitry Andric         return false;
2519fe013be4SDimitry Andric     } else {
2520fe013be4SDimitry Andric       if (!this->emitCall(Func, E))
2521fe013be4SDimitry Andric         return false;
2522fe013be4SDimitry Andric     }
2523fe013be4SDimitry Andric   } else {
2524fe013be4SDimitry Andric     // Indirect call. Visit the callee, which will leave a FunctionPointer on
2525fe013be4SDimitry Andric     // the stack. Cleanup of the returned value if necessary will be done after
2526fe013be4SDimitry Andric     // the function call completed.
2527fe013be4SDimitry Andric     if (!this->visit(E->getCallee()))
2528fe013be4SDimitry Andric       return false;
2529fe013be4SDimitry Andric 
2530fe013be4SDimitry Andric     if (!this->emitCallPtr(E))
2531fe013be4SDimitry Andric       return false;
2532fe013be4SDimitry Andric   }
2533fe013be4SDimitry Andric 
2534fe013be4SDimitry Andric   // Cleanup for discarded return values.
2535bdd1243dSDimitry Andric   if (DiscardResult && !ReturnType->isVoidType() && T)
2536bdd1243dSDimitry Andric     return this->emitPop(*T, E);
2537bdd1243dSDimitry Andric 
2538bdd1243dSDimitry Andric   return true;
2539bdd1243dSDimitry Andric }
2540bdd1243dSDimitry Andric 
2541bdd1243dSDimitry Andric template <class Emitter>
2542bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCXXDefaultInitExpr(
2543bdd1243dSDimitry Andric     const CXXDefaultInitExpr *E) {
2544*c9157d92SDimitry Andric   SourceLocScope<Emitter> SLS(this, E);
2545*c9157d92SDimitry Andric   if (Initializing)
2546*c9157d92SDimitry Andric     return this->visitInitializer(E->getExpr());
2547*c9157d92SDimitry Andric 
2548fe013be4SDimitry Andric   assert(classify(E->getType()));
2549bdd1243dSDimitry Andric   return this->visit(E->getExpr());
2550bdd1243dSDimitry Andric }
2551bdd1243dSDimitry Andric 
2552bdd1243dSDimitry Andric template <class Emitter>
2553bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCXXDefaultArgExpr(
2554bdd1243dSDimitry Andric     const CXXDefaultArgExpr *E) {
2555*c9157d92SDimitry Andric   SourceLocScope<Emitter> SLS(this, E);
2556*c9157d92SDimitry Andric 
2557*c9157d92SDimitry Andric   const Expr *SubExpr = E->getExpr();
2558*c9157d92SDimitry Andric   if (std::optional<PrimType> T = classify(E->getExpr()))
2559*c9157d92SDimitry Andric     return this->visit(SubExpr);
2560*c9157d92SDimitry Andric 
2561*c9157d92SDimitry Andric   assert(Initializing);
2562*c9157d92SDimitry Andric   return this->visitInitializer(SubExpr);
2563bdd1243dSDimitry Andric }
2564bdd1243dSDimitry Andric 
2565bdd1243dSDimitry Andric template <class Emitter>
2566bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCXXBoolLiteralExpr(
2567bdd1243dSDimitry Andric     const CXXBoolLiteralExpr *E) {
2568bdd1243dSDimitry Andric   if (DiscardResult)
2569bdd1243dSDimitry Andric     return true;
2570bdd1243dSDimitry Andric 
2571bdd1243dSDimitry Andric   return this->emitConstBool(E->getValue(), E);
2572bdd1243dSDimitry Andric }
2573bdd1243dSDimitry Andric 
2574bdd1243dSDimitry Andric template <class Emitter>
2575bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCXXNullPtrLiteralExpr(
2576bdd1243dSDimitry Andric     const CXXNullPtrLiteralExpr *E) {
2577bdd1243dSDimitry Andric   if (DiscardResult)
2578bdd1243dSDimitry Andric     return true;
2579bdd1243dSDimitry Andric 
2580bdd1243dSDimitry Andric   return this->emitNullPtr(E);
2581bdd1243dSDimitry Andric }
2582bdd1243dSDimitry Andric 
2583bdd1243dSDimitry Andric template <class Emitter>
2584*c9157d92SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitGNUNullExpr(const GNUNullExpr *E) {
2585*c9157d92SDimitry Andric   if (DiscardResult)
2586*c9157d92SDimitry Andric     return true;
2587*c9157d92SDimitry Andric 
2588*c9157d92SDimitry Andric   assert(E->getType()->isIntegerType());
2589*c9157d92SDimitry Andric 
2590*c9157d92SDimitry Andric   PrimType T = classifyPrim(E->getType());
2591*c9157d92SDimitry Andric   return this->emitZero(T, E);
2592*c9157d92SDimitry Andric }
2593*c9157d92SDimitry Andric 
2594*c9157d92SDimitry Andric template <class Emitter>
2595bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCXXThisExpr(const CXXThisExpr *E) {
2596bdd1243dSDimitry Andric   if (DiscardResult)
2597bdd1243dSDimitry Andric     return true;
2598*c9157d92SDimitry Andric 
2599*c9157d92SDimitry Andric   if (this->LambdaThisCapture > 0)
2600*c9157d92SDimitry Andric     return this->emitGetThisFieldPtr(this->LambdaThisCapture, E);
2601*c9157d92SDimitry Andric 
2602bdd1243dSDimitry Andric   return this->emitThis(E);
2603bdd1243dSDimitry Andric }
2604bdd1243dSDimitry Andric 
2605bdd1243dSDimitry Andric template <class Emitter>
2606bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitUnaryOperator(const UnaryOperator *E) {
2607bdd1243dSDimitry Andric   const Expr *SubExpr = E->getSubExpr();
2608bdd1243dSDimitry Andric   std::optional<PrimType> T = classify(SubExpr->getType());
2609bdd1243dSDimitry Andric 
2610bdd1243dSDimitry Andric   switch (E->getOpcode()) {
2611bdd1243dSDimitry Andric   case UO_PostInc: { // x++
2612bdd1243dSDimitry Andric     if (!this->visit(SubExpr))
2613bdd1243dSDimitry Andric       return false;
2614bdd1243dSDimitry Andric 
2615fe013be4SDimitry Andric     if (T == PT_Ptr) {
2616fe013be4SDimitry Andric       if (!this->emitIncPtr(E))
2617fe013be4SDimitry Andric         return false;
2618fe013be4SDimitry Andric 
2619fe013be4SDimitry Andric       return DiscardResult ? this->emitPopPtr(E) : true;
2620fe013be4SDimitry Andric     }
2621fe013be4SDimitry Andric 
2622fe013be4SDimitry Andric     if (T == PT_Float) {
2623fe013be4SDimitry Andric       return DiscardResult ? this->emitIncfPop(getRoundingMode(E), E)
2624fe013be4SDimitry Andric                            : this->emitIncf(getRoundingMode(E), E);
2625fe013be4SDimitry Andric     }
2626fe013be4SDimitry Andric 
2627bdd1243dSDimitry Andric     return DiscardResult ? this->emitIncPop(*T, E) : this->emitInc(*T, E);
2628bdd1243dSDimitry Andric   }
2629bdd1243dSDimitry Andric   case UO_PostDec: { // x--
2630bdd1243dSDimitry Andric     if (!this->visit(SubExpr))
2631bdd1243dSDimitry Andric       return false;
2632bdd1243dSDimitry Andric 
2633fe013be4SDimitry Andric     if (T == PT_Ptr) {
2634fe013be4SDimitry Andric       if (!this->emitDecPtr(E))
2635fe013be4SDimitry Andric         return false;
2636fe013be4SDimitry Andric 
2637fe013be4SDimitry Andric       return DiscardResult ? this->emitPopPtr(E) : true;
2638fe013be4SDimitry Andric     }
2639fe013be4SDimitry Andric 
2640fe013be4SDimitry Andric     if (T == PT_Float) {
2641fe013be4SDimitry Andric       return DiscardResult ? this->emitDecfPop(getRoundingMode(E), E)
2642fe013be4SDimitry Andric                            : this->emitDecf(getRoundingMode(E), E);
2643fe013be4SDimitry Andric     }
2644fe013be4SDimitry Andric 
2645bdd1243dSDimitry Andric     return DiscardResult ? this->emitDecPop(*T, E) : this->emitDec(*T, E);
2646bdd1243dSDimitry Andric   }
2647bdd1243dSDimitry Andric   case UO_PreInc: { // ++x
2648bdd1243dSDimitry Andric     if (!this->visit(SubExpr))
2649bdd1243dSDimitry Andric       return false;
2650bdd1243dSDimitry Andric 
2651fe013be4SDimitry Andric     if (T == PT_Ptr) {
2652*c9157d92SDimitry Andric       if (!this->emitLoadPtr(E))
2653*c9157d92SDimitry Andric         return false;
2654*c9157d92SDimitry Andric       if (!this->emitConstUint8(1, E))
2655*c9157d92SDimitry Andric         return false;
2656*c9157d92SDimitry Andric       if (!this->emitAddOffsetUint8(E))
2657*c9157d92SDimitry Andric         return false;
2658fe013be4SDimitry Andric       return DiscardResult ? this->emitStorePopPtr(E) : this->emitStorePtr(E);
2659fe013be4SDimitry Andric     }
2660bdd1243dSDimitry Andric 
2661fe013be4SDimitry Andric     // Post-inc and pre-inc are the same if the value is to be discarded.
2662fe013be4SDimitry Andric     if (DiscardResult) {
2663fe013be4SDimitry Andric       if (T == PT_Float)
2664fe013be4SDimitry Andric         return this->emitIncfPop(getRoundingMode(E), E);
2665fe013be4SDimitry Andric       return this->emitIncPop(*T, E);
2666fe013be4SDimitry Andric     }
2667fe013be4SDimitry Andric 
2668fe013be4SDimitry Andric     if (T == PT_Float) {
2669fe013be4SDimitry Andric       const auto &TargetSemantics = Ctx.getFloatSemantics(E->getType());
2670*c9157d92SDimitry Andric       if (!this->emitLoadFloat(E))
2671*c9157d92SDimitry Andric         return false;
2672*c9157d92SDimitry Andric       if (!this->emitConstFloat(llvm::APFloat(TargetSemantics, 1), E))
2673*c9157d92SDimitry Andric         return false;
2674*c9157d92SDimitry Andric       if (!this->emitAddf(getRoundingMode(E), E))
2675*c9157d92SDimitry Andric         return false;
2676fe013be4SDimitry Andric       return this->emitStoreFloat(E);
2677fe013be4SDimitry Andric     }
2678*c9157d92SDimitry Andric     if (!this->emitLoad(*T, E))
2679*c9157d92SDimitry Andric       return false;
2680*c9157d92SDimitry Andric     if (!this->emitConst(1, E))
2681*c9157d92SDimitry Andric       return false;
2682*c9157d92SDimitry Andric     if (!this->emitAdd(*T, E))
2683*c9157d92SDimitry Andric       return false;
2684bdd1243dSDimitry Andric     return this->emitStore(*T, E);
2685bdd1243dSDimitry Andric   }
2686bdd1243dSDimitry Andric   case UO_PreDec: { // --x
2687bdd1243dSDimitry Andric     if (!this->visit(SubExpr))
2688bdd1243dSDimitry Andric       return false;
2689bdd1243dSDimitry Andric 
2690fe013be4SDimitry Andric     if (T == PT_Ptr) {
2691*c9157d92SDimitry Andric       if (!this->emitLoadPtr(E))
2692*c9157d92SDimitry Andric         return false;
2693*c9157d92SDimitry Andric       if (!this->emitConstUint8(1, E))
2694*c9157d92SDimitry Andric         return false;
2695*c9157d92SDimitry Andric       if (!this->emitSubOffsetUint8(E))
2696*c9157d92SDimitry Andric         return false;
2697fe013be4SDimitry Andric       return DiscardResult ? this->emitStorePopPtr(E) : this->emitStorePtr(E);
2698fe013be4SDimitry Andric     }
2699bdd1243dSDimitry Andric 
2700fe013be4SDimitry Andric     // Post-dec and pre-dec are the same if the value is to be discarded.
2701fe013be4SDimitry Andric     if (DiscardResult) {
2702fe013be4SDimitry Andric       if (T == PT_Float)
2703fe013be4SDimitry Andric         return this->emitDecfPop(getRoundingMode(E), E);
2704fe013be4SDimitry Andric       return this->emitDecPop(*T, E);
2705fe013be4SDimitry Andric     }
2706fe013be4SDimitry Andric 
2707fe013be4SDimitry Andric     if (T == PT_Float) {
2708fe013be4SDimitry Andric       const auto &TargetSemantics = Ctx.getFloatSemantics(E->getType());
2709*c9157d92SDimitry Andric       if (!this->emitLoadFloat(E))
2710*c9157d92SDimitry Andric         return false;
2711*c9157d92SDimitry Andric       if (!this->emitConstFloat(llvm::APFloat(TargetSemantics, 1), E))
2712*c9157d92SDimitry Andric         return false;
2713*c9157d92SDimitry Andric       if (!this->emitSubf(getRoundingMode(E), E))
2714*c9157d92SDimitry Andric         return false;
2715fe013be4SDimitry Andric       return this->emitStoreFloat(E);
2716fe013be4SDimitry Andric     }
2717*c9157d92SDimitry Andric     if (!this->emitLoad(*T, E))
2718*c9157d92SDimitry Andric       return false;
2719*c9157d92SDimitry Andric     if (!this->emitConst(1, E))
2720*c9157d92SDimitry Andric       return false;
2721*c9157d92SDimitry Andric     if (!this->emitSub(*T, E))
2722*c9157d92SDimitry Andric       return false;
2723bdd1243dSDimitry Andric     return this->emitStore(*T, E);
2724bdd1243dSDimitry Andric   }
2725bdd1243dSDimitry Andric   case UO_LNot: // !x
2726*c9157d92SDimitry Andric     if (DiscardResult)
2727*c9157d92SDimitry Andric       return this->discard(SubExpr);
2728*c9157d92SDimitry Andric 
2729*c9157d92SDimitry Andric     if (!this->visitBool(SubExpr))
2730bdd1243dSDimitry Andric       return false;
2731*c9157d92SDimitry Andric 
2732*c9157d92SDimitry Andric     if (!this->emitInvBool(E))
2733*c9157d92SDimitry Andric       return false;
2734*c9157d92SDimitry Andric 
2735*c9157d92SDimitry Andric     if (PrimType ET = classifyPrim(E->getType()); ET != PT_Bool)
2736*c9157d92SDimitry Andric       return this->emitCast(PT_Bool, ET, E);
2737*c9157d92SDimitry Andric     return true;
2738bdd1243dSDimitry Andric   case UO_Minus: // -x
2739bdd1243dSDimitry Andric     if (!this->visit(SubExpr))
2740bdd1243dSDimitry Andric       return false;
2741bdd1243dSDimitry Andric     return DiscardResult ? this->emitPop(*T, E) : this->emitNeg(*T, E);
2742bdd1243dSDimitry Andric   case UO_Plus:  // +x
2743bdd1243dSDimitry Andric     if (!this->visit(SubExpr)) // noop
2744bdd1243dSDimitry Andric       return false;
2745bdd1243dSDimitry Andric     return DiscardResult ? this->emitPop(*T, E) : true;
2746bdd1243dSDimitry Andric   case UO_AddrOf: // &x
2747bdd1243dSDimitry Andric     // We should already have a pointer when we get here.
2748*c9157d92SDimitry Andric     return this->delegate(SubExpr);
2749bdd1243dSDimitry Andric   case UO_Deref:  // *x
2750bdd1243dSDimitry Andric     return dereference(
2751bdd1243dSDimitry Andric         SubExpr, DerefKind::Read,
2752bdd1243dSDimitry Andric         [](PrimType) {
2753bdd1243dSDimitry Andric           llvm_unreachable("Dereferencing requires a pointer");
2754bdd1243dSDimitry Andric           return false;
2755bdd1243dSDimitry Andric         },
2756bdd1243dSDimitry Andric         [this, E](PrimType T) {
2757bdd1243dSDimitry Andric           return DiscardResult ? this->emitPop(T, E) : true;
2758bdd1243dSDimitry Andric         });
2759bdd1243dSDimitry Andric   case UO_Not:    // ~x
2760bdd1243dSDimitry Andric     if (!this->visit(SubExpr))
2761bdd1243dSDimitry Andric       return false;
2762bdd1243dSDimitry Andric     return DiscardResult ? this->emitPop(*T, E) : this->emitComp(*T, E);
2763*c9157d92SDimitry Andric   case UO_Real: { // __real x
2764*c9157d92SDimitry Andric     assert(!T);
2765*c9157d92SDimitry Andric     if (!this->visit(SubExpr))
2766*c9157d92SDimitry Andric       return false;
2767*c9157d92SDimitry Andric     if (!this->emitConstUint8(0, E))
2768*c9157d92SDimitry Andric       return false;
2769*c9157d92SDimitry Andric     if (!this->emitArrayElemPtrPopUint8(E))
2770*c9157d92SDimitry Andric       return false;
2771*c9157d92SDimitry Andric 
2772*c9157d92SDimitry Andric     // Since our _Complex implementation does not map to a primitive type,
2773*c9157d92SDimitry Andric     // we sometimes have to do the lvalue-to-rvalue conversion here manually.
2774*c9157d92SDimitry Andric     if (!SubExpr->isLValue())
2775*c9157d92SDimitry Andric       return this->emitLoadPop(classifyPrim(E->getType()), E);
2776*c9157d92SDimitry Andric     return true;
2777*c9157d92SDimitry Andric   }
2778*c9157d92SDimitry Andric   case UO_Imag: { // __imag x
2779*c9157d92SDimitry Andric     assert(!T);
2780*c9157d92SDimitry Andric     if (!this->visit(SubExpr))
2781*c9157d92SDimitry Andric       return false;
2782*c9157d92SDimitry Andric     if (!this->emitConstUint8(1, E))
2783*c9157d92SDimitry Andric       return false;
2784*c9157d92SDimitry Andric     if (!this->emitArrayElemPtrPopUint8(E))
2785*c9157d92SDimitry Andric       return false;
2786*c9157d92SDimitry Andric 
2787*c9157d92SDimitry Andric     // Since our _Complex implementation does not map to a primitive type,
2788*c9157d92SDimitry Andric     // we sometimes have to do the lvalue-to-rvalue conversion here manually.
2789*c9157d92SDimitry Andric     if (!SubExpr->isLValue())
2790*c9157d92SDimitry Andric       return this->emitLoadPop(classifyPrim(E->getType()), E);
2791*c9157d92SDimitry Andric     return true;
2792*c9157d92SDimitry Andric   }
2793bdd1243dSDimitry Andric   case UO_Extension:
2794*c9157d92SDimitry Andric     return this->delegate(SubExpr);
2795bdd1243dSDimitry Andric   case UO_Coawait:
2796bdd1243dSDimitry Andric     assert(false && "Unhandled opcode");
2797bdd1243dSDimitry Andric   }
2798bdd1243dSDimitry Andric 
2799bdd1243dSDimitry Andric   return false;
2800bdd1243dSDimitry Andric }
2801bdd1243dSDimitry Andric 
2802bdd1243dSDimitry Andric template <class Emitter>
2803bdd1243dSDimitry Andric bool ByteCodeExprGen<Emitter>::VisitDeclRefExpr(const DeclRefExpr *E) {
2804fe013be4SDimitry Andric   if (DiscardResult)
2805fe013be4SDimitry Andric     return true;
2806fe013be4SDimitry Andric 
2807fe013be4SDimitry Andric   const auto *D = E->getDecl();
2808fe013be4SDimitry Andric 
2809fe013be4SDimitry Andric   if (const auto *ECD = dyn_cast<EnumConstantDecl>(D)) {
2810fe013be4SDimitry Andric     return this->emitConst(ECD->getInitVal(), E);
2811fe013be4SDimitry Andric   } else if (const auto *BD = dyn_cast<BindingDecl>(D)) {
2812fe013be4SDimitry Andric     return this->visit(BD->getBinding());
2813fe013be4SDimitry Andric   } else if (const auto *FuncDecl = dyn_cast<FunctionDecl>(D)) {
2814fe013be4SDimitry Andric     const Function *F = getFunction(FuncDecl);
2815fe013be4SDimitry Andric     return F && this->emitGetFnPtr(F, E);
2816fe013be4SDimitry Andric   }
2817fe013be4SDimitry Andric 
2818bdd1243dSDimitry Andric   // References are implemented via pointers, so when we see a DeclRefExpr
2819bdd1243dSDimitry Andric   // pointing to a reference, we need to get its value directly (i.e. the
2820bdd1243dSDimitry Andric   // pointer to the actual value) instead of a pointer to the pointer to the
2821bdd1243dSDimitry Andric   // value.
2822fe013be4SDimitry Andric   bool IsReference = D->getType()->isReferenceType();
2823bdd1243dSDimitry Andric 
2824fe013be4SDimitry Andric   // Check for local/global variables and parameters.
2825fe013be4SDimitry Andric   if (auto It = Locals.find(D); It != Locals.end()) {
2826bdd1243dSDimitry Andric     const unsigned Offset = It->second.Offset;
2827bdd1243dSDimitry Andric 
2828bdd1243dSDimitry Andric     if (IsReference)
2829bdd1243dSDimitry Andric       return this->emitGetLocal(PT_Ptr, Offset, E);
2830bdd1243dSDimitry Andric     return this->emitGetPtrLocal(Offset, E);
2831fe013be4SDimitry Andric   } else if (auto GlobalIndex = P.getGlobal(D)) {
2832bdd1243dSDimitry Andric     if (IsReference)
2833fe013be4SDimitry Andric       return this->emitGetGlobalPtr(*GlobalIndex, E);
2834bdd1243dSDimitry Andric 
2835bdd1243dSDimitry Andric     return this->emitGetPtrGlobal(*GlobalIndex, E);
2836fe013be4SDimitry Andric   } else if (const auto *PVD = dyn_cast<ParmVarDecl>(D)) {
2837bdd1243dSDimitry Andric     if (auto It = this->Params.find(PVD); It != this->Params.end()) {
2838*c9157d92SDimitry Andric       if (IsReference || !It->second.IsPtr)
2839*c9157d92SDimitry Andric         return this->emitGetParamPtr(It->second.Offset, E);
2840*c9157d92SDimitry Andric 
2841*c9157d92SDimitry Andric       return this->emitGetPtrParam(It->second.Offset, E);
2842bdd1243dSDimitry Andric     }
2843fe013be4SDimitry Andric   }
2844fe013be4SDimitry Andric 
2845fe013be4SDimitry Andric   // Handle lambda captures.
2846fe013be4SDimitry Andric   if (auto It = this->LambdaCaptures.find(D);
2847fe013be4SDimitry Andric       It != this->LambdaCaptures.end()) {
2848*c9157d92SDimitry Andric     auto [Offset, IsPtr] = It->second;
2849fe013be4SDimitry Andric 
2850*c9157d92SDimitry Andric     if (IsPtr)
2851fe013be4SDimitry Andric       return this->emitGetThisFieldPtr(Offset, E);
2852fe013be4SDimitry Andric     return this->emitGetPtrThisField(Offset, E);
2853bdd1243dSDimitry Andric   }
2854bdd1243dSDimitry Andric 
2855*c9157d92SDimitry Andric   // Lazily visit global declarations we haven't seen yet.
2856*c9157d92SDimitry Andric   // This happens in C.
2857*c9157d92SDimitry Andric   if (!Ctx.getLangOpts().CPlusPlus) {
2858*c9157d92SDimitry Andric     if (const auto *VD = dyn_cast<VarDecl>(D);
2859*c9157d92SDimitry Andric         VD && VD->hasGlobalStorage() && VD->getAnyInitializer() &&
2860*c9157d92SDimitry Andric         VD->getType().isConstQualified()) {
2861*c9157d92SDimitry Andric       if (!this->visitVarDecl(VD))
2862bdd1243dSDimitry Andric         return false;
2863*c9157d92SDimitry Andric       // Retry.
2864*c9157d92SDimitry Andric       return this->VisitDeclRefExpr(E);
2865*c9157d92SDimitry Andric     }
2866*c9157d92SDimitry Andric 
2867*c9157d92SDimitry Andric     if (std::optional<unsigned> I = P.getOrCreateDummy(D))
2868*c9157d92SDimitry Andric       return this->emitGetPtrGlobal(*I, E);
2869*c9157d92SDimitry Andric   }
2870*c9157d92SDimitry Andric 
2871*c9157d92SDimitry Andric   return this->emitInvalidDeclRef(E, E);
2872a7dea167SDimitry Andric }
2873a7dea167SDimitry Andric 
2874a7dea167SDimitry Andric template <class Emitter>
2875a7dea167SDimitry Andric void ByteCodeExprGen<Emitter>::emitCleanup() {
2876a7dea167SDimitry Andric   for (VariableScope<Emitter> *C = VarScope; C; C = C->getParent())
2877a7dea167SDimitry Andric     C->emitDestruction();
2878a7dea167SDimitry Andric }
2879a7dea167SDimitry Andric 
2880fe013be4SDimitry Andric template <class Emitter>
2881*c9157d92SDimitry Andric unsigned
2882*c9157d92SDimitry Andric ByteCodeExprGen<Emitter>::collectBaseOffset(const RecordType *BaseType,
2883*c9157d92SDimitry Andric                                             const RecordType *DerivedType) {
2884fe013be4SDimitry Andric   const auto *FinalDecl = cast<CXXRecordDecl>(BaseType->getDecl());
2885fe013be4SDimitry Andric   const RecordDecl *CurDecl = DerivedType->getDecl();
2886fe013be4SDimitry Andric   const Record *CurRecord = getRecord(CurDecl);
2887fe013be4SDimitry Andric   assert(CurDecl && FinalDecl);
2888*c9157d92SDimitry Andric 
2889*c9157d92SDimitry Andric   unsigned OffsetSum = 0;
2890fe013be4SDimitry Andric   for (;;) {
2891fe013be4SDimitry Andric     assert(CurRecord->getNumBases() > 0);
2892fe013be4SDimitry Andric     // One level up
2893fe013be4SDimitry Andric     for (const Record::Base &B : CurRecord->bases()) {
2894fe013be4SDimitry Andric       const auto *BaseDecl = cast<CXXRecordDecl>(B.Decl);
2895fe013be4SDimitry Andric 
2896fe013be4SDimitry Andric       if (BaseDecl == FinalDecl || BaseDecl->isDerivedFrom(FinalDecl)) {
2897*c9157d92SDimitry Andric         OffsetSum += B.Offset;
2898fe013be4SDimitry Andric         CurRecord = B.R;
2899fe013be4SDimitry Andric         CurDecl = BaseDecl;
2900fe013be4SDimitry Andric         break;
2901fe013be4SDimitry Andric       }
2902fe013be4SDimitry Andric     }
2903fe013be4SDimitry Andric     if (CurDecl == FinalDecl)
2904*c9157d92SDimitry Andric       break;
2905fe013be4SDimitry Andric   }
2906fe013be4SDimitry Andric 
2907*c9157d92SDimitry Andric   assert(OffsetSum > 0);
2908*c9157d92SDimitry Andric   return OffsetSum;
2909*c9157d92SDimitry Andric }
2910*c9157d92SDimitry Andric 
2911*c9157d92SDimitry Andric /// Emit casts from a PrimType to another PrimType.
2912*c9157d92SDimitry Andric template <class Emitter>
2913*c9157d92SDimitry Andric bool ByteCodeExprGen<Emitter>::emitPrimCast(PrimType FromT, PrimType ToT,
2914*c9157d92SDimitry Andric                                             QualType ToQT, const Expr *E) {
2915*c9157d92SDimitry Andric 
2916*c9157d92SDimitry Andric   if (FromT == PT_Float) {
2917*c9157d92SDimitry Andric     // Floating to floating.
2918*c9157d92SDimitry Andric     if (ToT == PT_Float) {
2919*c9157d92SDimitry Andric       const llvm::fltSemantics *ToSem = &Ctx.getFloatSemantics(ToQT);
2920*c9157d92SDimitry Andric       return this->emitCastFP(ToSem, getRoundingMode(E), E);
2921*c9157d92SDimitry Andric     }
2922*c9157d92SDimitry Andric 
2923*c9157d92SDimitry Andric     // Float to integral.
2924*c9157d92SDimitry Andric     if (isIntegralType(ToT) || ToT == PT_Bool)
2925*c9157d92SDimitry Andric       return this->emitCastFloatingIntegral(ToT, E);
2926*c9157d92SDimitry Andric   }
2927*c9157d92SDimitry Andric 
2928*c9157d92SDimitry Andric   if (isIntegralType(FromT) || FromT == PT_Bool) {
2929*c9157d92SDimitry Andric     // Integral to integral.
2930*c9157d92SDimitry Andric     if (isIntegralType(ToT) || ToT == PT_Bool)
2931*c9157d92SDimitry Andric       return FromT != ToT ? this->emitCast(FromT, ToT, E) : true;
2932*c9157d92SDimitry Andric 
2933*c9157d92SDimitry Andric     if (ToT == PT_Float) {
2934*c9157d92SDimitry Andric       // Integral to floating.
2935*c9157d92SDimitry Andric       const llvm::fltSemantics *ToSem = &Ctx.getFloatSemantics(ToQT);
2936*c9157d92SDimitry Andric       return this->emitCastIntegralFloating(FromT, ToSem, getRoundingMode(E),
2937*c9157d92SDimitry Andric                                             E);
2938*c9157d92SDimitry Andric     }
2939*c9157d92SDimitry Andric   }
2940*c9157d92SDimitry Andric 
2941fe013be4SDimitry Andric   return false;
2942fe013be4SDimitry Andric }
2943fe013be4SDimitry Andric 
2944fe013be4SDimitry Andric /// When calling this, we have a pointer of the local-to-destroy
2945fe013be4SDimitry Andric /// on the stack.
2946fe013be4SDimitry Andric /// Emit destruction of record types (or arrays of record types).
2947fe013be4SDimitry Andric /// FIXME: Handle virtual destructors.
2948fe013be4SDimitry Andric template <class Emitter>
2949fe013be4SDimitry Andric bool ByteCodeExprGen<Emitter>::emitRecordDestruction(const Descriptor *Desc) {
2950fe013be4SDimitry Andric   assert(Desc);
2951fe013be4SDimitry Andric   assert(!Desc->isPrimitive());
2952fe013be4SDimitry Andric   assert(!Desc->isPrimitiveArray());
2953fe013be4SDimitry Andric 
2954fe013be4SDimitry Andric   // Arrays.
2955fe013be4SDimitry Andric   if (Desc->isArray()) {
2956fe013be4SDimitry Andric     const Descriptor *ElemDesc = Desc->ElemDesc;
2957*c9157d92SDimitry Andric     assert(ElemDesc);
2958fe013be4SDimitry Andric 
2959*c9157d92SDimitry Andric     // Don't need to do anything for these.
2960*c9157d92SDimitry Andric     if (ElemDesc->isPrimitiveArray())
2961*c9157d92SDimitry Andric       return this->emitPopPtr(SourceInfo{});
2962*c9157d92SDimitry Andric 
2963*c9157d92SDimitry Andric     // If this is an array of record types, check if we need
2964*c9157d92SDimitry Andric     // to call the element destructors at all. If not, try
2965*c9157d92SDimitry Andric     // to save the work.
2966*c9157d92SDimitry Andric     if (const Record *ElemRecord = ElemDesc->ElemRecord) {
2967fe013be4SDimitry Andric       if (const CXXDestructorDecl *Dtor = ElemRecord->getDestructor();
2968*c9157d92SDimitry Andric           !Dtor || Dtor->isTrivial())
2969*c9157d92SDimitry Andric         return this->emitPopPtr(SourceInfo{});
2970*c9157d92SDimitry Andric     }
2971*c9157d92SDimitry Andric 
2972fe013be4SDimitry Andric     for (ssize_t I = Desc->getNumElems() - 1; I >= 0; --I) {
2973fe013be4SDimitry Andric       if (!this->emitConstUint64(I, SourceInfo{}))
2974fe013be4SDimitry Andric         return false;
2975fe013be4SDimitry Andric       if (!this->emitArrayElemPtrUint64(SourceInfo{}))
2976fe013be4SDimitry Andric         return false;
2977*c9157d92SDimitry Andric       if (!this->emitRecordDestruction(ElemDesc))
2978fe013be4SDimitry Andric         return false;
2979fe013be4SDimitry Andric     }
2980fe013be4SDimitry Andric     return this->emitPopPtr(SourceInfo{});
2981fe013be4SDimitry Andric   }
2982fe013be4SDimitry Andric 
2983fe013be4SDimitry Andric   const Record *R = Desc->ElemRecord;
2984fe013be4SDimitry Andric   assert(R);
2985fe013be4SDimitry Andric   // First, destroy all fields.
2986fe013be4SDimitry Andric   for (const Record::Field &Field : llvm::reverse(R->fields())) {
2987fe013be4SDimitry Andric     const Descriptor *D = Field.Desc;
2988fe013be4SDimitry Andric     if (!D->isPrimitive() && !D->isPrimitiveArray()) {
2989fe013be4SDimitry Andric       if (!this->emitDupPtr(SourceInfo{}))
2990fe013be4SDimitry Andric         return false;
2991fe013be4SDimitry Andric       if (!this->emitGetPtrField(Field.Offset, SourceInfo{}))
2992fe013be4SDimitry Andric         return false;
2993fe013be4SDimitry Andric       if (!this->emitRecordDestruction(D))
2994fe013be4SDimitry Andric         return false;
2995fe013be4SDimitry Andric     }
2996fe013be4SDimitry Andric   }
2997fe013be4SDimitry Andric 
2998fe013be4SDimitry Andric   // FIXME: Unions need to be handled differently here. We don't want to
2999fe013be4SDimitry Andric   //   call the destructor of its members.
3000fe013be4SDimitry Andric 
3001fe013be4SDimitry Andric   // Now emit the destructor and recurse into base classes.
3002fe013be4SDimitry Andric   if (const CXXDestructorDecl *Dtor = R->getDestructor();
3003fe013be4SDimitry Andric       Dtor && !Dtor->isTrivial()) {
3004*c9157d92SDimitry Andric     if (const Function *DtorFunc = getFunction(Dtor)) {
3005fe013be4SDimitry Andric       assert(DtorFunc->hasThisPointer());
3006fe013be4SDimitry Andric       assert(DtorFunc->getNumParams() == 1);
3007fe013be4SDimitry Andric       if (!this->emitDupPtr(SourceInfo{}))
3008fe013be4SDimitry Andric         return false;
3009fe013be4SDimitry Andric       if (!this->emitCall(DtorFunc, SourceInfo{}))
3010fe013be4SDimitry Andric         return false;
3011fe013be4SDimitry Andric     }
3012fe013be4SDimitry Andric   }
3013fe013be4SDimitry Andric 
3014fe013be4SDimitry Andric   for (const Record::Base &Base : llvm::reverse(R->bases())) {
3015fe013be4SDimitry Andric     if (!this->emitGetPtrBase(Base.Offset, SourceInfo{}))
3016fe013be4SDimitry Andric       return false;
3017fe013be4SDimitry Andric     if (!this->emitRecordDestruction(Base.Desc))
3018fe013be4SDimitry Andric       return false;
3019fe013be4SDimitry Andric   }
3020fe013be4SDimitry Andric   // FIXME: Virtual bases.
3021fe013be4SDimitry Andric 
3022fe013be4SDimitry Andric   // Remove the instance pointer.
3023fe013be4SDimitry Andric   return this->emitPopPtr(SourceInfo{});
3024fe013be4SDimitry Andric }
3025fe013be4SDimitry Andric 
3026a7dea167SDimitry Andric namespace clang {
3027a7dea167SDimitry Andric namespace interp {
3028a7dea167SDimitry Andric 
3029a7dea167SDimitry Andric template class ByteCodeExprGen<ByteCodeEmitter>;
3030a7dea167SDimitry Andric template class ByteCodeExprGen<EvalEmitter>;
3031a7dea167SDimitry Andric 
3032a7dea167SDimitry Andric } // namespace interp
3033a7dea167SDimitry Andric } // namespace clang
3034