xref: /openbsd-src/gnu/llvm/clang/lib/AST/Interp/ByteCodeExprGen.cpp (revision 12c855180aad702bbcca06e0398d774beeafb155)
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