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