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