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