clang 17.0.0git
ByteCodeExprGen.cpp
Go to the documentation of this file.
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 "Floating.h"
15#include "Function.h"
16#include "PrimType.h"
17#include "Program.h"
18#include "State.h"
19
20using namespace clang;
21using namespace clang::interp;
22
23using APSInt = llvm::APSInt;
24
25namespace clang {
26namespace interp {
27
28/// Scope used to handle temporaries in toplevel variable declarations.
29template <class Emitter> class DeclScope final : public LocalScope<Emitter> {
30public:
32 : LocalScope<Emitter>(Ctx), Scope(Ctx->P, VD) {}
33
34 void addExtended(const Scope::Local &Local) override {
35 return this->addLocal(Local);
36 }
37
38private:
40};
41
42/// Scope used to handle initialization methods.
43template <class Emitter> class OptionScope {
44public:
45 /// Root constructor, compiling or discarding primitives.
46 OptionScope(ByteCodeExprGen<Emitter> *Ctx, bool NewDiscardResult)
47 : Ctx(Ctx), OldDiscardResult(Ctx->DiscardResult) {
48 Ctx->DiscardResult = NewDiscardResult;
49 }
50
51 ~OptionScope() { Ctx->DiscardResult = OldDiscardResult; }
52
53private:
54 /// Parent context.
56 /// Old discard flag to restore.
57 bool OldDiscardResult;
58};
59
60} // namespace interp
61} // namespace clang
62
63template <class Emitter>
65 auto *SubExpr = CE->getSubExpr();
66 switch (CE->getCastKind()) {
67
68 case CK_LValueToRValue: {
69 return dereference(
70 CE->getSubExpr(), DerefKind::Read,
71 [](PrimType) {
72 // Value loaded - nothing to do here.
73 return true;
74 },
75 [this, CE](PrimType T) {
76 // Pointer on stack - dereference it.
77 if (!this->emitLoadPop(T, CE))
78 return false;
79 return DiscardResult ? this->emitPop(T, CE) : true;
80 });
81 }
82
83 case CK_UncheckedDerivedToBase:
84 case CK_DerivedToBase: {
85 if (!this->visit(SubExpr))
86 return false;
87
88 const CXXRecordDecl *FromDecl = getRecordDecl(SubExpr);
89 assert(FromDecl);
90 const CXXRecordDecl *ToDecl = getRecordDecl(CE);
91 assert(ToDecl);
92 const Record *R = getRecord(FromDecl);
93 const Record::Base *ToBase = R->getBase(ToDecl);
94 assert(ToBase);
95
96 return this->emitGetPtrBasePop(ToBase->Offset, CE);
97 }
98
99 case CK_FloatingCast: {
100 if (!this->visit(SubExpr))
101 return false;
102 const auto *TargetSemantics =
103 &Ctx.getASTContext().getFloatTypeSemantics(CE->getType());
104 return this->emitCastFP(TargetSemantics, getRoundingMode(CE), CE);
105 }
106
107 case CK_IntegralToFloating: {
108 std::optional<PrimType> FromT = classify(SubExpr->getType());
109 if (!FromT)
110 return false;
111
112 if (!this->visit(SubExpr))
113 return false;
114
115 const auto *TargetSemantics =
116 &Ctx.getASTContext().getFloatTypeSemantics(CE->getType());
117 llvm::RoundingMode RM = getRoundingMode(CE);
118 return this->emitCastIntegralFloating(*FromT, TargetSemantics, RM, CE);
119 }
120
121 case CK_FloatingToBoolean:
122 case CK_FloatingToIntegral: {
123 std::optional<PrimType> ToT = classify(CE->getType());
124
125 if (!ToT)
126 return false;
127
128 if (!this->visit(SubExpr))
129 return false;
130
131 return this->emitCastFloatingIntegral(*ToT, CE);
132 }
133
134 case CK_ArrayToPointerDecay:
135 case CK_AtomicToNonAtomic:
136 case CK_ConstructorConversion:
137 case CK_FunctionToPointerDecay:
138 case CK_NonAtomicToAtomic:
139 case CK_NoOp:
140 case CK_UserDefinedConversion:
141 case CK_NullToPointer:
142 return this->visit(SubExpr);
143
144 case CK_IntegralToBoolean:
145 case CK_IntegralCast: {
146 std::optional<PrimType> FromT = classify(SubExpr->getType());
147 std::optional<PrimType> ToT = classify(CE->getType());
148 if (!FromT || !ToT)
149 return false;
150
151 if (!this->visit(SubExpr))
152 return false;
153
154 // TODO: Emit this only if FromT != ToT.
155 return this->emitCast(*FromT, *ToT, CE);
156 }
157
158 case CK_ToVoid:
159 return discard(SubExpr);
160
161 default:
162 assert(false && "Cast not implemented");
163 }
164 llvm_unreachable("Unhandled clang::CastKind enum");
165}
166
167template <class Emitter>
169 if (DiscardResult)
170 return true;
171
172 return this->emitConst(LE->getValue(), LE);
173}
174
175template <class Emitter>
177 if (DiscardResult)
178 return true;
179
180 return this->emitConstFloat(E->getValue(), E);
181}
182
183template <class Emitter>
185 return this->visit(PE->getSubExpr());
186}
187
188template <class Emitter>
190 // Need short-circuiting for these.
191 if (BO->isLogicalOp())
192 return this->VisitLogicalBinOp(BO);
193
194 const Expr *LHS = BO->getLHS();
195 const Expr *RHS = BO->getRHS();
196
197 // Deal with operations which have composite or void types.
198 switch (BO->getOpcode()) {
199 case BO_Comma:
200 if (!discard(LHS))
201 return false;
202 if (!this->visit(RHS))
203 return false;
204 return true;
205 default:
206 break;
207 }
208
209 // Typecheck the args.
210 std::optional<PrimType> LT = classify(LHS->getType());
211 std::optional<PrimType> RT = classify(RHS->getType());
212 std::optional<PrimType> T = classify(BO->getType());
213 if (!LT || !RT || !T) {
214 return this->bail(BO);
215 }
216
217 auto Discard = [this, T, BO](bool Result) {
218 if (!Result)
219 return false;
220 return DiscardResult ? this->emitPop(*T, BO) : true;
221 };
222
223 // Pointer arithmetic special case.
224 if (BO->getOpcode() == BO_Add || BO->getOpcode() == BO_Sub) {
225 if (*T == PT_Ptr || (*LT == PT_Ptr && *RT == PT_Ptr))
226 return this->VisitPointerArithBinOp(BO);
227 }
228
229 if (!visit(LHS) || !visit(RHS))
230 return false;
231
232 switch (BO->getOpcode()) {
233 case BO_EQ:
234 return Discard(this->emitEQ(*LT, BO));
235 case BO_NE:
236 return Discard(this->emitNE(*LT, BO));
237 case BO_LT:
238 return Discard(this->emitLT(*LT, BO));
239 case BO_LE:
240 return Discard(this->emitLE(*LT, BO));
241 case BO_GT:
242 return Discard(this->emitGT(*LT, BO));
243 case BO_GE:
244 return Discard(this->emitGE(*LT, BO));
245 case BO_Sub:
246 if (BO->getType()->isFloatingType())
247 return Discard(this->emitSubf(getRoundingMode(BO), BO));
248 return Discard(this->emitSub(*T, BO));
249 case BO_Add:
250 if (BO->getType()->isFloatingType())
251 return Discard(this->emitAddf(getRoundingMode(BO), BO));
252 return Discard(this->emitAdd(*T, BO));
253 case BO_Mul:
254 if (BO->getType()->isFloatingType())
255 return Discard(this->emitMulf(getRoundingMode(BO), BO));
256 return Discard(this->emitMul(*T, BO));
257 case BO_Rem:
258 return Discard(this->emitRem(*T, BO));
259 case BO_Div:
260 if (BO->getType()->isFloatingType())
261 return Discard(this->emitDivf(getRoundingMode(BO), BO));
262 return Discard(this->emitDiv(*T, BO));
263 case BO_Assign:
264 if (DiscardResult)
265 return this->emitStorePop(*T, BO);
266 return this->emitStore(*T, BO);
267 case BO_And:
268 return Discard(this->emitBitAnd(*T, BO));
269 case BO_Or:
270 return Discard(this->emitBitOr(*T, BO));
271 case BO_Shl:
272 return Discard(this->emitShl(*LT, *RT, BO));
273 case BO_Shr:
274 return Discard(this->emitShr(*LT, *RT, BO));
275 case BO_Xor:
276 return Discard(this->emitBitXor(*T, BO));
277 case BO_LOr:
278 case BO_LAnd:
279 llvm_unreachable("Already handled earlier");
280 default:
281 return this->bail(BO);
282 }
283
284 llvm_unreachable("Unhandled binary op");
285}
286
287/// Perform addition/subtraction of a pointer and an integer or
288/// subtraction of two pointers.
289template <class Emitter>
292 const Expr *LHS = E->getLHS();
293 const Expr *RHS = E->getRHS();
294
295 if ((Op != BO_Add && Op != BO_Sub) ||
296 (!LHS->getType()->isPointerType() && !RHS->getType()->isPointerType()))
297 return false;
298
299 std::optional<PrimType> LT = classify(LHS);
300 std::optional<PrimType> RT = classify(RHS);
301
302 if (!LT || !RT)
303 return false;
304
305 if (LHS->getType()->isPointerType() && RHS->getType()->isPointerType()) {
306 if (Op != BO_Sub)
307 return false;
308
309 assert(E->getType()->isIntegerType());
310 if (!visit(RHS) || !visit(LHS))
311 return false;
312
313 return this->emitSubPtr(classifyPrim(E->getType()), E);
314 }
315
316 PrimType OffsetType;
317 if (LHS->getType()->isIntegerType()) {
318 if (!visit(RHS) || !visit(LHS))
319 return false;
320 OffsetType = *LT;
321 } else if (RHS->getType()->isIntegerType()) {
322 if (!visit(LHS) || !visit(RHS))
323 return false;
324 OffsetType = *RT;
325 } else {
326 return false;
327 }
328
329 if (Op == BO_Add)
330 return this->emitAddOffset(OffsetType, E);
331 else if (Op == BO_Sub)
332 return this->emitSubOffset(OffsetType, E);
333
334 return this->bail(E);
335}
336
337template <class Emitter>
339 assert(E->isLogicalOp());
341 const Expr *LHS = E->getLHS();
342 const Expr *RHS = E->getRHS();
343
344 if (Op == BO_LOr) {
345 // Logical OR. Visit LHS and only evaluate RHS if LHS was FALSE.
346 LabelTy LabelTrue = this->getLabel();
347 LabelTy LabelEnd = this->getLabel();
348
349 if (!this->visit(LHS))
350 return false;
351 if (!this->jumpTrue(LabelTrue))
352 return false;
353
354 if (!this->visit(RHS))
355 return false;
356 if (!this->jump(LabelEnd))
357 return false;
358
359 this->emitLabel(LabelTrue);
360 this->emitConstBool(true, E);
361 this->fallthrough(LabelEnd);
362 this->emitLabel(LabelEnd);
363
364 if (DiscardResult)
365 return this->emitPopBool(E);
366
367 return true;
368 }
369
370 // Logical AND.
371 // Visit LHS. Only visit RHS if LHS was TRUE.
372 LabelTy LabelFalse = this->getLabel();
373 LabelTy LabelEnd = this->getLabel();
374
375 if (!this->visit(LHS))
376 return false;
377 if (!this->jumpFalse(LabelFalse))
378 return false;
379
380 if (!this->visit(RHS))
381 return false;
382 if (!this->jump(LabelEnd))
383 return false;
384
385 this->emitLabel(LabelFalse);
386 this->emitConstBool(false, E);
387 this->fallthrough(LabelEnd);
388 this->emitLabel(LabelEnd);
389
390 if (DiscardResult)
391 return this->emitPopBool(E);
392
393 return true;
394}
395
396template <class Emitter>
398 std::optional<PrimType> T = classify(E);
399
400 if (!T)
401 return false;
402
403 if (E->getType()->isPointerType())
404 return this->emitNullPtr(E);
405
406 return this->emitZero(*T, E);
407}
408
409template <class Emitter>
411 const ArraySubscriptExpr *E) {
412 const Expr *Base = E->getBase();
413 const Expr *Index = E->getIdx();
414 PrimType IndexT = classifyPrim(Index->getType());
415
416 // Take pointer of LHS, add offset from RHS.
417 // What's left on the stack after this is a pointer.
418 if (!this->visit(Base))
419 return false;
420
421 if (!this->visit(Index))
422 return false;
423
424 if (!this->emitArrayElemPtrPop(IndexT, E))
425 return false;
426
427 if (DiscardResult)
428 return this->emitPopPtr(E);
429
430 return true;
431}
432
433template <class Emitter>
435 for (const Expr *Init : E->inits()) {
436 if (!this->visit(Init))
437 return false;
438 }
439 return true;
440}
441
442template <class Emitter>
445 return this->visit(E->getReplacement());
446}
447
448template <class Emitter>
450 // TODO: Check if the ConstantExpr already has a value set and if so,
451 // use that instead of evaluating it again.
452 return this->visit(E->getSubExpr());
453}
454
455static CharUnits AlignOfType(QualType T, const ASTContext &ASTCtx,
457 bool AlignOfReturnsPreferred =
458 ASTCtx.getLangOpts().getClangABICompat() <= LangOptions::ClangABI::Ver7;
459
460 // C++ [expr.alignof]p3:
461 // When alignof is applied to a reference type, the result is the
462 // alignment of the referenced type.
463 if (const auto *Ref = T->getAs<ReferenceType>())
464 T = Ref->getPointeeType();
465
466 // __alignof is defined to return the preferred alignment.
467 // Before 8, clang returned the preferred alignment for alignof and
468 // _Alignof as well.
469 if (Kind == UETT_PreferredAlignOf || AlignOfReturnsPreferred)
470 return ASTCtx.toCharUnitsFromBits(ASTCtx.getPreferredTypeAlign(T));
471
472 return ASTCtx.getTypeAlignInChars(T);
473}
474
475template <class Emitter>
477 const UnaryExprOrTypeTraitExpr *E) {
478 UnaryExprOrTypeTrait Kind = E->getKind();
479 ASTContext &ASTCtx = Ctx.getASTContext();
480
481 if (Kind == UETT_SizeOf) {
482 QualType ArgType = E->getTypeOfArgument();
483 CharUnits Size;
484 if (ArgType->isVoidType() || ArgType->isFunctionType())
485 Size = CharUnits::One();
486 else {
487 if (ArgType->isDependentType() || !ArgType->isConstantSizeType())
488 return false;
489
490 Size = ASTCtx.getTypeSizeInChars(ArgType);
491 }
492
493 return this->emitConst(Size.getQuantity(), E);
494 }
495
496 if (Kind == UETT_AlignOf || Kind == UETT_PreferredAlignOf) {
497 CharUnits Size;
498
499 if (E->isArgumentType()) {
500 QualType ArgType = E->getTypeOfArgument();
501
502 Size = AlignOfType(ArgType, ASTCtx, Kind);
503 } else {
504 // Argument is an expression, not a type.
505 const Expr *Arg = E->getArgumentExpr()->IgnoreParens();
506
507 // The kinds of expressions that we have special-case logic here for
508 // should be kept up to date with the special checks for those
509 // expressions in Sema.
510
511 // alignof decl is always accepted, even if it doesn't make sense: we
512 // default to 1 in those cases.
513 if (const auto *DRE = dyn_cast<DeclRefExpr>(Arg))
514 Size = ASTCtx.getDeclAlign(DRE->getDecl(),
515 /*RefAsPointee*/ true);
516 else if (const auto *ME = dyn_cast<MemberExpr>(Arg))
517 Size = ASTCtx.getDeclAlign(ME->getMemberDecl(),
518 /*RefAsPointee*/ true);
519 else
520 Size = AlignOfType(Arg->getType(), ASTCtx, Kind);
521 }
522
523 return this->emitConst(Size.getQuantity(), E);
524 }
525
526 return false;
527}
528
529template <class Emitter>
531 if (DiscardResult)
532 return true;
533
534 // 'Base.Member'
535 const Expr *Base = E->getBase();
536 const ValueDecl *Member = E->getMemberDecl();
537
538 if (!this->visit(Base))
539 return false;
540
541 // Base above gives us a pointer on the stack.
542 // TODO: Implement non-FieldDecl members.
543 if (const auto *FD = dyn_cast<FieldDecl>(Member)) {
544 const RecordDecl *RD = FD->getParent();
545 const Record *R = getRecord(RD);
546 const Record::Field *F = R->getField(FD);
547 // Leave a pointer to the field on the stack.
548 if (F->Decl->getType()->isReferenceType())
549 return this->emitGetFieldPop(PT_Ptr, F->Offset, E);
550 return this->emitGetPtrField(F->Offset, E);
551 }
552
553 return false;
554}
555
556template <class Emitter>
558 const ArrayInitIndexExpr *E) {
559 // ArrayIndex might not be set if a ArrayInitIndexExpr is being evaluated
560 // stand-alone, e.g. via EvaluateAsInt().
561 if (!ArrayIndex)
562 return false;
563 return this->emitConst(*ArrayIndex, E);
564}
565
566template <class Emitter>
568 return this->visit(E->getSourceExpr());
569}
570
571template <class Emitter>
574 const Expr *Condition = E->getCond();
575 const Expr *TrueExpr = E->getTrueExpr();
576 const Expr *FalseExpr = E->getFalseExpr();
577
578 LabelTy LabelEnd = this->getLabel(); // Label after the operator.
579 LabelTy LabelFalse = this->getLabel(); // Label for the false expr.
580
581 if (!this->visit(Condition))
582 return false;
583 if (!this->jumpFalse(LabelFalse))
584 return false;
585
586 if (!this->visit(TrueExpr))
587 return false;
588 if (!this->jump(LabelEnd))
589 return false;
590
591 this->emitLabel(LabelFalse);
592
593 if (!this->visit(FalseExpr))
594 return false;
595
596 this->fallthrough(LabelEnd);
597 this->emitLabel(LabelEnd);
598
599 return true;
600}
601
602template <class Emitter>
604 unsigned StringIndex = P.createGlobalString(E);
605 return this->emitGetPtrGlobal(StringIndex, E);
606}
607
608template <class Emitter>
610 const CharacterLiteral *E) {
611 return this->emitConst(E->getValue(), E);
612}
613
614template <class Emitter>
616 const CompoundAssignOperator *E) {
617 assert(E->getType()->isFloatingType());
618
619 const Expr *LHS = E->getLHS();
620 const Expr *RHS = E->getRHS();
621 llvm::RoundingMode RM = getRoundingMode(E);
622 QualType LHSComputationType = E->getComputationLHSType();
623 QualType ResultType = E->getComputationResultType();
624 std::optional<PrimType> LT = classify(LHSComputationType);
625 std::optional<PrimType> RT = classify(ResultType);
626
627 if (!LT || !RT)
628 return false;
629
630 // First, visit LHS.
631 if (!visit(LHS))
632 return false;
633
634 if (!this->emitLoad(*LT, E))
635 return false;
636
637 // If necessary, convert LHS to its computation type.
638 if (LHS->getType() != LHSComputationType) {
639 const auto *TargetSemantics =
640 &Ctx.getASTContext().getFloatTypeSemantics(LHSComputationType);
641
642 if (!this->emitCastFP(TargetSemantics, RM, E))
643 return false;
644 }
645
646 // Now load RHS.
647 if (!visit(RHS))
648 return false;
649
650 switch (E->getOpcode()) {
651 case BO_AddAssign:
652 if (!this->emitAddf(RM, E))
653 return false;
654 break;
655 case BO_SubAssign:
656 if (!this->emitSubf(RM, E))
657 return false;
658 break;
659 case BO_MulAssign:
660 if (!this->emitMulf(RM, E))
661 return false;
662 break;
663 case BO_DivAssign:
664 if (!this->emitDivf(RM, E))
665 return false;
666 break;
667 default:
668 return false;
669 }
670
671 // If necessary, convert result to LHS's type.
672 if (LHS->getType() != ResultType) {
673 const auto *TargetSemantics =
674 &Ctx.getASTContext().getFloatTypeSemantics(LHS->getType());
675
676 if (!this->emitCastFP(TargetSemantics, RM, E))
677 return false;
678 }
679
680 if (DiscardResult)
681 return this->emitStorePop(*LT, E);
682 return this->emitStore(*LT, E);
683}
684
685template <class Emitter>
687 const CompoundAssignOperator *E) {
689 const Expr *LHS = E->getLHS();
690 const Expr *RHS = E->getRHS();
691 std::optional<PrimType> LT = classify(LHS->getType());
692 std::optional<PrimType> RT = classify(RHS->getType());
693
694 if (Op != BO_AddAssign && Op != BO_SubAssign)
695 return false;
696
697 if (!LT || !RT)
698 return false;
699 assert(*LT == PT_Ptr);
700
701 if (!visit(LHS))
702 return false;
703
704 if (!this->emitLoadPtr(LHS))
705 return false;
706
707 if (!visit(RHS))
708 return false;
709
710 if (Op == BO_AddAssign)
711 this->emitAddOffset(*RT, E);
712 else
713 this->emitSubOffset(*RT, E);
714
715 if (DiscardResult)
716 return this->emitStorePopPtr(E);
717 return this->emitStorePtr(E);
718}
719
720template <class Emitter>
722 const CompoundAssignOperator *E) {
723
724 // Handle floating point operations separately here, since they
725 // require special care.
726 if (E->getType()->isFloatingType())
727 return VisitFloatCompoundAssignOperator(E);
728
729 if (E->getType()->isPointerType())
730 return VisitPointerCompoundAssignOperator(E);
731
732 const Expr *LHS = E->getLHS();
733 const Expr *RHS = E->getRHS();
734 std::optional<PrimType> LHSComputationT =
735 classify(E->getComputationLHSType());
736 std::optional<PrimType> LT = classify(LHS->getType());
737 std::optional<PrimType> RT = classify(E->getComputationResultType());
738 std::optional<PrimType> ResultT = classify(E->getType());
739
740 if (!LT || !RT || !ResultT || !LHSComputationT)
741 return false;
742
743 assert(!E->getType()->isPointerType() && "Handled above");
744 assert(!E->getType()->isFloatingType() && "Handled above");
745
746 // Get LHS pointer, load its value and get RHS value.
747 if (!visit(LHS))
748 return false;
749 if (!this->emitLoad(*LT, E))
750 return false;
751 // If necessary, cast LHS to its computation type.
752 if (*LT != *LHSComputationT) {
753 if (!this->emitCast(*LT, *LHSComputationT, E))
754 return false;
755 }
756
757 if (!visit(RHS))
758 return false;
759
760 // Perform operation.
761 switch (E->getOpcode()) {
762 case BO_AddAssign:
763 if (!this->emitAdd(*LHSComputationT, E))
764 return false;
765 break;
766 case BO_SubAssign:
767 if (!this->emitSub(*LHSComputationT, E))
768 return false;
769 break;
770 case BO_MulAssign:
771 if (!this->emitMul(*LHSComputationT, E))
772 return false;
773 break;
774 case BO_DivAssign:
775 if (!this->emitDiv(*LHSComputationT, E))
776 return false;
777 break;
778 case BO_RemAssign:
779 if (!this->emitRem(*LHSComputationT, E))
780 return false;
781 break;
782 case BO_ShlAssign:
783 if (!this->emitShl(*LHSComputationT, *RT, E))
784 return false;
785 break;
786 case BO_ShrAssign:
787 if (!this->emitShr(*LHSComputationT, *RT, E))
788 return false;
789 break;
790 case BO_AndAssign:
791 if (!this->emitBitAnd(*LHSComputationT, E))
792 return false;
793 break;
794 case BO_XorAssign:
795 if (!this->emitBitXor(*LHSComputationT, E))
796 return false;
797 break;
798 case BO_OrAssign:
799 if (!this->emitBitOr(*LHSComputationT, E))
800 return false;
801 break;
802 default:
803 llvm_unreachable("Unimplemented compound assign operator");
804 }
805
806 // And now cast from LHSComputationT to ResultT.
807 if (*ResultT != *LHSComputationT) {
808 if (!this->emitCast(*LHSComputationT, *ResultT, E))
809 return false;
810 }
811
812 // And store the result in LHS.
813 if (DiscardResult)
814 return this->emitStorePop(*ResultT, E);
815 return this->emitStore(*ResultT, E);
816}
817
818template <class Emitter>
820 const ExprWithCleanups *E) {
821 const Expr *SubExpr = E->getSubExpr();
822
823 assert(E->getNumObjects() == 0 && "TODO: Implement cleanups");
824 if (!this->visit(SubExpr))
825 return false;
826
827 if (DiscardResult)
828 return this->emitPopPtr(E);
829 return true;
830}
831
832template <class Emitter>
834 const MaterializeTemporaryExpr *E) {
835 const Expr *SubExpr = E->getSubExpr();
836 std::optional<PrimType> SubExprT = classify(SubExpr);
837
838 if (E->getStorageDuration() == SD_Static) {
839 if (std::optional<unsigned> GlobalIndex = P.createGlobal(E)) {
840 const LifetimeExtendedTemporaryDecl *TempDecl =
842
843 if (!this->visitInitializer(SubExpr))
844 return false;
845
846 if (!this->emitInitGlobalTemp(*SubExprT, *GlobalIndex, TempDecl, E))
847 return false;
848 return this->emitGetPtrGlobal(*GlobalIndex, E);
849 }
850
851 return false;
852 }
853
854 // For everyhing else, use local variables.
855 if (SubExprT) {
856 if (std::optional<unsigned> LocalIndex = allocateLocalPrimitive(
857 SubExpr, *SubExprT, /*IsMutable=*/true, /*IsExtended=*/true)) {
858 if (!this->visitInitializer(SubExpr))
859 return false;
860 this->emitSetLocal(*SubExprT, *LocalIndex, E);
861 return this->emitGetPtrLocal(*LocalIndex, E);
862 }
863 } else {
864 if (std::optional<unsigned> LocalIndex =
865 allocateLocal(SubExpr, /*IsExtended=*/true)) {
866 if (!this->emitGetPtrLocal(*LocalIndex, E))
867 return false;
868 return this->visitInitializer(SubExpr);
869 }
870 }
871 return false;
872}
873
874template <class Emitter>
876 const CompoundLiteralExpr *E) {
877 std::optional<PrimType> T = classify(E->getType());
878 const Expr *Init = E->getInitializer();
879 if (E->isFileScope()) {
880 if (std::optional<unsigned> GlobalIndex = P.createGlobal(E)) {
881 if (classify(E->getType()))
882 return this->visit(Init);
883 if (!this->emitGetPtrGlobal(*GlobalIndex, E))
884 return false;
885 return this->visitInitializer(Init);
886 }
887 }
888
889 // Otherwise, use a local variable.
890 if (T) {
891 // For primitive types, we just visit the initializer.
892 return this->visit(Init);
893 } else {
894 if (std::optional<unsigned> LocalIndex = allocateLocal(Init)) {
895 if (!this->emitGetPtrLocal(*LocalIndex, E))
896 return false;
897 return this->visitInitializer(Init);
898 }
899 }
900
901 return false;
902}
903
904template <class Emitter> bool ByteCodeExprGen<Emitter>::discard(const Expr *E) {
905 if (E->containsErrors())
906 return false;
907
908 OptionScope<Emitter> Scope(this, /*NewDiscardResult=*/true);
909 return this->Visit(E);
910}
911
912template <class Emitter>
914 if (E->containsErrors())
915 return false;
916
917 OptionScope<Emitter> Scope(this, /*NewDiscardResult=*/false);
918 return this->Visit(E);
919}
920
921template <class Emitter>
923 if (std::optional<PrimType> T = classify(E->getType())) {
924 return visit(E);
925 } else {
926 return this->bail(E);
927 }
928}
929
930template <class Emitter>
932 switch (T) {
933 case PT_Bool:
934 return this->emitZeroBool(E);
935 case PT_Sint8:
936 return this->emitZeroSint8(E);
937 case PT_Uint8:
938 return this->emitZeroUint8(E);
939 case PT_Sint16:
940 return this->emitZeroSint16(E);
941 case PT_Uint16:
942 return this->emitZeroUint16(E);
943 case PT_Sint32:
944 return this->emitZeroSint32(E);
945 case PT_Uint32:
946 return this->emitZeroUint32(E);
947 case PT_Sint64:
948 return this->emitZeroSint64(E);
949 case PT_Uint64:
950 return this->emitZeroUint64(E);
951 case PT_Ptr:
952 return this->emitNullPtr(E);
953 case PT_Float:
954 assert(false);
955 }
956 llvm_unreachable("unknown primitive type");
957}
958
959template <class Emitter>
961 const Expr *LV, DerefKind AK, llvm::function_ref<bool(PrimType)> Direct,
962 llvm::function_ref<bool(PrimType)> Indirect) {
963 if (std::optional<PrimType> T = classify(LV->getType())) {
964 if (!LV->refersToBitField()) {
965 // Only primitive, non bit-field types can be dereferenced directly.
966 if (const auto *DE = dyn_cast<DeclRefExpr>(LV)) {
967 if (!DE->getDecl()->getType()->isReferenceType()) {
968 if (const auto *PD = dyn_cast<ParmVarDecl>(DE->getDecl()))
969 return dereferenceParam(LV, *T, PD, AK, Direct, Indirect);
970 if (const auto *VD = dyn_cast<VarDecl>(DE->getDecl()))
971 return dereferenceVar(LV, *T, VD, AK, Direct, Indirect);
972 }
973 }
974 }
975
976 if (!visit(LV))
977 return false;
978 return Indirect(*T);
979 }
980
981 return false;
982}
983
984template <class Emitter>
986 const Expr *LV, PrimType T, const ParmVarDecl *PD, DerefKind AK,
987 llvm::function_ref<bool(PrimType)> Direct,
988 llvm::function_ref<bool(PrimType)> Indirect) {
989 auto It = this->Params.find(PD);
990 if (It != this->Params.end()) {
991 unsigned Idx = It->second;
992 switch (AK) {
993 case DerefKind::Read:
994 return DiscardResult ? true : this->emitGetParam(T, Idx, LV);
995
996 case DerefKind::Write:
997 if (!Direct(T))
998 return false;
999 if (!this->emitSetParam(T, Idx, LV))
1000 return false;
1001 return DiscardResult ? true : this->emitGetPtrParam(Idx, LV);
1002
1003 case DerefKind::ReadWrite:
1004 if (!this->emitGetParam(T, Idx, LV))
1005 return false;
1006 if (!Direct(T))
1007 return false;
1008 if (!this->emitSetParam(T, Idx, LV))
1009 return false;
1010 return DiscardResult ? true : this->emitGetPtrParam(Idx, LV);
1011 }
1012 return true;
1013 }
1014
1015 // If the param is a pointer, we can dereference a dummy value.
1016 if (!DiscardResult && T == PT_Ptr && AK == DerefKind::Read) {
1017 if (auto Idx = P.getOrCreateDummy(PD))
1018 return this->emitGetPtrGlobal(*Idx, PD);
1019 return false;
1020 }
1021
1022 // Value cannot be produced - try to emit pointer and do stuff with it.
1023 return visit(LV) && Indirect(T);
1024}
1025
1026template <class Emitter>
1028 const Expr *LV, PrimType T, const VarDecl *VD, DerefKind AK,
1029 llvm::function_ref<bool(PrimType)> Direct,
1030 llvm::function_ref<bool(PrimType)> Indirect) {
1031 auto It = Locals.find(VD);
1032 if (It != Locals.end()) {
1033 const auto &L = It->second;
1034 switch (AK) {
1035 case DerefKind::Read:
1036 if (!this->emitGetLocal(T, L.Offset, LV))
1037 return false;
1038 return DiscardResult ? this->emitPop(T, LV) : true;
1039
1040 case DerefKind::Write:
1041 if (!Direct(T))
1042 return false;
1043 if (!this->emitSetLocal(T, L.Offset, LV))
1044 return false;
1045 return DiscardResult ? true : this->emitGetPtrLocal(L.Offset, LV);
1046
1047 case DerefKind::ReadWrite:
1048 if (!this->emitGetLocal(T, L.Offset, LV))
1049 return false;
1050 if (!Direct(T))
1051 return false;
1052 if (!this->emitSetLocal(T, L.Offset, LV))
1053 return false;
1054 return DiscardResult ? true : this->emitGetPtrLocal(L.Offset, LV);
1055 }
1056 } else if (auto Idx = P.getGlobal(VD)) {
1057 switch (AK) {
1058 case DerefKind::Read:
1059 if (!this->emitGetGlobal(T, *Idx, LV))
1060 return false;
1061 return DiscardResult ? this->emitPop(T, LV) : true;
1062
1063 case DerefKind::Write:
1064 if (!Direct(T))
1065 return false;
1066 if (!this->emitSetGlobal(T, *Idx, LV))
1067 return false;
1068 return DiscardResult ? true : this->emitGetPtrGlobal(*Idx, LV);
1069
1070 case DerefKind::ReadWrite:
1071 if (!this->emitGetGlobal(T, *Idx, LV))
1072 return false;
1073 if (!Direct(T))
1074 return false;
1075 if (!this->emitSetGlobal(T, *Idx, LV))
1076 return false;
1077 return DiscardResult ? true : this->emitGetPtrGlobal(*Idx, LV);
1078 }
1079 }
1080
1081 // If the declaration is a constant value, emit it here even
1082 // though the declaration was not evaluated in the current scope.
1083 // The access mode can only be read in this case.
1084 if (!DiscardResult && AK == DerefKind::Read) {
1085 if (VD->hasLocalStorage() && VD->hasInit() && !VD->isConstexpr()) {
1086 QualType VT = VD->getType();
1087 if (VT.isConstQualified() && VT->isFundamentalType())
1088 return this->visit(VD->getInit());
1089 }
1090 }
1091
1092 // Value cannot be produced - try to emit pointer.
1093 return visit(LV) && Indirect(T);
1094}
1095
1096template <class Emitter>
1097template <typename T>
1099 switch (classifyPrim(E->getType())) {
1100 case PT_Sint8:
1101 return this->emitConstSint8(Value, E);
1102 case PT_Uint8:
1103 return this->emitConstUint8(Value, E);
1104 case PT_Sint16:
1105 return this->emitConstSint16(Value, E);
1106 case PT_Uint16:
1107 return this->emitConstUint16(Value, E);
1108 case PT_Sint32:
1109 return this->emitConstSint32(Value, E);
1110 case PT_Uint32:
1111 return this->emitConstUint32(Value, E);
1112 case PT_Sint64:
1113 return this->emitConstSint64(Value, E);
1114 case PT_Uint64:
1115 return this->emitConstUint64(Value, E);
1116 case PT_Bool:
1117 return this->emitConstBool(Value, E);
1118 case PT_Ptr:
1119 case PT_Float:
1120 llvm_unreachable("Invalid integral type");
1121 break;
1122 }
1123 llvm_unreachable("unknown primitive type");
1124}
1125
1126template <class Emitter>
1128 if (Value.isSigned())
1129 return this->emitConst(Value.getSExtValue(), E);
1130 return this->emitConst(Value.getZExtValue(), E);
1131}
1132
1133template <class Emitter>
1135 PrimType Ty,
1136 bool IsConst,
1137 bool IsExtended) {
1138 // Make sure we don't accidentally register the same decl twice.
1139 if (const auto *VD =
1140 dyn_cast_if_present<ValueDecl>(Src.dyn_cast<const Decl *>())) {
1141 assert(!P.getGlobal(VD));
1142 assert(!Locals.contains(VD));
1143 }
1144
1145 // FIXME: There are cases where Src.is<Expr*>() is wrong, e.g.
1146 // (int){12} in C. Consider using Expr::isTemporaryObject() instead
1147 // or isa<MaterializeTemporaryExpr>().
1148 Descriptor *D = P.createDescriptor(Src, Ty, Descriptor::InlineDescMD, IsConst,
1149 Src.is<const Expr *>());
1150 Scope::Local Local = this->createLocal(D);
1151 if (auto *VD = dyn_cast_if_present<ValueDecl>(Src.dyn_cast<const Decl *>()))
1152 Locals.insert({VD, Local});
1153 VarScope->add(Local, IsExtended);
1154 return Local.Offset;
1155}
1156
1157template <class Emitter>
1158std::optional<unsigned>
1160 // Make sure we don't accidentally register the same decl twice.
1161 if (const auto *VD =
1162 dyn_cast_if_present<ValueDecl>(Src.dyn_cast<const Decl *>())) {
1163 assert(!P.getGlobal(VD));
1164 assert(!Locals.contains(VD));
1165 }
1166
1167 QualType Ty;
1168 const ValueDecl *Key = nullptr;
1169 const Expr *Init = nullptr;
1170 bool IsTemporary = false;
1171 if (auto *VD = dyn_cast_if_present<ValueDecl>(Src.dyn_cast<const Decl *>())) {
1172 Key = VD;
1173 Ty = VD->getType();
1174
1175 if (const auto *VarD = dyn_cast<VarDecl>(VD))
1176 Init = VarD->getInit();
1177 }
1178 if (auto *E = Src.dyn_cast<const Expr *>()) {
1179 IsTemporary = true;
1180 Ty = E->getType();
1181 }
1182
1183 Descriptor *D = P.createDescriptor(
1185 IsTemporary, /*IsMutable=*/false, Init);
1186 if (!D)
1187 return {};
1188
1189 Scope::Local Local = this->createLocal(D);
1190 if (Key)
1191 Locals.insert({Key, Local});
1192 VarScope->add(Local, IsExtended);
1193 return Local.Offset;
1194}
1195
1196// NB: When calling this function, we have a pointer to the
1197// array-to-initialize on the stack.
1198template <class Emitter>
1200 assert(Initializer->getType()->isArrayType());
1201
1202 // TODO: Fillers?
1203 if (const auto *InitList = dyn_cast<InitListExpr>(Initializer)) {
1204 unsigned ElementIndex = 0;
1205 for (const Expr *Init : InitList->inits()) {
1206 if (std::optional<PrimType> T = classify(Init->getType())) {
1207 // Visit the primitive element like normal.
1208 if (!this->visit(Init))
1209 return false;
1210 if (!this->emitInitElem(*T, ElementIndex, Init))
1211 return false;
1212 } else {
1213 // Advance the pointer currently on the stack to the given
1214 // dimension.
1215 if (!this->emitConstUint32(ElementIndex, Init))
1216 return false;
1217 if (!this->emitArrayElemPtrUint32(Init))
1218 return false;
1219 if (!visitInitializer(Init))
1220 return false;
1221 if (!this->emitPopPtr(Init))
1222 return false;
1223 }
1224
1225 ++ElementIndex;
1226 }
1227 return true;
1228 } else if (const auto *DIE = dyn_cast<CXXDefaultInitExpr>(Initializer)) {
1229 return this->visitInitializer(DIE->getExpr());
1230 } else if (const auto *AILE = dyn_cast<ArrayInitLoopExpr>(Initializer)) {
1231 // TODO: This compiles to quite a lot of bytecode if the array is larger.
1232 // Investigate compiling this to a loop, or at least try to use
1233 // the AILE's Common expr.
1234 const Expr *SubExpr = AILE->getSubExpr();
1235 size_t Size = AILE->getArraySize().getZExtValue();
1236 std::optional<PrimType> ElemT = classify(SubExpr->getType());
1237
1238 // So, every iteration, we execute an assignment here
1239 // where the LHS is on the stack (the target array)
1240 // and the RHS is our SubExpr.
1241 for (size_t I = 0; I != Size; ++I) {
1242 ArrayIndexScope<Emitter> IndexScope(this, I);
1243
1244 if (ElemT) {
1245 if (!this->visit(SubExpr))
1246 return false;
1247 if (!this->emitInitElem(*ElemT, I, Initializer))
1248 return false;
1249 } else {
1250 // Get to our array element and recurse into visitInitializer()
1251 if (!this->emitConstUint64(I, SubExpr))
1252 return false;
1253 if (!this->emitArrayElemPtrUint64(SubExpr))
1254 return false;
1255 if (!visitInitializer(SubExpr))
1256 return false;
1257 if (!this->emitPopPtr(Initializer))
1258 return false;
1259 }
1260 }
1261 return true;
1262 } else if (const auto *IVIE = dyn_cast<ImplicitValueInitExpr>(Initializer)) {
1263 const ArrayType *AT = IVIE->getType()->getAsArrayTypeUnsafe();
1264 assert(AT);
1265 const auto *CAT = cast<ConstantArrayType>(AT);
1266 size_t NumElems = CAT->getSize().getZExtValue();
1267
1268 if (std::optional<PrimType> ElemT = classify(CAT->getElementType())) {
1269 // TODO(perf): For int and bool types, we can probably just skip this
1270 // since we memset our Block*s to 0 and so we have the desired value
1271 // without this.
1272 for (size_t I = 0; I != NumElems; ++I) {
1273 if (!this->emitZero(*ElemT, Initializer))
1274 return false;
1275 if (!this->emitInitElem(*ElemT, I, Initializer))
1276 return false;
1277 }
1278 } else {
1279 assert(false && "default initializer for non-primitive type");
1280 }
1281
1282 return true;
1283 } else if (const auto *Ctor = dyn_cast<CXXConstructExpr>(Initializer)) {
1284 const ConstantArrayType *CAT =
1285 Ctx.getASTContext().getAsConstantArrayType(Ctor->getType());
1286 assert(CAT);
1287 size_t NumElems = CAT->getSize().getZExtValue();
1288 const Function *Func = getFunction(Ctor->getConstructor());
1289 if (!Func || !Func->isConstexpr())
1290 return false;
1291
1292 // FIXME(perf): We're calling the constructor once per array element here,
1293 // in the old intepreter we had a special-case for trivial constructors.
1294 for (size_t I = 0; I != NumElems; ++I) {
1295 if (!this->emitConstUint64(I, Initializer))
1296 return false;
1297 if (!this->emitArrayElemPtrUint64(Initializer))
1298 return false;
1299
1300 // Constructor arguments.
1301 for (const auto *Arg : Ctor->arguments()) {
1302 if (!this->visit(Arg))
1303 return false;
1304 }
1305
1306 if (!this->emitCall(Func, Initializer))
1307 return false;
1308 }
1309 return true;
1310 } else if (const auto *SL = dyn_cast<StringLiteral>(Initializer)) {
1311 const ConstantArrayType *CAT =
1312 Ctx.getASTContext().getAsConstantArrayType(SL->getType());
1313 assert(CAT && "a string literal that's not a constant array?");
1314
1315 // If the initializer string is too long, a diagnostic has already been
1316 // emitted. Read only the array length from the string literal.
1317 unsigned N =
1318 std::min(unsigned(CAT->getSize().getZExtValue()), SL->getLength());
1319 size_t CharWidth = SL->getCharByteWidth();
1320
1321 for (unsigned I = 0; I != N; ++I) {
1322 uint32_t CodeUnit = SL->getCodeUnit(I);
1323
1324 if (CharWidth == 1) {
1325 this->emitConstSint8(CodeUnit, SL);
1326 this->emitInitElemSint8(I, SL);
1327 } else if (CharWidth == 2) {
1328 this->emitConstUint16(CodeUnit, SL);
1329 this->emitInitElemUint16(I, SL);
1330 } else if (CharWidth == 4) {
1331 this->emitConstUint32(CodeUnit, SL);
1332 this->emitInitElemUint32(I, SL);
1333 } else {
1334 llvm_unreachable("unsupported character width");
1335 }
1336 }
1337 return true;
1338 } else if (const auto *CLE = dyn_cast<CompoundLiteralExpr>(Initializer)) {
1339 return visitInitializer(CLE->getInitializer());
1340 } else if (const auto *EWC = dyn_cast<ExprWithCleanups>(Initializer)) {
1341 return visitInitializer(EWC->getSubExpr());
1342 }
1343
1344 assert(false && "Unknown expression for array initialization");
1345 return false;
1346}
1347
1348template <class Emitter>
1350 Initializer = Initializer->IgnoreParenImpCasts();
1351 assert(Initializer->getType()->isRecordType());
1352
1353 if (const auto CtorExpr = dyn_cast<CXXConstructExpr>(Initializer)) {
1354 const Function *Func = getFunction(CtorExpr->getConstructor());
1355
1356 if (!Func || !Func->isConstexpr())
1357 return false;
1358
1359 // The This pointer is already on the stack because this is an initializer,
1360 // but we need to dup() so the call() below has its own copy.
1361 if (!this->emitDupPtr(Initializer))
1362 return false;
1363
1364 // Constructor arguments.
1365 for (const auto *Arg : CtorExpr->arguments()) {
1366 if (!this->visit(Arg))
1367 return false;
1368 }
1369
1370 return this->emitCall(Func, Initializer);
1371 } else if (const auto *InitList = dyn_cast<InitListExpr>(Initializer)) {
1372 const Record *R = getRecord(InitList->getType());
1373
1374 unsigned InitIndex = 0;
1375 for (const Expr *Init : InitList->inits()) {
1376 const Record::Field *FieldToInit = R->getField(InitIndex);
1377
1378 if (!this->emitDupPtr(Initializer))
1379 return false;
1380
1381 if (std::optional<PrimType> T = classify(Init)) {
1382 if (!this->visit(Init))
1383 return false;
1384
1385 if (!this->emitInitField(*T, FieldToInit->Offset, Initializer))
1386 return false;
1387
1388 if (!this->emitPopPtr(Initializer))
1389 return false;
1390 } else {
1391 // Non-primitive case. Get a pointer to the field-to-initialize
1392 // on the stack and recurse into visitInitializer().
1393 if (!this->emitGetPtrField(FieldToInit->Offset, Init))
1394 return false;
1395
1396 if (!this->visitInitializer(Init))
1397 return false;
1398
1399 if (!this->emitPopPtr(Initializer))
1400 return false;
1401 }
1402 ++InitIndex;
1403 }
1404
1405 return true;
1406 } else if (const CallExpr *CE = dyn_cast<CallExpr>(Initializer)) {
1407 // RVO functions expect a pointer to initialize on the stack.
1408 // Dup our existing pointer so it has its own copy to use.
1409 if (!this->emitDupPtr(Initializer))
1410 return false;
1411
1412 return this->VisitCallExpr(CE);
1413 } else if (const auto *DIE = dyn_cast<CXXDefaultInitExpr>(Initializer)) {
1414 return this->visitInitializer(DIE->getExpr());
1415 } else if (const auto *CE = dyn_cast<CastExpr>(Initializer)) {
1416 return this->visitInitializer(CE->getSubExpr());
1417 } else if (const auto *CE = dyn_cast<CXXBindTemporaryExpr>(Initializer)) {
1418 return this->visitInitializer(CE->getSubExpr());
1419 }
1420
1421 return false;
1422}
1423
1424template <class Emitter>
1426 QualType InitializerType = Initializer->getType();
1427
1428 if (InitializerType->isArrayType())
1429 return visitArrayInitializer(Initializer);
1430
1431 if (InitializerType->isRecordType())
1432 return visitRecordInitializer(Initializer);
1433
1434 // Otherwise, visit the expression like normal.
1435 return this->visit(Initializer);
1436}
1437
1438template <class Emitter>
1440 if (const PointerType *PT = dyn_cast<PointerType>(Ty))
1441 return PT->getPointeeType()->getAs<RecordType>();
1442 else
1443 return Ty->getAs<RecordType>();
1444}
1445
1446template <class Emitter>
1448 if (auto *RecordTy = getRecordTy(Ty)) {
1449 return getRecord(RecordTy->getDecl());
1450 }
1451 return nullptr;
1452}
1453
1454template <class Emitter>
1456 return P.getOrCreateRecord(RD);
1457}
1458
1459template <class Emitter>
1461 assert(FD);
1462 const Function *Func = P.getFunction(FD);
1463 bool IsBeingCompiled = Func && !Func->isFullyCompiled();
1464 bool WasNotDefined = Func && !Func->hasBody();
1465
1466 if (IsBeingCompiled)
1467 return Func;
1468
1469 if (!Func || WasNotDefined) {
1470 if (auto R = ByteCodeStmtGen<ByteCodeEmitter>(Ctx, P).compileFunc(FD))
1471 Func = *R;
1472 else {
1473 llvm::consumeError(R.takeError());
1474 return nullptr;
1475 }
1476 }
1477
1478 return Func;
1479}
1480
1481template <class Emitter>
1483 ExprScope<Emitter> RootScope(this);
1484 if (!visit(Exp))
1485 return false;
1486
1487 if (std::optional<PrimType> T = classify(Exp))
1488 return this->emitRet(*T, Exp);
1489 else
1490 return this->emitRetValue(Exp);
1491}
1492
1493/// Toplevel visitDecl().
1494/// We get here from evaluateAsInitializer().
1495/// We need to evaluate the initializer and return its value.
1496template <class Emitter>
1498 assert(!VD->isInvalidDecl() && "Trying to constant evaluate an invalid decl");
1499 std::optional<PrimType> VarT = classify(VD->getType());
1500
1501 // Create and initialize the variable.
1502 if (!this->visitVarDecl(VD))
1503 return false;
1504
1505 // Get a pointer to the variable
1506 if (shouldBeGloballyIndexed(VD)) {
1507 auto GlobalIndex = P.getGlobal(VD);
1508 assert(GlobalIndex); // visitVarDecl() didn't return false.
1509 if (!this->emitGetPtrGlobal(*GlobalIndex, VD))
1510 return false;
1511 } else {
1512 auto Local = Locals.find(VD);
1513 assert(Local != Locals.end()); // Same here.
1514 if (!this->emitGetPtrLocal(Local->second.Offset, VD))
1515 return false;
1516 }
1517
1518 // Return the value
1519 if (VarT) {
1520 if (!this->emitLoadPop(*VarT, VD))
1521 return false;
1522
1523 return this->emitRet(*VarT, VD);
1524 }
1525
1526 return this->emitRetValue(VD);
1527}
1528
1529template <class Emitter>
1531 // We don't know what to do with these, so just return false.
1532 if (VD->getType().isNull())
1533 return false;
1534
1535 const Expr *Init = VD->getInit();
1536 std::optional<PrimType> VarT = classify(VD->getType());
1537
1538 if (shouldBeGloballyIndexed(VD)) {
1539 std::optional<unsigned> GlobalIndex = P.getOrCreateGlobal(VD, Init);
1540
1541 if (!GlobalIndex)
1542 return this->bail(VD);
1543
1544 assert(Init);
1545 {
1547
1548 if (VarT) {
1549 if (!this->visit(Init))
1550 return false;
1551 return this->emitInitGlobal(*VarT, *GlobalIndex, VD);
1552 }
1553 return this->visitGlobalInitializer(Init, *GlobalIndex);
1554 }
1555 } else {
1557 if (VarT) {
1558 unsigned Offset = this->allocateLocalPrimitive(
1559 VD, *VarT, VD->getType().isConstQualified());
1560 if (Init) {
1561 // Compile the initializer in its own scope.
1563 if (!this->visit(Init))
1564 return false;
1565
1566 return this->emitSetLocal(*VarT, Offset, VD);
1567 }
1568 } else {
1569 if (std::optional<unsigned> Offset = this->allocateLocal(VD)) {
1570 if (Init)
1571 return this->visitLocalInitializer(Init, *Offset);
1572 }
1573 }
1574 return true;
1575 }
1576
1577 return false;
1578}
1579
1580template <class Emitter>
1582 const Function *Func = getFunction(E->getDirectCallee());
1583 if (!Func)
1584 return false;
1585
1586 // Put arguments on the stack.
1587 for (const auto *Arg : E->arguments()) {
1588 if (!this->visit(Arg))
1589 return false;
1590 }
1591
1592 if (!this->emitCallBI(Func, E))
1593 return false;
1594
1595 QualType ReturnType = E->getCallReturnType(Ctx.getASTContext());
1596 if (DiscardResult && !ReturnType->isVoidType()) {
1597 PrimType T = classifyPrim(ReturnType);
1598 return this->emitPop(T, E);
1599 }
1600
1601 return true;
1602}
1603
1604template <class Emitter>
1606 if (E->getBuiltinCallee())
1607 return VisitBuiltinCallExpr(E);
1608
1609 const Decl *Callee = E->getCalleeDecl();
1610 if (const auto *FuncDecl = dyn_cast_if_present<FunctionDecl>(Callee)) {
1611 const Function *Func = getFunction(FuncDecl);
1612 if (!Func)
1613 return false;
1614 // If the function is being compiled right now, this is a recursive call.
1615 // In that case, the function can't be valid yet, even though it will be
1616 // later.
1617 // If the function is already fully compiled but not constexpr, it was
1618 // found to be faulty earlier on, so bail out.
1619 if (Func->isFullyCompiled() && !Func->isConstexpr())
1620 return false;
1621
1622 QualType ReturnType = E->getCallReturnType(Ctx.getASTContext());
1623 std::optional<PrimType> T = classify(ReturnType);
1624
1625 if (Func->hasRVO() && DiscardResult) {
1626 // If we need to discard the return value but the function returns its
1627 // value via an RVO pointer, we need to create one such pointer just
1628 // for this call.
1629 if (std::optional<unsigned> LocalIndex = allocateLocal(E)) {
1630 if (!this->emitGetPtrLocal(*LocalIndex, E))
1631 return false;
1632 }
1633 }
1634
1635 // Put arguments on the stack.
1636 for (const auto *Arg : E->arguments()) {
1637 if (!this->visit(Arg))
1638 return false;
1639 }
1640
1641 // In any case call the function. The return value will end up on the stack
1642 // and if the function has RVO, we already have the pointer on the stack to
1643 // write the result into.
1644 if (!this->emitCall(Func, E))
1645 return false;
1646
1647 if (DiscardResult && !ReturnType->isVoidType() && T)
1648 return this->emitPop(*T, E);
1649
1650 return true;
1651 } else {
1652 assert(false && "We don't support non-FunctionDecl callees right now.");
1653 }
1654
1655 return false;
1656}
1657
1658template <class Emitter>
1660 const CXXMemberCallExpr *E) {
1661 // Get a This pointer on the stack.
1662 if (!this->visit(E->getImplicitObjectArgument()))
1663 return false;
1664
1665 return VisitCallExpr(E);
1666}
1667
1668template <class Emitter>
1670 const CXXDefaultInitExpr *E) {
1671 return this->visit(E->getExpr());
1672}
1673
1674template <class Emitter>
1676 const CXXDefaultArgExpr *E) {
1677 return this->visit(E->getExpr());
1678}
1679
1680template <class Emitter>
1682 const CXXBoolLiteralExpr *E) {
1683 if (DiscardResult)
1684 return true;
1685
1686 return this->emitConstBool(E->getValue(), E);
1687}
1688
1689template <class Emitter>
1691 const CXXNullPtrLiteralExpr *E) {
1692 if (DiscardResult)
1693 return true;
1694
1695 return this->emitNullPtr(E);
1696}
1697
1698template <class Emitter>
1700 if (DiscardResult)
1701 return true;
1702 return this->emitThis(E);
1703}
1704
1705template <class Emitter>
1707 const Expr *SubExpr = E->getSubExpr();
1708 std::optional<PrimType> T = classify(SubExpr->getType());
1709
1710 switch (E->getOpcode()) {
1711 case UO_PostInc: { // x++
1712 if (!this->visit(SubExpr))
1713 return false;
1714
1715 if (T == PT_Ptr) {
1716 if (!this->emitIncPtr(E))
1717 return false;
1718
1719 return DiscardResult ? this->emitPopPtr(E) : true;
1720 }
1721
1722 return DiscardResult ? this->emitIncPop(*T, E) : this->emitInc(*T, E);
1723 }
1724 case UO_PostDec: { // x--
1725 if (!this->visit(SubExpr))
1726 return false;
1727
1728 if (T == PT_Ptr) {
1729 if (!this->emitDecPtr(E))
1730 return false;
1731
1732 return DiscardResult ? this->emitPopPtr(E) : true;
1733 }
1734
1735 return DiscardResult ? this->emitDecPop(*T, E) : this->emitDec(*T, E);
1736 }
1737 case UO_PreInc: { // ++x
1738 if (!this->visit(SubExpr))
1739 return false;
1740
1741 if (T == PT_Ptr) {
1742 this->emitLoadPtr(E);
1743 this->emitConstUint8(1, E);
1744 this->emitAddOffsetUint8(E);
1745 return DiscardResult ? this->emitStorePopPtr(E) : this->emitStorePtr(E);
1746 }
1747
1748 // Post-inc and pre-inc are the same if the value is to be discarded.
1749 if (DiscardResult)
1750 return this->emitIncPop(*T, E);
1751
1752 this->emitLoad(*T, E);
1753 this->emitConst(1, E);
1754 this->emitAdd(*T, E);
1755 return this->emitStore(*T, E);
1756 }
1757 case UO_PreDec: { // --x
1758 if (!this->visit(SubExpr))
1759 return false;
1760
1761 if (T == PT_Ptr) {
1762 this->emitLoadPtr(E);
1763 this->emitConstUint8(1, E);
1764 this->emitSubOffsetUint8(E);
1765 return DiscardResult ? this->emitStorePopPtr(E) : this->emitStorePtr(E);
1766 }
1767
1768 // Post-dec and pre-dec are the same if the value is to be discarded.
1769 if (DiscardResult)
1770 return this->emitDecPop(*T, E);
1771
1772 this->emitLoad(*T, E);
1773 this->emitConst(1, E);
1774 this->emitSub(*T, E);
1775 return this->emitStore(*T, E);
1776 }
1777 case UO_LNot: // !x
1778 if (!this->visit(SubExpr))
1779 return false;
1780 // The Inv doesn't change anything, so skip it if we don't need the result.
1781 return DiscardResult ? this->emitPop(*T, E) : this->emitInvBool(E);
1782 case UO_Minus: // -x
1783 if (!this->visit(SubExpr))
1784 return false;
1785 return DiscardResult ? this->emitPop(*T, E) : this->emitNeg(*T, E);
1786 case UO_Plus: // +x
1787 if (!this->visit(SubExpr)) // noop
1788 return false;
1789 return DiscardResult ? this->emitPop(*T, E) : true;
1790 case UO_AddrOf: // &x
1791 // We should already have a pointer when we get here.
1792 if (!this->visit(SubExpr))
1793 return false;
1794 return DiscardResult ? this->emitPop(*T, E) : true;
1795 case UO_Deref: // *x
1796 return dereference(
1797 SubExpr, DerefKind::Read,
1798 [](PrimType) {
1799 llvm_unreachable("Dereferencing requires a pointer");
1800 return false;
1801 },
1802 [this, E](PrimType T) {
1803 return DiscardResult ? this->emitPop(T, E) : true;
1804 });
1805 case UO_Not: // ~x
1806 if (!this->visit(SubExpr))
1807 return false;
1808 return DiscardResult ? this->emitPop(*T, E) : this->emitComp(*T, E);
1809 case UO_Real: // __real x
1810 case UO_Imag: // __imag x
1811 case UO_Extension:
1812 case UO_Coawait:
1813 assert(false && "Unhandled opcode");
1814 }
1815
1816 return false;
1817}
1818
1819template <class Emitter>
1821 const auto *Decl = E->getDecl();
1822 // References are implemented via pointers, so when we see a DeclRefExpr
1823 // pointing to a reference, we need to get its value directly (i.e. the
1824 // pointer to the actual value) instead of a pointer to the pointer to the
1825 // value.
1826 bool IsReference = Decl->getType()->isReferenceType();
1827
1828 if (auto It = Locals.find(Decl); It != Locals.end()) {
1829 const unsigned Offset = It->second.Offset;
1830
1831 if (IsReference)
1832 return this->emitGetLocal(PT_Ptr, Offset, E);
1833 return this->emitGetPtrLocal(Offset, E);
1834 } else if (auto GlobalIndex = P.getGlobal(Decl)) {
1835 if (IsReference)
1836 return this->emitGetGlobal(PT_Ptr, *GlobalIndex, E);
1837
1838 return this->emitGetPtrGlobal(*GlobalIndex, E);
1839 } else if (const auto *PVD = dyn_cast<ParmVarDecl>(Decl)) {
1840 if (auto It = this->Params.find(PVD); It != this->Params.end()) {
1841 if (IsReference)
1842 return this->emitGetParam(PT_Ptr, It->second, E);
1843 return this->emitGetPtrParam(It->second, E);
1844 }
1845 } else if (const auto *ECD = dyn_cast<EnumConstantDecl>(Decl)) {
1846 return this->emitConst(ECD->getInitVal(), E);
1847 } else if (const auto *BD = dyn_cast<BindingDecl>(Decl)) {
1848 return this->visit(BD->getBinding());
1849 }
1850
1851 return false;
1852}
1853
1854template <class Emitter>
1856 for (VariableScope<Emitter> *C = VarScope; C; C = C->getParent())
1857 C->emitDestruction();
1858}
1859
1860namespace clang {
1861namespace interp {
1862
1864template class ByteCodeExprGen<EvalEmitter>;
1865
1866} // namespace interp
1867} // namespace clang
ASTImporterLookupTable & LT
StringRef P
llvm::APSInt APSInt
static CharUnits AlignOfType(QualType T, const ASTContext &ASTCtx, UnaryExprOrTypeTrait Kind)
unsigned Offset
Definition: Format.cpp:2776
const NamedDecl * FromDecl
static std::optional< DereferenceInfo > dereference(ProgramStateRef State, const FieldRegion *FR)
Dereferences FR and returns with the pointee's region, and whether it needs to be casted back to it's...
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:182
CharUnits getTypeAlignInChars(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in characters.
unsigned getPreferredTypeAlign(QualType T) const
Return the "preferred" alignment of the specified type T for the current target, in bits.
Definition: ASTContext.h:2370
const LangOptions & getLangOpts() const
Definition: ASTContext.h:762
CharUnits getDeclAlign(const Decl *D, bool ForAlignof=false) const
Return a conservative estimate of the alignment of the specified decl D.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
AbstractConditionalOperator - An abstract base class for ConditionalOperator and BinaryConditionalOpe...
Definition: Expr.h:4114
Represents the index of the current element of an array being initialized by an ArrayInitLoopExpr.
Definition: Expr.h:5481
ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
Definition: Expr.h:2656
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Definition: Type.h:3031
A builtin binary operation expression such as "x + y" or "x <= y".
Definition: Expr.h:3814
static bool isLogicalOp(Opcode Opc)
Definition: Expr.h:3946
Expr * getLHS() const
Definition: Expr.h:3863
Expr * getRHS() const
Definition: Expr.h:3865
Opcode getOpcode() const
Definition: Expr.h:3858
A boolean literal, per ([C++ lex.bool] Boolean literals).
Definition: ExprCXX.h:720
bool getValue() const
Definition: ExprCXX.h:737
A default argument (C++ [dcl.fct.default]).
Definition: ExprCXX.h:1249
A use of a default initializer in a constructor or in aggregate initialization.
Definition: ExprCXX.h:1356
Expr * getExpr()
Get the initialization expression that will be used.
Definition: ExprCXX.cpp:1026
Represents a call to a member function that may be written either with member call syntax (e....
Definition: ExprCXX.h:176
Expr * getImplicitObjectArgument() const
Retrieve the implicit object argument for the member call.
Definition: ExprCXX.cpp:651
The null pointer literal (C++11 [lex.nullptr])
Definition: ExprCXX.h:765
Represents a C++ struct/union/class.
Definition: DeclCXX.h:254
Represents the this expression in C++.
Definition: ExprCXX.h:1148
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition: Expr.h:2812
unsigned getBuiltinCallee() const
getBuiltinCallee - If this is a call to a builtin, return the builtin ID of the callee.
Definition: Expr.cpp:1565
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
Definition: Expr.h:2982
arg_range arguments()
Definition: Expr.h:3051
Decl * getCalleeDecl()
Definition: Expr.h:2976
QualType getCallReturnType(const ASTContext &Ctx) const
getCallReturnType - Get the return type of the call expr.
Definition: Expr.cpp:1576
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
Definition: Expr.h:3482
CastKind getCastKind() const
Definition: Expr.h:3526
Expr * getSubExpr()
Definition: Expr.h:3532
CharUnits - This is an opaque type for sizes expressed in character units.
Definition: CharUnits.h:38
static CharUnits One()
One - Construct a CharUnits quantity of one.
Definition: CharUnits.h:58
unsigned getValue() const
Definition: Expr.h:1629
CompoundAssignOperator - For compound assignments (e.g.
Definition: Expr.h:4061
QualType getComputationLHSType() const
Definition: Expr.h:4095
QualType getComputationResultType() const
Definition: Expr.h:4098
CompoundLiteralExpr - [C99 6.5.2.5].
Definition: Expr.h:3412
bool isFileScope() const
Definition: Expr.h:3439
const Expr * getInitializer() const
Definition: Expr.h:3435
Represents the canonical version of C arrays with a specified constant size.
Definition: Type.h:3079
const llvm::APInt & getSize() const
Definition: Type.h:3100
ConstantExpr - An expression that occurs in a constant context and optionally the result of evaluatin...
Definition: Expr.h:1045
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Definition: DeclBase.h:1933
A reference to a declared variable, function, enum, etc.
Definition: Expr.h:1238
ValueDecl * getDecl()
Definition: Expr.h:1306
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:83
bool isInvalidDecl() const
Definition: DeclBase.h:571
Represents an expression – generally a full-expression – that introduces cleanups to be run at the en...
Definition: ExprCXX.h:3420
unsigned getNumObjects() const
Definition: ExprCXX.h:3448
This represents one expression.
Definition: Expr.h:110
bool containsErrors() const
Whether this expression contains subexpressions which had errors, e.g.
Definition: Expr.h:239
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
Definition: Expr.cpp:3042
bool refersToBitField() const
Returns true if this expression is a gl-value that potentially refers to a bit-field.
Definition: Expr.h:463
QualType getType() const
Definition: Expr.h:142
llvm::APFloat getValue() const
Definition: Expr.h:1664
const Expr * getSubExpr() const
Definition: Expr.h:1028
Represents a function declaration or definition.
Definition: Decl.h:1917
Represents an implicitly-generated value initialization of an object of a given type.
Definition: Expr.h:5517
Describes an C or C++ initializer list.
Definition: Expr.h:4800
ArrayRef< Expr * > inits()
Definition: Expr.h:4840
Implicit declaration of a temporary that was materialized by a MaterializeTemporaryExpr and lifetime-...
Definition: DeclCXX.h:3166
Represents a prvalue temporary that is written into memory so that a reference can bind to it.
Definition: ExprCXX.h:4562
StorageDuration getStorageDuration() const
Retrieve the storage duration for the materialized temporary.
Definition: ExprCXX.h:4587
Expr * getSubExpr() const
Retrieve the temporary-generating subexpression whose value will be materialized into a glvalue.
Definition: ExprCXX.h:4579
LifetimeExtendedTemporaryDecl * getLifetimeExtendedTemporaryDecl()
Definition: ExprCXX.h:4602
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
Definition: Expr.h:3175
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
Definition: Expr.h:3254
Expr * getBase() const
Definition: Expr.h:3248
OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.
Definition: Expr.h:1146
Expr * getSourceExpr() const
The source expression of an opaque value expression is the expression which originally generated the ...
Definition: Expr.h:1196
ParenExpr - This represents a parethesized expression, e.g.
Definition: Expr.h:2123
const Expr * getSubExpr() const
Definition: Expr.h:2138
Represents a parameter to a function.
Definition: Decl.h:1722
PointerType - C99 6.7.5.1 - Pointer Declarators.
Definition: Type.h:2788
A (possibly-)qualified type.
Definition: Type.h:736
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition: Type.h:803
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition: Type.h:6649
bool isConstQualified() const
Determine whether this type is const-qualified.
Definition: Type.h:6721
Represents a struct/union/class.
Definition: Decl.h:3998
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
Definition: Type.h:4835
Base for LValueReferenceType and RValueReferenceType.
Definition: Type.h:2899
StringLiteral - This represents a string literal expression, e.g.
Definition: Expr.h:1781
Represents a reference to a non-type template parameter that has been substituted with a template arg...
Definition: ExprCXX.h:4318
bool isVoidType() const
Definition: Type.h:7218
bool isFundamentalType() const
Tests whether the type is categorized as a fundamental type.
Definition: Type.h:6873
bool isConstantSizeType() const
Return true if this is not a variable sized type, according to the rules of C99 6....
Definition: Type.cpp:2249
bool isArrayType() const
Definition: Type.h:6976
bool isPointerType() const
Definition: Type.h:6910
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
Definition: Type.h:7250
bool isReferenceType() const
Definition: Type.h:6922
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition: Type.cpp:629
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
Definition: Type.h:2317
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
Definition: Type.h:7477
bool isFunctionType() const
Definition: Type.h:6906
bool isFloatingType() const
Definition: Type.cpp:2145
const T * getAs() const
Member-template getAs<specific type>'.
Definition: Type.h:7424
bool isRecordType() const
Definition: Type.h:7000
UnaryExprOrTypeTraitExpr - expression with either a type or (unevaluated) expression operand.
Definition: Expr.h:2560
QualType getTypeOfArgument() const
Gets the argument type, or the type of the argument expression, whichever is appropriate.
Definition: Expr.h:2629
bool isArgumentType() const
Definition: Expr.h:2602
UnaryExprOrTypeTrait getKind() const
Definition: Expr.h:2592
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Definition: Expr.h:2176
Expr * getSubExpr() const
Definition: Expr.h:2221
Opcode getOpcode() const
Definition: Expr.h:2216
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition: Decl.h:701
QualType getType() const
Definition: Decl.h:712
Represents a variable declaration or definition.
Definition: Decl.h:913
bool isConstexpr() const
Whether this variable is (C++11) constexpr.
Definition: Decl.h:1519
bool hasInit() const
Definition: Decl.cpp:2343
const Expr * getInit() const
Definition: Decl.h:1325
bool hasLocalStorage() const
Returns true if a variable with function scope is a non-static local variable.
Definition: Decl.h:1141
Compilation context for expressions.
bool visitExpr(const Expr *E) override
std::optional< unsigned > allocateLocal(DeclTy &&Decl, bool IsExtended=false)
Allocates a space storing a local given its type.
bool VisitIntegerLiteral(const IntegerLiteral *E)
bool VisitCharacterLiteral(const CharacterLiteral *E)
bool VisitDeclRefExpr(const DeclRefExpr *E)
bool VisitExprWithCleanups(const ExprWithCleanups *E)
bool VisitMemberExpr(const MemberExpr *E)
bool discard(const Expr *E)
Evaluates an expression for side effects and discards the result.
bool visitDecl(const VarDecl *VD) override
Toplevel visitDecl().
bool visitInitializer(const Expr *E)
Compiles an initializer.
unsigned allocateLocalPrimitive(DeclTy &&Decl, PrimType Ty, bool IsMutable, bool IsExtended=false)
Creates a local primitive value.
bool visitRecordInitializer(const Expr *Initializer)
Compiles a record initializer.
bool VisitParenExpr(const ParenExpr *E)
bool VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *E)
bool VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *E)
bool VisitCompoundLiteralExpr(const CompoundLiteralExpr *E)
bool VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *E)
bool VisitBuiltinCallExpr(const CallExpr *E)
bool VisitCXXMemberCallExpr(const CXXMemberCallExpr *E)
void emitCleanup()
Emits scope cleanup instructions.
bool VisitCXXNullPtrLiteralExpr(const CXXNullPtrLiteralExpr *E)
bool VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E)
bool visitBool(const Expr *E)
Visits an expression and converts it to a boolean.
bool VisitBinaryOperator(const BinaryOperator *E)
bool visit(const Expr *E)
Evaluates an expression and places result on stack.
bool VisitInitListExpr(const InitListExpr *E)
bool VisitFloatingLiteral(const FloatingLiteral *E)
bool VisitAbstractConditionalOperator(const AbstractConditionalOperator *E)
bool VisitUnaryOperator(const UnaryOperator *E)
bool VisitArrayInitIndexExpr(const ArrayInitIndexExpr *E)
bool VisitPointerCompoundAssignOperator(const CompoundAssignOperator *E)
bool VisitFloatCompoundAssignOperator(const CompoundAssignOperator *E)
bool DiscardResult
Flag indicating if return value is to be discarded.
bool VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *E)
bool VisitArraySubscriptExpr(const ArraySubscriptExpr *E)
const Function * getFunction(const FunctionDecl *FD)
bool VisitLogicalBinOp(const BinaryOperator *E)
bool visitVarDecl(const VarDecl *VD)
Creates and initializes a variable from the given decl.
bool VisitStringLiteral(const StringLiteral *E)
Record * getRecord(QualType Ty)
Returns a record from a record or pointer type.
bool VisitOpaqueValueExpr(const OpaqueValueExpr *E)
bool VisitCXXThisExpr(const CXXThisExpr *E)
typename Emitter::LabelTy LabelTy
bool VisitPointerArithBinOp(const BinaryOperator *E)
Perform addition/subtraction of a pointer and an integer or subtraction of two pointers.
bool VisitSubstNonTypeTemplateParmExpr(const SubstNonTypeTemplateParmExpr *E)
bool VisitCompoundAssignOperator(const CompoundAssignOperator *E)
bool VisitCallExpr(const CallExpr *E)
const RecordType * getRecordTy(QualType Ty)
Returns a record type from a record or pointer type.
bool VisitConstantExpr(const ConstantExpr *E)
bool VisitCastExpr(const CastExpr *E)
bool VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *E)
bool visitArrayInitializer(const Expr *Initializer)
Compiles an array initializer.
Compilation context for statements.
Scope used to handle temporaries in toplevel variable declarations.
void addExtended(const Scope::Local &Local) override
DeclScope(ByteCodeExprGen< Emitter > *Ctx, const ValueDecl *VD)
Expression scope which tracks potentially lifetime extended temporaries which are hoisted to the pare...
Bytecode function.
Definition: Function.h:74
bool isFullyCompiled() const
Checks if the function is fully done compiling.
Definition: Function.h:141
bool hasBody() const
Definition: Function.h:146
bool isConstexpr() const
Checks if the function is valid to call in constexpr.
Definition: Function.h:130
bool hasRVO() const
Checks if the first argument is a RVO pointer.
Definition: Function.h:107
Scope for local variables.
void addLocal(const Scope::Local &Local) override
Scope used to handle initialization methods.
OptionScope(ByteCodeExprGen< Emitter > *Ctx, bool NewDiscardResult)
Root constructor, compiling or discarding primitives.
Context to manage declaration lifetimes.
Definition: Program.h:132
Structure/Class descriptor.
Definition: Record.h:25
const Field * getField(const FieldDecl *FD) const
Returns a field.
Definition: Record.cpp:30
const Base * getBase(const RecordDecl *FD) const
Returns a base descriptor.
Definition: Record.cpp:36
Describes a scope block.
Definition: Function.h:32
Scope chain managing the variable lifetimes.
ByteCodeExprGen< Emitter > * Ctx
ByteCodeExprGen instance.
bool LE(InterpState &S, CodePtr OpPC)
Definition: Interp.h:628
PrimType
Enumeration of the primitive types of the VM.
Definition: PrimType.h:29
llvm::PointerUnion< const Decl *, const Expr * > DeclTy
Definition: Descriptor.h:26
BinaryOperatorKind
UnaryExprOrTypeTrait
Names for the "expression or type" traits.
Definition: TypeTraits.h:51
@ C
Languages that the frontend can parse and compile.
@ SD_Static
Static storage duration.
Definition: Specifiers.h:315
#define true
Definition: stdbool.h:21
Describes a memory block created by an allocation site.
Definition: Descriptor.h:76
static constexpr MetadataSize InlineDescMD
Definition: Descriptor.h:97
Describes a base class.
Definition: Record.h:35
Describes a record field.
Definition: Record.h:28
const FieldDecl * Decl
Definition: Record.h:29
Information about a local's storage.
Definition: Function.h:35