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