1*700637cbSDimitry Andric //===--- Compiler.cpp - Code generator for expressions ---*- C++ -*-===//
2*700637cbSDimitry Andric //
3*700637cbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*700637cbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*700637cbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*700637cbSDimitry Andric //
7*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
8*700637cbSDimitry Andric
9*700637cbSDimitry Andric #include "Compiler.h"
10*700637cbSDimitry Andric #include "ByteCodeEmitter.h"
11*700637cbSDimitry Andric #include "Context.h"
12*700637cbSDimitry Andric #include "FixedPoint.h"
13*700637cbSDimitry Andric #include "Floating.h"
14*700637cbSDimitry Andric #include "Function.h"
15*700637cbSDimitry Andric #include "InterpShared.h"
16*700637cbSDimitry Andric #include "PrimType.h"
17*700637cbSDimitry Andric #include "Program.h"
18*700637cbSDimitry Andric #include "clang/AST/Attr.h"
19*700637cbSDimitry Andric
20*700637cbSDimitry Andric using namespace clang;
21*700637cbSDimitry Andric using namespace clang::interp;
22*700637cbSDimitry Andric
23*700637cbSDimitry Andric using APSInt = llvm::APSInt;
24*700637cbSDimitry Andric
25*700637cbSDimitry Andric namespace clang {
26*700637cbSDimitry Andric namespace interp {
27*700637cbSDimitry Andric
getBoolValue(const Expr * E)28*700637cbSDimitry Andric static std::optional<bool> getBoolValue(const Expr *E) {
29*700637cbSDimitry Andric if (const auto *CE = dyn_cast_if_present<ConstantExpr>(E);
30*700637cbSDimitry Andric CE && CE->hasAPValueResult() &&
31*700637cbSDimitry Andric CE->getResultAPValueKind() == APValue::ValueKind::Int) {
32*700637cbSDimitry Andric return CE->getResultAsAPSInt().getBoolValue();
33*700637cbSDimitry Andric }
34*700637cbSDimitry Andric
35*700637cbSDimitry Andric return std::nullopt;
36*700637cbSDimitry Andric }
37*700637cbSDimitry Andric
38*700637cbSDimitry Andric /// Scope used to handle temporaries in toplevel variable declarations.
39*700637cbSDimitry Andric template <class Emitter> class DeclScope final : public LocalScope<Emitter> {
40*700637cbSDimitry Andric public:
DeclScope(Compiler<Emitter> * Ctx,const ValueDecl * VD)41*700637cbSDimitry Andric DeclScope(Compiler<Emitter> *Ctx, const ValueDecl *VD)
42*700637cbSDimitry Andric : LocalScope<Emitter>(Ctx, VD), Scope(Ctx->P),
43*700637cbSDimitry Andric OldInitializingDecl(Ctx->InitializingDecl) {
44*700637cbSDimitry Andric Ctx->InitializingDecl = VD;
45*700637cbSDimitry Andric Ctx->InitStack.push_back(InitLink::Decl(VD));
46*700637cbSDimitry Andric }
47*700637cbSDimitry Andric
~DeclScope()48*700637cbSDimitry Andric ~DeclScope() {
49*700637cbSDimitry Andric this->Ctx->InitializingDecl = OldInitializingDecl;
50*700637cbSDimitry Andric this->Ctx->InitStack.pop_back();
51*700637cbSDimitry Andric }
52*700637cbSDimitry Andric
53*700637cbSDimitry Andric private:
54*700637cbSDimitry Andric Program::DeclScope Scope;
55*700637cbSDimitry Andric const ValueDecl *OldInitializingDecl;
56*700637cbSDimitry Andric };
57*700637cbSDimitry Andric
58*700637cbSDimitry Andric /// Scope used to handle initialization methods.
59*700637cbSDimitry Andric template <class Emitter> class OptionScope final {
60*700637cbSDimitry Andric public:
61*700637cbSDimitry Andric /// Root constructor, compiling or discarding primitives.
OptionScope(Compiler<Emitter> * Ctx,bool NewDiscardResult,bool NewInitializing)62*700637cbSDimitry Andric OptionScope(Compiler<Emitter> *Ctx, bool NewDiscardResult,
63*700637cbSDimitry Andric bool NewInitializing)
64*700637cbSDimitry Andric : Ctx(Ctx), OldDiscardResult(Ctx->DiscardResult),
65*700637cbSDimitry Andric OldInitializing(Ctx->Initializing) {
66*700637cbSDimitry Andric Ctx->DiscardResult = NewDiscardResult;
67*700637cbSDimitry Andric Ctx->Initializing = NewInitializing;
68*700637cbSDimitry Andric }
69*700637cbSDimitry Andric
~OptionScope()70*700637cbSDimitry Andric ~OptionScope() {
71*700637cbSDimitry Andric Ctx->DiscardResult = OldDiscardResult;
72*700637cbSDimitry Andric Ctx->Initializing = OldInitializing;
73*700637cbSDimitry Andric }
74*700637cbSDimitry Andric
75*700637cbSDimitry Andric private:
76*700637cbSDimitry Andric /// Parent context.
77*700637cbSDimitry Andric Compiler<Emitter> *Ctx;
78*700637cbSDimitry Andric /// Old discard flag to restore.
79*700637cbSDimitry Andric bool OldDiscardResult;
80*700637cbSDimitry Andric bool OldInitializing;
81*700637cbSDimitry Andric };
82*700637cbSDimitry Andric
83*700637cbSDimitry Andric template <class Emitter>
emit(Compiler<Emitter> * Ctx,const Expr * E) const84*700637cbSDimitry Andric bool InitLink::emit(Compiler<Emitter> *Ctx, const Expr *E) const {
85*700637cbSDimitry Andric switch (Kind) {
86*700637cbSDimitry Andric case K_This:
87*700637cbSDimitry Andric return Ctx->emitThis(E);
88*700637cbSDimitry Andric case K_Field:
89*700637cbSDimitry Andric // We're assuming there's a base pointer on the stack already.
90*700637cbSDimitry Andric return Ctx->emitGetPtrFieldPop(Offset, E);
91*700637cbSDimitry Andric case K_Temp:
92*700637cbSDimitry Andric return Ctx->emitGetPtrLocal(Offset, E);
93*700637cbSDimitry Andric case K_Decl:
94*700637cbSDimitry Andric return Ctx->visitDeclRef(D, E);
95*700637cbSDimitry Andric case K_Elem:
96*700637cbSDimitry Andric if (!Ctx->emitConstUint32(Offset, E))
97*700637cbSDimitry Andric return false;
98*700637cbSDimitry Andric return Ctx->emitArrayElemPtrPopUint32(E);
99*700637cbSDimitry Andric case K_RVO:
100*700637cbSDimitry Andric return Ctx->emitRVOPtr(E);
101*700637cbSDimitry Andric case K_InitList:
102*700637cbSDimitry Andric return true;
103*700637cbSDimitry Andric default:
104*700637cbSDimitry Andric llvm_unreachable("Unhandled InitLink kind");
105*700637cbSDimitry Andric }
106*700637cbSDimitry Andric return true;
107*700637cbSDimitry Andric }
108*700637cbSDimitry Andric
109*700637cbSDimitry Andric /// Scope managing label targets.
110*700637cbSDimitry Andric template <class Emitter> class LabelScope {
111*700637cbSDimitry Andric public:
~LabelScope()112*700637cbSDimitry Andric virtual ~LabelScope() {}
113*700637cbSDimitry Andric
114*700637cbSDimitry Andric protected:
LabelScope(Compiler<Emitter> * Ctx)115*700637cbSDimitry Andric LabelScope(Compiler<Emitter> *Ctx) : Ctx(Ctx) {}
116*700637cbSDimitry Andric /// Compiler instance.
117*700637cbSDimitry Andric Compiler<Emitter> *Ctx;
118*700637cbSDimitry Andric };
119*700637cbSDimitry Andric
120*700637cbSDimitry Andric /// Sets the context for break/continue statements.
121*700637cbSDimitry Andric template <class Emitter> class LoopScope final : public LabelScope<Emitter> {
122*700637cbSDimitry Andric public:
123*700637cbSDimitry Andric using LabelTy = typename Compiler<Emitter>::LabelTy;
124*700637cbSDimitry Andric using OptLabelTy = typename Compiler<Emitter>::OptLabelTy;
125*700637cbSDimitry Andric
LoopScope(Compiler<Emitter> * Ctx,LabelTy BreakLabel,LabelTy ContinueLabel)126*700637cbSDimitry Andric LoopScope(Compiler<Emitter> *Ctx, LabelTy BreakLabel, LabelTy ContinueLabel)
127*700637cbSDimitry Andric : LabelScope<Emitter>(Ctx), OldBreakLabel(Ctx->BreakLabel),
128*700637cbSDimitry Andric OldContinueLabel(Ctx->ContinueLabel),
129*700637cbSDimitry Andric OldBreakVarScope(Ctx->BreakVarScope),
130*700637cbSDimitry Andric OldContinueVarScope(Ctx->ContinueVarScope) {
131*700637cbSDimitry Andric this->Ctx->BreakLabel = BreakLabel;
132*700637cbSDimitry Andric this->Ctx->ContinueLabel = ContinueLabel;
133*700637cbSDimitry Andric this->Ctx->BreakVarScope = this->Ctx->VarScope;
134*700637cbSDimitry Andric this->Ctx->ContinueVarScope = this->Ctx->VarScope;
135*700637cbSDimitry Andric }
136*700637cbSDimitry Andric
~LoopScope()137*700637cbSDimitry Andric ~LoopScope() {
138*700637cbSDimitry Andric this->Ctx->BreakLabel = OldBreakLabel;
139*700637cbSDimitry Andric this->Ctx->ContinueLabel = OldContinueLabel;
140*700637cbSDimitry Andric this->Ctx->ContinueVarScope = OldContinueVarScope;
141*700637cbSDimitry Andric this->Ctx->BreakVarScope = OldBreakVarScope;
142*700637cbSDimitry Andric }
143*700637cbSDimitry Andric
144*700637cbSDimitry Andric private:
145*700637cbSDimitry Andric OptLabelTy OldBreakLabel;
146*700637cbSDimitry Andric OptLabelTy OldContinueLabel;
147*700637cbSDimitry Andric VariableScope<Emitter> *OldBreakVarScope;
148*700637cbSDimitry Andric VariableScope<Emitter> *OldContinueVarScope;
149*700637cbSDimitry Andric };
150*700637cbSDimitry Andric
151*700637cbSDimitry Andric // Sets the context for a switch scope, mapping labels.
152*700637cbSDimitry Andric template <class Emitter> class SwitchScope final : public LabelScope<Emitter> {
153*700637cbSDimitry Andric public:
154*700637cbSDimitry Andric using LabelTy = typename Compiler<Emitter>::LabelTy;
155*700637cbSDimitry Andric using OptLabelTy = typename Compiler<Emitter>::OptLabelTy;
156*700637cbSDimitry Andric using CaseMap = typename Compiler<Emitter>::CaseMap;
157*700637cbSDimitry Andric
SwitchScope(Compiler<Emitter> * Ctx,CaseMap && CaseLabels,LabelTy BreakLabel,OptLabelTy DefaultLabel)158*700637cbSDimitry Andric SwitchScope(Compiler<Emitter> *Ctx, CaseMap &&CaseLabels, LabelTy BreakLabel,
159*700637cbSDimitry Andric OptLabelTy DefaultLabel)
160*700637cbSDimitry Andric : LabelScope<Emitter>(Ctx), OldBreakLabel(Ctx->BreakLabel),
161*700637cbSDimitry Andric OldDefaultLabel(this->Ctx->DefaultLabel),
162*700637cbSDimitry Andric OldCaseLabels(std::move(this->Ctx->CaseLabels)),
163*700637cbSDimitry Andric OldLabelVarScope(Ctx->BreakVarScope) {
164*700637cbSDimitry Andric this->Ctx->BreakLabel = BreakLabel;
165*700637cbSDimitry Andric this->Ctx->DefaultLabel = DefaultLabel;
166*700637cbSDimitry Andric this->Ctx->CaseLabels = std::move(CaseLabels);
167*700637cbSDimitry Andric this->Ctx->BreakVarScope = this->Ctx->VarScope;
168*700637cbSDimitry Andric }
169*700637cbSDimitry Andric
~SwitchScope()170*700637cbSDimitry Andric ~SwitchScope() {
171*700637cbSDimitry Andric this->Ctx->BreakLabel = OldBreakLabel;
172*700637cbSDimitry Andric this->Ctx->DefaultLabel = OldDefaultLabel;
173*700637cbSDimitry Andric this->Ctx->CaseLabels = std::move(OldCaseLabels);
174*700637cbSDimitry Andric this->Ctx->BreakVarScope = OldLabelVarScope;
175*700637cbSDimitry Andric }
176*700637cbSDimitry Andric
177*700637cbSDimitry Andric private:
178*700637cbSDimitry Andric OptLabelTy OldBreakLabel;
179*700637cbSDimitry Andric OptLabelTy OldDefaultLabel;
180*700637cbSDimitry Andric CaseMap OldCaseLabels;
181*700637cbSDimitry Andric VariableScope<Emitter> *OldLabelVarScope;
182*700637cbSDimitry Andric };
183*700637cbSDimitry Andric
184*700637cbSDimitry Andric template <class Emitter> class StmtExprScope final {
185*700637cbSDimitry Andric public:
StmtExprScope(Compiler<Emitter> * Ctx)186*700637cbSDimitry Andric StmtExprScope(Compiler<Emitter> *Ctx) : Ctx(Ctx), OldFlag(Ctx->InStmtExpr) {
187*700637cbSDimitry Andric Ctx->InStmtExpr = true;
188*700637cbSDimitry Andric }
189*700637cbSDimitry Andric
~StmtExprScope()190*700637cbSDimitry Andric ~StmtExprScope() { Ctx->InStmtExpr = OldFlag; }
191*700637cbSDimitry Andric
192*700637cbSDimitry Andric private:
193*700637cbSDimitry Andric Compiler<Emitter> *Ctx;
194*700637cbSDimitry Andric bool OldFlag;
195*700637cbSDimitry Andric };
196*700637cbSDimitry Andric
197*700637cbSDimitry Andric } // namespace interp
198*700637cbSDimitry Andric } // namespace clang
199*700637cbSDimitry Andric
200*700637cbSDimitry Andric template <class Emitter>
VisitCastExpr(const CastExpr * CE)201*700637cbSDimitry Andric bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
202*700637cbSDimitry Andric const Expr *SubExpr = CE->getSubExpr();
203*700637cbSDimitry Andric
204*700637cbSDimitry Andric if (DiscardResult)
205*700637cbSDimitry Andric return this->delegate(SubExpr);
206*700637cbSDimitry Andric
207*700637cbSDimitry Andric switch (CE->getCastKind()) {
208*700637cbSDimitry Andric case CK_LValueToRValue: {
209*700637cbSDimitry Andric if (SubExpr->getType().isVolatileQualified())
210*700637cbSDimitry Andric return this->emitInvalidCast(CastKind::Volatile, /*Fatal=*/true, CE);
211*700637cbSDimitry Andric
212*700637cbSDimitry Andric std::optional<PrimType> SubExprT = classify(SubExpr->getType());
213*700637cbSDimitry Andric // Prepare storage for the result.
214*700637cbSDimitry Andric if (!Initializing && !SubExprT) {
215*700637cbSDimitry Andric std::optional<unsigned> LocalIndex = allocateLocal(SubExpr);
216*700637cbSDimitry Andric if (!LocalIndex)
217*700637cbSDimitry Andric return false;
218*700637cbSDimitry Andric if (!this->emitGetPtrLocal(*LocalIndex, CE))
219*700637cbSDimitry Andric return false;
220*700637cbSDimitry Andric }
221*700637cbSDimitry Andric
222*700637cbSDimitry Andric if (!this->visit(SubExpr))
223*700637cbSDimitry Andric return false;
224*700637cbSDimitry Andric
225*700637cbSDimitry Andric if (SubExprT)
226*700637cbSDimitry Andric return this->emitLoadPop(*SubExprT, CE);
227*700637cbSDimitry Andric
228*700637cbSDimitry Andric // If the subexpr type is not primitive, we need to perform a copy here.
229*700637cbSDimitry Andric // This happens for example in C when dereferencing a pointer of struct
230*700637cbSDimitry Andric // type.
231*700637cbSDimitry Andric return this->emitMemcpy(CE);
232*700637cbSDimitry Andric }
233*700637cbSDimitry Andric
234*700637cbSDimitry Andric case CK_DerivedToBaseMemberPointer: {
235*700637cbSDimitry Andric assert(classifyPrim(CE->getType()) == PT_MemberPtr);
236*700637cbSDimitry Andric assert(classifyPrim(SubExpr->getType()) == PT_MemberPtr);
237*700637cbSDimitry Andric const auto *FromMP = SubExpr->getType()->castAs<MemberPointerType>();
238*700637cbSDimitry Andric const auto *ToMP = CE->getType()->castAs<MemberPointerType>();
239*700637cbSDimitry Andric
240*700637cbSDimitry Andric unsigned DerivedOffset =
241*700637cbSDimitry Andric Ctx.collectBaseOffset(ToMP->getMostRecentCXXRecordDecl(),
242*700637cbSDimitry Andric FromMP->getMostRecentCXXRecordDecl());
243*700637cbSDimitry Andric
244*700637cbSDimitry Andric if (!this->delegate(SubExpr))
245*700637cbSDimitry Andric return false;
246*700637cbSDimitry Andric
247*700637cbSDimitry Andric return this->emitGetMemberPtrBasePop(DerivedOffset, CE);
248*700637cbSDimitry Andric }
249*700637cbSDimitry Andric
250*700637cbSDimitry Andric case CK_BaseToDerivedMemberPointer: {
251*700637cbSDimitry Andric assert(classifyPrim(CE) == PT_MemberPtr);
252*700637cbSDimitry Andric assert(classifyPrim(SubExpr) == PT_MemberPtr);
253*700637cbSDimitry Andric const auto *FromMP = SubExpr->getType()->castAs<MemberPointerType>();
254*700637cbSDimitry Andric const auto *ToMP = CE->getType()->castAs<MemberPointerType>();
255*700637cbSDimitry Andric
256*700637cbSDimitry Andric unsigned DerivedOffset =
257*700637cbSDimitry Andric Ctx.collectBaseOffset(FromMP->getMostRecentCXXRecordDecl(),
258*700637cbSDimitry Andric ToMP->getMostRecentCXXRecordDecl());
259*700637cbSDimitry Andric
260*700637cbSDimitry Andric if (!this->delegate(SubExpr))
261*700637cbSDimitry Andric return false;
262*700637cbSDimitry Andric return this->emitGetMemberPtrBasePop(-DerivedOffset, CE);
263*700637cbSDimitry Andric }
264*700637cbSDimitry Andric
265*700637cbSDimitry Andric case CK_UncheckedDerivedToBase:
266*700637cbSDimitry Andric case CK_DerivedToBase: {
267*700637cbSDimitry Andric if (!this->delegate(SubExpr))
268*700637cbSDimitry Andric return false;
269*700637cbSDimitry Andric
270*700637cbSDimitry Andric const auto extractRecordDecl = [](QualType Ty) -> const CXXRecordDecl * {
271*700637cbSDimitry Andric if (const auto *PT = dyn_cast<PointerType>(Ty))
272*700637cbSDimitry Andric return PT->getPointeeType()->getAsCXXRecordDecl();
273*700637cbSDimitry Andric return Ty->getAsCXXRecordDecl();
274*700637cbSDimitry Andric };
275*700637cbSDimitry Andric
276*700637cbSDimitry Andric // FIXME: We can express a series of non-virtual casts as a single
277*700637cbSDimitry Andric // GetPtrBasePop op.
278*700637cbSDimitry Andric QualType CurType = SubExpr->getType();
279*700637cbSDimitry Andric for (const CXXBaseSpecifier *B : CE->path()) {
280*700637cbSDimitry Andric if (B->isVirtual()) {
281*700637cbSDimitry Andric if (!this->emitGetPtrVirtBasePop(extractRecordDecl(B->getType()), CE))
282*700637cbSDimitry Andric return false;
283*700637cbSDimitry Andric CurType = B->getType();
284*700637cbSDimitry Andric } else {
285*700637cbSDimitry Andric unsigned DerivedOffset = collectBaseOffset(B->getType(), CurType);
286*700637cbSDimitry Andric if (!this->emitGetPtrBasePop(
287*700637cbSDimitry Andric DerivedOffset, /*NullOK=*/CE->getType()->isPointerType(), CE))
288*700637cbSDimitry Andric return false;
289*700637cbSDimitry Andric CurType = B->getType();
290*700637cbSDimitry Andric }
291*700637cbSDimitry Andric }
292*700637cbSDimitry Andric
293*700637cbSDimitry Andric return true;
294*700637cbSDimitry Andric }
295*700637cbSDimitry Andric
296*700637cbSDimitry Andric case CK_BaseToDerived: {
297*700637cbSDimitry Andric if (!this->delegate(SubExpr))
298*700637cbSDimitry Andric return false;
299*700637cbSDimitry Andric unsigned DerivedOffset =
300*700637cbSDimitry Andric collectBaseOffset(SubExpr->getType(), CE->getType());
301*700637cbSDimitry Andric
302*700637cbSDimitry Andric const Type *TargetType = CE->getType().getTypePtr();
303*700637cbSDimitry Andric if (TargetType->isPointerOrReferenceType())
304*700637cbSDimitry Andric TargetType = TargetType->getPointeeType().getTypePtr();
305*700637cbSDimitry Andric return this->emitGetPtrDerivedPop(DerivedOffset,
306*700637cbSDimitry Andric /*NullOK=*/CE->getType()->isPointerType(),
307*700637cbSDimitry Andric TargetType, CE);
308*700637cbSDimitry Andric }
309*700637cbSDimitry Andric
310*700637cbSDimitry Andric case CK_FloatingCast: {
311*700637cbSDimitry Andric // HLSL uses CK_FloatingCast to cast between vectors.
312*700637cbSDimitry Andric if (!SubExpr->getType()->isFloatingType() ||
313*700637cbSDimitry Andric !CE->getType()->isFloatingType())
314*700637cbSDimitry Andric return false;
315*700637cbSDimitry Andric if (!this->visit(SubExpr))
316*700637cbSDimitry Andric return false;
317*700637cbSDimitry Andric const auto *TargetSemantics = &Ctx.getFloatSemantics(CE->getType());
318*700637cbSDimitry Andric return this->emitCastFP(TargetSemantics, getRoundingMode(CE), CE);
319*700637cbSDimitry Andric }
320*700637cbSDimitry Andric
321*700637cbSDimitry Andric case CK_IntegralToFloating: {
322*700637cbSDimitry Andric if (!CE->getType()->isRealFloatingType())
323*700637cbSDimitry Andric return false;
324*700637cbSDimitry Andric if (!this->visit(SubExpr))
325*700637cbSDimitry Andric return false;
326*700637cbSDimitry Andric const auto *TargetSemantics = &Ctx.getFloatSemantics(CE->getType());
327*700637cbSDimitry Andric return this->emitCastIntegralFloating(
328*700637cbSDimitry Andric classifyPrim(SubExpr), TargetSemantics, getFPOptions(CE), CE);
329*700637cbSDimitry Andric }
330*700637cbSDimitry Andric
331*700637cbSDimitry Andric case CK_FloatingToBoolean: {
332*700637cbSDimitry Andric if (!SubExpr->getType()->isRealFloatingType() ||
333*700637cbSDimitry Andric !CE->getType()->isBooleanType())
334*700637cbSDimitry Andric return false;
335*700637cbSDimitry Andric if (const auto *FL = dyn_cast<FloatingLiteral>(SubExpr))
336*700637cbSDimitry Andric return this->emitConstBool(FL->getValue().isNonZero(), CE);
337*700637cbSDimitry Andric if (!this->visit(SubExpr))
338*700637cbSDimitry Andric return false;
339*700637cbSDimitry Andric return this->emitCastFloatingIntegralBool(getFPOptions(CE), CE);
340*700637cbSDimitry Andric }
341*700637cbSDimitry Andric
342*700637cbSDimitry Andric case CK_FloatingToIntegral: {
343*700637cbSDimitry Andric if (!this->visit(SubExpr))
344*700637cbSDimitry Andric return false;
345*700637cbSDimitry Andric PrimType ToT = classifyPrim(CE);
346*700637cbSDimitry Andric if (ToT == PT_IntAP)
347*700637cbSDimitry Andric return this->emitCastFloatingIntegralAP(Ctx.getBitWidth(CE->getType()),
348*700637cbSDimitry Andric getFPOptions(CE), CE);
349*700637cbSDimitry Andric if (ToT == PT_IntAPS)
350*700637cbSDimitry Andric return this->emitCastFloatingIntegralAPS(Ctx.getBitWidth(CE->getType()),
351*700637cbSDimitry Andric getFPOptions(CE), CE);
352*700637cbSDimitry Andric
353*700637cbSDimitry Andric return this->emitCastFloatingIntegral(ToT, getFPOptions(CE), CE);
354*700637cbSDimitry Andric }
355*700637cbSDimitry Andric
356*700637cbSDimitry Andric case CK_NullToPointer:
357*700637cbSDimitry Andric case CK_NullToMemberPointer: {
358*700637cbSDimitry Andric if (!this->discard(SubExpr))
359*700637cbSDimitry Andric return false;
360*700637cbSDimitry Andric const Descriptor *Desc = nullptr;
361*700637cbSDimitry Andric const QualType PointeeType = CE->getType()->getPointeeType();
362*700637cbSDimitry Andric if (!PointeeType.isNull()) {
363*700637cbSDimitry Andric if (std::optional<PrimType> T = classify(PointeeType))
364*700637cbSDimitry Andric Desc = P.createDescriptor(SubExpr, *T);
365*700637cbSDimitry Andric else
366*700637cbSDimitry Andric Desc = P.createDescriptor(SubExpr, PointeeType.getTypePtr(),
367*700637cbSDimitry Andric std::nullopt, /*IsConst=*/true);
368*700637cbSDimitry Andric }
369*700637cbSDimitry Andric
370*700637cbSDimitry Andric uint64_t Val = Ctx.getASTContext().getTargetNullPointerValue(CE->getType());
371*700637cbSDimitry Andric return this->emitNull(classifyPrim(CE->getType()), Val, Desc, CE);
372*700637cbSDimitry Andric }
373*700637cbSDimitry Andric
374*700637cbSDimitry Andric case CK_PointerToIntegral: {
375*700637cbSDimitry Andric if (!this->visit(SubExpr))
376*700637cbSDimitry Andric return false;
377*700637cbSDimitry Andric
378*700637cbSDimitry Andric // If SubExpr doesn't result in a pointer, make it one.
379*700637cbSDimitry Andric if (PrimType FromT = classifyPrim(SubExpr->getType()); FromT != PT_Ptr) {
380*700637cbSDimitry Andric assert(isPtrType(FromT));
381*700637cbSDimitry Andric if (!this->emitDecayPtr(FromT, PT_Ptr, CE))
382*700637cbSDimitry Andric return false;
383*700637cbSDimitry Andric }
384*700637cbSDimitry Andric
385*700637cbSDimitry Andric PrimType T = classifyPrim(CE->getType());
386*700637cbSDimitry Andric if (T == PT_IntAP)
387*700637cbSDimitry Andric return this->emitCastPointerIntegralAP(Ctx.getBitWidth(CE->getType()),
388*700637cbSDimitry Andric CE);
389*700637cbSDimitry Andric if (T == PT_IntAPS)
390*700637cbSDimitry Andric return this->emitCastPointerIntegralAPS(Ctx.getBitWidth(CE->getType()),
391*700637cbSDimitry Andric CE);
392*700637cbSDimitry Andric return this->emitCastPointerIntegral(T, CE);
393*700637cbSDimitry Andric }
394*700637cbSDimitry Andric
395*700637cbSDimitry Andric case CK_ArrayToPointerDecay: {
396*700637cbSDimitry Andric if (!this->visit(SubExpr))
397*700637cbSDimitry Andric return false;
398*700637cbSDimitry Andric return this->emitArrayDecay(CE);
399*700637cbSDimitry Andric }
400*700637cbSDimitry Andric
401*700637cbSDimitry Andric case CK_IntegralToPointer: {
402*700637cbSDimitry Andric QualType IntType = SubExpr->getType();
403*700637cbSDimitry Andric assert(IntType->isIntegralOrEnumerationType());
404*700637cbSDimitry Andric if (!this->visit(SubExpr))
405*700637cbSDimitry Andric return false;
406*700637cbSDimitry Andric // FIXME: I think the discard is wrong since the int->ptr cast might cause a
407*700637cbSDimitry Andric // diagnostic.
408*700637cbSDimitry Andric PrimType T = classifyPrim(IntType);
409*700637cbSDimitry Andric QualType PtrType = CE->getType();
410*700637cbSDimitry Andric const Descriptor *Desc;
411*700637cbSDimitry Andric if (std::optional<PrimType> T = classify(PtrType->getPointeeType()))
412*700637cbSDimitry Andric Desc = P.createDescriptor(SubExpr, *T);
413*700637cbSDimitry Andric else if (PtrType->getPointeeType()->isVoidType())
414*700637cbSDimitry Andric Desc = nullptr;
415*700637cbSDimitry Andric else
416*700637cbSDimitry Andric Desc = P.createDescriptor(CE, PtrType->getPointeeType().getTypePtr(),
417*700637cbSDimitry Andric Descriptor::InlineDescMD, /*IsConst=*/true);
418*700637cbSDimitry Andric
419*700637cbSDimitry Andric if (!this->emitGetIntPtr(T, Desc, CE))
420*700637cbSDimitry Andric return false;
421*700637cbSDimitry Andric
422*700637cbSDimitry Andric PrimType DestPtrT = classifyPrim(PtrType);
423*700637cbSDimitry Andric if (DestPtrT == PT_Ptr)
424*700637cbSDimitry Andric return true;
425*700637cbSDimitry Andric
426*700637cbSDimitry Andric // In case we're converting the integer to a non-Pointer.
427*700637cbSDimitry Andric return this->emitDecayPtr(PT_Ptr, DestPtrT, CE);
428*700637cbSDimitry Andric }
429*700637cbSDimitry Andric
430*700637cbSDimitry Andric case CK_AtomicToNonAtomic:
431*700637cbSDimitry Andric case CK_ConstructorConversion:
432*700637cbSDimitry Andric case CK_FunctionToPointerDecay:
433*700637cbSDimitry Andric case CK_NonAtomicToAtomic:
434*700637cbSDimitry Andric case CK_NoOp:
435*700637cbSDimitry Andric case CK_UserDefinedConversion:
436*700637cbSDimitry Andric case CK_AddressSpaceConversion:
437*700637cbSDimitry Andric case CK_CPointerToObjCPointerCast:
438*700637cbSDimitry Andric return this->delegate(SubExpr);
439*700637cbSDimitry Andric
440*700637cbSDimitry Andric case CK_BitCast: {
441*700637cbSDimitry Andric // Reject bitcasts to atomic types.
442*700637cbSDimitry Andric if (CE->getType()->isAtomicType()) {
443*700637cbSDimitry Andric if (!this->discard(SubExpr))
444*700637cbSDimitry Andric return false;
445*700637cbSDimitry Andric return this->emitInvalidCast(CastKind::Reinterpret, /*Fatal=*/true, CE);
446*700637cbSDimitry Andric }
447*700637cbSDimitry Andric QualType SubExprTy = SubExpr->getType();
448*700637cbSDimitry Andric std::optional<PrimType> FromT = classify(SubExprTy);
449*700637cbSDimitry Andric // Casts from integer/vector to vector.
450*700637cbSDimitry Andric if (CE->getType()->isVectorType())
451*700637cbSDimitry Andric return this->emitBuiltinBitCast(CE);
452*700637cbSDimitry Andric
453*700637cbSDimitry Andric std::optional<PrimType> ToT = classify(CE->getType());
454*700637cbSDimitry Andric if (!FromT || !ToT)
455*700637cbSDimitry Andric return false;
456*700637cbSDimitry Andric
457*700637cbSDimitry Andric assert(isPtrType(*FromT));
458*700637cbSDimitry Andric assert(isPtrType(*ToT));
459*700637cbSDimitry Andric if (FromT == ToT) {
460*700637cbSDimitry Andric if (CE->getType()->isVoidPointerType())
461*700637cbSDimitry Andric return this->delegate(SubExpr);
462*700637cbSDimitry Andric
463*700637cbSDimitry Andric if (!this->visit(SubExpr))
464*700637cbSDimitry Andric return false;
465*700637cbSDimitry Andric if (CE->getType()->isFunctionPointerType())
466*700637cbSDimitry Andric return true;
467*700637cbSDimitry Andric if (FromT == PT_Ptr)
468*700637cbSDimitry Andric return this->emitPtrPtrCast(SubExprTy->isVoidPointerType(), CE);
469*700637cbSDimitry Andric return true;
470*700637cbSDimitry Andric }
471*700637cbSDimitry Andric
472*700637cbSDimitry Andric if (!this->visit(SubExpr))
473*700637cbSDimitry Andric return false;
474*700637cbSDimitry Andric return this->emitDecayPtr(*FromT, *ToT, CE);
475*700637cbSDimitry Andric }
476*700637cbSDimitry Andric case CK_IntegralToBoolean:
477*700637cbSDimitry Andric case CK_FixedPointToBoolean: {
478*700637cbSDimitry Andric // HLSL uses this to cast to one-element vectors.
479*700637cbSDimitry Andric std::optional<PrimType> FromT = classify(SubExpr->getType());
480*700637cbSDimitry Andric if (!FromT)
481*700637cbSDimitry Andric return false;
482*700637cbSDimitry Andric
483*700637cbSDimitry Andric if (const auto *IL = dyn_cast<IntegerLiteral>(SubExpr))
484*700637cbSDimitry Andric return this->emitConst(IL->getValue(), CE);
485*700637cbSDimitry Andric if (!this->visit(SubExpr))
486*700637cbSDimitry Andric return false;
487*700637cbSDimitry Andric return this->emitCast(*FromT, classifyPrim(CE), CE);
488*700637cbSDimitry Andric }
489*700637cbSDimitry Andric
490*700637cbSDimitry Andric case CK_BooleanToSignedIntegral:
491*700637cbSDimitry Andric case CK_IntegralCast: {
492*700637cbSDimitry Andric std::optional<PrimType> FromT = classify(SubExpr->getType());
493*700637cbSDimitry Andric std::optional<PrimType> ToT = classify(CE->getType());
494*700637cbSDimitry Andric if (!FromT || !ToT)
495*700637cbSDimitry Andric return false;
496*700637cbSDimitry Andric
497*700637cbSDimitry Andric // Try to emit a casted known constant value directly.
498*700637cbSDimitry Andric if (const auto *IL = dyn_cast<IntegerLiteral>(SubExpr)) {
499*700637cbSDimitry Andric if (ToT != PT_IntAP && ToT != PT_IntAPS && FromT != PT_IntAP &&
500*700637cbSDimitry Andric FromT != PT_IntAPS && !CE->getType()->isEnumeralType())
501*700637cbSDimitry Andric return this->emitConst(IL->getValue(), CE);
502*700637cbSDimitry Andric if (!this->emitConst(IL->getValue(), SubExpr))
503*700637cbSDimitry Andric return false;
504*700637cbSDimitry Andric } else {
505*700637cbSDimitry Andric if (!this->visit(SubExpr))
506*700637cbSDimitry Andric return false;
507*700637cbSDimitry Andric }
508*700637cbSDimitry Andric
509*700637cbSDimitry Andric // Possibly diagnose casts to enum types if the target type does not
510*700637cbSDimitry Andric // have a fixed size.
511*700637cbSDimitry Andric if (Ctx.getLangOpts().CPlusPlus && CE->getType()->isEnumeralType()) {
512*700637cbSDimitry Andric if (const auto *ET = CE->getType().getCanonicalType()->castAs<EnumType>();
513*700637cbSDimitry Andric !ET->getDecl()->isFixed()) {
514*700637cbSDimitry Andric if (!this->emitCheckEnumValue(*FromT, ET->getDecl(), CE))
515*700637cbSDimitry Andric return false;
516*700637cbSDimitry Andric }
517*700637cbSDimitry Andric }
518*700637cbSDimitry Andric
519*700637cbSDimitry Andric if (ToT == PT_IntAP) {
520*700637cbSDimitry Andric if (!this->emitCastAP(*FromT, Ctx.getBitWidth(CE->getType()), CE))
521*700637cbSDimitry Andric return false;
522*700637cbSDimitry Andric } else if (ToT == PT_IntAPS) {
523*700637cbSDimitry Andric if (!this->emitCastAPS(*FromT, Ctx.getBitWidth(CE->getType()), CE))
524*700637cbSDimitry Andric return false;
525*700637cbSDimitry Andric } else {
526*700637cbSDimitry Andric if (FromT == ToT)
527*700637cbSDimitry Andric return true;
528*700637cbSDimitry Andric if (!this->emitCast(*FromT, *ToT, CE))
529*700637cbSDimitry Andric return false;
530*700637cbSDimitry Andric }
531*700637cbSDimitry Andric if (CE->getCastKind() == CK_BooleanToSignedIntegral)
532*700637cbSDimitry Andric return this->emitNeg(*ToT, CE);
533*700637cbSDimitry Andric return true;
534*700637cbSDimitry Andric }
535*700637cbSDimitry Andric
536*700637cbSDimitry Andric case CK_PointerToBoolean:
537*700637cbSDimitry Andric case CK_MemberPointerToBoolean: {
538*700637cbSDimitry Andric PrimType PtrT = classifyPrim(SubExpr->getType());
539*700637cbSDimitry Andric
540*700637cbSDimitry Andric if (!this->visit(SubExpr))
541*700637cbSDimitry Andric return false;
542*700637cbSDimitry Andric return this->emitIsNonNull(PtrT, CE);
543*700637cbSDimitry Andric }
544*700637cbSDimitry Andric
545*700637cbSDimitry Andric case CK_IntegralComplexToBoolean:
546*700637cbSDimitry Andric case CK_FloatingComplexToBoolean: {
547*700637cbSDimitry Andric if (!this->visit(SubExpr))
548*700637cbSDimitry Andric return false;
549*700637cbSDimitry Andric return this->emitComplexBoolCast(SubExpr);
550*700637cbSDimitry Andric }
551*700637cbSDimitry Andric
552*700637cbSDimitry Andric case CK_IntegralComplexToReal:
553*700637cbSDimitry Andric case CK_FloatingComplexToReal:
554*700637cbSDimitry Andric return this->emitComplexReal(SubExpr);
555*700637cbSDimitry Andric
556*700637cbSDimitry Andric case CK_IntegralRealToComplex:
557*700637cbSDimitry Andric case CK_FloatingRealToComplex: {
558*700637cbSDimitry Andric // We're creating a complex value here, so we need to
559*700637cbSDimitry Andric // allocate storage for it.
560*700637cbSDimitry Andric if (!Initializing) {
561*700637cbSDimitry Andric std::optional<unsigned> LocalIndex = allocateTemporary(CE);
562*700637cbSDimitry Andric if (!LocalIndex)
563*700637cbSDimitry Andric return false;
564*700637cbSDimitry Andric if (!this->emitGetPtrLocal(*LocalIndex, CE))
565*700637cbSDimitry Andric return false;
566*700637cbSDimitry Andric }
567*700637cbSDimitry Andric
568*700637cbSDimitry Andric PrimType T = classifyPrim(SubExpr->getType());
569*700637cbSDimitry Andric // Init the complex value to {SubExpr, 0}.
570*700637cbSDimitry Andric if (!this->visitArrayElemInit(0, SubExpr, T))
571*700637cbSDimitry Andric return false;
572*700637cbSDimitry Andric // Zero-init the second element.
573*700637cbSDimitry Andric if (!this->visitZeroInitializer(T, SubExpr->getType(), SubExpr))
574*700637cbSDimitry Andric return false;
575*700637cbSDimitry Andric return this->emitInitElem(T, 1, SubExpr);
576*700637cbSDimitry Andric }
577*700637cbSDimitry Andric
578*700637cbSDimitry Andric case CK_IntegralComplexCast:
579*700637cbSDimitry Andric case CK_FloatingComplexCast:
580*700637cbSDimitry Andric case CK_IntegralComplexToFloatingComplex:
581*700637cbSDimitry Andric case CK_FloatingComplexToIntegralComplex: {
582*700637cbSDimitry Andric assert(CE->getType()->isAnyComplexType());
583*700637cbSDimitry Andric assert(SubExpr->getType()->isAnyComplexType());
584*700637cbSDimitry Andric if (!Initializing) {
585*700637cbSDimitry Andric std::optional<unsigned> LocalIndex = allocateLocal(CE);
586*700637cbSDimitry Andric if (!LocalIndex)
587*700637cbSDimitry Andric return false;
588*700637cbSDimitry Andric if (!this->emitGetPtrLocal(*LocalIndex, CE))
589*700637cbSDimitry Andric return false;
590*700637cbSDimitry Andric }
591*700637cbSDimitry Andric
592*700637cbSDimitry Andric // Location for the SubExpr.
593*700637cbSDimitry Andric // Since SubExpr is of complex type, visiting it results in a pointer
594*700637cbSDimitry Andric // anyway, so we just create a temporary pointer variable.
595*700637cbSDimitry Andric unsigned SubExprOffset =
596*700637cbSDimitry Andric allocateLocalPrimitive(SubExpr, PT_Ptr, /*IsConst=*/true);
597*700637cbSDimitry Andric if (!this->visit(SubExpr))
598*700637cbSDimitry Andric return false;
599*700637cbSDimitry Andric if (!this->emitSetLocal(PT_Ptr, SubExprOffset, CE))
600*700637cbSDimitry Andric return false;
601*700637cbSDimitry Andric
602*700637cbSDimitry Andric PrimType SourceElemT = classifyComplexElementType(SubExpr->getType());
603*700637cbSDimitry Andric QualType DestElemType =
604*700637cbSDimitry Andric CE->getType()->getAs<ComplexType>()->getElementType();
605*700637cbSDimitry Andric PrimType DestElemT = classifyPrim(DestElemType);
606*700637cbSDimitry Andric // Cast both elements individually.
607*700637cbSDimitry Andric for (unsigned I = 0; I != 2; ++I) {
608*700637cbSDimitry Andric if (!this->emitGetLocal(PT_Ptr, SubExprOffset, CE))
609*700637cbSDimitry Andric return false;
610*700637cbSDimitry Andric if (!this->emitArrayElemPop(SourceElemT, I, CE))
611*700637cbSDimitry Andric return false;
612*700637cbSDimitry Andric
613*700637cbSDimitry Andric // Do the cast.
614*700637cbSDimitry Andric if (!this->emitPrimCast(SourceElemT, DestElemT, DestElemType, CE))
615*700637cbSDimitry Andric return false;
616*700637cbSDimitry Andric
617*700637cbSDimitry Andric // Save the value.
618*700637cbSDimitry Andric if (!this->emitInitElem(DestElemT, I, CE))
619*700637cbSDimitry Andric return false;
620*700637cbSDimitry Andric }
621*700637cbSDimitry Andric return true;
622*700637cbSDimitry Andric }
623*700637cbSDimitry Andric
624*700637cbSDimitry Andric case CK_VectorSplat: {
625*700637cbSDimitry Andric assert(!classify(CE->getType()));
626*700637cbSDimitry Andric assert(classify(SubExpr->getType()));
627*700637cbSDimitry Andric assert(CE->getType()->isVectorType());
628*700637cbSDimitry Andric
629*700637cbSDimitry Andric if (!Initializing) {
630*700637cbSDimitry Andric std::optional<unsigned> LocalIndex = allocateLocal(CE);
631*700637cbSDimitry Andric if (!LocalIndex)
632*700637cbSDimitry Andric return false;
633*700637cbSDimitry Andric if (!this->emitGetPtrLocal(*LocalIndex, CE))
634*700637cbSDimitry Andric return false;
635*700637cbSDimitry Andric }
636*700637cbSDimitry Andric
637*700637cbSDimitry Andric const auto *VT = CE->getType()->getAs<VectorType>();
638*700637cbSDimitry Andric PrimType ElemT = classifyPrim(SubExpr->getType());
639*700637cbSDimitry Andric unsigned ElemOffset =
640*700637cbSDimitry Andric allocateLocalPrimitive(SubExpr, ElemT, /*IsConst=*/true);
641*700637cbSDimitry Andric
642*700637cbSDimitry Andric // Prepare a local variable for the scalar value.
643*700637cbSDimitry Andric if (!this->visit(SubExpr))
644*700637cbSDimitry Andric return false;
645*700637cbSDimitry Andric if (classifyPrim(SubExpr) == PT_Ptr && !this->emitLoadPop(ElemT, CE))
646*700637cbSDimitry Andric return false;
647*700637cbSDimitry Andric
648*700637cbSDimitry Andric if (!this->emitSetLocal(ElemT, ElemOffset, CE))
649*700637cbSDimitry Andric return false;
650*700637cbSDimitry Andric
651*700637cbSDimitry Andric for (unsigned I = 0; I != VT->getNumElements(); ++I) {
652*700637cbSDimitry Andric if (!this->emitGetLocal(ElemT, ElemOffset, CE))
653*700637cbSDimitry Andric return false;
654*700637cbSDimitry Andric if (!this->emitInitElem(ElemT, I, CE))
655*700637cbSDimitry Andric return false;
656*700637cbSDimitry Andric }
657*700637cbSDimitry Andric
658*700637cbSDimitry Andric return true;
659*700637cbSDimitry Andric }
660*700637cbSDimitry Andric
661*700637cbSDimitry Andric case CK_HLSLVectorTruncation: {
662*700637cbSDimitry Andric assert(SubExpr->getType()->isVectorType());
663*700637cbSDimitry Andric if (std::optional<PrimType> ResultT = classify(CE)) {
664*700637cbSDimitry Andric assert(!DiscardResult);
665*700637cbSDimitry Andric // Result must be either a float or integer. Take the first element.
666*700637cbSDimitry Andric if (!this->visit(SubExpr))
667*700637cbSDimitry Andric return false;
668*700637cbSDimitry Andric return this->emitArrayElemPop(*ResultT, 0, CE);
669*700637cbSDimitry Andric }
670*700637cbSDimitry Andric // Otherwise, this truncates from one vector type to another.
671*700637cbSDimitry Andric assert(CE->getType()->isVectorType());
672*700637cbSDimitry Andric
673*700637cbSDimitry Andric if (!Initializing) {
674*700637cbSDimitry Andric std::optional<unsigned> LocalIndex = allocateTemporary(CE);
675*700637cbSDimitry Andric if (!LocalIndex)
676*700637cbSDimitry Andric return false;
677*700637cbSDimitry Andric if (!this->emitGetPtrLocal(*LocalIndex, CE))
678*700637cbSDimitry Andric return false;
679*700637cbSDimitry Andric }
680*700637cbSDimitry Andric unsigned ToSize = CE->getType()->getAs<VectorType>()->getNumElements();
681*700637cbSDimitry Andric assert(SubExpr->getType()->getAs<VectorType>()->getNumElements() > ToSize);
682*700637cbSDimitry Andric if (!this->visit(SubExpr))
683*700637cbSDimitry Andric return false;
684*700637cbSDimitry Andric return this->emitCopyArray(classifyVectorElementType(CE->getType()), 0, 0,
685*700637cbSDimitry Andric ToSize, CE);
686*700637cbSDimitry Andric };
687*700637cbSDimitry Andric
688*700637cbSDimitry Andric case CK_IntegralToFixedPoint: {
689*700637cbSDimitry Andric if (!this->visit(SubExpr))
690*700637cbSDimitry Andric return false;
691*700637cbSDimitry Andric
692*700637cbSDimitry Andric auto Sem =
693*700637cbSDimitry Andric Ctx.getASTContext().getFixedPointSemantics(CE->getType()).toOpaqueInt();
694*700637cbSDimitry Andric return this->emitCastIntegralFixedPoint(classifyPrim(SubExpr->getType()),
695*700637cbSDimitry Andric Sem, CE);
696*700637cbSDimitry Andric }
697*700637cbSDimitry Andric case CK_FloatingToFixedPoint: {
698*700637cbSDimitry Andric if (!this->visit(SubExpr))
699*700637cbSDimitry Andric return false;
700*700637cbSDimitry Andric
701*700637cbSDimitry Andric auto Sem =
702*700637cbSDimitry Andric Ctx.getASTContext().getFixedPointSemantics(CE->getType()).toOpaqueInt();
703*700637cbSDimitry Andric return this->emitCastFloatingFixedPoint(Sem, CE);
704*700637cbSDimitry Andric }
705*700637cbSDimitry Andric case CK_FixedPointToFloating: {
706*700637cbSDimitry Andric if (!this->visit(SubExpr))
707*700637cbSDimitry Andric return false;
708*700637cbSDimitry Andric const auto *TargetSemantics = &Ctx.getFloatSemantics(CE->getType());
709*700637cbSDimitry Andric return this->emitCastFixedPointFloating(TargetSemantics, CE);
710*700637cbSDimitry Andric }
711*700637cbSDimitry Andric case CK_FixedPointToIntegral: {
712*700637cbSDimitry Andric if (!this->visit(SubExpr))
713*700637cbSDimitry Andric return false;
714*700637cbSDimitry Andric return this->emitCastFixedPointIntegral(classifyPrim(CE->getType()), CE);
715*700637cbSDimitry Andric }
716*700637cbSDimitry Andric case CK_FixedPointCast: {
717*700637cbSDimitry Andric if (!this->visit(SubExpr))
718*700637cbSDimitry Andric return false;
719*700637cbSDimitry Andric auto Sem =
720*700637cbSDimitry Andric Ctx.getASTContext().getFixedPointSemantics(CE->getType()).toOpaqueInt();
721*700637cbSDimitry Andric return this->emitCastFixedPoint(Sem, CE);
722*700637cbSDimitry Andric }
723*700637cbSDimitry Andric
724*700637cbSDimitry Andric case CK_ToVoid:
725*700637cbSDimitry Andric return discard(SubExpr);
726*700637cbSDimitry Andric
727*700637cbSDimitry Andric default:
728*700637cbSDimitry Andric return this->emitInvalid(CE);
729*700637cbSDimitry Andric }
730*700637cbSDimitry Andric llvm_unreachable("Unhandled clang::CastKind enum");
731*700637cbSDimitry Andric }
732*700637cbSDimitry Andric
733*700637cbSDimitry Andric template <class Emitter>
VisitBuiltinBitCastExpr(const BuiltinBitCastExpr * E)734*700637cbSDimitry Andric bool Compiler<Emitter>::VisitBuiltinBitCastExpr(const BuiltinBitCastExpr *E) {
735*700637cbSDimitry Andric return this->emitBuiltinBitCast(E);
736*700637cbSDimitry Andric }
737*700637cbSDimitry Andric
738*700637cbSDimitry Andric template <class Emitter>
VisitIntegerLiteral(const IntegerLiteral * LE)739*700637cbSDimitry Andric bool Compiler<Emitter>::VisitIntegerLiteral(const IntegerLiteral *LE) {
740*700637cbSDimitry Andric if (DiscardResult)
741*700637cbSDimitry Andric return true;
742*700637cbSDimitry Andric
743*700637cbSDimitry Andric return this->emitConst(LE->getValue(), LE);
744*700637cbSDimitry Andric }
745*700637cbSDimitry Andric
746*700637cbSDimitry Andric template <class Emitter>
VisitFloatingLiteral(const FloatingLiteral * E)747*700637cbSDimitry Andric bool Compiler<Emitter>::VisitFloatingLiteral(const FloatingLiteral *E) {
748*700637cbSDimitry Andric if (DiscardResult)
749*700637cbSDimitry Andric return true;
750*700637cbSDimitry Andric
751*700637cbSDimitry Andric APFloat F = E->getValue();
752*700637cbSDimitry Andric return this->emitFloat(F, E);
753*700637cbSDimitry Andric }
754*700637cbSDimitry Andric
755*700637cbSDimitry Andric template <class Emitter>
VisitImaginaryLiteral(const ImaginaryLiteral * E)756*700637cbSDimitry Andric bool Compiler<Emitter>::VisitImaginaryLiteral(const ImaginaryLiteral *E) {
757*700637cbSDimitry Andric assert(E->getType()->isAnyComplexType());
758*700637cbSDimitry Andric if (DiscardResult)
759*700637cbSDimitry Andric return true;
760*700637cbSDimitry Andric
761*700637cbSDimitry Andric if (!Initializing) {
762*700637cbSDimitry Andric std::optional<unsigned> LocalIndex = allocateTemporary(E);
763*700637cbSDimitry Andric if (!LocalIndex)
764*700637cbSDimitry Andric return false;
765*700637cbSDimitry Andric if (!this->emitGetPtrLocal(*LocalIndex, E))
766*700637cbSDimitry Andric return false;
767*700637cbSDimitry Andric }
768*700637cbSDimitry Andric
769*700637cbSDimitry Andric const Expr *SubExpr = E->getSubExpr();
770*700637cbSDimitry Andric PrimType SubExprT = classifyPrim(SubExpr->getType());
771*700637cbSDimitry Andric
772*700637cbSDimitry Andric if (!this->visitZeroInitializer(SubExprT, SubExpr->getType(), SubExpr))
773*700637cbSDimitry Andric return false;
774*700637cbSDimitry Andric if (!this->emitInitElem(SubExprT, 0, SubExpr))
775*700637cbSDimitry Andric return false;
776*700637cbSDimitry Andric return this->visitArrayElemInit(1, SubExpr, SubExprT);
777*700637cbSDimitry Andric }
778*700637cbSDimitry Andric
779*700637cbSDimitry Andric template <class Emitter>
VisitFixedPointLiteral(const FixedPointLiteral * E)780*700637cbSDimitry Andric bool Compiler<Emitter>::VisitFixedPointLiteral(const FixedPointLiteral *E) {
781*700637cbSDimitry Andric assert(E->getType()->isFixedPointType());
782*700637cbSDimitry Andric assert(classifyPrim(E) == PT_FixedPoint);
783*700637cbSDimitry Andric
784*700637cbSDimitry Andric if (DiscardResult)
785*700637cbSDimitry Andric return true;
786*700637cbSDimitry Andric
787*700637cbSDimitry Andric auto Sem = Ctx.getASTContext().getFixedPointSemantics(E->getType());
788*700637cbSDimitry Andric APInt Value = E->getValue();
789*700637cbSDimitry Andric return this->emitConstFixedPoint(FixedPoint(Value, Sem), E);
790*700637cbSDimitry Andric }
791*700637cbSDimitry Andric
792*700637cbSDimitry Andric template <class Emitter>
VisitParenExpr(const ParenExpr * E)793*700637cbSDimitry Andric bool Compiler<Emitter>::VisitParenExpr(const ParenExpr *E) {
794*700637cbSDimitry Andric return this->delegate(E->getSubExpr());
795*700637cbSDimitry Andric }
796*700637cbSDimitry Andric
797*700637cbSDimitry Andric template <class Emitter>
VisitBinaryOperator(const BinaryOperator * BO)798*700637cbSDimitry Andric bool Compiler<Emitter>::VisitBinaryOperator(const BinaryOperator *BO) {
799*700637cbSDimitry Andric // Need short-circuiting for these.
800*700637cbSDimitry Andric if (BO->isLogicalOp() && !BO->getType()->isVectorType())
801*700637cbSDimitry Andric return this->VisitLogicalBinOp(BO);
802*700637cbSDimitry Andric
803*700637cbSDimitry Andric const Expr *LHS = BO->getLHS();
804*700637cbSDimitry Andric const Expr *RHS = BO->getRHS();
805*700637cbSDimitry Andric
806*700637cbSDimitry Andric // Handle comma operators. Just discard the LHS
807*700637cbSDimitry Andric // and delegate to RHS.
808*700637cbSDimitry Andric if (BO->isCommaOp()) {
809*700637cbSDimitry Andric if (!this->discard(LHS))
810*700637cbSDimitry Andric return false;
811*700637cbSDimitry Andric if (RHS->getType()->isVoidType())
812*700637cbSDimitry Andric return this->discard(RHS);
813*700637cbSDimitry Andric
814*700637cbSDimitry Andric return this->delegate(RHS);
815*700637cbSDimitry Andric }
816*700637cbSDimitry Andric
817*700637cbSDimitry Andric if (BO->getType()->isAnyComplexType())
818*700637cbSDimitry Andric return this->VisitComplexBinOp(BO);
819*700637cbSDimitry Andric if (BO->getType()->isVectorType())
820*700637cbSDimitry Andric return this->VisitVectorBinOp(BO);
821*700637cbSDimitry Andric if ((LHS->getType()->isAnyComplexType() ||
822*700637cbSDimitry Andric RHS->getType()->isAnyComplexType()) &&
823*700637cbSDimitry Andric BO->isComparisonOp())
824*700637cbSDimitry Andric return this->emitComplexComparison(LHS, RHS, BO);
825*700637cbSDimitry Andric if (LHS->getType()->isFixedPointType() || RHS->getType()->isFixedPointType())
826*700637cbSDimitry Andric return this->VisitFixedPointBinOp(BO);
827*700637cbSDimitry Andric
828*700637cbSDimitry Andric if (BO->isPtrMemOp()) {
829*700637cbSDimitry Andric if (!this->visit(LHS))
830*700637cbSDimitry Andric return false;
831*700637cbSDimitry Andric
832*700637cbSDimitry Andric if (!this->visit(RHS))
833*700637cbSDimitry Andric return false;
834*700637cbSDimitry Andric
835*700637cbSDimitry Andric if (!this->emitToMemberPtr(BO))
836*700637cbSDimitry Andric return false;
837*700637cbSDimitry Andric
838*700637cbSDimitry Andric if (classifyPrim(BO) == PT_MemberPtr)
839*700637cbSDimitry Andric return true;
840*700637cbSDimitry Andric
841*700637cbSDimitry Andric if (!this->emitCastMemberPtrPtr(BO))
842*700637cbSDimitry Andric return false;
843*700637cbSDimitry Andric return DiscardResult ? this->emitPopPtr(BO) : true;
844*700637cbSDimitry Andric }
845*700637cbSDimitry Andric
846*700637cbSDimitry Andric // Typecheck the args.
847*700637cbSDimitry Andric std::optional<PrimType> LT = classify(LHS);
848*700637cbSDimitry Andric std::optional<PrimType> RT = classify(RHS);
849*700637cbSDimitry Andric std::optional<PrimType> T = classify(BO->getType());
850*700637cbSDimitry Andric
851*700637cbSDimitry Andric // Special case for C++'s three-way/spaceship operator <=>, which
852*700637cbSDimitry Andric // returns a std::{strong,weak,partial}_ordering (which is a class, so doesn't
853*700637cbSDimitry Andric // have a PrimType).
854*700637cbSDimitry Andric if (!T && BO->getOpcode() == BO_Cmp) {
855*700637cbSDimitry Andric if (DiscardResult)
856*700637cbSDimitry Andric return true;
857*700637cbSDimitry Andric const ComparisonCategoryInfo *CmpInfo =
858*700637cbSDimitry Andric Ctx.getASTContext().CompCategories.lookupInfoForType(BO->getType());
859*700637cbSDimitry Andric assert(CmpInfo);
860*700637cbSDimitry Andric
861*700637cbSDimitry Andric // We need a temporary variable holding our return value.
862*700637cbSDimitry Andric if (!Initializing) {
863*700637cbSDimitry Andric std::optional<unsigned> ResultIndex = this->allocateLocal(BO);
864*700637cbSDimitry Andric if (!this->emitGetPtrLocal(*ResultIndex, BO))
865*700637cbSDimitry Andric return false;
866*700637cbSDimitry Andric }
867*700637cbSDimitry Andric
868*700637cbSDimitry Andric if (!visit(LHS) || !visit(RHS))
869*700637cbSDimitry Andric return false;
870*700637cbSDimitry Andric
871*700637cbSDimitry Andric return this->emitCMP3(*LT, CmpInfo, BO);
872*700637cbSDimitry Andric }
873*700637cbSDimitry Andric
874*700637cbSDimitry Andric if (!LT || !RT || !T)
875*700637cbSDimitry Andric return false;
876*700637cbSDimitry Andric
877*700637cbSDimitry Andric // Pointer arithmetic special case.
878*700637cbSDimitry Andric if (BO->getOpcode() == BO_Add || BO->getOpcode() == BO_Sub) {
879*700637cbSDimitry Andric if (isPtrType(*T) || (isPtrType(*LT) && isPtrType(*RT)))
880*700637cbSDimitry Andric return this->VisitPointerArithBinOp(BO);
881*700637cbSDimitry Andric }
882*700637cbSDimitry Andric
883*700637cbSDimitry Andric // Assignments require us to evalute the RHS first.
884*700637cbSDimitry Andric if (BO->getOpcode() == BO_Assign) {
885*700637cbSDimitry Andric
886*700637cbSDimitry Andric if (!visit(RHS) || !visit(LHS))
887*700637cbSDimitry Andric return false;
888*700637cbSDimitry Andric
889*700637cbSDimitry Andric // We don't support assignments in C.
890*700637cbSDimitry Andric if (!Ctx.getLangOpts().CPlusPlus && !this->emitInvalid(BO))
891*700637cbSDimitry Andric return false;
892*700637cbSDimitry Andric
893*700637cbSDimitry Andric if (!this->emitFlip(*LT, *RT, BO))
894*700637cbSDimitry Andric return false;
895*700637cbSDimitry Andric } else {
896*700637cbSDimitry Andric if (!visit(LHS) || !visit(RHS))
897*700637cbSDimitry Andric return false;
898*700637cbSDimitry Andric }
899*700637cbSDimitry Andric
900*700637cbSDimitry Andric // For languages such as C, cast the result of one
901*700637cbSDimitry Andric // of our comparision opcodes to T (which is usually int).
902*700637cbSDimitry Andric auto MaybeCastToBool = [this, T, BO](bool Result) {
903*700637cbSDimitry Andric if (!Result)
904*700637cbSDimitry Andric return false;
905*700637cbSDimitry Andric if (DiscardResult)
906*700637cbSDimitry Andric return this->emitPop(*T, BO);
907*700637cbSDimitry Andric if (T != PT_Bool)
908*700637cbSDimitry Andric return this->emitCast(PT_Bool, *T, BO);
909*700637cbSDimitry Andric return true;
910*700637cbSDimitry Andric };
911*700637cbSDimitry Andric
912*700637cbSDimitry Andric auto Discard = [this, T, BO](bool Result) {
913*700637cbSDimitry Andric if (!Result)
914*700637cbSDimitry Andric return false;
915*700637cbSDimitry Andric return DiscardResult ? this->emitPop(*T, BO) : true;
916*700637cbSDimitry Andric };
917*700637cbSDimitry Andric
918*700637cbSDimitry Andric switch (BO->getOpcode()) {
919*700637cbSDimitry Andric case BO_EQ:
920*700637cbSDimitry Andric return MaybeCastToBool(this->emitEQ(*LT, BO));
921*700637cbSDimitry Andric case BO_NE:
922*700637cbSDimitry Andric return MaybeCastToBool(this->emitNE(*LT, BO));
923*700637cbSDimitry Andric case BO_LT:
924*700637cbSDimitry Andric return MaybeCastToBool(this->emitLT(*LT, BO));
925*700637cbSDimitry Andric case BO_LE:
926*700637cbSDimitry Andric return MaybeCastToBool(this->emitLE(*LT, BO));
927*700637cbSDimitry Andric case BO_GT:
928*700637cbSDimitry Andric return MaybeCastToBool(this->emitGT(*LT, BO));
929*700637cbSDimitry Andric case BO_GE:
930*700637cbSDimitry Andric return MaybeCastToBool(this->emitGE(*LT, BO));
931*700637cbSDimitry Andric case BO_Sub:
932*700637cbSDimitry Andric if (BO->getType()->isFloatingType())
933*700637cbSDimitry Andric return Discard(this->emitSubf(getFPOptions(BO), BO));
934*700637cbSDimitry Andric return Discard(this->emitSub(*T, BO));
935*700637cbSDimitry Andric case BO_Add:
936*700637cbSDimitry Andric if (BO->getType()->isFloatingType())
937*700637cbSDimitry Andric return Discard(this->emitAddf(getFPOptions(BO), BO));
938*700637cbSDimitry Andric return Discard(this->emitAdd(*T, BO));
939*700637cbSDimitry Andric case BO_Mul:
940*700637cbSDimitry Andric if (BO->getType()->isFloatingType())
941*700637cbSDimitry Andric return Discard(this->emitMulf(getFPOptions(BO), BO));
942*700637cbSDimitry Andric return Discard(this->emitMul(*T, BO));
943*700637cbSDimitry Andric case BO_Rem:
944*700637cbSDimitry Andric return Discard(this->emitRem(*T, BO));
945*700637cbSDimitry Andric case BO_Div:
946*700637cbSDimitry Andric if (BO->getType()->isFloatingType())
947*700637cbSDimitry Andric return Discard(this->emitDivf(getFPOptions(BO), BO));
948*700637cbSDimitry Andric return Discard(this->emitDiv(*T, BO));
949*700637cbSDimitry Andric case BO_Assign:
950*700637cbSDimitry Andric if (DiscardResult)
951*700637cbSDimitry Andric return LHS->refersToBitField() ? this->emitStoreBitFieldPop(*T, BO)
952*700637cbSDimitry Andric : this->emitStorePop(*T, BO);
953*700637cbSDimitry Andric if (LHS->refersToBitField()) {
954*700637cbSDimitry Andric if (!this->emitStoreBitField(*T, BO))
955*700637cbSDimitry Andric return false;
956*700637cbSDimitry Andric } else {
957*700637cbSDimitry Andric if (!this->emitStore(*T, BO))
958*700637cbSDimitry Andric return false;
959*700637cbSDimitry Andric }
960*700637cbSDimitry Andric // Assignments aren't necessarily lvalues in C.
961*700637cbSDimitry Andric // Load from them in that case.
962*700637cbSDimitry Andric if (!BO->isLValue())
963*700637cbSDimitry Andric return this->emitLoadPop(*T, BO);
964*700637cbSDimitry Andric return true;
965*700637cbSDimitry Andric case BO_And:
966*700637cbSDimitry Andric return Discard(this->emitBitAnd(*T, BO));
967*700637cbSDimitry Andric case BO_Or:
968*700637cbSDimitry Andric return Discard(this->emitBitOr(*T, BO));
969*700637cbSDimitry Andric case BO_Shl:
970*700637cbSDimitry Andric return Discard(this->emitShl(*LT, *RT, BO));
971*700637cbSDimitry Andric case BO_Shr:
972*700637cbSDimitry Andric return Discard(this->emitShr(*LT, *RT, BO));
973*700637cbSDimitry Andric case BO_Xor:
974*700637cbSDimitry Andric return Discard(this->emitBitXor(*T, BO));
975*700637cbSDimitry Andric case BO_LOr:
976*700637cbSDimitry Andric case BO_LAnd:
977*700637cbSDimitry Andric llvm_unreachable("Already handled earlier");
978*700637cbSDimitry Andric default:
979*700637cbSDimitry Andric return false;
980*700637cbSDimitry Andric }
981*700637cbSDimitry Andric
982*700637cbSDimitry Andric llvm_unreachable("Unhandled binary op");
983*700637cbSDimitry Andric }
984*700637cbSDimitry Andric
985*700637cbSDimitry Andric /// Perform addition/subtraction of a pointer and an integer or
986*700637cbSDimitry Andric /// subtraction of two pointers.
987*700637cbSDimitry Andric template <class Emitter>
VisitPointerArithBinOp(const BinaryOperator * E)988*700637cbSDimitry Andric bool Compiler<Emitter>::VisitPointerArithBinOp(const BinaryOperator *E) {
989*700637cbSDimitry Andric BinaryOperatorKind Op = E->getOpcode();
990*700637cbSDimitry Andric const Expr *LHS = E->getLHS();
991*700637cbSDimitry Andric const Expr *RHS = E->getRHS();
992*700637cbSDimitry Andric
993*700637cbSDimitry Andric if ((Op != BO_Add && Op != BO_Sub) ||
994*700637cbSDimitry Andric (!LHS->getType()->isPointerType() && !RHS->getType()->isPointerType()))
995*700637cbSDimitry Andric return false;
996*700637cbSDimitry Andric
997*700637cbSDimitry Andric std::optional<PrimType> LT = classify(LHS);
998*700637cbSDimitry Andric std::optional<PrimType> RT = classify(RHS);
999*700637cbSDimitry Andric
1000*700637cbSDimitry Andric if (!LT || !RT)
1001*700637cbSDimitry Andric return false;
1002*700637cbSDimitry Andric
1003*700637cbSDimitry Andric // Visit the given pointer expression and optionally convert to a PT_Ptr.
1004*700637cbSDimitry Andric auto visitAsPointer = [&](const Expr *E, PrimType T) -> bool {
1005*700637cbSDimitry Andric if (!this->visit(E))
1006*700637cbSDimitry Andric return false;
1007*700637cbSDimitry Andric if (T != PT_Ptr)
1008*700637cbSDimitry Andric return this->emitDecayPtr(T, PT_Ptr, E);
1009*700637cbSDimitry Andric return true;
1010*700637cbSDimitry Andric };
1011*700637cbSDimitry Andric
1012*700637cbSDimitry Andric if (LHS->getType()->isPointerType() && RHS->getType()->isPointerType()) {
1013*700637cbSDimitry Andric if (Op != BO_Sub)
1014*700637cbSDimitry Andric return false;
1015*700637cbSDimitry Andric
1016*700637cbSDimitry Andric assert(E->getType()->isIntegerType());
1017*700637cbSDimitry Andric if (!visitAsPointer(RHS, *RT) || !visitAsPointer(LHS, *LT))
1018*700637cbSDimitry Andric return false;
1019*700637cbSDimitry Andric
1020*700637cbSDimitry Andric PrimType IntT = classifyPrim(E->getType());
1021*700637cbSDimitry Andric if (!this->emitSubPtr(IntT, E))
1022*700637cbSDimitry Andric return false;
1023*700637cbSDimitry Andric return DiscardResult ? this->emitPop(IntT, E) : true;
1024*700637cbSDimitry Andric }
1025*700637cbSDimitry Andric
1026*700637cbSDimitry Andric PrimType OffsetType;
1027*700637cbSDimitry Andric if (LHS->getType()->isIntegerType()) {
1028*700637cbSDimitry Andric if (!visitAsPointer(RHS, *RT))
1029*700637cbSDimitry Andric return false;
1030*700637cbSDimitry Andric if (!this->visit(LHS))
1031*700637cbSDimitry Andric return false;
1032*700637cbSDimitry Andric OffsetType = *LT;
1033*700637cbSDimitry Andric } else if (RHS->getType()->isIntegerType()) {
1034*700637cbSDimitry Andric if (!visitAsPointer(LHS, *LT))
1035*700637cbSDimitry Andric return false;
1036*700637cbSDimitry Andric if (!this->visit(RHS))
1037*700637cbSDimitry Andric return false;
1038*700637cbSDimitry Andric OffsetType = *RT;
1039*700637cbSDimitry Andric } else {
1040*700637cbSDimitry Andric return false;
1041*700637cbSDimitry Andric }
1042*700637cbSDimitry Andric
1043*700637cbSDimitry Andric // Do the operation and optionally transform to
1044*700637cbSDimitry Andric // result pointer type.
1045*700637cbSDimitry Andric if (Op == BO_Add) {
1046*700637cbSDimitry Andric if (!this->emitAddOffset(OffsetType, E))
1047*700637cbSDimitry Andric return false;
1048*700637cbSDimitry Andric
1049*700637cbSDimitry Andric if (classifyPrim(E) != PT_Ptr)
1050*700637cbSDimitry Andric return this->emitDecayPtr(PT_Ptr, classifyPrim(E), E);
1051*700637cbSDimitry Andric return true;
1052*700637cbSDimitry Andric } else if (Op == BO_Sub) {
1053*700637cbSDimitry Andric if (!this->emitSubOffset(OffsetType, E))
1054*700637cbSDimitry Andric return false;
1055*700637cbSDimitry Andric
1056*700637cbSDimitry Andric if (classifyPrim(E) != PT_Ptr)
1057*700637cbSDimitry Andric return this->emitDecayPtr(PT_Ptr, classifyPrim(E), E);
1058*700637cbSDimitry Andric return true;
1059*700637cbSDimitry Andric }
1060*700637cbSDimitry Andric
1061*700637cbSDimitry Andric return false;
1062*700637cbSDimitry Andric }
1063*700637cbSDimitry Andric
1064*700637cbSDimitry Andric template <class Emitter>
VisitLogicalBinOp(const BinaryOperator * E)1065*700637cbSDimitry Andric bool Compiler<Emitter>::VisitLogicalBinOp(const BinaryOperator *E) {
1066*700637cbSDimitry Andric assert(E->isLogicalOp());
1067*700637cbSDimitry Andric BinaryOperatorKind Op = E->getOpcode();
1068*700637cbSDimitry Andric const Expr *LHS = E->getLHS();
1069*700637cbSDimitry Andric const Expr *RHS = E->getRHS();
1070*700637cbSDimitry Andric std::optional<PrimType> T = classify(E->getType());
1071*700637cbSDimitry Andric
1072*700637cbSDimitry Andric if (Op == BO_LOr) {
1073*700637cbSDimitry Andric // Logical OR. Visit LHS and only evaluate RHS if LHS was FALSE.
1074*700637cbSDimitry Andric LabelTy LabelTrue = this->getLabel();
1075*700637cbSDimitry Andric LabelTy LabelEnd = this->getLabel();
1076*700637cbSDimitry Andric
1077*700637cbSDimitry Andric if (!this->visitBool(LHS))
1078*700637cbSDimitry Andric return false;
1079*700637cbSDimitry Andric if (!this->jumpTrue(LabelTrue))
1080*700637cbSDimitry Andric return false;
1081*700637cbSDimitry Andric
1082*700637cbSDimitry Andric if (!this->visitBool(RHS))
1083*700637cbSDimitry Andric return false;
1084*700637cbSDimitry Andric if (!this->jump(LabelEnd))
1085*700637cbSDimitry Andric return false;
1086*700637cbSDimitry Andric
1087*700637cbSDimitry Andric this->emitLabel(LabelTrue);
1088*700637cbSDimitry Andric this->emitConstBool(true, E);
1089*700637cbSDimitry Andric this->fallthrough(LabelEnd);
1090*700637cbSDimitry Andric this->emitLabel(LabelEnd);
1091*700637cbSDimitry Andric
1092*700637cbSDimitry Andric } else {
1093*700637cbSDimitry Andric assert(Op == BO_LAnd);
1094*700637cbSDimitry Andric // Logical AND.
1095*700637cbSDimitry Andric // Visit LHS. Only visit RHS if LHS was TRUE.
1096*700637cbSDimitry Andric LabelTy LabelFalse = this->getLabel();
1097*700637cbSDimitry Andric LabelTy LabelEnd = this->getLabel();
1098*700637cbSDimitry Andric
1099*700637cbSDimitry Andric if (!this->visitBool(LHS))
1100*700637cbSDimitry Andric return false;
1101*700637cbSDimitry Andric if (!this->jumpFalse(LabelFalse))
1102*700637cbSDimitry Andric return false;
1103*700637cbSDimitry Andric
1104*700637cbSDimitry Andric if (!this->visitBool(RHS))
1105*700637cbSDimitry Andric return false;
1106*700637cbSDimitry Andric if (!this->jump(LabelEnd))
1107*700637cbSDimitry Andric return false;
1108*700637cbSDimitry Andric
1109*700637cbSDimitry Andric this->emitLabel(LabelFalse);
1110*700637cbSDimitry Andric this->emitConstBool(false, E);
1111*700637cbSDimitry Andric this->fallthrough(LabelEnd);
1112*700637cbSDimitry Andric this->emitLabel(LabelEnd);
1113*700637cbSDimitry Andric }
1114*700637cbSDimitry Andric
1115*700637cbSDimitry Andric if (DiscardResult)
1116*700637cbSDimitry Andric return this->emitPopBool(E);
1117*700637cbSDimitry Andric
1118*700637cbSDimitry Andric // For C, cast back to integer type.
1119*700637cbSDimitry Andric assert(T);
1120*700637cbSDimitry Andric if (T != PT_Bool)
1121*700637cbSDimitry Andric return this->emitCast(PT_Bool, *T, E);
1122*700637cbSDimitry Andric return true;
1123*700637cbSDimitry Andric }
1124*700637cbSDimitry Andric
1125*700637cbSDimitry Andric template <class Emitter>
VisitComplexBinOp(const BinaryOperator * E)1126*700637cbSDimitry Andric bool Compiler<Emitter>::VisitComplexBinOp(const BinaryOperator *E) {
1127*700637cbSDimitry Andric // Prepare storage for result.
1128*700637cbSDimitry Andric if (!Initializing) {
1129*700637cbSDimitry Andric std::optional<unsigned> LocalIndex = allocateTemporary(E);
1130*700637cbSDimitry Andric if (!LocalIndex)
1131*700637cbSDimitry Andric return false;
1132*700637cbSDimitry Andric if (!this->emitGetPtrLocal(*LocalIndex, E))
1133*700637cbSDimitry Andric return false;
1134*700637cbSDimitry Andric }
1135*700637cbSDimitry Andric
1136*700637cbSDimitry Andric // Both LHS and RHS might _not_ be of complex type, but one of them
1137*700637cbSDimitry Andric // needs to be.
1138*700637cbSDimitry Andric const Expr *LHS = E->getLHS();
1139*700637cbSDimitry Andric const Expr *RHS = E->getRHS();
1140*700637cbSDimitry Andric
1141*700637cbSDimitry Andric PrimType ResultElemT = this->classifyComplexElementType(E->getType());
1142*700637cbSDimitry Andric unsigned ResultOffset = ~0u;
1143*700637cbSDimitry Andric if (!DiscardResult)
1144*700637cbSDimitry Andric ResultOffset = this->allocateLocalPrimitive(E, PT_Ptr, /*IsConst=*/true);
1145*700637cbSDimitry Andric
1146*700637cbSDimitry Andric // Save result pointer in ResultOffset
1147*700637cbSDimitry Andric if (!this->DiscardResult) {
1148*700637cbSDimitry Andric if (!this->emitDupPtr(E))
1149*700637cbSDimitry Andric return false;
1150*700637cbSDimitry Andric if (!this->emitSetLocal(PT_Ptr, ResultOffset, E))
1151*700637cbSDimitry Andric return false;
1152*700637cbSDimitry Andric }
1153*700637cbSDimitry Andric QualType LHSType = LHS->getType();
1154*700637cbSDimitry Andric if (const auto *AT = LHSType->getAs<AtomicType>())
1155*700637cbSDimitry Andric LHSType = AT->getValueType();
1156*700637cbSDimitry Andric QualType RHSType = RHS->getType();
1157*700637cbSDimitry Andric if (const auto *AT = RHSType->getAs<AtomicType>())
1158*700637cbSDimitry Andric RHSType = AT->getValueType();
1159*700637cbSDimitry Andric
1160*700637cbSDimitry Andric bool LHSIsComplex = LHSType->isAnyComplexType();
1161*700637cbSDimitry Andric unsigned LHSOffset;
1162*700637cbSDimitry Andric bool RHSIsComplex = RHSType->isAnyComplexType();
1163*700637cbSDimitry Andric
1164*700637cbSDimitry Andric // For ComplexComplex Mul, we have special ops to make their implementation
1165*700637cbSDimitry Andric // easier.
1166*700637cbSDimitry Andric BinaryOperatorKind Op = E->getOpcode();
1167*700637cbSDimitry Andric if (Op == BO_Mul && LHSIsComplex && RHSIsComplex) {
1168*700637cbSDimitry Andric assert(classifyPrim(LHSType->getAs<ComplexType>()->getElementType()) ==
1169*700637cbSDimitry Andric classifyPrim(RHSType->getAs<ComplexType>()->getElementType()));
1170*700637cbSDimitry Andric PrimType ElemT =
1171*700637cbSDimitry Andric classifyPrim(LHSType->getAs<ComplexType>()->getElementType());
1172*700637cbSDimitry Andric if (!this->visit(LHS))
1173*700637cbSDimitry Andric return false;
1174*700637cbSDimitry Andric if (!this->visit(RHS))
1175*700637cbSDimitry Andric return false;
1176*700637cbSDimitry Andric return this->emitMulc(ElemT, E);
1177*700637cbSDimitry Andric }
1178*700637cbSDimitry Andric
1179*700637cbSDimitry Andric if (Op == BO_Div && RHSIsComplex) {
1180*700637cbSDimitry Andric QualType ElemQT = RHSType->getAs<ComplexType>()->getElementType();
1181*700637cbSDimitry Andric PrimType ElemT = classifyPrim(ElemQT);
1182*700637cbSDimitry Andric // If the LHS is not complex, we still need to do the full complex
1183*700637cbSDimitry Andric // division, so just stub create a complex value and stub it out with
1184*700637cbSDimitry Andric // the LHS and a zero.
1185*700637cbSDimitry Andric
1186*700637cbSDimitry Andric if (!LHSIsComplex) {
1187*700637cbSDimitry Andric // This is using the RHS type for the fake-complex LHS.
1188*700637cbSDimitry Andric std::optional<unsigned> LocalIndex = allocateTemporary(RHS);
1189*700637cbSDimitry Andric if (!LocalIndex)
1190*700637cbSDimitry Andric return false;
1191*700637cbSDimitry Andric LHSOffset = *LocalIndex;
1192*700637cbSDimitry Andric
1193*700637cbSDimitry Andric if (!this->emitGetPtrLocal(LHSOffset, E))
1194*700637cbSDimitry Andric return false;
1195*700637cbSDimitry Andric
1196*700637cbSDimitry Andric if (!this->visit(LHS))
1197*700637cbSDimitry Andric return false;
1198*700637cbSDimitry Andric // real is LHS
1199*700637cbSDimitry Andric if (!this->emitInitElem(ElemT, 0, E))
1200*700637cbSDimitry Andric return false;
1201*700637cbSDimitry Andric // imag is zero
1202*700637cbSDimitry Andric if (!this->visitZeroInitializer(ElemT, ElemQT, E))
1203*700637cbSDimitry Andric return false;
1204*700637cbSDimitry Andric if (!this->emitInitElem(ElemT, 1, E))
1205*700637cbSDimitry Andric return false;
1206*700637cbSDimitry Andric } else {
1207*700637cbSDimitry Andric if (!this->visit(LHS))
1208*700637cbSDimitry Andric return false;
1209*700637cbSDimitry Andric }
1210*700637cbSDimitry Andric
1211*700637cbSDimitry Andric if (!this->visit(RHS))
1212*700637cbSDimitry Andric return false;
1213*700637cbSDimitry Andric return this->emitDivc(ElemT, E);
1214*700637cbSDimitry Andric }
1215*700637cbSDimitry Andric
1216*700637cbSDimitry Andric // Evaluate LHS and save value to LHSOffset.
1217*700637cbSDimitry Andric if (LHSType->isAnyComplexType()) {
1218*700637cbSDimitry Andric LHSOffset = this->allocateLocalPrimitive(LHS, PT_Ptr, /*IsConst=*/true);
1219*700637cbSDimitry Andric if (!this->visit(LHS))
1220*700637cbSDimitry Andric return false;
1221*700637cbSDimitry Andric if (!this->emitSetLocal(PT_Ptr, LHSOffset, E))
1222*700637cbSDimitry Andric return false;
1223*700637cbSDimitry Andric } else {
1224*700637cbSDimitry Andric PrimType LHST = classifyPrim(LHSType);
1225*700637cbSDimitry Andric LHSOffset = this->allocateLocalPrimitive(LHS, LHST, /*IsConst=*/true);
1226*700637cbSDimitry Andric if (!this->visit(LHS))
1227*700637cbSDimitry Andric return false;
1228*700637cbSDimitry Andric if (!this->emitSetLocal(LHST, LHSOffset, E))
1229*700637cbSDimitry Andric return false;
1230*700637cbSDimitry Andric }
1231*700637cbSDimitry Andric
1232*700637cbSDimitry Andric // Same with RHS.
1233*700637cbSDimitry Andric unsigned RHSOffset;
1234*700637cbSDimitry Andric if (RHSType->isAnyComplexType()) {
1235*700637cbSDimitry Andric RHSOffset = this->allocateLocalPrimitive(RHS, PT_Ptr, /*IsConst=*/true);
1236*700637cbSDimitry Andric if (!this->visit(RHS))
1237*700637cbSDimitry Andric return false;
1238*700637cbSDimitry Andric if (!this->emitSetLocal(PT_Ptr, RHSOffset, E))
1239*700637cbSDimitry Andric return false;
1240*700637cbSDimitry Andric } else {
1241*700637cbSDimitry Andric PrimType RHST = classifyPrim(RHSType);
1242*700637cbSDimitry Andric RHSOffset = this->allocateLocalPrimitive(RHS, RHST, /*IsConst=*/true);
1243*700637cbSDimitry Andric if (!this->visit(RHS))
1244*700637cbSDimitry Andric return false;
1245*700637cbSDimitry Andric if (!this->emitSetLocal(RHST, RHSOffset, E))
1246*700637cbSDimitry Andric return false;
1247*700637cbSDimitry Andric }
1248*700637cbSDimitry Andric
1249*700637cbSDimitry Andric // For both LHS and RHS, either load the value from the complex pointer, or
1250*700637cbSDimitry Andric // directly from the local variable. For index 1 (i.e. the imaginary part),
1251*700637cbSDimitry Andric // just load 0 and do the operation anyway.
1252*700637cbSDimitry Andric auto loadComplexValue = [this](bool IsComplex, bool LoadZero,
1253*700637cbSDimitry Andric unsigned ElemIndex, unsigned Offset,
1254*700637cbSDimitry Andric const Expr *E) -> bool {
1255*700637cbSDimitry Andric if (IsComplex) {
1256*700637cbSDimitry Andric if (!this->emitGetLocal(PT_Ptr, Offset, E))
1257*700637cbSDimitry Andric return false;
1258*700637cbSDimitry Andric return this->emitArrayElemPop(classifyComplexElementType(E->getType()),
1259*700637cbSDimitry Andric ElemIndex, E);
1260*700637cbSDimitry Andric }
1261*700637cbSDimitry Andric if (ElemIndex == 0 || !LoadZero)
1262*700637cbSDimitry Andric return this->emitGetLocal(classifyPrim(E->getType()), Offset, E);
1263*700637cbSDimitry Andric return this->visitZeroInitializer(classifyPrim(E->getType()), E->getType(),
1264*700637cbSDimitry Andric E);
1265*700637cbSDimitry Andric };
1266*700637cbSDimitry Andric
1267*700637cbSDimitry Andric // Now we can get pointers to the LHS and RHS from the offsets above.
1268*700637cbSDimitry Andric for (unsigned ElemIndex = 0; ElemIndex != 2; ++ElemIndex) {
1269*700637cbSDimitry Andric // Result pointer for the store later.
1270*700637cbSDimitry Andric if (!this->DiscardResult) {
1271*700637cbSDimitry Andric if (!this->emitGetLocal(PT_Ptr, ResultOffset, E))
1272*700637cbSDimitry Andric return false;
1273*700637cbSDimitry Andric }
1274*700637cbSDimitry Andric
1275*700637cbSDimitry Andric // The actual operation.
1276*700637cbSDimitry Andric switch (Op) {
1277*700637cbSDimitry Andric case BO_Add:
1278*700637cbSDimitry Andric if (!loadComplexValue(LHSIsComplex, true, ElemIndex, LHSOffset, LHS))
1279*700637cbSDimitry Andric return false;
1280*700637cbSDimitry Andric
1281*700637cbSDimitry Andric if (!loadComplexValue(RHSIsComplex, true, ElemIndex, RHSOffset, RHS))
1282*700637cbSDimitry Andric return false;
1283*700637cbSDimitry Andric if (ResultElemT == PT_Float) {
1284*700637cbSDimitry Andric if (!this->emitAddf(getFPOptions(E), E))
1285*700637cbSDimitry Andric return false;
1286*700637cbSDimitry Andric } else {
1287*700637cbSDimitry Andric if (!this->emitAdd(ResultElemT, E))
1288*700637cbSDimitry Andric return false;
1289*700637cbSDimitry Andric }
1290*700637cbSDimitry Andric break;
1291*700637cbSDimitry Andric case BO_Sub:
1292*700637cbSDimitry Andric if (!loadComplexValue(LHSIsComplex, true, ElemIndex, LHSOffset, LHS))
1293*700637cbSDimitry Andric return false;
1294*700637cbSDimitry Andric
1295*700637cbSDimitry Andric if (!loadComplexValue(RHSIsComplex, true, ElemIndex, RHSOffset, RHS))
1296*700637cbSDimitry Andric return false;
1297*700637cbSDimitry Andric if (ResultElemT == PT_Float) {
1298*700637cbSDimitry Andric if (!this->emitSubf(getFPOptions(E), E))
1299*700637cbSDimitry Andric return false;
1300*700637cbSDimitry Andric } else {
1301*700637cbSDimitry Andric if (!this->emitSub(ResultElemT, E))
1302*700637cbSDimitry Andric return false;
1303*700637cbSDimitry Andric }
1304*700637cbSDimitry Andric break;
1305*700637cbSDimitry Andric case BO_Mul:
1306*700637cbSDimitry Andric if (!loadComplexValue(LHSIsComplex, false, ElemIndex, LHSOffset, LHS))
1307*700637cbSDimitry Andric return false;
1308*700637cbSDimitry Andric
1309*700637cbSDimitry Andric if (!loadComplexValue(RHSIsComplex, false, ElemIndex, RHSOffset, RHS))
1310*700637cbSDimitry Andric return false;
1311*700637cbSDimitry Andric
1312*700637cbSDimitry Andric if (ResultElemT == PT_Float) {
1313*700637cbSDimitry Andric if (!this->emitMulf(getFPOptions(E), E))
1314*700637cbSDimitry Andric return false;
1315*700637cbSDimitry Andric } else {
1316*700637cbSDimitry Andric if (!this->emitMul(ResultElemT, E))
1317*700637cbSDimitry Andric return false;
1318*700637cbSDimitry Andric }
1319*700637cbSDimitry Andric break;
1320*700637cbSDimitry Andric case BO_Div:
1321*700637cbSDimitry Andric assert(!RHSIsComplex);
1322*700637cbSDimitry Andric if (!loadComplexValue(LHSIsComplex, false, ElemIndex, LHSOffset, LHS))
1323*700637cbSDimitry Andric return false;
1324*700637cbSDimitry Andric
1325*700637cbSDimitry Andric if (!loadComplexValue(RHSIsComplex, false, ElemIndex, RHSOffset, RHS))
1326*700637cbSDimitry Andric return false;
1327*700637cbSDimitry Andric
1328*700637cbSDimitry Andric if (ResultElemT == PT_Float) {
1329*700637cbSDimitry Andric if (!this->emitDivf(getFPOptions(E), E))
1330*700637cbSDimitry Andric return false;
1331*700637cbSDimitry Andric } else {
1332*700637cbSDimitry Andric if (!this->emitDiv(ResultElemT, E))
1333*700637cbSDimitry Andric return false;
1334*700637cbSDimitry Andric }
1335*700637cbSDimitry Andric break;
1336*700637cbSDimitry Andric
1337*700637cbSDimitry Andric default:
1338*700637cbSDimitry Andric return false;
1339*700637cbSDimitry Andric }
1340*700637cbSDimitry Andric
1341*700637cbSDimitry Andric if (!this->DiscardResult) {
1342*700637cbSDimitry Andric // Initialize array element with the value we just computed.
1343*700637cbSDimitry Andric if (!this->emitInitElemPop(ResultElemT, ElemIndex, E))
1344*700637cbSDimitry Andric return false;
1345*700637cbSDimitry Andric } else {
1346*700637cbSDimitry Andric if (!this->emitPop(ResultElemT, E))
1347*700637cbSDimitry Andric return false;
1348*700637cbSDimitry Andric }
1349*700637cbSDimitry Andric }
1350*700637cbSDimitry Andric return true;
1351*700637cbSDimitry Andric }
1352*700637cbSDimitry Andric
1353*700637cbSDimitry Andric template <class Emitter>
VisitVectorBinOp(const BinaryOperator * E)1354*700637cbSDimitry Andric bool Compiler<Emitter>::VisitVectorBinOp(const BinaryOperator *E) {
1355*700637cbSDimitry Andric assert(!E->isCommaOp() &&
1356*700637cbSDimitry Andric "Comma op should be handled in VisitBinaryOperator");
1357*700637cbSDimitry Andric assert(E->getType()->isVectorType());
1358*700637cbSDimitry Andric assert(E->getLHS()->getType()->isVectorType());
1359*700637cbSDimitry Andric assert(E->getRHS()->getType()->isVectorType());
1360*700637cbSDimitry Andric
1361*700637cbSDimitry Andric // Prepare storage for result.
1362*700637cbSDimitry Andric if (!Initializing && !E->isCompoundAssignmentOp()) {
1363*700637cbSDimitry Andric std::optional<unsigned> LocalIndex = allocateTemporary(E);
1364*700637cbSDimitry Andric if (!LocalIndex)
1365*700637cbSDimitry Andric return false;
1366*700637cbSDimitry Andric if (!this->emitGetPtrLocal(*LocalIndex, E))
1367*700637cbSDimitry Andric return false;
1368*700637cbSDimitry Andric }
1369*700637cbSDimitry Andric
1370*700637cbSDimitry Andric const Expr *LHS = E->getLHS();
1371*700637cbSDimitry Andric const Expr *RHS = E->getRHS();
1372*700637cbSDimitry Andric const auto *VecTy = E->getType()->getAs<VectorType>();
1373*700637cbSDimitry Andric auto Op = E->isCompoundAssignmentOp()
1374*700637cbSDimitry Andric ? BinaryOperator::getOpForCompoundAssignment(E->getOpcode())
1375*700637cbSDimitry Andric : E->getOpcode();
1376*700637cbSDimitry Andric
1377*700637cbSDimitry Andric PrimType ElemT = this->classifyVectorElementType(LHS->getType());
1378*700637cbSDimitry Andric PrimType RHSElemT = this->classifyVectorElementType(RHS->getType());
1379*700637cbSDimitry Andric PrimType ResultElemT = this->classifyVectorElementType(E->getType());
1380*700637cbSDimitry Andric
1381*700637cbSDimitry Andric // Evaluate LHS and save value to LHSOffset.
1382*700637cbSDimitry Andric unsigned LHSOffset =
1383*700637cbSDimitry Andric this->allocateLocalPrimitive(LHS, PT_Ptr, /*IsConst=*/true);
1384*700637cbSDimitry Andric if (!this->visit(LHS))
1385*700637cbSDimitry Andric return false;
1386*700637cbSDimitry Andric if (!this->emitSetLocal(PT_Ptr, LHSOffset, E))
1387*700637cbSDimitry Andric return false;
1388*700637cbSDimitry Andric
1389*700637cbSDimitry Andric // Evaluate RHS and save value to RHSOffset.
1390*700637cbSDimitry Andric unsigned RHSOffset =
1391*700637cbSDimitry Andric this->allocateLocalPrimitive(RHS, PT_Ptr, /*IsConst=*/true);
1392*700637cbSDimitry Andric if (!this->visit(RHS))
1393*700637cbSDimitry Andric return false;
1394*700637cbSDimitry Andric if (!this->emitSetLocal(PT_Ptr, RHSOffset, E))
1395*700637cbSDimitry Andric return false;
1396*700637cbSDimitry Andric
1397*700637cbSDimitry Andric if (E->isCompoundAssignmentOp() && !this->emitGetLocal(PT_Ptr, LHSOffset, E))
1398*700637cbSDimitry Andric return false;
1399*700637cbSDimitry Andric
1400*700637cbSDimitry Andric // BitAdd/BitOr/BitXor/Shl/Shr doesn't support bool type, we need perform the
1401*700637cbSDimitry Andric // integer promotion.
1402*700637cbSDimitry Andric bool NeedIntPromot = ElemT == PT_Bool && (E->isBitwiseOp() || E->isShiftOp());
1403*700637cbSDimitry Andric QualType PromotTy =
1404*700637cbSDimitry Andric Ctx.getASTContext().getPromotedIntegerType(Ctx.getASTContext().BoolTy);
1405*700637cbSDimitry Andric PrimType PromotT = classifyPrim(PromotTy);
1406*700637cbSDimitry Andric PrimType OpT = NeedIntPromot ? PromotT : ElemT;
1407*700637cbSDimitry Andric
1408*700637cbSDimitry Andric auto getElem = [=](unsigned Offset, PrimType ElemT, unsigned Index) {
1409*700637cbSDimitry Andric if (!this->emitGetLocal(PT_Ptr, Offset, E))
1410*700637cbSDimitry Andric return false;
1411*700637cbSDimitry Andric if (!this->emitArrayElemPop(ElemT, Index, E))
1412*700637cbSDimitry Andric return false;
1413*700637cbSDimitry Andric if (E->isLogicalOp()) {
1414*700637cbSDimitry Andric if (!this->emitPrimCast(ElemT, PT_Bool, Ctx.getASTContext().BoolTy, E))
1415*700637cbSDimitry Andric return false;
1416*700637cbSDimitry Andric if (!this->emitPrimCast(PT_Bool, ResultElemT, VecTy->getElementType(), E))
1417*700637cbSDimitry Andric return false;
1418*700637cbSDimitry Andric } else if (NeedIntPromot) {
1419*700637cbSDimitry Andric if (!this->emitPrimCast(ElemT, PromotT, PromotTy, E))
1420*700637cbSDimitry Andric return false;
1421*700637cbSDimitry Andric }
1422*700637cbSDimitry Andric return true;
1423*700637cbSDimitry Andric };
1424*700637cbSDimitry Andric
1425*700637cbSDimitry Andric #define EMIT_ARITH_OP(OP) \
1426*700637cbSDimitry Andric { \
1427*700637cbSDimitry Andric if (ElemT == PT_Float) { \
1428*700637cbSDimitry Andric if (!this->emit##OP##f(getFPOptions(E), E)) \
1429*700637cbSDimitry Andric return false; \
1430*700637cbSDimitry Andric } else { \
1431*700637cbSDimitry Andric if (!this->emit##OP(ElemT, E)) \
1432*700637cbSDimitry Andric return false; \
1433*700637cbSDimitry Andric } \
1434*700637cbSDimitry Andric break; \
1435*700637cbSDimitry Andric }
1436*700637cbSDimitry Andric
1437*700637cbSDimitry Andric for (unsigned I = 0; I != VecTy->getNumElements(); ++I) {
1438*700637cbSDimitry Andric if (!getElem(LHSOffset, ElemT, I))
1439*700637cbSDimitry Andric return false;
1440*700637cbSDimitry Andric if (!getElem(RHSOffset, RHSElemT, I))
1441*700637cbSDimitry Andric return false;
1442*700637cbSDimitry Andric switch (Op) {
1443*700637cbSDimitry Andric case BO_Add:
1444*700637cbSDimitry Andric EMIT_ARITH_OP(Add)
1445*700637cbSDimitry Andric case BO_Sub:
1446*700637cbSDimitry Andric EMIT_ARITH_OP(Sub)
1447*700637cbSDimitry Andric case BO_Mul:
1448*700637cbSDimitry Andric EMIT_ARITH_OP(Mul)
1449*700637cbSDimitry Andric case BO_Div:
1450*700637cbSDimitry Andric EMIT_ARITH_OP(Div)
1451*700637cbSDimitry Andric case BO_Rem:
1452*700637cbSDimitry Andric if (!this->emitRem(ElemT, E))
1453*700637cbSDimitry Andric return false;
1454*700637cbSDimitry Andric break;
1455*700637cbSDimitry Andric case BO_And:
1456*700637cbSDimitry Andric if (!this->emitBitAnd(OpT, E))
1457*700637cbSDimitry Andric return false;
1458*700637cbSDimitry Andric break;
1459*700637cbSDimitry Andric case BO_Or:
1460*700637cbSDimitry Andric if (!this->emitBitOr(OpT, E))
1461*700637cbSDimitry Andric return false;
1462*700637cbSDimitry Andric break;
1463*700637cbSDimitry Andric case BO_Xor:
1464*700637cbSDimitry Andric if (!this->emitBitXor(OpT, E))
1465*700637cbSDimitry Andric return false;
1466*700637cbSDimitry Andric break;
1467*700637cbSDimitry Andric case BO_Shl:
1468*700637cbSDimitry Andric if (!this->emitShl(OpT, RHSElemT, E))
1469*700637cbSDimitry Andric return false;
1470*700637cbSDimitry Andric break;
1471*700637cbSDimitry Andric case BO_Shr:
1472*700637cbSDimitry Andric if (!this->emitShr(OpT, RHSElemT, E))
1473*700637cbSDimitry Andric return false;
1474*700637cbSDimitry Andric break;
1475*700637cbSDimitry Andric case BO_EQ:
1476*700637cbSDimitry Andric if (!this->emitEQ(ElemT, E))
1477*700637cbSDimitry Andric return false;
1478*700637cbSDimitry Andric break;
1479*700637cbSDimitry Andric case BO_NE:
1480*700637cbSDimitry Andric if (!this->emitNE(ElemT, E))
1481*700637cbSDimitry Andric return false;
1482*700637cbSDimitry Andric break;
1483*700637cbSDimitry Andric case BO_LE:
1484*700637cbSDimitry Andric if (!this->emitLE(ElemT, E))
1485*700637cbSDimitry Andric return false;
1486*700637cbSDimitry Andric break;
1487*700637cbSDimitry Andric case BO_LT:
1488*700637cbSDimitry Andric if (!this->emitLT(ElemT, E))
1489*700637cbSDimitry Andric return false;
1490*700637cbSDimitry Andric break;
1491*700637cbSDimitry Andric case BO_GE:
1492*700637cbSDimitry Andric if (!this->emitGE(ElemT, E))
1493*700637cbSDimitry Andric return false;
1494*700637cbSDimitry Andric break;
1495*700637cbSDimitry Andric case BO_GT:
1496*700637cbSDimitry Andric if (!this->emitGT(ElemT, E))
1497*700637cbSDimitry Andric return false;
1498*700637cbSDimitry Andric break;
1499*700637cbSDimitry Andric case BO_LAnd:
1500*700637cbSDimitry Andric // a && b is equivalent to a!=0 & b!=0
1501*700637cbSDimitry Andric if (!this->emitBitAnd(ResultElemT, E))
1502*700637cbSDimitry Andric return false;
1503*700637cbSDimitry Andric break;
1504*700637cbSDimitry Andric case BO_LOr:
1505*700637cbSDimitry Andric // a || b is equivalent to a!=0 | b!=0
1506*700637cbSDimitry Andric if (!this->emitBitOr(ResultElemT, E))
1507*700637cbSDimitry Andric return false;
1508*700637cbSDimitry Andric break;
1509*700637cbSDimitry Andric default:
1510*700637cbSDimitry Andric return this->emitInvalid(E);
1511*700637cbSDimitry Andric }
1512*700637cbSDimitry Andric
1513*700637cbSDimitry Andric // The result of the comparison is a vector of the same width and number
1514*700637cbSDimitry Andric // of elements as the comparison operands with a signed integral element
1515*700637cbSDimitry Andric // type.
1516*700637cbSDimitry Andric //
1517*700637cbSDimitry Andric // https://gcc.gnu.org/onlinedocs/gcc/Vector-Extensions.html
1518*700637cbSDimitry Andric if (E->isComparisonOp()) {
1519*700637cbSDimitry Andric if (!this->emitPrimCast(PT_Bool, ResultElemT, VecTy->getElementType(), E))
1520*700637cbSDimitry Andric return false;
1521*700637cbSDimitry Andric if (!this->emitNeg(ResultElemT, E))
1522*700637cbSDimitry Andric return false;
1523*700637cbSDimitry Andric }
1524*700637cbSDimitry Andric
1525*700637cbSDimitry Andric // If we performed an integer promotion, we need to cast the compute result
1526*700637cbSDimitry Andric // into result vector element type.
1527*700637cbSDimitry Andric if (NeedIntPromot &&
1528*700637cbSDimitry Andric !this->emitPrimCast(PromotT, ResultElemT, VecTy->getElementType(), E))
1529*700637cbSDimitry Andric return false;
1530*700637cbSDimitry Andric
1531*700637cbSDimitry Andric // Initialize array element with the value we just computed.
1532*700637cbSDimitry Andric if (!this->emitInitElem(ResultElemT, I, E))
1533*700637cbSDimitry Andric return false;
1534*700637cbSDimitry Andric }
1535*700637cbSDimitry Andric
1536*700637cbSDimitry Andric if (DiscardResult && E->isCompoundAssignmentOp() && !this->emitPopPtr(E))
1537*700637cbSDimitry Andric return false;
1538*700637cbSDimitry Andric return true;
1539*700637cbSDimitry Andric }
1540*700637cbSDimitry Andric
1541*700637cbSDimitry Andric template <class Emitter>
VisitFixedPointBinOp(const BinaryOperator * E)1542*700637cbSDimitry Andric bool Compiler<Emitter>::VisitFixedPointBinOp(const BinaryOperator *E) {
1543*700637cbSDimitry Andric const Expr *LHS = E->getLHS();
1544*700637cbSDimitry Andric const Expr *RHS = E->getRHS();
1545*700637cbSDimitry Andric const ASTContext &ASTCtx = Ctx.getASTContext();
1546*700637cbSDimitry Andric
1547*700637cbSDimitry Andric assert(LHS->getType()->isFixedPointType() ||
1548*700637cbSDimitry Andric RHS->getType()->isFixedPointType());
1549*700637cbSDimitry Andric
1550*700637cbSDimitry Andric auto LHSSema = ASTCtx.getFixedPointSemantics(LHS->getType());
1551*700637cbSDimitry Andric auto LHSSemaInt = LHSSema.toOpaqueInt();
1552*700637cbSDimitry Andric auto RHSSema = ASTCtx.getFixedPointSemantics(RHS->getType());
1553*700637cbSDimitry Andric auto RHSSemaInt = RHSSema.toOpaqueInt();
1554*700637cbSDimitry Andric
1555*700637cbSDimitry Andric if (!this->visit(LHS))
1556*700637cbSDimitry Andric return false;
1557*700637cbSDimitry Andric if (!LHS->getType()->isFixedPointType()) {
1558*700637cbSDimitry Andric if (!this->emitCastIntegralFixedPoint(classifyPrim(LHS->getType()),
1559*700637cbSDimitry Andric LHSSemaInt, E))
1560*700637cbSDimitry Andric return false;
1561*700637cbSDimitry Andric }
1562*700637cbSDimitry Andric
1563*700637cbSDimitry Andric if (!this->visit(RHS))
1564*700637cbSDimitry Andric return false;
1565*700637cbSDimitry Andric if (!RHS->getType()->isFixedPointType()) {
1566*700637cbSDimitry Andric if (!this->emitCastIntegralFixedPoint(classifyPrim(RHS->getType()),
1567*700637cbSDimitry Andric RHSSemaInt, E))
1568*700637cbSDimitry Andric return false;
1569*700637cbSDimitry Andric }
1570*700637cbSDimitry Andric
1571*700637cbSDimitry Andric // Convert the result to the target semantics.
1572*700637cbSDimitry Andric auto ConvertResult = [&](bool R) -> bool {
1573*700637cbSDimitry Andric if (!R)
1574*700637cbSDimitry Andric return false;
1575*700637cbSDimitry Andric auto ResultSema = ASTCtx.getFixedPointSemantics(E->getType()).toOpaqueInt();
1576*700637cbSDimitry Andric auto CommonSema = LHSSema.getCommonSemantics(RHSSema).toOpaqueInt();
1577*700637cbSDimitry Andric if (ResultSema != CommonSema)
1578*700637cbSDimitry Andric return this->emitCastFixedPoint(ResultSema, E);
1579*700637cbSDimitry Andric return true;
1580*700637cbSDimitry Andric };
1581*700637cbSDimitry Andric
1582*700637cbSDimitry Andric auto MaybeCastToBool = [&](bool Result) {
1583*700637cbSDimitry Andric if (!Result)
1584*700637cbSDimitry Andric return false;
1585*700637cbSDimitry Andric PrimType T = classifyPrim(E);
1586*700637cbSDimitry Andric if (DiscardResult)
1587*700637cbSDimitry Andric return this->emitPop(T, E);
1588*700637cbSDimitry Andric if (T != PT_Bool)
1589*700637cbSDimitry Andric return this->emitCast(PT_Bool, T, E);
1590*700637cbSDimitry Andric return true;
1591*700637cbSDimitry Andric };
1592*700637cbSDimitry Andric
1593*700637cbSDimitry Andric switch (E->getOpcode()) {
1594*700637cbSDimitry Andric case BO_EQ:
1595*700637cbSDimitry Andric return MaybeCastToBool(this->emitEQFixedPoint(E));
1596*700637cbSDimitry Andric case BO_NE:
1597*700637cbSDimitry Andric return MaybeCastToBool(this->emitNEFixedPoint(E));
1598*700637cbSDimitry Andric case BO_LT:
1599*700637cbSDimitry Andric return MaybeCastToBool(this->emitLTFixedPoint(E));
1600*700637cbSDimitry Andric case BO_LE:
1601*700637cbSDimitry Andric return MaybeCastToBool(this->emitLEFixedPoint(E));
1602*700637cbSDimitry Andric case BO_GT:
1603*700637cbSDimitry Andric return MaybeCastToBool(this->emitGTFixedPoint(E));
1604*700637cbSDimitry Andric case BO_GE:
1605*700637cbSDimitry Andric return MaybeCastToBool(this->emitGEFixedPoint(E));
1606*700637cbSDimitry Andric case BO_Add:
1607*700637cbSDimitry Andric return ConvertResult(this->emitAddFixedPoint(E));
1608*700637cbSDimitry Andric case BO_Sub:
1609*700637cbSDimitry Andric return ConvertResult(this->emitSubFixedPoint(E));
1610*700637cbSDimitry Andric case BO_Mul:
1611*700637cbSDimitry Andric return ConvertResult(this->emitMulFixedPoint(E));
1612*700637cbSDimitry Andric case BO_Div:
1613*700637cbSDimitry Andric return ConvertResult(this->emitDivFixedPoint(E));
1614*700637cbSDimitry Andric case BO_Shl:
1615*700637cbSDimitry Andric return ConvertResult(this->emitShiftFixedPoint(/*Left=*/true, E));
1616*700637cbSDimitry Andric case BO_Shr:
1617*700637cbSDimitry Andric return ConvertResult(this->emitShiftFixedPoint(/*Left=*/false, E));
1618*700637cbSDimitry Andric
1619*700637cbSDimitry Andric default:
1620*700637cbSDimitry Andric return this->emitInvalid(E);
1621*700637cbSDimitry Andric }
1622*700637cbSDimitry Andric
1623*700637cbSDimitry Andric llvm_unreachable("unhandled binop opcode");
1624*700637cbSDimitry Andric }
1625*700637cbSDimitry Andric
1626*700637cbSDimitry Andric template <class Emitter>
VisitFixedPointUnaryOperator(const UnaryOperator * E)1627*700637cbSDimitry Andric bool Compiler<Emitter>::VisitFixedPointUnaryOperator(const UnaryOperator *E) {
1628*700637cbSDimitry Andric const Expr *SubExpr = E->getSubExpr();
1629*700637cbSDimitry Andric assert(SubExpr->getType()->isFixedPointType());
1630*700637cbSDimitry Andric
1631*700637cbSDimitry Andric switch (E->getOpcode()) {
1632*700637cbSDimitry Andric case UO_Plus:
1633*700637cbSDimitry Andric return this->delegate(SubExpr);
1634*700637cbSDimitry Andric case UO_Minus:
1635*700637cbSDimitry Andric if (!this->visit(SubExpr))
1636*700637cbSDimitry Andric return false;
1637*700637cbSDimitry Andric return this->emitNegFixedPoint(E);
1638*700637cbSDimitry Andric default:
1639*700637cbSDimitry Andric return false;
1640*700637cbSDimitry Andric }
1641*700637cbSDimitry Andric
1642*700637cbSDimitry Andric llvm_unreachable("Unhandled unary opcode");
1643*700637cbSDimitry Andric }
1644*700637cbSDimitry Andric
1645*700637cbSDimitry Andric template <class Emitter>
VisitImplicitValueInitExpr(const ImplicitValueInitExpr * E)1646*700637cbSDimitry Andric bool Compiler<Emitter>::VisitImplicitValueInitExpr(
1647*700637cbSDimitry Andric const ImplicitValueInitExpr *E) {
1648*700637cbSDimitry Andric QualType QT = E->getType();
1649*700637cbSDimitry Andric
1650*700637cbSDimitry Andric if (std::optional<PrimType> T = classify(QT))
1651*700637cbSDimitry Andric return this->visitZeroInitializer(*T, QT, E);
1652*700637cbSDimitry Andric
1653*700637cbSDimitry Andric if (QT->isRecordType()) {
1654*700637cbSDimitry Andric const RecordDecl *RD = QT->getAsRecordDecl();
1655*700637cbSDimitry Andric assert(RD);
1656*700637cbSDimitry Andric if (RD->isInvalidDecl())
1657*700637cbSDimitry Andric return false;
1658*700637cbSDimitry Andric
1659*700637cbSDimitry Andric if (const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD);
1660*700637cbSDimitry Andric CXXRD && CXXRD->getNumVBases() > 0) {
1661*700637cbSDimitry Andric // TODO: Diagnose.
1662*700637cbSDimitry Andric return false;
1663*700637cbSDimitry Andric }
1664*700637cbSDimitry Andric
1665*700637cbSDimitry Andric const Record *R = getRecord(QT);
1666*700637cbSDimitry Andric if (!R)
1667*700637cbSDimitry Andric return false;
1668*700637cbSDimitry Andric
1669*700637cbSDimitry Andric assert(Initializing);
1670*700637cbSDimitry Andric return this->visitZeroRecordInitializer(R, E);
1671*700637cbSDimitry Andric }
1672*700637cbSDimitry Andric
1673*700637cbSDimitry Andric if (QT->isIncompleteArrayType())
1674*700637cbSDimitry Andric return true;
1675*700637cbSDimitry Andric
1676*700637cbSDimitry Andric if (QT->isArrayType())
1677*700637cbSDimitry Andric return this->visitZeroArrayInitializer(QT, E);
1678*700637cbSDimitry Andric
1679*700637cbSDimitry Andric if (const auto *ComplexTy = E->getType()->getAs<ComplexType>()) {
1680*700637cbSDimitry Andric assert(Initializing);
1681*700637cbSDimitry Andric QualType ElemQT = ComplexTy->getElementType();
1682*700637cbSDimitry Andric PrimType ElemT = classifyPrim(ElemQT);
1683*700637cbSDimitry Andric for (unsigned I = 0; I < 2; ++I) {
1684*700637cbSDimitry Andric if (!this->visitZeroInitializer(ElemT, ElemQT, E))
1685*700637cbSDimitry Andric return false;
1686*700637cbSDimitry Andric if (!this->emitInitElem(ElemT, I, E))
1687*700637cbSDimitry Andric return false;
1688*700637cbSDimitry Andric }
1689*700637cbSDimitry Andric return true;
1690*700637cbSDimitry Andric }
1691*700637cbSDimitry Andric
1692*700637cbSDimitry Andric if (const auto *VecT = E->getType()->getAs<VectorType>()) {
1693*700637cbSDimitry Andric unsigned NumVecElements = VecT->getNumElements();
1694*700637cbSDimitry Andric QualType ElemQT = VecT->getElementType();
1695*700637cbSDimitry Andric PrimType ElemT = classifyPrim(ElemQT);
1696*700637cbSDimitry Andric
1697*700637cbSDimitry Andric for (unsigned I = 0; I < NumVecElements; ++I) {
1698*700637cbSDimitry Andric if (!this->visitZeroInitializer(ElemT, ElemQT, E))
1699*700637cbSDimitry Andric return false;
1700*700637cbSDimitry Andric if (!this->emitInitElem(ElemT, I, E))
1701*700637cbSDimitry Andric return false;
1702*700637cbSDimitry Andric }
1703*700637cbSDimitry Andric return true;
1704*700637cbSDimitry Andric }
1705*700637cbSDimitry Andric
1706*700637cbSDimitry Andric return false;
1707*700637cbSDimitry Andric }
1708*700637cbSDimitry Andric
1709*700637cbSDimitry Andric template <class Emitter>
VisitArraySubscriptExpr(const ArraySubscriptExpr * E)1710*700637cbSDimitry Andric bool Compiler<Emitter>::VisitArraySubscriptExpr(const ArraySubscriptExpr *E) {
1711*700637cbSDimitry Andric const Expr *LHS = E->getLHS();
1712*700637cbSDimitry Andric const Expr *RHS = E->getRHS();
1713*700637cbSDimitry Andric const Expr *Index = E->getIdx();
1714*700637cbSDimitry Andric const Expr *Base = E->getBase();
1715*700637cbSDimitry Andric
1716*700637cbSDimitry Andric // C++17's rules require us to evaluate the LHS first, regardless of which
1717*700637cbSDimitry Andric // side is the base.
1718*700637cbSDimitry Andric bool Success = true;
1719*700637cbSDimitry Andric for (const Expr *SubExpr : {LHS, RHS}) {
1720*700637cbSDimitry Andric if (!this->visit(SubExpr)) {
1721*700637cbSDimitry Andric Success = false;
1722*700637cbSDimitry Andric continue;
1723*700637cbSDimitry Andric }
1724*700637cbSDimitry Andric
1725*700637cbSDimitry Andric // Expand the base if this is a subscript on a
1726*700637cbSDimitry Andric // pointer expression.
1727*700637cbSDimitry Andric if (SubExpr == Base && Base->getType()->isPointerType()) {
1728*700637cbSDimitry Andric if (!this->emitExpandPtr(E))
1729*700637cbSDimitry Andric Success = false;
1730*700637cbSDimitry Andric }
1731*700637cbSDimitry Andric }
1732*700637cbSDimitry Andric
1733*700637cbSDimitry Andric if (!Success)
1734*700637cbSDimitry Andric return false;
1735*700637cbSDimitry Andric
1736*700637cbSDimitry Andric std::optional<PrimType> IndexT = classify(Index->getType());
1737*700637cbSDimitry Andric // In error-recovery cases, the index expression has a dependent type.
1738*700637cbSDimitry Andric if (!IndexT)
1739*700637cbSDimitry Andric return this->emitError(E);
1740*700637cbSDimitry Andric // If the index is first, we need to change that.
1741*700637cbSDimitry Andric if (LHS == Index) {
1742*700637cbSDimitry Andric if (!this->emitFlip(PT_Ptr, *IndexT, E))
1743*700637cbSDimitry Andric return false;
1744*700637cbSDimitry Andric }
1745*700637cbSDimitry Andric
1746*700637cbSDimitry Andric if (!this->emitArrayElemPtrPop(*IndexT, E))
1747*700637cbSDimitry Andric return false;
1748*700637cbSDimitry Andric if (DiscardResult)
1749*700637cbSDimitry Andric return this->emitPopPtr(E);
1750*700637cbSDimitry Andric return true;
1751*700637cbSDimitry Andric }
1752*700637cbSDimitry Andric
1753*700637cbSDimitry Andric template <class Emitter>
visitInitList(ArrayRef<const Expr * > Inits,const Expr * ArrayFiller,const Expr * E)1754*700637cbSDimitry Andric bool Compiler<Emitter>::visitInitList(ArrayRef<const Expr *> Inits,
1755*700637cbSDimitry Andric const Expr *ArrayFiller, const Expr *E) {
1756*700637cbSDimitry Andric InitLinkScope<Emitter> ILS(this, InitLink::InitList());
1757*700637cbSDimitry Andric
1758*700637cbSDimitry Andric QualType QT = E->getType();
1759*700637cbSDimitry Andric if (const auto *AT = QT->getAs<AtomicType>())
1760*700637cbSDimitry Andric QT = AT->getValueType();
1761*700637cbSDimitry Andric
1762*700637cbSDimitry Andric if (QT->isVoidType()) {
1763*700637cbSDimitry Andric if (Inits.size() == 0)
1764*700637cbSDimitry Andric return true;
1765*700637cbSDimitry Andric return this->emitInvalid(E);
1766*700637cbSDimitry Andric }
1767*700637cbSDimitry Andric
1768*700637cbSDimitry Andric // Handle discarding first.
1769*700637cbSDimitry Andric if (DiscardResult) {
1770*700637cbSDimitry Andric for (const Expr *Init : Inits) {
1771*700637cbSDimitry Andric if (!this->discard(Init))
1772*700637cbSDimitry Andric return false;
1773*700637cbSDimitry Andric }
1774*700637cbSDimitry Andric return true;
1775*700637cbSDimitry Andric }
1776*700637cbSDimitry Andric
1777*700637cbSDimitry Andric // Primitive values.
1778*700637cbSDimitry Andric if (std::optional<PrimType> T = classify(QT)) {
1779*700637cbSDimitry Andric assert(!DiscardResult);
1780*700637cbSDimitry Andric if (Inits.size() == 0)
1781*700637cbSDimitry Andric return this->visitZeroInitializer(*T, QT, E);
1782*700637cbSDimitry Andric assert(Inits.size() == 1);
1783*700637cbSDimitry Andric return this->delegate(Inits[0]);
1784*700637cbSDimitry Andric }
1785*700637cbSDimitry Andric
1786*700637cbSDimitry Andric if (QT->isRecordType()) {
1787*700637cbSDimitry Andric const Record *R = getRecord(QT);
1788*700637cbSDimitry Andric
1789*700637cbSDimitry Andric if (Inits.size() == 1 && E->getType() == Inits[0]->getType())
1790*700637cbSDimitry Andric return this->delegate(Inits[0]);
1791*700637cbSDimitry Andric
1792*700637cbSDimitry Andric auto initPrimitiveField = [=](const Record::Field *FieldToInit,
1793*700637cbSDimitry Andric const Expr *Init, PrimType T) -> bool {
1794*700637cbSDimitry Andric InitStackScope<Emitter> ISS(this, isa<CXXDefaultInitExpr>(Init));
1795*700637cbSDimitry Andric InitLinkScope<Emitter> ILS(this, InitLink::Field(FieldToInit->Offset));
1796*700637cbSDimitry Andric if (!this->visit(Init))
1797*700637cbSDimitry Andric return false;
1798*700637cbSDimitry Andric
1799*700637cbSDimitry Andric if (FieldToInit->isBitField())
1800*700637cbSDimitry Andric return this->emitInitBitField(T, FieldToInit, E);
1801*700637cbSDimitry Andric return this->emitInitField(T, FieldToInit->Offset, E);
1802*700637cbSDimitry Andric };
1803*700637cbSDimitry Andric
1804*700637cbSDimitry Andric auto initCompositeField = [=](const Record::Field *FieldToInit,
1805*700637cbSDimitry Andric const Expr *Init) -> bool {
1806*700637cbSDimitry Andric InitStackScope<Emitter> ISS(this, isa<CXXDefaultInitExpr>(Init));
1807*700637cbSDimitry Andric InitLinkScope<Emitter> ILS(this, InitLink::Field(FieldToInit->Offset));
1808*700637cbSDimitry Andric
1809*700637cbSDimitry Andric // Non-primitive case. Get a pointer to the field-to-initialize
1810*700637cbSDimitry Andric // on the stack and recurse into visitInitializer().
1811*700637cbSDimitry Andric if (!this->emitGetPtrField(FieldToInit->Offset, Init))
1812*700637cbSDimitry Andric return false;
1813*700637cbSDimitry Andric if (!this->visitInitializer(Init))
1814*700637cbSDimitry Andric return false;
1815*700637cbSDimitry Andric return this->emitPopPtr(E);
1816*700637cbSDimitry Andric };
1817*700637cbSDimitry Andric
1818*700637cbSDimitry Andric if (R->isUnion()) {
1819*700637cbSDimitry Andric if (Inits.size() == 0) {
1820*700637cbSDimitry Andric if (!this->visitZeroRecordInitializer(R, E))
1821*700637cbSDimitry Andric return false;
1822*700637cbSDimitry Andric } else {
1823*700637cbSDimitry Andric const Expr *Init = Inits[0];
1824*700637cbSDimitry Andric const FieldDecl *FToInit = nullptr;
1825*700637cbSDimitry Andric if (const auto *ILE = dyn_cast<InitListExpr>(E))
1826*700637cbSDimitry Andric FToInit = ILE->getInitializedFieldInUnion();
1827*700637cbSDimitry Andric else
1828*700637cbSDimitry Andric FToInit = cast<CXXParenListInitExpr>(E)->getInitializedFieldInUnion();
1829*700637cbSDimitry Andric
1830*700637cbSDimitry Andric const Record::Field *FieldToInit = R->getField(FToInit);
1831*700637cbSDimitry Andric if (std::optional<PrimType> T = classify(Init)) {
1832*700637cbSDimitry Andric if (!initPrimitiveField(FieldToInit, Init, *T))
1833*700637cbSDimitry Andric return false;
1834*700637cbSDimitry Andric } else {
1835*700637cbSDimitry Andric if (!initCompositeField(FieldToInit, Init))
1836*700637cbSDimitry Andric return false;
1837*700637cbSDimitry Andric }
1838*700637cbSDimitry Andric }
1839*700637cbSDimitry Andric return this->emitFinishInit(E);
1840*700637cbSDimitry Andric }
1841*700637cbSDimitry Andric
1842*700637cbSDimitry Andric assert(!R->isUnion());
1843*700637cbSDimitry Andric unsigned InitIndex = 0;
1844*700637cbSDimitry Andric for (const Expr *Init : Inits) {
1845*700637cbSDimitry Andric // Skip unnamed bitfields.
1846*700637cbSDimitry Andric while (InitIndex < R->getNumFields() &&
1847*700637cbSDimitry Andric R->getField(InitIndex)->isUnnamedBitField())
1848*700637cbSDimitry Andric ++InitIndex;
1849*700637cbSDimitry Andric
1850*700637cbSDimitry Andric if (std::optional<PrimType> T = classify(Init)) {
1851*700637cbSDimitry Andric const Record::Field *FieldToInit = R->getField(InitIndex);
1852*700637cbSDimitry Andric if (!initPrimitiveField(FieldToInit, Init, *T))
1853*700637cbSDimitry Andric return false;
1854*700637cbSDimitry Andric ++InitIndex;
1855*700637cbSDimitry Andric } else {
1856*700637cbSDimitry Andric // Initializer for a direct base class.
1857*700637cbSDimitry Andric if (const Record::Base *B = R->getBase(Init->getType())) {
1858*700637cbSDimitry Andric if (!this->emitGetPtrBase(B->Offset, Init))
1859*700637cbSDimitry Andric return false;
1860*700637cbSDimitry Andric
1861*700637cbSDimitry Andric if (!this->visitInitializer(Init))
1862*700637cbSDimitry Andric return false;
1863*700637cbSDimitry Andric
1864*700637cbSDimitry Andric if (!this->emitFinishInitPop(E))
1865*700637cbSDimitry Andric return false;
1866*700637cbSDimitry Andric // Base initializers don't increase InitIndex, since they don't count
1867*700637cbSDimitry Andric // into the Record's fields.
1868*700637cbSDimitry Andric } else {
1869*700637cbSDimitry Andric const Record::Field *FieldToInit = R->getField(InitIndex);
1870*700637cbSDimitry Andric if (!initCompositeField(FieldToInit, Init))
1871*700637cbSDimitry Andric return false;
1872*700637cbSDimitry Andric ++InitIndex;
1873*700637cbSDimitry Andric }
1874*700637cbSDimitry Andric }
1875*700637cbSDimitry Andric }
1876*700637cbSDimitry Andric return this->emitFinishInit(E);
1877*700637cbSDimitry Andric }
1878*700637cbSDimitry Andric
1879*700637cbSDimitry Andric if (QT->isArrayType()) {
1880*700637cbSDimitry Andric if (Inits.size() == 1 && QT == Inits[0]->getType())
1881*700637cbSDimitry Andric return this->delegate(Inits[0]);
1882*700637cbSDimitry Andric
1883*700637cbSDimitry Andric const ConstantArrayType *CAT =
1884*700637cbSDimitry Andric Ctx.getASTContext().getAsConstantArrayType(QT);
1885*700637cbSDimitry Andric uint64_t NumElems = CAT->getZExtSize();
1886*700637cbSDimitry Andric
1887*700637cbSDimitry Andric if (!this->emitCheckArraySize(NumElems, E))
1888*700637cbSDimitry Andric return false;
1889*700637cbSDimitry Andric
1890*700637cbSDimitry Andric std::optional<PrimType> InitT = classify(CAT->getElementType());
1891*700637cbSDimitry Andric unsigned ElementIndex = 0;
1892*700637cbSDimitry Andric for (const Expr *Init : Inits) {
1893*700637cbSDimitry Andric if (const auto *EmbedS =
1894*700637cbSDimitry Andric dyn_cast<EmbedExpr>(Init->IgnoreParenImpCasts())) {
1895*700637cbSDimitry Andric PrimType TargetT = classifyPrim(Init->getType());
1896*700637cbSDimitry Andric
1897*700637cbSDimitry Andric auto Eval = [&](const Expr *Init, unsigned ElemIndex) {
1898*700637cbSDimitry Andric PrimType InitT = classifyPrim(Init->getType());
1899*700637cbSDimitry Andric if (!this->visit(Init))
1900*700637cbSDimitry Andric return false;
1901*700637cbSDimitry Andric if (InitT != TargetT) {
1902*700637cbSDimitry Andric if (!this->emitCast(InitT, TargetT, E))
1903*700637cbSDimitry Andric return false;
1904*700637cbSDimitry Andric }
1905*700637cbSDimitry Andric return this->emitInitElem(TargetT, ElemIndex, Init);
1906*700637cbSDimitry Andric };
1907*700637cbSDimitry Andric if (!EmbedS->doForEachDataElement(Eval, ElementIndex))
1908*700637cbSDimitry Andric return false;
1909*700637cbSDimitry Andric } else {
1910*700637cbSDimitry Andric if (!this->visitArrayElemInit(ElementIndex, Init, InitT))
1911*700637cbSDimitry Andric return false;
1912*700637cbSDimitry Andric ++ElementIndex;
1913*700637cbSDimitry Andric }
1914*700637cbSDimitry Andric }
1915*700637cbSDimitry Andric
1916*700637cbSDimitry Andric // Expand the filler expression.
1917*700637cbSDimitry Andric // FIXME: This should go away.
1918*700637cbSDimitry Andric if (ArrayFiller) {
1919*700637cbSDimitry Andric for (; ElementIndex != NumElems; ++ElementIndex) {
1920*700637cbSDimitry Andric if (!this->visitArrayElemInit(ElementIndex, ArrayFiller, InitT))
1921*700637cbSDimitry Andric return false;
1922*700637cbSDimitry Andric }
1923*700637cbSDimitry Andric }
1924*700637cbSDimitry Andric
1925*700637cbSDimitry Andric return this->emitFinishInit(E);
1926*700637cbSDimitry Andric }
1927*700637cbSDimitry Andric
1928*700637cbSDimitry Andric if (const auto *ComplexTy = QT->getAs<ComplexType>()) {
1929*700637cbSDimitry Andric unsigned NumInits = Inits.size();
1930*700637cbSDimitry Andric
1931*700637cbSDimitry Andric if (NumInits == 1)
1932*700637cbSDimitry Andric return this->delegate(Inits[0]);
1933*700637cbSDimitry Andric
1934*700637cbSDimitry Andric QualType ElemQT = ComplexTy->getElementType();
1935*700637cbSDimitry Andric PrimType ElemT = classifyPrim(ElemQT);
1936*700637cbSDimitry Andric if (NumInits == 0) {
1937*700637cbSDimitry Andric // Zero-initialize both elements.
1938*700637cbSDimitry Andric for (unsigned I = 0; I < 2; ++I) {
1939*700637cbSDimitry Andric if (!this->visitZeroInitializer(ElemT, ElemQT, E))
1940*700637cbSDimitry Andric return false;
1941*700637cbSDimitry Andric if (!this->emitInitElem(ElemT, I, E))
1942*700637cbSDimitry Andric return false;
1943*700637cbSDimitry Andric }
1944*700637cbSDimitry Andric } else if (NumInits == 2) {
1945*700637cbSDimitry Andric unsigned InitIndex = 0;
1946*700637cbSDimitry Andric for (const Expr *Init : Inits) {
1947*700637cbSDimitry Andric if (!this->visit(Init))
1948*700637cbSDimitry Andric return false;
1949*700637cbSDimitry Andric
1950*700637cbSDimitry Andric if (!this->emitInitElem(ElemT, InitIndex, E))
1951*700637cbSDimitry Andric return false;
1952*700637cbSDimitry Andric ++InitIndex;
1953*700637cbSDimitry Andric }
1954*700637cbSDimitry Andric }
1955*700637cbSDimitry Andric return true;
1956*700637cbSDimitry Andric }
1957*700637cbSDimitry Andric
1958*700637cbSDimitry Andric if (const auto *VecT = QT->getAs<VectorType>()) {
1959*700637cbSDimitry Andric unsigned NumVecElements = VecT->getNumElements();
1960*700637cbSDimitry Andric assert(NumVecElements >= Inits.size());
1961*700637cbSDimitry Andric
1962*700637cbSDimitry Andric QualType ElemQT = VecT->getElementType();
1963*700637cbSDimitry Andric PrimType ElemT = classifyPrim(ElemQT);
1964*700637cbSDimitry Andric
1965*700637cbSDimitry Andric // All initializer elements.
1966*700637cbSDimitry Andric unsigned InitIndex = 0;
1967*700637cbSDimitry Andric for (const Expr *Init : Inits) {
1968*700637cbSDimitry Andric if (!this->visit(Init))
1969*700637cbSDimitry Andric return false;
1970*700637cbSDimitry Andric
1971*700637cbSDimitry Andric // If the initializer is of vector type itself, we have to deconstruct
1972*700637cbSDimitry Andric // that and initialize all the target fields from the initializer fields.
1973*700637cbSDimitry Andric if (const auto *InitVecT = Init->getType()->getAs<VectorType>()) {
1974*700637cbSDimitry Andric if (!this->emitCopyArray(ElemT, 0, InitIndex,
1975*700637cbSDimitry Andric InitVecT->getNumElements(), E))
1976*700637cbSDimitry Andric return false;
1977*700637cbSDimitry Andric InitIndex += InitVecT->getNumElements();
1978*700637cbSDimitry Andric } else {
1979*700637cbSDimitry Andric if (!this->emitInitElem(ElemT, InitIndex, E))
1980*700637cbSDimitry Andric return false;
1981*700637cbSDimitry Andric ++InitIndex;
1982*700637cbSDimitry Andric }
1983*700637cbSDimitry Andric }
1984*700637cbSDimitry Andric
1985*700637cbSDimitry Andric assert(InitIndex <= NumVecElements);
1986*700637cbSDimitry Andric
1987*700637cbSDimitry Andric // Fill the rest with zeroes.
1988*700637cbSDimitry Andric for (; InitIndex != NumVecElements; ++InitIndex) {
1989*700637cbSDimitry Andric if (!this->visitZeroInitializer(ElemT, ElemQT, E))
1990*700637cbSDimitry Andric return false;
1991*700637cbSDimitry Andric if (!this->emitInitElem(ElemT, InitIndex, E))
1992*700637cbSDimitry Andric return false;
1993*700637cbSDimitry Andric }
1994*700637cbSDimitry Andric return true;
1995*700637cbSDimitry Andric }
1996*700637cbSDimitry Andric
1997*700637cbSDimitry Andric return false;
1998*700637cbSDimitry Andric }
1999*700637cbSDimitry Andric
2000*700637cbSDimitry Andric /// Pointer to the array(not the element!) must be on the stack when calling
2001*700637cbSDimitry Andric /// this.
2002*700637cbSDimitry Andric template <class Emitter>
visitArrayElemInit(unsigned ElemIndex,const Expr * Init,std::optional<PrimType> InitT)2003*700637cbSDimitry Andric bool Compiler<Emitter>::visitArrayElemInit(unsigned ElemIndex, const Expr *Init,
2004*700637cbSDimitry Andric std::optional<PrimType> InitT) {
2005*700637cbSDimitry Andric if (InitT) {
2006*700637cbSDimitry Andric // Visit the primitive element like normal.
2007*700637cbSDimitry Andric if (!this->visit(Init))
2008*700637cbSDimitry Andric return false;
2009*700637cbSDimitry Andric return this->emitInitElem(*InitT, ElemIndex, Init);
2010*700637cbSDimitry Andric }
2011*700637cbSDimitry Andric
2012*700637cbSDimitry Andric InitLinkScope<Emitter> ILS(this, InitLink::Elem(ElemIndex));
2013*700637cbSDimitry Andric // Advance the pointer currently on the stack to the given
2014*700637cbSDimitry Andric // dimension.
2015*700637cbSDimitry Andric if (!this->emitConstUint32(ElemIndex, Init))
2016*700637cbSDimitry Andric return false;
2017*700637cbSDimitry Andric if (!this->emitArrayElemPtrUint32(Init))
2018*700637cbSDimitry Andric return false;
2019*700637cbSDimitry Andric if (!this->visitInitializer(Init))
2020*700637cbSDimitry Andric return false;
2021*700637cbSDimitry Andric return this->emitFinishInitPop(Init);
2022*700637cbSDimitry Andric }
2023*700637cbSDimitry Andric
2024*700637cbSDimitry Andric template <class Emitter>
visitCallArgs(ArrayRef<const Expr * > Args,const FunctionDecl * FuncDecl)2025*700637cbSDimitry Andric bool Compiler<Emitter>::visitCallArgs(ArrayRef<const Expr *> Args,
2026*700637cbSDimitry Andric const FunctionDecl *FuncDecl) {
2027*700637cbSDimitry Andric assert(VarScope->getKind() == ScopeKind::Call);
2028*700637cbSDimitry Andric llvm::BitVector NonNullArgs = collectNonNullArgs(FuncDecl, Args);
2029*700637cbSDimitry Andric
2030*700637cbSDimitry Andric unsigned ArgIndex = 0;
2031*700637cbSDimitry Andric for (const Expr *Arg : Args) {
2032*700637cbSDimitry Andric if (std::optional<PrimType> T = classify(Arg)) {
2033*700637cbSDimitry Andric if (!this->visit(Arg))
2034*700637cbSDimitry Andric return false;
2035*700637cbSDimitry Andric } else {
2036*700637cbSDimitry Andric
2037*700637cbSDimitry Andric std::optional<unsigned> LocalIndex = allocateLocal(
2038*700637cbSDimitry Andric Arg, Arg->getType(), /*ExtendingDecl=*/nullptr, ScopeKind::Call);
2039*700637cbSDimitry Andric if (!LocalIndex)
2040*700637cbSDimitry Andric return false;
2041*700637cbSDimitry Andric
2042*700637cbSDimitry Andric if (!this->emitGetPtrLocal(*LocalIndex, Arg))
2043*700637cbSDimitry Andric return false;
2044*700637cbSDimitry Andric InitLinkScope<Emitter> ILS(this, InitLink::Temp(*LocalIndex));
2045*700637cbSDimitry Andric if (!this->visitInitializer(Arg))
2046*700637cbSDimitry Andric return false;
2047*700637cbSDimitry Andric }
2048*700637cbSDimitry Andric
2049*700637cbSDimitry Andric if (FuncDecl && NonNullArgs[ArgIndex]) {
2050*700637cbSDimitry Andric PrimType ArgT = classify(Arg).value_or(PT_Ptr);
2051*700637cbSDimitry Andric if (ArgT == PT_Ptr) {
2052*700637cbSDimitry Andric if (!this->emitCheckNonNullArg(ArgT, Arg))
2053*700637cbSDimitry Andric return false;
2054*700637cbSDimitry Andric }
2055*700637cbSDimitry Andric }
2056*700637cbSDimitry Andric
2057*700637cbSDimitry Andric ++ArgIndex;
2058*700637cbSDimitry Andric }
2059*700637cbSDimitry Andric
2060*700637cbSDimitry Andric return true;
2061*700637cbSDimitry Andric }
2062*700637cbSDimitry Andric
2063*700637cbSDimitry Andric template <class Emitter>
VisitInitListExpr(const InitListExpr * E)2064*700637cbSDimitry Andric bool Compiler<Emitter>::VisitInitListExpr(const InitListExpr *E) {
2065*700637cbSDimitry Andric return this->visitInitList(E->inits(), E->getArrayFiller(), E);
2066*700637cbSDimitry Andric }
2067*700637cbSDimitry Andric
2068*700637cbSDimitry Andric template <class Emitter>
VisitCXXParenListInitExpr(const CXXParenListInitExpr * E)2069*700637cbSDimitry Andric bool Compiler<Emitter>::VisitCXXParenListInitExpr(
2070*700637cbSDimitry Andric const CXXParenListInitExpr *E) {
2071*700637cbSDimitry Andric return this->visitInitList(E->getInitExprs(), E->getArrayFiller(), E);
2072*700637cbSDimitry Andric }
2073*700637cbSDimitry Andric
2074*700637cbSDimitry Andric template <class Emitter>
VisitSubstNonTypeTemplateParmExpr(const SubstNonTypeTemplateParmExpr * E)2075*700637cbSDimitry Andric bool Compiler<Emitter>::VisitSubstNonTypeTemplateParmExpr(
2076*700637cbSDimitry Andric const SubstNonTypeTemplateParmExpr *E) {
2077*700637cbSDimitry Andric return this->delegate(E->getReplacement());
2078*700637cbSDimitry Andric }
2079*700637cbSDimitry Andric
2080*700637cbSDimitry Andric template <class Emitter>
VisitConstantExpr(const ConstantExpr * E)2081*700637cbSDimitry Andric bool Compiler<Emitter>::VisitConstantExpr(const ConstantExpr *E) {
2082*700637cbSDimitry Andric std::optional<PrimType> T = classify(E->getType());
2083*700637cbSDimitry Andric if (T && E->hasAPValueResult()) {
2084*700637cbSDimitry Andric // Try to emit the APValue directly, without visiting the subexpr.
2085*700637cbSDimitry Andric // This will only fail if we can't emit the APValue, so won't emit any
2086*700637cbSDimitry Andric // diagnostics or any double values.
2087*700637cbSDimitry Andric if (DiscardResult)
2088*700637cbSDimitry Andric return true;
2089*700637cbSDimitry Andric
2090*700637cbSDimitry Andric if (this->visitAPValue(E->getAPValueResult(), *T, E))
2091*700637cbSDimitry Andric return true;
2092*700637cbSDimitry Andric }
2093*700637cbSDimitry Andric return this->delegate(E->getSubExpr());
2094*700637cbSDimitry Andric }
2095*700637cbSDimitry Andric
2096*700637cbSDimitry Andric template <class Emitter>
VisitEmbedExpr(const EmbedExpr * E)2097*700637cbSDimitry Andric bool Compiler<Emitter>::VisitEmbedExpr(const EmbedExpr *E) {
2098*700637cbSDimitry Andric auto It = E->begin();
2099*700637cbSDimitry Andric return this->visit(*It);
2100*700637cbSDimitry Andric }
2101*700637cbSDimitry Andric
AlignOfType(QualType T,const ASTContext & ASTCtx,UnaryExprOrTypeTrait Kind)2102*700637cbSDimitry Andric static CharUnits AlignOfType(QualType T, const ASTContext &ASTCtx,
2103*700637cbSDimitry Andric UnaryExprOrTypeTrait Kind) {
2104*700637cbSDimitry Andric bool AlignOfReturnsPreferred =
2105*700637cbSDimitry Andric ASTCtx.getLangOpts().getClangABICompat() <= LangOptions::ClangABI::Ver7;
2106*700637cbSDimitry Andric
2107*700637cbSDimitry Andric // C++ [expr.alignof]p3:
2108*700637cbSDimitry Andric // When alignof is applied to a reference type, the result is the
2109*700637cbSDimitry Andric // alignment of the referenced type.
2110*700637cbSDimitry Andric if (const auto *Ref = T->getAs<ReferenceType>())
2111*700637cbSDimitry Andric T = Ref->getPointeeType();
2112*700637cbSDimitry Andric
2113*700637cbSDimitry Andric if (T.getQualifiers().hasUnaligned())
2114*700637cbSDimitry Andric return CharUnits::One();
2115*700637cbSDimitry Andric
2116*700637cbSDimitry Andric // __alignof is defined to return the preferred alignment.
2117*700637cbSDimitry Andric // Before 8, clang returned the preferred alignment for alignof and
2118*700637cbSDimitry Andric // _Alignof as well.
2119*700637cbSDimitry Andric if (Kind == UETT_PreferredAlignOf || AlignOfReturnsPreferred)
2120*700637cbSDimitry Andric return ASTCtx.toCharUnitsFromBits(ASTCtx.getPreferredTypeAlign(T));
2121*700637cbSDimitry Andric
2122*700637cbSDimitry Andric return ASTCtx.getTypeAlignInChars(T);
2123*700637cbSDimitry Andric }
2124*700637cbSDimitry Andric
2125*700637cbSDimitry Andric template <class Emitter>
VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr * E)2126*700637cbSDimitry Andric bool Compiler<Emitter>::VisitUnaryExprOrTypeTraitExpr(
2127*700637cbSDimitry Andric const UnaryExprOrTypeTraitExpr *E) {
2128*700637cbSDimitry Andric UnaryExprOrTypeTrait Kind = E->getKind();
2129*700637cbSDimitry Andric const ASTContext &ASTCtx = Ctx.getASTContext();
2130*700637cbSDimitry Andric
2131*700637cbSDimitry Andric if (Kind == UETT_SizeOf || Kind == UETT_DataSizeOf) {
2132*700637cbSDimitry Andric QualType ArgType = E->getTypeOfArgument();
2133*700637cbSDimitry Andric
2134*700637cbSDimitry Andric // C++ [expr.sizeof]p2: "When applied to a reference or a reference type,
2135*700637cbSDimitry Andric // the result is the size of the referenced type."
2136*700637cbSDimitry Andric if (const auto *Ref = ArgType->getAs<ReferenceType>())
2137*700637cbSDimitry Andric ArgType = Ref->getPointeeType();
2138*700637cbSDimitry Andric
2139*700637cbSDimitry Andric CharUnits Size;
2140*700637cbSDimitry Andric if (ArgType->isVoidType() || ArgType->isFunctionType())
2141*700637cbSDimitry Andric Size = CharUnits::One();
2142*700637cbSDimitry Andric else {
2143*700637cbSDimitry Andric if (ArgType->isDependentType() || !ArgType->isConstantSizeType())
2144*700637cbSDimitry Andric return this->emitInvalid(E);
2145*700637cbSDimitry Andric
2146*700637cbSDimitry Andric if (Kind == UETT_SizeOf)
2147*700637cbSDimitry Andric Size = ASTCtx.getTypeSizeInChars(ArgType);
2148*700637cbSDimitry Andric else
2149*700637cbSDimitry Andric Size = ASTCtx.getTypeInfoDataSizeInChars(ArgType).Width;
2150*700637cbSDimitry Andric }
2151*700637cbSDimitry Andric
2152*700637cbSDimitry Andric if (DiscardResult)
2153*700637cbSDimitry Andric return true;
2154*700637cbSDimitry Andric
2155*700637cbSDimitry Andric return this->emitConst(Size.getQuantity(), E);
2156*700637cbSDimitry Andric }
2157*700637cbSDimitry Andric
2158*700637cbSDimitry Andric if (Kind == UETT_CountOf) {
2159*700637cbSDimitry Andric QualType Ty = E->getTypeOfArgument();
2160*700637cbSDimitry Andric assert(Ty->isArrayType());
2161*700637cbSDimitry Andric
2162*700637cbSDimitry Andric // We don't need to worry about array element qualifiers, so getting the
2163*700637cbSDimitry Andric // unsafe array type is fine.
2164*700637cbSDimitry Andric if (const auto *CAT =
2165*700637cbSDimitry Andric dyn_cast<ConstantArrayType>(Ty->getAsArrayTypeUnsafe())) {
2166*700637cbSDimitry Andric if (DiscardResult)
2167*700637cbSDimitry Andric return true;
2168*700637cbSDimitry Andric return this->emitConst(CAT->getSize(), E);
2169*700637cbSDimitry Andric }
2170*700637cbSDimitry Andric
2171*700637cbSDimitry Andric assert(!Ty->isConstantSizeType());
2172*700637cbSDimitry Andric
2173*700637cbSDimitry Andric // If it's a variable-length array type, we need to check whether it is a
2174*700637cbSDimitry Andric // multidimensional array. If so, we need to check the size expression of
2175*700637cbSDimitry Andric // the VLA to see if it's a constant size. If so, we can return that value.
2176*700637cbSDimitry Andric const auto *VAT = ASTCtx.getAsVariableArrayType(Ty);
2177*700637cbSDimitry Andric assert(VAT);
2178*700637cbSDimitry Andric if (VAT->getElementType()->isArrayType()) {
2179*700637cbSDimitry Andric std::optional<APSInt> Res =
2180*700637cbSDimitry Andric VAT->getSizeExpr()->getIntegerConstantExpr(ASTCtx);
2181*700637cbSDimitry Andric if (Res) {
2182*700637cbSDimitry Andric if (DiscardResult)
2183*700637cbSDimitry Andric return true;
2184*700637cbSDimitry Andric return this->emitConst(*Res, E);
2185*700637cbSDimitry Andric }
2186*700637cbSDimitry Andric }
2187*700637cbSDimitry Andric }
2188*700637cbSDimitry Andric
2189*700637cbSDimitry Andric if (Kind == UETT_AlignOf || Kind == UETT_PreferredAlignOf) {
2190*700637cbSDimitry Andric CharUnits Size;
2191*700637cbSDimitry Andric
2192*700637cbSDimitry Andric if (E->isArgumentType()) {
2193*700637cbSDimitry Andric QualType ArgType = E->getTypeOfArgument();
2194*700637cbSDimitry Andric
2195*700637cbSDimitry Andric Size = AlignOfType(ArgType, ASTCtx, Kind);
2196*700637cbSDimitry Andric } else {
2197*700637cbSDimitry Andric // Argument is an expression, not a type.
2198*700637cbSDimitry Andric const Expr *Arg = E->getArgumentExpr()->IgnoreParens();
2199*700637cbSDimitry Andric
2200*700637cbSDimitry Andric // The kinds of expressions that we have special-case logic here for
2201*700637cbSDimitry Andric // should be kept up to date with the special checks for those
2202*700637cbSDimitry Andric // expressions in Sema.
2203*700637cbSDimitry Andric
2204*700637cbSDimitry Andric // alignof decl is always accepted, even if it doesn't make sense: we
2205*700637cbSDimitry Andric // default to 1 in those cases.
2206*700637cbSDimitry Andric if (const auto *DRE = dyn_cast<DeclRefExpr>(Arg))
2207*700637cbSDimitry Andric Size = ASTCtx.getDeclAlign(DRE->getDecl(),
2208*700637cbSDimitry Andric /*RefAsPointee*/ true);
2209*700637cbSDimitry Andric else if (const auto *ME = dyn_cast<MemberExpr>(Arg))
2210*700637cbSDimitry Andric Size = ASTCtx.getDeclAlign(ME->getMemberDecl(),
2211*700637cbSDimitry Andric /*RefAsPointee*/ true);
2212*700637cbSDimitry Andric else
2213*700637cbSDimitry Andric Size = AlignOfType(Arg->getType(), ASTCtx, Kind);
2214*700637cbSDimitry Andric }
2215*700637cbSDimitry Andric
2216*700637cbSDimitry Andric if (DiscardResult)
2217*700637cbSDimitry Andric return true;
2218*700637cbSDimitry Andric
2219*700637cbSDimitry Andric return this->emitConst(Size.getQuantity(), E);
2220*700637cbSDimitry Andric }
2221*700637cbSDimitry Andric
2222*700637cbSDimitry Andric if (Kind == UETT_VectorElements) {
2223*700637cbSDimitry Andric if (const auto *VT = E->getTypeOfArgument()->getAs<VectorType>())
2224*700637cbSDimitry Andric return this->emitConst(VT->getNumElements(), E);
2225*700637cbSDimitry Andric assert(E->getTypeOfArgument()->isSizelessVectorType());
2226*700637cbSDimitry Andric return this->emitSizelessVectorElementSize(E);
2227*700637cbSDimitry Andric }
2228*700637cbSDimitry Andric
2229*700637cbSDimitry Andric if (Kind == UETT_VecStep) {
2230*700637cbSDimitry Andric if (const auto *VT = E->getTypeOfArgument()->getAs<VectorType>()) {
2231*700637cbSDimitry Andric unsigned N = VT->getNumElements();
2232*700637cbSDimitry Andric
2233*700637cbSDimitry Andric // The vec_step built-in functions that take a 3-component
2234*700637cbSDimitry Andric // vector return 4. (OpenCL 1.1 spec 6.11.12)
2235*700637cbSDimitry Andric if (N == 3)
2236*700637cbSDimitry Andric N = 4;
2237*700637cbSDimitry Andric
2238*700637cbSDimitry Andric return this->emitConst(N, E);
2239*700637cbSDimitry Andric }
2240*700637cbSDimitry Andric return this->emitConst(1, E);
2241*700637cbSDimitry Andric }
2242*700637cbSDimitry Andric
2243*700637cbSDimitry Andric if (Kind == UETT_OpenMPRequiredSimdAlign) {
2244*700637cbSDimitry Andric assert(E->isArgumentType());
2245*700637cbSDimitry Andric unsigned Bits = ASTCtx.getOpenMPDefaultSimdAlign(E->getArgumentType());
2246*700637cbSDimitry Andric
2247*700637cbSDimitry Andric return this->emitConst(ASTCtx.toCharUnitsFromBits(Bits).getQuantity(), E);
2248*700637cbSDimitry Andric }
2249*700637cbSDimitry Andric
2250*700637cbSDimitry Andric if (Kind == UETT_PtrAuthTypeDiscriminator) {
2251*700637cbSDimitry Andric if (E->getArgumentType()->isDependentType())
2252*700637cbSDimitry Andric return this->emitInvalid(E);
2253*700637cbSDimitry Andric
2254*700637cbSDimitry Andric return this->emitConst(
2255*700637cbSDimitry Andric const_cast<ASTContext &>(ASTCtx).getPointerAuthTypeDiscriminator(
2256*700637cbSDimitry Andric E->getArgumentType()),
2257*700637cbSDimitry Andric E);
2258*700637cbSDimitry Andric }
2259*700637cbSDimitry Andric
2260*700637cbSDimitry Andric return false;
2261*700637cbSDimitry Andric }
2262*700637cbSDimitry Andric
2263*700637cbSDimitry Andric template <class Emitter>
VisitMemberExpr(const MemberExpr * E)2264*700637cbSDimitry Andric bool Compiler<Emitter>::VisitMemberExpr(const MemberExpr *E) {
2265*700637cbSDimitry Andric // 'Base.Member'
2266*700637cbSDimitry Andric const Expr *Base = E->getBase();
2267*700637cbSDimitry Andric const ValueDecl *Member = E->getMemberDecl();
2268*700637cbSDimitry Andric
2269*700637cbSDimitry Andric if (DiscardResult)
2270*700637cbSDimitry Andric return this->discard(Base);
2271*700637cbSDimitry Andric
2272*700637cbSDimitry Andric // MemberExprs are almost always lvalues, in which case we don't need to
2273*700637cbSDimitry Andric // do the load. But sometimes they aren't.
2274*700637cbSDimitry Andric const auto maybeLoadValue = [&]() -> bool {
2275*700637cbSDimitry Andric if (E->isGLValue())
2276*700637cbSDimitry Andric return true;
2277*700637cbSDimitry Andric if (std::optional<PrimType> T = classify(E))
2278*700637cbSDimitry Andric return this->emitLoadPop(*T, E);
2279*700637cbSDimitry Andric return false;
2280*700637cbSDimitry Andric };
2281*700637cbSDimitry Andric
2282*700637cbSDimitry Andric if (const auto *VD = dyn_cast<VarDecl>(Member)) {
2283*700637cbSDimitry Andric // I am almost confident in saying that a var decl must be static
2284*700637cbSDimitry Andric // and therefore registered as a global variable. But this will probably
2285*700637cbSDimitry Andric // turn out to be wrong some time in the future, as always.
2286*700637cbSDimitry Andric if (auto GlobalIndex = P.getGlobal(VD))
2287*700637cbSDimitry Andric return this->emitGetPtrGlobal(*GlobalIndex, E) && maybeLoadValue();
2288*700637cbSDimitry Andric return false;
2289*700637cbSDimitry Andric }
2290*700637cbSDimitry Andric
2291*700637cbSDimitry Andric if (!isa<FieldDecl>(Member)) {
2292*700637cbSDimitry Andric if (!this->discard(Base) && !this->emitSideEffect(E))
2293*700637cbSDimitry Andric return false;
2294*700637cbSDimitry Andric
2295*700637cbSDimitry Andric return this->visitDeclRef(Member, E);
2296*700637cbSDimitry Andric }
2297*700637cbSDimitry Andric
2298*700637cbSDimitry Andric if (Initializing) {
2299*700637cbSDimitry Andric if (!this->delegate(Base))
2300*700637cbSDimitry Andric return false;
2301*700637cbSDimitry Andric } else {
2302*700637cbSDimitry Andric if (!this->visit(Base))
2303*700637cbSDimitry Andric return false;
2304*700637cbSDimitry Andric }
2305*700637cbSDimitry Andric
2306*700637cbSDimitry Andric // Base above gives us a pointer on the stack.
2307*700637cbSDimitry Andric const auto *FD = cast<FieldDecl>(Member);
2308*700637cbSDimitry Andric const RecordDecl *RD = FD->getParent();
2309*700637cbSDimitry Andric const Record *R = getRecord(RD);
2310*700637cbSDimitry Andric if (!R)
2311*700637cbSDimitry Andric return false;
2312*700637cbSDimitry Andric const Record::Field *F = R->getField(FD);
2313*700637cbSDimitry Andric // Leave a pointer to the field on the stack.
2314*700637cbSDimitry Andric if (F->Decl->getType()->isReferenceType())
2315*700637cbSDimitry Andric return this->emitGetFieldPop(PT_Ptr, F->Offset, E) && maybeLoadValue();
2316*700637cbSDimitry Andric return this->emitGetPtrFieldPop(F->Offset, E) && maybeLoadValue();
2317*700637cbSDimitry Andric }
2318*700637cbSDimitry Andric
2319*700637cbSDimitry Andric template <class Emitter>
VisitArrayInitIndexExpr(const ArrayInitIndexExpr * E)2320*700637cbSDimitry Andric bool Compiler<Emitter>::VisitArrayInitIndexExpr(const ArrayInitIndexExpr *E) {
2321*700637cbSDimitry Andric // ArrayIndex might not be set if a ArrayInitIndexExpr is being evaluated
2322*700637cbSDimitry Andric // stand-alone, e.g. via EvaluateAsInt().
2323*700637cbSDimitry Andric if (!ArrayIndex)
2324*700637cbSDimitry Andric return false;
2325*700637cbSDimitry Andric return this->emitConst(*ArrayIndex, E);
2326*700637cbSDimitry Andric }
2327*700637cbSDimitry Andric
2328*700637cbSDimitry Andric template <class Emitter>
VisitArrayInitLoopExpr(const ArrayInitLoopExpr * E)2329*700637cbSDimitry Andric bool Compiler<Emitter>::VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E) {
2330*700637cbSDimitry Andric assert(Initializing);
2331*700637cbSDimitry Andric assert(!DiscardResult);
2332*700637cbSDimitry Andric
2333*700637cbSDimitry Andric // We visit the common opaque expression here once so we have its value
2334*700637cbSDimitry Andric // cached.
2335*700637cbSDimitry Andric if (!this->discard(E->getCommonExpr()))
2336*700637cbSDimitry Andric return false;
2337*700637cbSDimitry Andric
2338*700637cbSDimitry Andric // TODO: This compiles to quite a lot of bytecode if the array is larger.
2339*700637cbSDimitry Andric // Investigate compiling this to a loop.
2340*700637cbSDimitry Andric const Expr *SubExpr = E->getSubExpr();
2341*700637cbSDimitry Andric size_t Size = E->getArraySize().getZExtValue();
2342*700637cbSDimitry Andric std::optional<PrimType> SubExprT = classify(SubExpr);
2343*700637cbSDimitry Andric
2344*700637cbSDimitry Andric // So, every iteration, we execute an assignment here
2345*700637cbSDimitry Andric // where the LHS is on the stack (the target array)
2346*700637cbSDimitry Andric // and the RHS is our SubExpr.
2347*700637cbSDimitry Andric for (size_t I = 0; I != Size; ++I) {
2348*700637cbSDimitry Andric ArrayIndexScope<Emitter> IndexScope(this, I);
2349*700637cbSDimitry Andric BlockScope<Emitter> BS(this);
2350*700637cbSDimitry Andric
2351*700637cbSDimitry Andric if (!this->visitArrayElemInit(I, SubExpr, SubExprT))
2352*700637cbSDimitry Andric return false;
2353*700637cbSDimitry Andric if (!BS.destroyLocals())
2354*700637cbSDimitry Andric return false;
2355*700637cbSDimitry Andric }
2356*700637cbSDimitry Andric return true;
2357*700637cbSDimitry Andric }
2358*700637cbSDimitry Andric
2359*700637cbSDimitry Andric template <class Emitter>
VisitOpaqueValueExpr(const OpaqueValueExpr * E)2360*700637cbSDimitry Andric bool Compiler<Emitter>::VisitOpaqueValueExpr(const OpaqueValueExpr *E) {
2361*700637cbSDimitry Andric const Expr *SourceExpr = E->getSourceExpr();
2362*700637cbSDimitry Andric if (!SourceExpr)
2363*700637cbSDimitry Andric return false;
2364*700637cbSDimitry Andric
2365*700637cbSDimitry Andric if (Initializing)
2366*700637cbSDimitry Andric return this->visitInitializer(SourceExpr);
2367*700637cbSDimitry Andric
2368*700637cbSDimitry Andric PrimType SubExprT = classify(SourceExpr).value_or(PT_Ptr);
2369*700637cbSDimitry Andric if (auto It = OpaqueExprs.find(E); It != OpaqueExprs.end())
2370*700637cbSDimitry Andric return this->emitGetLocal(SubExprT, It->second, E);
2371*700637cbSDimitry Andric
2372*700637cbSDimitry Andric if (!this->visit(SourceExpr))
2373*700637cbSDimitry Andric return false;
2374*700637cbSDimitry Andric
2375*700637cbSDimitry Andric // At this point we either have the evaluated source expression or a pointer
2376*700637cbSDimitry Andric // to an object on the stack. We want to create a local variable that stores
2377*700637cbSDimitry Andric // this value.
2378*700637cbSDimitry Andric unsigned LocalIndex = allocateLocalPrimitive(E, SubExprT, /*IsConst=*/true);
2379*700637cbSDimitry Andric if (!this->emitSetLocal(SubExprT, LocalIndex, E))
2380*700637cbSDimitry Andric return false;
2381*700637cbSDimitry Andric
2382*700637cbSDimitry Andric // Here the local variable is created but the value is removed from the stack,
2383*700637cbSDimitry Andric // so we put it back if the caller needs it.
2384*700637cbSDimitry Andric if (!DiscardResult) {
2385*700637cbSDimitry Andric if (!this->emitGetLocal(SubExprT, LocalIndex, E))
2386*700637cbSDimitry Andric return false;
2387*700637cbSDimitry Andric }
2388*700637cbSDimitry Andric
2389*700637cbSDimitry Andric // This is cleaned up when the local variable is destroyed.
2390*700637cbSDimitry Andric OpaqueExprs.insert({E, LocalIndex});
2391*700637cbSDimitry Andric
2392*700637cbSDimitry Andric return true;
2393*700637cbSDimitry Andric }
2394*700637cbSDimitry Andric
2395*700637cbSDimitry Andric template <class Emitter>
VisitAbstractConditionalOperator(const AbstractConditionalOperator * E)2396*700637cbSDimitry Andric bool Compiler<Emitter>::VisitAbstractConditionalOperator(
2397*700637cbSDimitry Andric const AbstractConditionalOperator *E) {
2398*700637cbSDimitry Andric const Expr *Condition = E->getCond();
2399*700637cbSDimitry Andric const Expr *TrueExpr = E->getTrueExpr();
2400*700637cbSDimitry Andric const Expr *FalseExpr = E->getFalseExpr();
2401*700637cbSDimitry Andric
2402*700637cbSDimitry Andric auto visitChildExpr = [&](const Expr *E) -> bool {
2403*700637cbSDimitry Andric LocalScope<Emitter> S(this);
2404*700637cbSDimitry Andric if (!this->delegate(E))
2405*700637cbSDimitry Andric return false;
2406*700637cbSDimitry Andric return S.destroyLocals();
2407*700637cbSDimitry Andric };
2408*700637cbSDimitry Andric
2409*700637cbSDimitry Andric if (std::optional<bool> BoolValue = getBoolValue(Condition)) {
2410*700637cbSDimitry Andric if (BoolValue)
2411*700637cbSDimitry Andric return visitChildExpr(TrueExpr);
2412*700637cbSDimitry Andric return visitChildExpr(FalseExpr);
2413*700637cbSDimitry Andric }
2414*700637cbSDimitry Andric
2415*700637cbSDimitry Andric bool IsBcpCall = false;
2416*700637cbSDimitry Andric if (const auto *CE = dyn_cast<CallExpr>(Condition->IgnoreParenCasts());
2417*700637cbSDimitry Andric CE && CE->getBuiltinCallee() == Builtin::BI__builtin_constant_p) {
2418*700637cbSDimitry Andric IsBcpCall = true;
2419*700637cbSDimitry Andric }
2420*700637cbSDimitry Andric
2421*700637cbSDimitry Andric LabelTy LabelEnd = this->getLabel(); // Label after the operator.
2422*700637cbSDimitry Andric LabelTy LabelFalse = this->getLabel(); // Label for the false expr.
2423*700637cbSDimitry Andric
2424*700637cbSDimitry Andric if (IsBcpCall) {
2425*700637cbSDimitry Andric if (!this->emitStartSpeculation(E))
2426*700637cbSDimitry Andric return false;
2427*700637cbSDimitry Andric }
2428*700637cbSDimitry Andric
2429*700637cbSDimitry Andric if (!this->visitBool(Condition)) {
2430*700637cbSDimitry Andric // If the condition failed and we're checking for undefined behavior
2431*700637cbSDimitry Andric // (which only happens with EvalEmitter) check the TrueExpr and FalseExpr
2432*700637cbSDimitry Andric // as well.
2433*700637cbSDimitry Andric if (this->checkingForUndefinedBehavior()) {
2434*700637cbSDimitry Andric if (!this->discard(TrueExpr))
2435*700637cbSDimitry Andric return false;
2436*700637cbSDimitry Andric if (!this->discard(FalseExpr))
2437*700637cbSDimitry Andric return false;
2438*700637cbSDimitry Andric }
2439*700637cbSDimitry Andric return false;
2440*700637cbSDimitry Andric }
2441*700637cbSDimitry Andric
2442*700637cbSDimitry Andric if (!this->jumpFalse(LabelFalse))
2443*700637cbSDimitry Andric return false;
2444*700637cbSDimitry Andric if (!visitChildExpr(TrueExpr))
2445*700637cbSDimitry Andric return false;
2446*700637cbSDimitry Andric if (!this->jump(LabelEnd))
2447*700637cbSDimitry Andric return false;
2448*700637cbSDimitry Andric this->emitLabel(LabelFalse);
2449*700637cbSDimitry Andric if (!visitChildExpr(FalseExpr))
2450*700637cbSDimitry Andric return false;
2451*700637cbSDimitry Andric this->fallthrough(LabelEnd);
2452*700637cbSDimitry Andric this->emitLabel(LabelEnd);
2453*700637cbSDimitry Andric
2454*700637cbSDimitry Andric if (IsBcpCall)
2455*700637cbSDimitry Andric return this->emitEndSpeculation(E);
2456*700637cbSDimitry Andric return true;
2457*700637cbSDimitry Andric }
2458*700637cbSDimitry Andric
2459*700637cbSDimitry Andric template <class Emitter>
VisitStringLiteral(const StringLiteral * E)2460*700637cbSDimitry Andric bool Compiler<Emitter>::VisitStringLiteral(const StringLiteral *E) {
2461*700637cbSDimitry Andric if (DiscardResult)
2462*700637cbSDimitry Andric return true;
2463*700637cbSDimitry Andric
2464*700637cbSDimitry Andric if (!Initializing) {
2465*700637cbSDimitry Andric unsigned StringIndex = P.createGlobalString(E);
2466*700637cbSDimitry Andric return this->emitGetPtrGlobal(StringIndex, E);
2467*700637cbSDimitry Andric }
2468*700637cbSDimitry Andric
2469*700637cbSDimitry Andric // We are initializing an array on the stack.
2470*700637cbSDimitry Andric const ConstantArrayType *CAT =
2471*700637cbSDimitry Andric Ctx.getASTContext().getAsConstantArrayType(E->getType());
2472*700637cbSDimitry Andric assert(CAT && "a string literal that's not a constant array?");
2473*700637cbSDimitry Andric
2474*700637cbSDimitry Andric // If the initializer string is too long, a diagnostic has already been
2475*700637cbSDimitry Andric // emitted. Read only the array length from the string literal.
2476*700637cbSDimitry Andric unsigned ArraySize = CAT->getZExtSize();
2477*700637cbSDimitry Andric unsigned N = std::min(ArraySize, E->getLength());
2478*700637cbSDimitry Andric unsigned CharWidth = E->getCharByteWidth();
2479*700637cbSDimitry Andric
2480*700637cbSDimitry Andric for (unsigned I = 0; I != N; ++I) {
2481*700637cbSDimitry Andric uint32_t CodeUnit = E->getCodeUnit(I);
2482*700637cbSDimitry Andric
2483*700637cbSDimitry Andric if (CharWidth == 1) {
2484*700637cbSDimitry Andric this->emitConstSint8(CodeUnit, E);
2485*700637cbSDimitry Andric this->emitInitElemSint8(I, E);
2486*700637cbSDimitry Andric } else if (CharWidth == 2) {
2487*700637cbSDimitry Andric this->emitConstUint16(CodeUnit, E);
2488*700637cbSDimitry Andric this->emitInitElemUint16(I, E);
2489*700637cbSDimitry Andric } else if (CharWidth == 4) {
2490*700637cbSDimitry Andric this->emitConstUint32(CodeUnit, E);
2491*700637cbSDimitry Andric this->emitInitElemUint32(I, E);
2492*700637cbSDimitry Andric } else {
2493*700637cbSDimitry Andric llvm_unreachable("unsupported character width");
2494*700637cbSDimitry Andric }
2495*700637cbSDimitry Andric }
2496*700637cbSDimitry Andric
2497*700637cbSDimitry Andric // Fill up the rest of the char array with NUL bytes.
2498*700637cbSDimitry Andric for (unsigned I = N; I != ArraySize; ++I) {
2499*700637cbSDimitry Andric if (CharWidth == 1) {
2500*700637cbSDimitry Andric this->emitConstSint8(0, E);
2501*700637cbSDimitry Andric this->emitInitElemSint8(I, E);
2502*700637cbSDimitry Andric } else if (CharWidth == 2) {
2503*700637cbSDimitry Andric this->emitConstUint16(0, E);
2504*700637cbSDimitry Andric this->emitInitElemUint16(I, E);
2505*700637cbSDimitry Andric } else if (CharWidth == 4) {
2506*700637cbSDimitry Andric this->emitConstUint32(0, E);
2507*700637cbSDimitry Andric this->emitInitElemUint32(I, E);
2508*700637cbSDimitry Andric } else {
2509*700637cbSDimitry Andric llvm_unreachable("unsupported character width");
2510*700637cbSDimitry Andric }
2511*700637cbSDimitry Andric }
2512*700637cbSDimitry Andric
2513*700637cbSDimitry Andric return true;
2514*700637cbSDimitry Andric }
2515*700637cbSDimitry Andric
2516*700637cbSDimitry Andric template <class Emitter>
VisitObjCStringLiteral(const ObjCStringLiteral * E)2517*700637cbSDimitry Andric bool Compiler<Emitter>::VisitObjCStringLiteral(const ObjCStringLiteral *E) {
2518*700637cbSDimitry Andric if (DiscardResult)
2519*700637cbSDimitry Andric return true;
2520*700637cbSDimitry Andric return this->emitDummyPtr(E, E);
2521*700637cbSDimitry Andric }
2522*700637cbSDimitry Andric
2523*700637cbSDimitry Andric template <class Emitter>
VisitObjCEncodeExpr(const ObjCEncodeExpr * E)2524*700637cbSDimitry Andric bool Compiler<Emitter>::VisitObjCEncodeExpr(const ObjCEncodeExpr *E) {
2525*700637cbSDimitry Andric auto &A = Ctx.getASTContext();
2526*700637cbSDimitry Andric std::string Str;
2527*700637cbSDimitry Andric A.getObjCEncodingForType(E->getEncodedType(), Str);
2528*700637cbSDimitry Andric StringLiteral *SL =
2529*700637cbSDimitry Andric StringLiteral::Create(A, Str, StringLiteralKind::Ordinary,
2530*700637cbSDimitry Andric /*Pascal=*/false, E->getType(), E->getAtLoc());
2531*700637cbSDimitry Andric return this->delegate(SL);
2532*700637cbSDimitry Andric }
2533*700637cbSDimitry Andric
2534*700637cbSDimitry Andric template <class Emitter>
VisitSYCLUniqueStableNameExpr(const SYCLUniqueStableNameExpr * E)2535*700637cbSDimitry Andric bool Compiler<Emitter>::VisitSYCLUniqueStableNameExpr(
2536*700637cbSDimitry Andric const SYCLUniqueStableNameExpr *E) {
2537*700637cbSDimitry Andric if (DiscardResult)
2538*700637cbSDimitry Andric return true;
2539*700637cbSDimitry Andric
2540*700637cbSDimitry Andric assert(!Initializing);
2541*700637cbSDimitry Andric
2542*700637cbSDimitry Andric auto &A = Ctx.getASTContext();
2543*700637cbSDimitry Andric std::string ResultStr = E->ComputeName(A);
2544*700637cbSDimitry Andric
2545*700637cbSDimitry Andric QualType CharTy = A.CharTy.withConst();
2546*700637cbSDimitry Andric APInt Size(A.getTypeSize(A.getSizeType()), ResultStr.size() + 1);
2547*700637cbSDimitry Andric QualType ArrayTy = A.getConstantArrayType(CharTy, Size, nullptr,
2548*700637cbSDimitry Andric ArraySizeModifier::Normal, 0);
2549*700637cbSDimitry Andric
2550*700637cbSDimitry Andric StringLiteral *SL =
2551*700637cbSDimitry Andric StringLiteral::Create(A, ResultStr, StringLiteralKind::Ordinary,
2552*700637cbSDimitry Andric /*Pascal=*/false, ArrayTy, E->getLocation());
2553*700637cbSDimitry Andric
2554*700637cbSDimitry Andric unsigned StringIndex = P.createGlobalString(SL);
2555*700637cbSDimitry Andric return this->emitGetPtrGlobal(StringIndex, E);
2556*700637cbSDimitry Andric }
2557*700637cbSDimitry Andric
2558*700637cbSDimitry Andric template <class Emitter>
VisitCharacterLiteral(const CharacterLiteral * E)2559*700637cbSDimitry Andric bool Compiler<Emitter>::VisitCharacterLiteral(const CharacterLiteral *E) {
2560*700637cbSDimitry Andric if (DiscardResult)
2561*700637cbSDimitry Andric return true;
2562*700637cbSDimitry Andric return this->emitConst(E->getValue(), E);
2563*700637cbSDimitry Andric }
2564*700637cbSDimitry Andric
2565*700637cbSDimitry Andric template <class Emitter>
VisitFloatCompoundAssignOperator(const CompoundAssignOperator * E)2566*700637cbSDimitry Andric bool Compiler<Emitter>::VisitFloatCompoundAssignOperator(
2567*700637cbSDimitry Andric const CompoundAssignOperator *E) {
2568*700637cbSDimitry Andric
2569*700637cbSDimitry Andric const Expr *LHS = E->getLHS();
2570*700637cbSDimitry Andric const Expr *RHS = E->getRHS();
2571*700637cbSDimitry Andric QualType LHSType = LHS->getType();
2572*700637cbSDimitry Andric QualType LHSComputationType = E->getComputationLHSType();
2573*700637cbSDimitry Andric QualType ResultType = E->getComputationResultType();
2574*700637cbSDimitry Andric std::optional<PrimType> LT = classify(LHSComputationType);
2575*700637cbSDimitry Andric std::optional<PrimType> RT = classify(ResultType);
2576*700637cbSDimitry Andric
2577*700637cbSDimitry Andric assert(ResultType->isFloatingType());
2578*700637cbSDimitry Andric
2579*700637cbSDimitry Andric if (!LT || !RT)
2580*700637cbSDimitry Andric return false;
2581*700637cbSDimitry Andric
2582*700637cbSDimitry Andric PrimType LHST = classifyPrim(LHSType);
2583*700637cbSDimitry Andric
2584*700637cbSDimitry Andric // C++17 onwards require that we evaluate the RHS first.
2585*700637cbSDimitry Andric // Compute RHS and save it in a temporary variable so we can
2586*700637cbSDimitry Andric // load it again later.
2587*700637cbSDimitry Andric if (!visit(RHS))
2588*700637cbSDimitry Andric return false;
2589*700637cbSDimitry Andric
2590*700637cbSDimitry Andric unsigned TempOffset = this->allocateLocalPrimitive(E, *RT, /*IsConst=*/true);
2591*700637cbSDimitry Andric if (!this->emitSetLocal(*RT, TempOffset, E))
2592*700637cbSDimitry Andric return false;
2593*700637cbSDimitry Andric
2594*700637cbSDimitry Andric // First, visit LHS.
2595*700637cbSDimitry Andric if (!visit(LHS))
2596*700637cbSDimitry Andric return false;
2597*700637cbSDimitry Andric if (!this->emitLoad(LHST, E))
2598*700637cbSDimitry Andric return false;
2599*700637cbSDimitry Andric
2600*700637cbSDimitry Andric // If necessary, convert LHS to its computation type.
2601*700637cbSDimitry Andric if (!this->emitPrimCast(LHST, classifyPrim(LHSComputationType),
2602*700637cbSDimitry Andric LHSComputationType, E))
2603*700637cbSDimitry Andric return false;
2604*700637cbSDimitry Andric
2605*700637cbSDimitry Andric // Now load RHS.
2606*700637cbSDimitry Andric if (!this->emitGetLocal(*RT, TempOffset, E))
2607*700637cbSDimitry Andric return false;
2608*700637cbSDimitry Andric
2609*700637cbSDimitry Andric switch (E->getOpcode()) {
2610*700637cbSDimitry Andric case BO_AddAssign:
2611*700637cbSDimitry Andric if (!this->emitAddf(getFPOptions(E), E))
2612*700637cbSDimitry Andric return false;
2613*700637cbSDimitry Andric break;
2614*700637cbSDimitry Andric case BO_SubAssign:
2615*700637cbSDimitry Andric if (!this->emitSubf(getFPOptions(E), E))
2616*700637cbSDimitry Andric return false;
2617*700637cbSDimitry Andric break;
2618*700637cbSDimitry Andric case BO_MulAssign:
2619*700637cbSDimitry Andric if (!this->emitMulf(getFPOptions(E), E))
2620*700637cbSDimitry Andric return false;
2621*700637cbSDimitry Andric break;
2622*700637cbSDimitry Andric case BO_DivAssign:
2623*700637cbSDimitry Andric if (!this->emitDivf(getFPOptions(E), E))
2624*700637cbSDimitry Andric return false;
2625*700637cbSDimitry Andric break;
2626*700637cbSDimitry Andric default:
2627*700637cbSDimitry Andric return false;
2628*700637cbSDimitry Andric }
2629*700637cbSDimitry Andric
2630*700637cbSDimitry Andric if (!this->emitPrimCast(classifyPrim(ResultType), LHST, LHS->getType(), E))
2631*700637cbSDimitry Andric return false;
2632*700637cbSDimitry Andric
2633*700637cbSDimitry Andric if (DiscardResult)
2634*700637cbSDimitry Andric return this->emitStorePop(LHST, E);
2635*700637cbSDimitry Andric return this->emitStore(LHST, E);
2636*700637cbSDimitry Andric }
2637*700637cbSDimitry Andric
2638*700637cbSDimitry Andric template <class Emitter>
VisitPointerCompoundAssignOperator(const CompoundAssignOperator * E)2639*700637cbSDimitry Andric bool Compiler<Emitter>::VisitPointerCompoundAssignOperator(
2640*700637cbSDimitry Andric const CompoundAssignOperator *E) {
2641*700637cbSDimitry Andric BinaryOperatorKind Op = E->getOpcode();
2642*700637cbSDimitry Andric const Expr *LHS = E->getLHS();
2643*700637cbSDimitry Andric const Expr *RHS = E->getRHS();
2644*700637cbSDimitry Andric std::optional<PrimType> LT = classify(LHS->getType());
2645*700637cbSDimitry Andric std::optional<PrimType> RT = classify(RHS->getType());
2646*700637cbSDimitry Andric
2647*700637cbSDimitry Andric if (Op != BO_AddAssign && Op != BO_SubAssign)
2648*700637cbSDimitry Andric return false;
2649*700637cbSDimitry Andric
2650*700637cbSDimitry Andric if (!LT || !RT)
2651*700637cbSDimitry Andric return false;
2652*700637cbSDimitry Andric
2653*700637cbSDimitry Andric if (!visit(LHS))
2654*700637cbSDimitry Andric return false;
2655*700637cbSDimitry Andric
2656*700637cbSDimitry Andric if (!this->emitLoad(*LT, LHS))
2657*700637cbSDimitry Andric return false;
2658*700637cbSDimitry Andric
2659*700637cbSDimitry Andric if (!visit(RHS))
2660*700637cbSDimitry Andric return false;
2661*700637cbSDimitry Andric
2662*700637cbSDimitry Andric if (Op == BO_AddAssign) {
2663*700637cbSDimitry Andric if (!this->emitAddOffset(*RT, E))
2664*700637cbSDimitry Andric return false;
2665*700637cbSDimitry Andric } else {
2666*700637cbSDimitry Andric if (!this->emitSubOffset(*RT, E))
2667*700637cbSDimitry Andric return false;
2668*700637cbSDimitry Andric }
2669*700637cbSDimitry Andric
2670*700637cbSDimitry Andric if (DiscardResult)
2671*700637cbSDimitry Andric return this->emitStorePopPtr(E);
2672*700637cbSDimitry Andric return this->emitStorePtr(E);
2673*700637cbSDimitry Andric }
2674*700637cbSDimitry Andric
2675*700637cbSDimitry Andric template <class Emitter>
VisitCompoundAssignOperator(const CompoundAssignOperator * E)2676*700637cbSDimitry Andric bool Compiler<Emitter>::VisitCompoundAssignOperator(
2677*700637cbSDimitry Andric const CompoundAssignOperator *E) {
2678*700637cbSDimitry Andric if (E->getType()->isVectorType())
2679*700637cbSDimitry Andric return VisitVectorBinOp(E);
2680*700637cbSDimitry Andric
2681*700637cbSDimitry Andric const Expr *LHS = E->getLHS();
2682*700637cbSDimitry Andric const Expr *RHS = E->getRHS();
2683*700637cbSDimitry Andric std::optional<PrimType> LHSComputationT =
2684*700637cbSDimitry Andric classify(E->getComputationLHSType());
2685*700637cbSDimitry Andric std::optional<PrimType> LT = classify(LHS->getType());
2686*700637cbSDimitry Andric std::optional<PrimType> RT = classify(RHS->getType());
2687*700637cbSDimitry Andric std::optional<PrimType> ResultT = classify(E->getType());
2688*700637cbSDimitry Andric
2689*700637cbSDimitry Andric if (!Ctx.getLangOpts().CPlusPlus14)
2690*700637cbSDimitry Andric return this->visit(RHS) && this->visit(LHS) && this->emitError(E);
2691*700637cbSDimitry Andric
2692*700637cbSDimitry Andric if (!LT || !RT || !ResultT || !LHSComputationT)
2693*700637cbSDimitry Andric return false;
2694*700637cbSDimitry Andric
2695*700637cbSDimitry Andric // Handle floating point operations separately here, since they
2696*700637cbSDimitry Andric // require special care.
2697*700637cbSDimitry Andric
2698*700637cbSDimitry Andric if (ResultT == PT_Float || RT == PT_Float)
2699*700637cbSDimitry Andric return VisitFloatCompoundAssignOperator(E);
2700*700637cbSDimitry Andric
2701*700637cbSDimitry Andric if (E->getType()->isPointerType())
2702*700637cbSDimitry Andric return VisitPointerCompoundAssignOperator(E);
2703*700637cbSDimitry Andric
2704*700637cbSDimitry Andric assert(!E->getType()->isPointerType() && "Handled above");
2705*700637cbSDimitry Andric assert(!E->getType()->isFloatingType() && "Handled above");
2706*700637cbSDimitry Andric
2707*700637cbSDimitry Andric // C++17 onwards require that we evaluate the RHS first.
2708*700637cbSDimitry Andric // Compute RHS and save it in a temporary variable so we can
2709*700637cbSDimitry Andric // load it again later.
2710*700637cbSDimitry Andric // FIXME: Compound assignments are unsequenced in C, so we might
2711*700637cbSDimitry Andric // have to figure out how to reject them.
2712*700637cbSDimitry Andric if (!visit(RHS))
2713*700637cbSDimitry Andric return false;
2714*700637cbSDimitry Andric
2715*700637cbSDimitry Andric unsigned TempOffset = this->allocateLocalPrimitive(E, *RT, /*IsConst=*/true);
2716*700637cbSDimitry Andric
2717*700637cbSDimitry Andric if (!this->emitSetLocal(*RT, TempOffset, E))
2718*700637cbSDimitry Andric return false;
2719*700637cbSDimitry Andric
2720*700637cbSDimitry Andric // Get LHS pointer, load its value and cast it to the
2721*700637cbSDimitry Andric // computation type if necessary.
2722*700637cbSDimitry Andric if (!visit(LHS))
2723*700637cbSDimitry Andric return false;
2724*700637cbSDimitry Andric if (!this->emitLoad(*LT, E))
2725*700637cbSDimitry Andric return false;
2726*700637cbSDimitry Andric if (LT != LHSComputationT) {
2727*700637cbSDimitry Andric if (!this->emitCast(*LT, *LHSComputationT, E))
2728*700637cbSDimitry Andric return false;
2729*700637cbSDimitry Andric }
2730*700637cbSDimitry Andric
2731*700637cbSDimitry Andric // Get the RHS value on the stack.
2732*700637cbSDimitry Andric if (!this->emitGetLocal(*RT, TempOffset, E))
2733*700637cbSDimitry Andric return false;
2734*700637cbSDimitry Andric
2735*700637cbSDimitry Andric // Perform operation.
2736*700637cbSDimitry Andric switch (E->getOpcode()) {
2737*700637cbSDimitry Andric case BO_AddAssign:
2738*700637cbSDimitry Andric if (!this->emitAdd(*LHSComputationT, E))
2739*700637cbSDimitry Andric return false;
2740*700637cbSDimitry Andric break;
2741*700637cbSDimitry Andric case BO_SubAssign:
2742*700637cbSDimitry Andric if (!this->emitSub(*LHSComputationT, E))
2743*700637cbSDimitry Andric return false;
2744*700637cbSDimitry Andric break;
2745*700637cbSDimitry Andric case BO_MulAssign:
2746*700637cbSDimitry Andric if (!this->emitMul(*LHSComputationT, E))
2747*700637cbSDimitry Andric return false;
2748*700637cbSDimitry Andric break;
2749*700637cbSDimitry Andric case BO_DivAssign:
2750*700637cbSDimitry Andric if (!this->emitDiv(*LHSComputationT, E))
2751*700637cbSDimitry Andric return false;
2752*700637cbSDimitry Andric break;
2753*700637cbSDimitry Andric case BO_RemAssign:
2754*700637cbSDimitry Andric if (!this->emitRem(*LHSComputationT, E))
2755*700637cbSDimitry Andric return false;
2756*700637cbSDimitry Andric break;
2757*700637cbSDimitry Andric case BO_ShlAssign:
2758*700637cbSDimitry Andric if (!this->emitShl(*LHSComputationT, *RT, E))
2759*700637cbSDimitry Andric return false;
2760*700637cbSDimitry Andric break;
2761*700637cbSDimitry Andric case BO_ShrAssign:
2762*700637cbSDimitry Andric if (!this->emitShr(*LHSComputationT, *RT, E))
2763*700637cbSDimitry Andric return false;
2764*700637cbSDimitry Andric break;
2765*700637cbSDimitry Andric case BO_AndAssign:
2766*700637cbSDimitry Andric if (!this->emitBitAnd(*LHSComputationT, E))
2767*700637cbSDimitry Andric return false;
2768*700637cbSDimitry Andric break;
2769*700637cbSDimitry Andric case BO_XorAssign:
2770*700637cbSDimitry Andric if (!this->emitBitXor(*LHSComputationT, E))
2771*700637cbSDimitry Andric return false;
2772*700637cbSDimitry Andric break;
2773*700637cbSDimitry Andric case BO_OrAssign:
2774*700637cbSDimitry Andric if (!this->emitBitOr(*LHSComputationT, E))
2775*700637cbSDimitry Andric return false;
2776*700637cbSDimitry Andric break;
2777*700637cbSDimitry Andric default:
2778*700637cbSDimitry Andric llvm_unreachable("Unimplemented compound assign operator");
2779*700637cbSDimitry Andric }
2780*700637cbSDimitry Andric
2781*700637cbSDimitry Andric // And now cast from LHSComputationT to ResultT.
2782*700637cbSDimitry Andric if (ResultT != LHSComputationT) {
2783*700637cbSDimitry Andric if (!this->emitCast(*LHSComputationT, *ResultT, E))
2784*700637cbSDimitry Andric return false;
2785*700637cbSDimitry Andric }
2786*700637cbSDimitry Andric
2787*700637cbSDimitry Andric // And store the result in LHS.
2788*700637cbSDimitry Andric if (DiscardResult) {
2789*700637cbSDimitry Andric if (LHS->refersToBitField())
2790*700637cbSDimitry Andric return this->emitStoreBitFieldPop(*ResultT, E);
2791*700637cbSDimitry Andric return this->emitStorePop(*ResultT, E);
2792*700637cbSDimitry Andric }
2793*700637cbSDimitry Andric if (LHS->refersToBitField())
2794*700637cbSDimitry Andric return this->emitStoreBitField(*ResultT, E);
2795*700637cbSDimitry Andric return this->emitStore(*ResultT, E);
2796*700637cbSDimitry Andric }
2797*700637cbSDimitry Andric
2798*700637cbSDimitry Andric template <class Emitter>
VisitExprWithCleanups(const ExprWithCleanups * E)2799*700637cbSDimitry Andric bool Compiler<Emitter>::VisitExprWithCleanups(const ExprWithCleanups *E) {
2800*700637cbSDimitry Andric LocalScope<Emitter> ES(this);
2801*700637cbSDimitry Andric const Expr *SubExpr = E->getSubExpr();
2802*700637cbSDimitry Andric
2803*700637cbSDimitry Andric return this->delegate(SubExpr) && ES.destroyLocals(E);
2804*700637cbSDimitry Andric }
2805*700637cbSDimitry Andric
2806*700637cbSDimitry Andric template <class Emitter>
VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr * E)2807*700637cbSDimitry Andric bool Compiler<Emitter>::VisitMaterializeTemporaryExpr(
2808*700637cbSDimitry Andric const MaterializeTemporaryExpr *E) {
2809*700637cbSDimitry Andric const Expr *SubExpr = E->getSubExpr();
2810*700637cbSDimitry Andric
2811*700637cbSDimitry Andric if (Initializing) {
2812*700637cbSDimitry Andric // We already have a value, just initialize that.
2813*700637cbSDimitry Andric return this->delegate(SubExpr);
2814*700637cbSDimitry Andric }
2815*700637cbSDimitry Andric // If we don't end up using the materialized temporary anyway, don't
2816*700637cbSDimitry Andric // bother creating it.
2817*700637cbSDimitry Andric if (DiscardResult)
2818*700637cbSDimitry Andric return this->discard(SubExpr);
2819*700637cbSDimitry Andric
2820*700637cbSDimitry Andric // When we're initializing a global variable *or* the storage duration of
2821*700637cbSDimitry Andric // the temporary is explicitly static, create a global variable.
2822*700637cbSDimitry Andric std::optional<PrimType> SubExprT = classify(SubExpr);
2823*700637cbSDimitry Andric bool IsStatic = E->getStorageDuration() == SD_Static;
2824*700637cbSDimitry Andric if (IsStatic) {
2825*700637cbSDimitry Andric std::optional<unsigned> GlobalIndex = P.createGlobal(E);
2826*700637cbSDimitry Andric if (!GlobalIndex)
2827*700637cbSDimitry Andric return false;
2828*700637cbSDimitry Andric
2829*700637cbSDimitry Andric const LifetimeExtendedTemporaryDecl *TempDecl =
2830*700637cbSDimitry Andric E->getLifetimeExtendedTemporaryDecl();
2831*700637cbSDimitry Andric if (IsStatic)
2832*700637cbSDimitry Andric assert(TempDecl);
2833*700637cbSDimitry Andric
2834*700637cbSDimitry Andric if (SubExprT) {
2835*700637cbSDimitry Andric if (!this->visit(SubExpr))
2836*700637cbSDimitry Andric return false;
2837*700637cbSDimitry Andric if (IsStatic) {
2838*700637cbSDimitry Andric if (!this->emitInitGlobalTemp(*SubExprT, *GlobalIndex, TempDecl, E))
2839*700637cbSDimitry Andric return false;
2840*700637cbSDimitry Andric } else {
2841*700637cbSDimitry Andric if (!this->emitInitGlobal(*SubExprT, *GlobalIndex, E))
2842*700637cbSDimitry Andric return false;
2843*700637cbSDimitry Andric }
2844*700637cbSDimitry Andric return this->emitGetPtrGlobal(*GlobalIndex, E);
2845*700637cbSDimitry Andric }
2846*700637cbSDimitry Andric
2847*700637cbSDimitry Andric if (!this->checkLiteralType(SubExpr))
2848*700637cbSDimitry Andric return false;
2849*700637cbSDimitry Andric // Non-primitive values.
2850*700637cbSDimitry Andric if (!this->emitGetPtrGlobal(*GlobalIndex, E))
2851*700637cbSDimitry Andric return false;
2852*700637cbSDimitry Andric if (!this->visitInitializer(SubExpr))
2853*700637cbSDimitry Andric return false;
2854*700637cbSDimitry Andric if (IsStatic)
2855*700637cbSDimitry Andric return this->emitInitGlobalTempComp(TempDecl, E);
2856*700637cbSDimitry Andric return true;
2857*700637cbSDimitry Andric }
2858*700637cbSDimitry Andric
2859*700637cbSDimitry Andric // For everyhing else, use local variables.
2860*700637cbSDimitry Andric if (SubExprT) {
2861*700637cbSDimitry Andric bool IsConst = SubExpr->getType().isConstQualified();
2862*700637cbSDimitry Andric unsigned LocalIndex =
2863*700637cbSDimitry Andric allocateLocalPrimitive(E, *SubExprT, IsConst, E->getExtendingDecl());
2864*700637cbSDimitry Andric if (!this->visit(SubExpr))
2865*700637cbSDimitry Andric return false;
2866*700637cbSDimitry Andric if (!this->emitSetLocal(*SubExprT, LocalIndex, E))
2867*700637cbSDimitry Andric return false;
2868*700637cbSDimitry Andric return this->emitGetPtrLocal(LocalIndex, E);
2869*700637cbSDimitry Andric } else {
2870*700637cbSDimitry Andric
2871*700637cbSDimitry Andric if (!this->checkLiteralType(SubExpr))
2872*700637cbSDimitry Andric return false;
2873*700637cbSDimitry Andric
2874*700637cbSDimitry Andric const Expr *Inner = E->getSubExpr()->skipRValueSubobjectAdjustments();
2875*700637cbSDimitry Andric if (std::optional<unsigned> LocalIndex =
2876*700637cbSDimitry Andric allocateLocal(E, Inner->getType(), E->getExtendingDecl())) {
2877*700637cbSDimitry Andric InitLinkScope<Emitter> ILS(this, InitLink::Temp(*LocalIndex));
2878*700637cbSDimitry Andric if (!this->emitGetPtrLocal(*LocalIndex, E))
2879*700637cbSDimitry Andric return false;
2880*700637cbSDimitry Andric return this->visitInitializer(SubExpr) && this->emitFinishInit(E);
2881*700637cbSDimitry Andric }
2882*700637cbSDimitry Andric }
2883*700637cbSDimitry Andric return false;
2884*700637cbSDimitry Andric }
2885*700637cbSDimitry Andric
2886*700637cbSDimitry Andric template <class Emitter>
VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr * E)2887*700637cbSDimitry Andric bool Compiler<Emitter>::VisitCXXBindTemporaryExpr(
2888*700637cbSDimitry Andric const CXXBindTemporaryExpr *E) {
2889*700637cbSDimitry Andric const Expr *SubExpr = E->getSubExpr();
2890*700637cbSDimitry Andric
2891*700637cbSDimitry Andric if (Initializing)
2892*700637cbSDimitry Andric return this->delegate(SubExpr);
2893*700637cbSDimitry Andric
2894*700637cbSDimitry Andric // Make sure we create a temporary even if we're discarding, since that will
2895*700637cbSDimitry Andric // make sure we will also call the destructor.
2896*700637cbSDimitry Andric
2897*700637cbSDimitry Andric if (!this->visit(SubExpr))
2898*700637cbSDimitry Andric return false;
2899*700637cbSDimitry Andric
2900*700637cbSDimitry Andric if (DiscardResult)
2901*700637cbSDimitry Andric return this->emitPopPtr(E);
2902*700637cbSDimitry Andric return true;
2903*700637cbSDimitry Andric }
2904*700637cbSDimitry Andric
2905*700637cbSDimitry Andric template <class Emitter>
VisitCompoundLiteralExpr(const CompoundLiteralExpr * E)2906*700637cbSDimitry Andric bool Compiler<Emitter>::VisitCompoundLiteralExpr(const CompoundLiteralExpr *E) {
2907*700637cbSDimitry Andric const Expr *Init = E->getInitializer();
2908*700637cbSDimitry Andric if (DiscardResult)
2909*700637cbSDimitry Andric return this->discard(Init);
2910*700637cbSDimitry Andric
2911*700637cbSDimitry Andric if (Initializing) {
2912*700637cbSDimitry Andric // We already have a value, just initialize that.
2913*700637cbSDimitry Andric return this->visitInitializer(Init) && this->emitFinishInit(E);
2914*700637cbSDimitry Andric }
2915*700637cbSDimitry Andric
2916*700637cbSDimitry Andric std::optional<PrimType> T = classify(E->getType());
2917*700637cbSDimitry Andric if (E->isFileScope()) {
2918*700637cbSDimitry Andric // Avoid creating a variable if this is a primitive RValue anyway.
2919*700637cbSDimitry Andric if (T && !E->isLValue())
2920*700637cbSDimitry Andric return this->delegate(Init);
2921*700637cbSDimitry Andric
2922*700637cbSDimitry Andric if (std::optional<unsigned> GlobalIndex = P.createGlobal(E)) {
2923*700637cbSDimitry Andric if (!this->emitGetPtrGlobal(*GlobalIndex, E))
2924*700637cbSDimitry Andric return false;
2925*700637cbSDimitry Andric
2926*700637cbSDimitry Andric if (T) {
2927*700637cbSDimitry Andric if (!this->visit(Init))
2928*700637cbSDimitry Andric return false;
2929*700637cbSDimitry Andric return this->emitInitGlobal(*T, *GlobalIndex, E);
2930*700637cbSDimitry Andric }
2931*700637cbSDimitry Andric
2932*700637cbSDimitry Andric return this->visitInitializer(Init) && this->emitFinishInit(E);
2933*700637cbSDimitry Andric }
2934*700637cbSDimitry Andric
2935*700637cbSDimitry Andric return false;
2936*700637cbSDimitry Andric }
2937*700637cbSDimitry Andric
2938*700637cbSDimitry Andric // Otherwise, use a local variable.
2939*700637cbSDimitry Andric if (T && !E->isLValue()) {
2940*700637cbSDimitry Andric // For primitive types, we just visit the initializer.
2941*700637cbSDimitry Andric return this->delegate(Init);
2942*700637cbSDimitry Andric }
2943*700637cbSDimitry Andric
2944*700637cbSDimitry Andric unsigned LocalIndex;
2945*700637cbSDimitry Andric if (T)
2946*700637cbSDimitry Andric LocalIndex = this->allocateLocalPrimitive(Init, *T, /*IsConst=*/false);
2947*700637cbSDimitry Andric else if (std::optional<unsigned> MaybeIndex = this->allocateLocal(Init))
2948*700637cbSDimitry Andric LocalIndex = *MaybeIndex;
2949*700637cbSDimitry Andric else
2950*700637cbSDimitry Andric return false;
2951*700637cbSDimitry Andric
2952*700637cbSDimitry Andric if (!this->emitGetPtrLocal(LocalIndex, E))
2953*700637cbSDimitry Andric return false;
2954*700637cbSDimitry Andric
2955*700637cbSDimitry Andric if (T)
2956*700637cbSDimitry Andric return this->visit(Init) && this->emitInit(*T, E);
2957*700637cbSDimitry Andric return this->visitInitializer(Init) && this->emitFinishInit(E);
2958*700637cbSDimitry Andric }
2959*700637cbSDimitry Andric
2960*700637cbSDimitry Andric template <class Emitter>
VisitTypeTraitExpr(const TypeTraitExpr * E)2961*700637cbSDimitry Andric bool Compiler<Emitter>::VisitTypeTraitExpr(const TypeTraitExpr *E) {
2962*700637cbSDimitry Andric if (DiscardResult)
2963*700637cbSDimitry Andric return true;
2964*700637cbSDimitry Andric if (E->isStoredAsBoolean()) {
2965*700637cbSDimitry Andric if (E->getType()->isBooleanType())
2966*700637cbSDimitry Andric return this->emitConstBool(E->getBoolValue(), E);
2967*700637cbSDimitry Andric return this->emitConst(E->getBoolValue(), E);
2968*700637cbSDimitry Andric }
2969*700637cbSDimitry Andric PrimType T = classifyPrim(E->getType());
2970*700637cbSDimitry Andric return this->visitAPValue(E->getAPValue(), T, E);
2971*700637cbSDimitry Andric }
2972*700637cbSDimitry Andric
2973*700637cbSDimitry Andric template <class Emitter>
VisitArrayTypeTraitExpr(const ArrayTypeTraitExpr * E)2974*700637cbSDimitry Andric bool Compiler<Emitter>::VisitArrayTypeTraitExpr(const ArrayTypeTraitExpr *E) {
2975*700637cbSDimitry Andric if (DiscardResult)
2976*700637cbSDimitry Andric return true;
2977*700637cbSDimitry Andric return this->emitConst(E->getValue(), E);
2978*700637cbSDimitry Andric }
2979*700637cbSDimitry Andric
2980*700637cbSDimitry Andric template <class Emitter>
VisitLambdaExpr(const LambdaExpr * E)2981*700637cbSDimitry Andric bool Compiler<Emitter>::VisitLambdaExpr(const LambdaExpr *E) {
2982*700637cbSDimitry Andric if (DiscardResult)
2983*700637cbSDimitry Andric return true;
2984*700637cbSDimitry Andric
2985*700637cbSDimitry Andric assert(Initializing);
2986*700637cbSDimitry Andric const Record *R = P.getOrCreateRecord(E->getLambdaClass());
2987*700637cbSDimitry Andric if (!R)
2988*700637cbSDimitry Andric return false;
2989*700637cbSDimitry Andric
2990*700637cbSDimitry Andric auto *CaptureInitIt = E->capture_init_begin();
2991*700637cbSDimitry Andric // Initialize all fields (which represent lambda captures) of the
2992*700637cbSDimitry Andric // record with their initializers.
2993*700637cbSDimitry Andric for (const Record::Field &F : R->fields()) {
2994*700637cbSDimitry Andric const Expr *Init = *CaptureInitIt;
2995*700637cbSDimitry Andric if (!Init || Init->containsErrors())
2996*700637cbSDimitry Andric continue;
2997*700637cbSDimitry Andric ++CaptureInitIt;
2998*700637cbSDimitry Andric
2999*700637cbSDimitry Andric if (std::optional<PrimType> T = classify(Init)) {
3000*700637cbSDimitry Andric if (!this->visit(Init))
3001*700637cbSDimitry Andric return false;
3002*700637cbSDimitry Andric
3003*700637cbSDimitry Andric if (!this->emitInitField(*T, F.Offset, E))
3004*700637cbSDimitry Andric return false;
3005*700637cbSDimitry Andric } else {
3006*700637cbSDimitry Andric if (!this->emitGetPtrField(F.Offset, E))
3007*700637cbSDimitry Andric return false;
3008*700637cbSDimitry Andric
3009*700637cbSDimitry Andric if (!this->visitInitializer(Init))
3010*700637cbSDimitry Andric return false;
3011*700637cbSDimitry Andric
3012*700637cbSDimitry Andric if (!this->emitPopPtr(E))
3013*700637cbSDimitry Andric return false;
3014*700637cbSDimitry Andric }
3015*700637cbSDimitry Andric }
3016*700637cbSDimitry Andric
3017*700637cbSDimitry Andric return true;
3018*700637cbSDimitry Andric }
3019*700637cbSDimitry Andric
3020*700637cbSDimitry Andric template <class Emitter>
VisitPredefinedExpr(const PredefinedExpr * E)3021*700637cbSDimitry Andric bool Compiler<Emitter>::VisitPredefinedExpr(const PredefinedExpr *E) {
3022*700637cbSDimitry Andric if (DiscardResult)
3023*700637cbSDimitry Andric return true;
3024*700637cbSDimitry Andric
3025*700637cbSDimitry Andric if (!Initializing) {
3026*700637cbSDimitry Andric unsigned StringIndex = P.createGlobalString(E->getFunctionName(), E);
3027*700637cbSDimitry Andric return this->emitGetPtrGlobal(StringIndex, E);
3028*700637cbSDimitry Andric }
3029*700637cbSDimitry Andric
3030*700637cbSDimitry Andric return this->delegate(E->getFunctionName());
3031*700637cbSDimitry Andric }
3032*700637cbSDimitry Andric
3033*700637cbSDimitry Andric template <class Emitter>
VisitCXXThrowExpr(const CXXThrowExpr * E)3034*700637cbSDimitry Andric bool Compiler<Emitter>::VisitCXXThrowExpr(const CXXThrowExpr *E) {
3035*700637cbSDimitry Andric if (E->getSubExpr() && !this->discard(E->getSubExpr()))
3036*700637cbSDimitry Andric return false;
3037*700637cbSDimitry Andric
3038*700637cbSDimitry Andric return this->emitInvalid(E);
3039*700637cbSDimitry Andric }
3040*700637cbSDimitry Andric
3041*700637cbSDimitry Andric template <class Emitter>
VisitCXXReinterpretCastExpr(const CXXReinterpretCastExpr * E)3042*700637cbSDimitry Andric bool Compiler<Emitter>::VisitCXXReinterpretCastExpr(
3043*700637cbSDimitry Andric const CXXReinterpretCastExpr *E) {
3044*700637cbSDimitry Andric const Expr *SubExpr = E->getSubExpr();
3045*700637cbSDimitry Andric
3046*700637cbSDimitry Andric std::optional<PrimType> FromT = classify(SubExpr);
3047*700637cbSDimitry Andric std::optional<PrimType> ToT = classify(E);
3048*700637cbSDimitry Andric
3049*700637cbSDimitry Andric if (!FromT || !ToT)
3050*700637cbSDimitry Andric return this->emitInvalidCast(CastKind::Reinterpret, /*Fatal=*/true, E);
3051*700637cbSDimitry Andric
3052*700637cbSDimitry Andric if (FromT == PT_Ptr || ToT == PT_Ptr) {
3053*700637cbSDimitry Andric // Both types could be PT_Ptr because their expressions are glvalues.
3054*700637cbSDimitry Andric std::optional<PrimType> PointeeFromT;
3055*700637cbSDimitry Andric if (SubExpr->getType()->isPointerOrReferenceType())
3056*700637cbSDimitry Andric PointeeFromT = classify(SubExpr->getType()->getPointeeType());
3057*700637cbSDimitry Andric else
3058*700637cbSDimitry Andric PointeeFromT = classify(SubExpr->getType());
3059*700637cbSDimitry Andric
3060*700637cbSDimitry Andric std::optional<PrimType> PointeeToT;
3061*700637cbSDimitry Andric if (E->getType()->isPointerOrReferenceType())
3062*700637cbSDimitry Andric PointeeToT = classify(E->getType()->getPointeeType());
3063*700637cbSDimitry Andric else
3064*700637cbSDimitry Andric PointeeToT = classify(E->getType());
3065*700637cbSDimitry Andric
3066*700637cbSDimitry Andric bool Fatal = true;
3067*700637cbSDimitry Andric if (PointeeToT && PointeeFromT) {
3068*700637cbSDimitry Andric if (isIntegralType(*PointeeFromT) && isIntegralType(*PointeeToT))
3069*700637cbSDimitry Andric Fatal = false;
3070*700637cbSDimitry Andric } else {
3071*700637cbSDimitry Andric Fatal = SubExpr->getType().getTypePtr() != E->getType().getTypePtr();
3072*700637cbSDimitry Andric }
3073*700637cbSDimitry Andric
3074*700637cbSDimitry Andric if (!this->emitInvalidCast(CastKind::Reinterpret, Fatal, E))
3075*700637cbSDimitry Andric return false;
3076*700637cbSDimitry Andric
3077*700637cbSDimitry Andric if (E->getCastKind() == CK_LValueBitCast)
3078*700637cbSDimitry Andric return this->delegate(SubExpr);
3079*700637cbSDimitry Andric return this->VisitCastExpr(E);
3080*700637cbSDimitry Andric }
3081*700637cbSDimitry Andric
3082*700637cbSDimitry Andric // Try to actually do the cast.
3083*700637cbSDimitry Andric bool Fatal = (ToT != FromT);
3084*700637cbSDimitry Andric if (!this->emitInvalidCast(CastKind::Reinterpret, Fatal, E))
3085*700637cbSDimitry Andric return false;
3086*700637cbSDimitry Andric
3087*700637cbSDimitry Andric return this->VisitCastExpr(E);
3088*700637cbSDimitry Andric }
3089*700637cbSDimitry Andric
3090*700637cbSDimitry Andric template <class Emitter>
VisitCXXDynamicCastExpr(const CXXDynamicCastExpr * E)3091*700637cbSDimitry Andric bool Compiler<Emitter>::VisitCXXDynamicCastExpr(const CXXDynamicCastExpr *E) {
3092*700637cbSDimitry Andric
3093*700637cbSDimitry Andric if (!Ctx.getLangOpts().CPlusPlus20) {
3094*700637cbSDimitry Andric if (!this->emitInvalidCast(CastKind::Dynamic, /*Fatal=*/false, E))
3095*700637cbSDimitry Andric return false;
3096*700637cbSDimitry Andric }
3097*700637cbSDimitry Andric
3098*700637cbSDimitry Andric return this->VisitCastExpr(E);
3099*700637cbSDimitry Andric }
3100*700637cbSDimitry Andric
3101*700637cbSDimitry Andric template <class Emitter>
VisitCXXNoexceptExpr(const CXXNoexceptExpr * E)3102*700637cbSDimitry Andric bool Compiler<Emitter>::VisitCXXNoexceptExpr(const CXXNoexceptExpr *E) {
3103*700637cbSDimitry Andric assert(E->getType()->isBooleanType());
3104*700637cbSDimitry Andric
3105*700637cbSDimitry Andric if (DiscardResult)
3106*700637cbSDimitry Andric return true;
3107*700637cbSDimitry Andric return this->emitConstBool(E->getValue(), E);
3108*700637cbSDimitry Andric }
3109*700637cbSDimitry Andric
3110*700637cbSDimitry Andric template <class Emitter>
VisitCXXConstructExpr(const CXXConstructExpr * E)3111*700637cbSDimitry Andric bool Compiler<Emitter>::VisitCXXConstructExpr(const CXXConstructExpr *E) {
3112*700637cbSDimitry Andric QualType T = E->getType();
3113*700637cbSDimitry Andric assert(!classify(T));
3114*700637cbSDimitry Andric
3115*700637cbSDimitry Andric if (T->isRecordType()) {
3116*700637cbSDimitry Andric const CXXConstructorDecl *Ctor = E->getConstructor();
3117*700637cbSDimitry Andric
3118*700637cbSDimitry Andric // Trivial copy/move constructor. Avoid copy.
3119*700637cbSDimitry Andric if (Ctor->isDefaulted() && Ctor->isCopyOrMoveConstructor() &&
3120*700637cbSDimitry Andric Ctor->isTrivial() &&
3121*700637cbSDimitry Andric E->getArg(0)->isTemporaryObject(Ctx.getASTContext(),
3122*700637cbSDimitry Andric T->getAsCXXRecordDecl()))
3123*700637cbSDimitry Andric return this->visitInitializer(E->getArg(0));
3124*700637cbSDimitry Andric
3125*700637cbSDimitry Andric // If we're discarding a construct expression, we still need
3126*700637cbSDimitry Andric // to allocate a variable and call the constructor and destructor.
3127*700637cbSDimitry Andric if (DiscardResult) {
3128*700637cbSDimitry Andric if (Ctor->isTrivial())
3129*700637cbSDimitry Andric return true;
3130*700637cbSDimitry Andric assert(!Initializing);
3131*700637cbSDimitry Andric std::optional<unsigned> LocalIndex = allocateLocal(E);
3132*700637cbSDimitry Andric
3133*700637cbSDimitry Andric if (!LocalIndex)
3134*700637cbSDimitry Andric return false;
3135*700637cbSDimitry Andric
3136*700637cbSDimitry Andric if (!this->emitGetPtrLocal(*LocalIndex, E))
3137*700637cbSDimitry Andric return false;
3138*700637cbSDimitry Andric }
3139*700637cbSDimitry Andric
3140*700637cbSDimitry Andric // Zero initialization.
3141*700637cbSDimitry Andric if (E->requiresZeroInitialization()) {
3142*700637cbSDimitry Andric const Record *R = getRecord(E->getType());
3143*700637cbSDimitry Andric
3144*700637cbSDimitry Andric if (!this->visitZeroRecordInitializer(R, E))
3145*700637cbSDimitry Andric return false;
3146*700637cbSDimitry Andric
3147*700637cbSDimitry Andric // If the constructor is trivial anyway, we're done.
3148*700637cbSDimitry Andric if (Ctor->isTrivial())
3149*700637cbSDimitry Andric return true;
3150*700637cbSDimitry Andric }
3151*700637cbSDimitry Andric
3152*700637cbSDimitry Andric const Function *Func = getFunction(Ctor);
3153*700637cbSDimitry Andric
3154*700637cbSDimitry Andric if (!Func)
3155*700637cbSDimitry Andric return false;
3156*700637cbSDimitry Andric
3157*700637cbSDimitry Andric assert(Func->hasThisPointer());
3158*700637cbSDimitry Andric assert(!Func->hasRVO());
3159*700637cbSDimitry Andric
3160*700637cbSDimitry Andric // The This pointer is already on the stack because this is an initializer,
3161*700637cbSDimitry Andric // but we need to dup() so the call() below has its own copy.
3162*700637cbSDimitry Andric if (!this->emitDupPtr(E))
3163*700637cbSDimitry Andric return false;
3164*700637cbSDimitry Andric
3165*700637cbSDimitry Andric // Constructor arguments.
3166*700637cbSDimitry Andric for (const auto *Arg : E->arguments()) {
3167*700637cbSDimitry Andric if (!this->visit(Arg))
3168*700637cbSDimitry Andric return false;
3169*700637cbSDimitry Andric }
3170*700637cbSDimitry Andric
3171*700637cbSDimitry Andric if (Func->isVariadic()) {
3172*700637cbSDimitry Andric uint32_t VarArgSize = 0;
3173*700637cbSDimitry Andric unsigned NumParams = Func->getNumWrittenParams();
3174*700637cbSDimitry Andric for (unsigned I = NumParams, N = E->getNumArgs(); I != N; ++I) {
3175*700637cbSDimitry Andric VarArgSize +=
3176*700637cbSDimitry Andric align(primSize(classify(E->getArg(I)->getType()).value_or(PT_Ptr)));
3177*700637cbSDimitry Andric }
3178*700637cbSDimitry Andric if (!this->emitCallVar(Func, VarArgSize, E))
3179*700637cbSDimitry Andric return false;
3180*700637cbSDimitry Andric } else {
3181*700637cbSDimitry Andric if (!this->emitCall(Func, 0, E)) {
3182*700637cbSDimitry Andric // When discarding, we don't need the result anyway, so clean up
3183*700637cbSDimitry Andric // the instance dup we did earlier in case surrounding code wants
3184*700637cbSDimitry Andric // to keep evaluating.
3185*700637cbSDimitry Andric if (DiscardResult)
3186*700637cbSDimitry Andric (void)this->emitPopPtr(E);
3187*700637cbSDimitry Andric return false;
3188*700637cbSDimitry Andric }
3189*700637cbSDimitry Andric }
3190*700637cbSDimitry Andric
3191*700637cbSDimitry Andric if (DiscardResult)
3192*700637cbSDimitry Andric return this->emitPopPtr(E);
3193*700637cbSDimitry Andric return this->emitFinishInit(E);
3194*700637cbSDimitry Andric }
3195*700637cbSDimitry Andric
3196*700637cbSDimitry Andric if (T->isArrayType()) {
3197*700637cbSDimitry Andric const ConstantArrayType *CAT =
3198*700637cbSDimitry Andric Ctx.getASTContext().getAsConstantArrayType(E->getType());
3199*700637cbSDimitry Andric if (!CAT)
3200*700637cbSDimitry Andric return false;
3201*700637cbSDimitry Andric
3202*700637cbSDimitry Andric size_t NumElems = CAT->getZExtSize();
3203*700637cbSDimitry Andric const Function *Func = getFunction(E->getConstructor());
3204*700637cbSDimitry Andric if (!Func)
3205*700637cbSDimitry Andric return false;
3206*700637cbSDimitry Andric
3207*700637cbSDimitry Andric // FIXME(perf): We're calling the constructor once per array element here,
3208*700637cbSDimitry Andric // in the old intepreter we had a special-case for trivial constructors.
3209*700637cbSDimitry Andric for (size_t I = 0; I != NumElems; ++I) {
3210*700637cbSDimitry Andric if (!this->emitConstUint64(I, E))
3211*700637cbSDimitry Andric return false;
3212*700637cbSDimitry Andric if (!this->emitArrayElemPtrUint64(E))
3213*700637cbSDimitry Andric return false;
3214*700637cbSDimitry Andric
3215*700637cbSDimitry Andric // Constructor arguments.
3216*700637cbSDimitry Andric for (const auto *Arg : E->arguments()) {
3217*700637cbSDimitry Andric if (!this->visit(Arg))
3218*700637cbSDimitry Andric return false;
3219*700637cbSDimitry Andric }
3220*700637cbSDimitry Andric
3221*700637cbSDimitry Andric if (!this->emitCall(Func, 0, E))
3222*700637cbSDimitry Andric return false;
3223*700637cbSDimitry Andric }
3224*700637cbSDimitry Andric return true;
3225*700637cbSDimitry Andric }
3226*700637cbSDimitry Andric
3227*700637cbSDimitry Andric return false;
3228*700637cbSDimitry Andric }
3229*700637cbSDimitry Andric
3230*700637cbSDimitry Andric template <class Emitter>
VisitSourceLocExpr(const SourceLocExpr * E)3231*700637cbSDimitry Andric bool Compiler<Emitter>::VisitSourceLocExpr(const SourceLocExpr *E) {
3232*700637cbSDimitry Andric if (DiscardResult)
3233*700637cbSDimitry Andric return true;
3234*700637cbSDimitry Andric
3235*700637cbSDimitry Andric const APValue Val =
3236*700637cbSDimitry Andric E->EvaluateInContext(Ctx.getASTContext(), SourceLocDefaultExpr);
3237*700637cbSDimitry Andric
3238*700637cbSDimitry Andric // Things like __builtin_LINE().
3239*700637cbSDimitry Andric if (E->getType()->isIntegerType()) {
3240*700637cbSDimitry Andric assert(Val.isInt());
3241*700637cbSDimitry Andric const APSInt &I = Val.getInt();
3242*700637cbSDimitry Andric return this->emitConst(I, E);
3243*700637cbSDimitry Andric }
3244*700637cbSDimitry Andric // Otherwise, the APValue is an LValue, with only one element.
3245*700637cbSDimitry Andric // Theoretically, we don't need the APValue at all of course.
3246*700637cbSDimitry Andric assert(E->getType()->isPointerType());
3247*700637cbSDimitry Andric assert(Val.isLValue());
3248*700637cbSDimitry Andric const APValue::LValueBase &Base = Val.getLValueBase();
3249*700637cbSDimitry Andric if (const Expr *LValueExpr = Base.dyn_cast<const Expr *>())
3250*700637cbSDimitry Andric return this->visit(LValueExpr);
3251*700637cbSDimitry Andric
3252*700637cbSDimitry Andric // Otherwise, we have a decl (which is the case for
3253*700637cbSDimitry Andric // __builtin_source_location).
3254*700637cbSDimitry Andric assert(Base.is<const ValueDecl *>());
3255*700637cbSDimitry Andric assert(Val.getLValuePath().size() == 0);
3256*700637cbSDimitry Andric const auto *BaseDecl = Base.dyn_cast<const ValueDecl *>();
3257*700637cbSDimitry Andric assert(BaseDecl);
3258*700637cbSDimitry Andric
3259*700637cbSDimitry Andric auto *UGCD = cast<UnnamedGlobalConstantDecl>(BaseDecl);
3260*700637cbSDimitry Andric
3261*700637cbSDimitry Andric std::optional<unsigned> GlobalIndex = P.getOrCreateGlobal(UGCD);
3262*700637cbSDimitry Andric if (!GlobalIndex)
3263*700637cbSDimitry Andric return false;
3264*700637cbSDimitry Andric
3265*700637cbSDimitry Andric if (!this->emitGetPtrGlobal(*GlobalIndex, E))
3266*700637cbSDimitry Andric return false;
3267*700637cbSDimitry Andric
3268*700637cbSDimitry Andric const Record *R = getRecord(E->getType());
3269*700637cbSDimitry Andric const APValue &V = UGCD->getValue();
3270*700637cbSDimitry Andric for (unsigned I = 0, N = R->getNumFields(); I != N; ++I) {
3271*700637cbSDimitry Andric const Record::Field *F = R->getField(I);
3272*700637cbSDimitry Andric const APValue &FieldValue = V.getStructField(I);
3273*700637cbSDimitry Andric
3274*700637cbSDimitry Andric PrimType FieldT = classifyPrim(F->Decl->getType());
3275*700637cbSDimitry Andric
3276*700637cbSDimitry Andric if (!this->visitAPValue(FieldValue, FieldT, E))
3277*700637cbSDimitry Andric return false;
3278*700637cbSDimitry Andric if (!this->emitInitField(FieldT, F->Offset, E))
3279*700637cbSDimitry Andric return false;
3280*700637cbSDimitry Andric }
3281*700637cbSDimitry Andric
3282*700637cbSDimitry Andric // Leave the pointer to the global on the stack.
3283*700637cbSDimitry Andric return true;
3284*700637cbSDimitry Andric }
3285*700637cbSDimitry Andric
3286*700637cbSDimitry Andric template <class Emitter>
VisitOffsetOfExpr(const OffsetOfExpr * E)3287*700637cbSDimitry Andric bool Compiler<Emitter>::VisitOffsetOfExpr(const OffsetOfExpr *E) {
3288*700637cbSDimitry Andric unsigned N = E->getNumComponents();
3289*700637cbSDimitry Andric if (N == 0)
3290*700637cbSDimitry Andric return false;
3291*700637cbSDimitry Andric
3292*700637cbSDimitry Andric for (unsigned I = 0; I != N; ++I) {
3293*700637cbSDimitry Andric const OffsetOfNode &Node = E->getComponent(I);
3294*700637cbSDimitry Andric if (Node.getKind() == OffsetOfNode::Array) {
3295*700637cbSDimitry Andric const Expr *ArrayIndexExpr = E->getIndexExpr(Node.getArrayExprIndex());
3296*700637cbSDimitry Andric PrimType IndexT = classifyPrim(ArrayIndexExpr->getType());
3297*700637cbSDimitry Andric
3298*700637cbSDimitry Andric if (DiscardResult) {
3299*700637cbSDimitry Andric if (!this->discard(ArrayIndexExpr))
3300*700637cbSDimitry Andric return false;
3301*700637cbSDimitry Andric continue;
3302*700637cbSDimitry Andric }
3303*700637cbSDimitry Andric
3304*700637cbSDimitry Andric if (!this->visit(ArrayIndexExpr))
3305*700637cbSDimitry Andric return false;
3306*700637cbSDimitry Andric // Cast to Sint64.
3307*700637cbSDimitry Andric if (IndexT != PT_Sint64) {
3308*700637cbSDimitry Andric if (!this->emitCast(IndexT, PT_Sint64, E))
3309*700637cbSDimitry Andric return false;
3310*700637cbSDimitry Andric }
3311*700637cbSDimitry Andric }
3312*700637cbSDimitry Andric }
3313*700637cbSDimitry Andric
3314*700637cbSDimitry Andric if (DiscardResult)
3315*700637cbSDimitry Andric return true;
3316*700637cbSDimitry Andric
3317*700637cbSDimitry Andric PrimType T = classifyPrim(E->getType());
3318*700637cbSDimitry Andric return this->emitOffsetOf(T, E, E);
3319*700637cbSDimitry Andric }
3320*700637cbSDimitry Andric
3321*700637cbSDimitry Andric template <class Emitter>
VisitCXXScalarValueInitExpr(const CXXScalarValueInitExpr * E)3322*700637cbSDimitry Andric bool Compiler<Emitter>::VisitCXXScalarValueInitExpr(
3323*700637cbSDimitry Andric const CXXScalarValueInitExpr *E) {
3324*700637cbSDimitry Andric QualType Ty = E->getType();
3325*700637cbSDimitry Andric
3326*700637cbSDimitry Andric if (DiscardResult || Ty->isVoidType())
3327*700637cbSDimitry Andric return true;
3328*700637cbSDimitry Andric
3329*700637cbSDimitry Andric if (std::optional<PrimType> T = classify(Ty))
3330*700637cbSDimitry Andric return this->visitZeroInitializer(*T, Ty, E);
3331*700637cbSDimitry Andric
3332*700637cbSDimitry Andric if (const auto *CT = Ty->getAs<ComplexType>()) {
3333*700637cbSDimitry Andric if (!Initializing) {
3334*700637cbSDimitry Andric std::optional<unsigned> LocalIndex = allocateLocal(E);
3335*700637cbSDimitry Andric if (!LocalIndex)
3336*700637cbSDimitry Andric return false;
3337*700637cbSDimitry Andric if (!this->emitGetPtrLocal(*LocalIndex, E))
3338*700637cbSDimitry Andric return false;
3339*700637cbSDimitry Andric }
3340*700637cbSDimitry Andric
3341*700637cbSDimitry Andric // Initialize both fields to 0.
3342*700637cbSDimitry Andric QualType ElemQT = CT->getElementType();
3343*700637cbSDimitry Andric PrimType ElemT = classifyPrim(ElemQT);
3344*700637cbSDimitry Andric
3345*700637cbSDimitry Andric for (unsigned I = 0; I != 2; ++I) {
3346*700637cbSDimitry Andric if (!this->visitZeroInitializer(ElemT, ElemQT, E))
3347*700637cbSDimitry Andric return false;
3348*700637cbSDimitry Andric if (!this->emitInitElem(ElemT, I, E))
3349*700637cbSDimitry Andric return false;
3350*700637cbSDimitry Andric }
3351*700637cbSDimitry Andric return true;
3352*700637cbSDimitry Andric }
3353*700637cbSDimitry Andric
3354*700637cbSDimitry Andric if (const auto *VT = Ty->getAs<VectorType>()) {
3355*700637cbSDimitry Andric // FIXME: Code duplication with the _Complex case above.
3356*700637cbSDimitry Andric if (!Initializing) {
3357*700637cbSDimitry Andric std::optional<unsigned> LocalIndex = allocateLocal(E);
3358*700637cbSDimitry Andric if (!LocalIndex)
3359*700637cbSDimitry Andric return false;
3360*700637cbSDimitry Andric if (!this->emitGetPtrLocal(*LocalIndex, E))
3361*700637cbSDimitry Andric return false;
3362*700637cbSDimitry Andric }
3363*700637cbSDimitry Andric
3364*700637cbSDimitry Andric // Initialize all fields to 0.
3365*700637cbSDimitry Andric QualType ElemQT = VT->getElementType();
3366*700637cbSDimitry Andric PrimType ElemT = classifyPrim(ElemQT);
3367*700637cbSDimitry Andric
3368*700637cbSDimitry Andric for (unsigned I = 0, N = VT->getNumElements(); I != N; ++I) {
3369*700637cbSDimitry Andric if (!this->visitZeroInitializer(ElemT, ElemQT, E))
3370*700637cbSDimitry Andric return false;
3371*700637cbSDimitry Andric if (!this->emitInitElem(ElemT, I, E))
3372*700637cbSDimitry Andric return false;
3373*700637cbSDimitry Andric }
3374*700637cbSDimitry Andric return true;
3375*700637cbSDimitry Andric }
3376*700637cbSDimitry Andric
3377*700637cbSDimitry Andric return false;
3378*700637cbSDimitry Andric }
3379*700637cbSDimitry Andric
3380*700637cbSDimitry Andric template <class Emitter>
VisitSizeOfPackExpr(const SizeOfPackExpr * E)3381*700637cbSDimitry Andric bool Compiler<Emitter>::VisitSizeOfPackExpr(const SizeOfPackExpr *E) {
3382*700637cbSDimitry Andric return this->emitConst(E->getPackLength(), E);
3383*700637cbSDimitry Andric }
3384*700637cbSDimitry Andric
3385*700637cbSDimitry Andric template <class Emitter>
VisitGenericSelectionExpr(const GenericSelectionExpr * E)3386*700637cbSDimitry Andric bool Compiler<Emitter>::VisitGenericSelectionExpr(
3387*700637cbSDimitry Andric const GenericSelectionExpr *E) {
3388*700637cbSDimitry Andric return this->delegate(E->getResultExpr());
3389*700637cbSDimitry Andric }
3390*700637cbSDimitry Andric
3391*700637cbSDimitry Andric template <class Emitter>
VisitChooseExpr(const ChooseExpr * E)3392*700637cbSDimitry Andric bool Compiler<Emitter>::VisitChooseExpr(const ChooseExpr *E) {
3393*700637cbSDimitry Andric return this->delegate(E->getChosenSubExpr());
3394*700637cbSDimitry Andric }
3395*700637cbSDimitry Andric
3396*700637cbSDimitry Andric template <class Emitter>
VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr * E)3397*700637cbSDimitry Andric bool Compiler<Emitter>::VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *E) {
3398*700637cbSDimitry Andric if (DiscardResult)
3399*700637cbSDimitry Andric return true;
3400*700637cbSDimitry Andric
3401*700637cbSDimitry Andric return this->emitConst(E->getValue(), E);
3402*700637cbSDimitry Andric }
3403*700637cbSDimitry Andric
3404*700637cbSDimitry Andric template <class Emitter>
VisitCXXInheritedCtorInitExpr(const CXXInheritedCtorInitExpr * E)3405*700637cbSDimitry Andric bool Compiler<Emitter>::VisitCXXInheritedCtorInitExpr(
3406*700637cbSDimitry Andric const CXXInheritedCtorInitExpr *E) {
3407*700637cbSDimitry Andric const CXXConstructorDecl *Ctor = E->getConstructor();
3408*700637cbSDimitry Andric assert(!Ctor->isTrivial() &&
3409*700637cbSDimitry Andric "Trivial CXXInheritedCtorInitExpr, implement. (possible?)");
3410*700637cbSDimitry Andric const Function *F = this->getFunction(Ctor);
3411*700637cbSDimitry Andric assert(F);
3412*700637cbSDimitry Andric assert(!F->hasRVO());
3413*700637cbSDimitry Andric assert(F->hasThisPointer());
3414*700637cbSDimitry Andric
3415*700637cbSDimitry Andric if (!this->emitDupPtr(SourceInfo{}))
3416*700637cbSDimitry Andric return false;
3417*700637cbSDimitry Andric
3418*700637cbSDimitry Andric // Forward all arguments of the current function (which should be a
3419*700637cbSDimitry Andric // constructor itself) to the inherited ctor.
3420*700637cbSDimitry Andric // This is necessary because the calling code has pushed the pointer
3421*700637cbSDimitry Andric // of the correct base for us already, but the arguments need
3422*700637cbSDimitry Andric // to come after.
3423*700637cbSDimitry Andric unsigned Offset = align(primSize(PT_Ptr)); // instance pointer.
3424*700637cbSDimitry Andric for (const ParmVarDecl *PD : Ctor->parameters()) {
3425*700637cbSDimitry Andric PrimType PT = this->classify(PD->getType()).value_or(PT_Ptr);
3426*700637cbSDimitry Andric
3427*700637cbSDimitry Andric if (!this->emitGetParam(PT, Offset, E))
3428*700637cbSDimitry Andric return false;
3429*700637cbSDimitry Andric Offset += align(primSize(PT));
3430*700637cbSDimitry Andric }
3431*700637cbSDimitry Andric
3432*700637cbSDimitry Andric return this->emitCall(F, 0, E);
3433*700637cbSDimitry Andric }
3434*700637cbSDimitry Andric
3435*700637cbSDimitry Andric // FIXME: This function has become rather unwieldy, especially
3436*700637cbSDimitry Andric // the part where we initialize an array allocation of dynamic size.
3437*700637cbSDimitry Andric template <class Emitter>
VisitCXXNewExpr(const CXXNewExpr * E)3438*700637cbSDimitry Andric bool Compiler<Emitter>::VisitCXXNewExpr(const CXXNewExpr *E) {
3439*700637cbSDimitry Andric assert(classifyPrim(E->getType()) == PT_Ptr);
3440*700637cbSDimitry Andric const Expr *Init = E->getInitializer();
3441*700637cbSDimitry Andric QualType ElementType = E->getAllocatedType();
3442*700637cbSDimitry Andric std::optional<PrimType> ElemT = classify(ElementType);
3443*700637cbSDimitry Andric unsigned PlacementArgs = E->getNumPlacementArgs();
3444*700637cbSDimitry Andric const FunctionDecl *OperatorNew = E->getOperatorNew();
3445*700637cbSDimitry Andric const Expr *PlacementDest = nullptr;
3446*700637cbSDimitry Andric bool IsNoThrow = false;
3447*700637cbSDimitry Andric
3448*700637cbSDimitry Andric if (PlacementArgs != 0) {
3449*700637cbSDimitry Andric // FIXME: There is no restriction on this, but it's not clear that any
3450*700637cbSDimitry Andric // other form makes any sense. We get here for cases such as:
3451*700637cbSDimitry Andric //
3452*700637cbSDimitry Andric // new (std::align_val_t{N}) X(int)
3453*700637cbSDimitry Andric //
3454*700637cbSDimitry Andric // (which should presumably be valid only if N is a multiple of
3455*700637cbSDimitry Andric // alignof(int), and in any case can't be deallocated unless N is
3456*700637cbSDimitry Andric // alignof(X) and X has new-extended alignment).
3457*700637cbSDimitry Andric if (PlacementArgs == 1) {
3458*700637cbSDimitry Andric const Expr *Arg1 = E->getPlacementArg(0);
3459*700637cbSDimitry Andric if (Arg1->getType()->isNothrowT()) {
3460*700637cbSDimitry Andric if (!this->discard(Arg1))
3461*700637cbSDimitry Andric return false;
3462*700637cbSDimitry Andric IsNoThrow = true;
3463*700637cbSDimitry Andric } else {
3464*700637cbSDimitry Andric // Invalid unless we have C++26 or are in a std:: function.
3465*700637cbSDimitry Andric if (!this->emitInvalidNewDeleteExpr(E, E))
3466*700637cbSDimitry Andric return false;
3467*700637cbSDimitry Andric
3468*700637cbSDimitry Andric // If we have a placement-new destination, we'll later use that instead
3469*700637cbSDimitry Andric // of allocating.
3470*700637cbSDimitry Andric if (OperatorNew->isReservedGlobalPlacementOperator())
3471*700637cbSDimitry Andric PlacementDest = Arg1;
3472*700637cbSDimitry Andric }
3473*700637cbSDimitry Andric } else {
3474*700637cbSDimitry Andric // Always invalid.
3475*700637cbSDimitry Andric return this->emitInvalid(E);
3476*700637cbSDimitry Andric }
3477*700637cbSDimitry Andric } else if (!OperatorNew
3478*700637cbSDimitry Andric ->isUsableAsGlobalAllocationFunctionInConstantEvaluation())
3479*700637cbSDimitry Andric return this->emitInvalidNewDeleteExpr(E, E);
3480*700637cbSDimitry Andric
3481*700637cbSDimitry Andric const Descriptor *Desc;
3482*700637cbSDimitry Andric if (!PlacementDest) {
3483*700637cbSDimitry Andric if (ElemT) {
3484*700637cbSDimitry Andric if (E->isArray())
3485*700637cbSDimitry Andric Desc = nullptr; // We're not going to use it in this case.
3486*700637cbSDimitry Andric else
3487*700637cbSDimitry Andric Desc = P.createDescriptor(E, *ElemT, /*SourceTy=*/nullptr,
3488*700637cbSDimitry Andric Descriptor::InlineDescMD);
3489*700637cbSDimitry Andric } else {
3490*700637cbSDimitry Andric Desc = P.createDescriptor(
3491*700637cbSDimitry Andric E, ElementType.getTypePtr(),
3492*700637cbSDimitry Andric E->isArray() ? std::nullopt : Descriptor::InlineDescMD,
3493*700637cbSDimitry Andric /*IsConst=*/false, /*IsTemporary=*/false, /*IsMutable=*/false,
3494*700637cbSDimitry Andric /*IsVolatile=*/false, Init);
3495*700637cbSDimitry Andric }
3496*700637cbSDimitry Andric }
3497*700637cbSDimitry Andric
3498*700637cbSDimitry Andric if (E->isArray()) {
3499*700637cbSDimitry Andric std::optional<const Expr *> ArraySizeExpr = E->getArraySize();
3500*700637cbSDimitry Andric if (!ArraySizeExpr)
3501*700637cbSDimitry Andric return false;
3502*700637cbSDimitry Andric
3503*700637cbSDimitry Andric const Expr *Stripped = *ArraySizeExpr;
3504*700637cbSDimitry Andric for (; auto *ICE = dyn_cast<ImplicitCastExpr>(Stripped);
3505*700637cbSDimitry Andric Stripped = ICE->getSubExpr())
3506*700637cbSDimitry Andric if (ICE->getCastKind() != CK_NoOp &&
3507*700637cbSDimitry Andric ICE->getCastKind() != CK_IntegralCast)
3508*700637cbSDimitry Andric break;
3509*700637cbSDimitry Andric
3510*700637cbSDimitry Andric PrimType SizeT = classifyPrim(Stripped->getType());
3511*700637cbSDimitry Andric
3512*700637cbSDimitry Andric // Save evaluated array size to a variable.
3513*700637cbSDimitry Andric unsigned ArrayLen =
3514*700637cbSDimitry Andric allocateLocalPrimitive(Stripped, SizeT, /*IsConst=*/false);
3515*700637cbSDimitry Andric if (!this->visit(Stripped))
3516*700637cbSDimitry Andric return false;
3517*700637cbSDimitry Andric if (!this->emitSetLocal(SizeT, ArrayLen, E))
3518*700637cbSDimitry Andric return false;
3519*700637cbSDimitry Andric
3520*700637cbSDimitry Andric if (PlacementDest) {
3521*700637cbSDimitry Andric if (!this->visit(PlacementDest))
3522*700637cbSDimitry Andric return false;
3523*700637cbSDimitry Andric if (!this->emitStartLifetime(E))
3524*700637cbSDimitry Andric return false;
3525*700637cbSDimitry Andric if (!this->emitGetLocal(SizeT, ArrayLen, E))
3526*700637cbSDimitry Andric return false;
3527*700637cbSDimitry Andric if (!this->emitCheckNewTypeMismatchArray(SizeT, E, E))
3528*700637cbSDimitry Andric return false;
3529*700637cbSDimitry Andric } else {
3530*700637cbSDimitry Andric if (!this->emitGetLocal(SizeT, ArrayLen, E))
3531*700637cbSDimitry Andric return false;
3532*700637cbSDimitry Andric
3533*700637cbSDimitry Andric if (ElemT) {
3534*700637cbSDimitry Andric // N primitive elements.
3535*700637cbSDimitry Andric if (!this->emitAllocN(SizeT, *ElemT, E, IsNoThrow, E))
3536*700637cbSDimitry Andric return false;
3537*700637cbSDimitry Andric } else {
3538*700637cbSDimitry Andric // N Composite elements.
3539*700637cbSDimitry Andric if (!this->emitAllocCN(SizeT, Desc, IsNoThrow, E))
3540*700637cbSDimitry Andric return false;
3541*700637cbSDimitry Andric }
3542*700637cbSDimitry Andric }
3543*700637cbSDimitry Andric
3544*700637cbSDimitry Andric if (Init) {
3545*700637cbSDimitry Andric QualType InitType = Init->getType();
3546*700637cbSDimitry Andric size_t StaticInitElems = 0;
3547*700637cbSDimitry Andric const Expr *DynamicInit = nullptr;
3548*700637cbSDimitry Andric if (const ConstantArrayType *CAT =
3549*700637cbSDimitry Andric Ctx.getASTContext().getAsConstantArrayType(InitType)) {
3550*700637cbSDimitry Andric StaticInitElems = CAT->getZExtSize();
3551*700637cbSDimitry Andric if (!this->visitInitializer(Init))
3552*700637cbSDimitry Andric return false;
3553*700637cbSDimitry Andric
3554*700637cbSDimitry Andric if (const auto *ILE = dyn_cast<InitListExpr>(Init);
3555*700637cbSDimitry Andric ILE && ILE->hasArrayFiller())
3556*700637cbSDimitry Andric DynamicInit = ILE->getArrayFiller();
3557*700637cbSDimitry Andric }
3558*700637cbSDimitry Andric
3559*700637cbSDimitry Andric // The initializer initializes a certain number of elements, S.
3560*700637cbSDimitry Andric // However, the complete number of elements, N, might be larger than that.
3561*700637cbSDimitry Andric // In this case, we need to get an initializer for the remaining elements.
3562*700637cbSDimitry Andric // There are to cases:
3563*700637cbSDimitry Andric // 1) For the form 'new Struct[n];', the initializer is a
3564*700637cbSDimitry Andric // CXXConstructExpr and its type is an IncompleteArrayType.
3565*700637cbSDimitry Andric // 2) For the form 'new Struct[n]{1,2,3}', the initializer is an
3566*700637cbSDimitry Andric // InitListExpr and the initializer for the remaining elements
3567*700637cbSDimitry Andric // is the array filler.
3568*700637cbSDimitry Andric
3569*700637cbSDimitry Andric if (DynamicInit || InitType->isIncompleteArrayType()) {
3570*700637cbSDimitry Andric const Function *CtorFunc = nullptr;
3571*700637cbSDimitry Andric if (const auto *CE = dyn_cast<CXXConstructExpr>(Init)) {
3572*700637cbSDimitry Andric CtorFunc = getFunction(CE->getConstructor());
3573*700637cbSDimitry Andric if (!CtorFunc)
3574*700637cbSDimitry Andric return false;
3575*700637cbSDimitry Andric } else if (!DynamicInit)
3576*700637cbSDimitry Andric DynamicInit = Init;
3577*700637cbSDimitry Andric
3578*700637cbSDimitry Andric LabelTy EndLabel = this->getLabel();
3579*700637cbSDimitry Andric LabelTy StartLabel = this->getLabel();
3580*700637cbSDimitry Andric
3581*700637cbSDimitry Andric // In the nothrow case, the alloc above might have returned nullptr.
3582*700637cbSDimitry Andric // Don't call any constructors that case.
3583*700637cbSDimitry Andric if (IsNoThrow) {
3584*700637cbSDimitry Andric if (!this->emitDupPtr(E))
3585*700637cbSDimitry Andric return false;
3586*700637cbSDimitry Andric if (!this->emitNullPtr(0, nullptr, E))
3587*700637cbSDimitry Andric return false;
3588*700637cbSDimitry Andric if (!this->emitEQPtr(E))
3589*700637cbSDimitry Andric return false;
3590*700637cbSDimitry Andric if (!this->jumpTrue(EndLabel))
3591*700637cbSDimitry Andric return false;
3592*700637cbSDimitry Andric }
3593*700637cbSDimitry Andric
3594*700637cbSDimitry Andric // Create loop variables.
3595*700637cbSDimitry Andric unsigned Iter =
3596*700637cbSDimitry Andric allocateLocalPrimitive(Stripped, SizeT, /*IsConst=*/false);
3597*700637cbSDimitry Andric if (!this->emitConst(StaticInitElems, SizeT, E))
3598*700637cbSDimitry Andric return false;
3599*700637cbSDimitry Andric if (!this->emitSetLocal(SizeT, Iter, E))
3600*700637cbSDimitry Andric return false;
3601*700637cbSDimitry Andric
3602*700637cbSDimitry Andric this->fallthrough(StartLabel);
3603*700637cbSDimitry Andric this->emitLabel(StartLabel);
3604*700637cbSDimitry Andric // Condition. Iter < ArrayLen?
3605*700637cbSDimitry Andric if (!this->emitGetLocal(SizeT, Iter, E))
3606*700637cbSDimitry Andric return false;
3607*700637cbSDimitry Andric if (!this->emitGetLocal(SizeT, ArrayLen, E))
3608*700637cbSDimitry Andric return false;
3609*700637cbSDimitry Andric if (!this->emitLT(SizeT, E))
3610*700637cbSDimitry Andric return false;
3611*700637cbSDimitry Andric if (!this->jumpFalse(EndLabel))
3612*700637cbSDimitry Andric return false;
3613*700637cbSDimitry Andric
3614*700637cbSDimitry Andric // Pointer to the allocated array is already on the stack.
3615*700637cbSDimitry Andric if (!this->emitGetLocal(SizeT, Iter, E))
3616*700637cbSDimitry Andric return false;
3617*700637cbSDimitry Andric if (!this->emitArrayElemPtr(SizeT, E))
3618*700637cbSDimitry Andric return false;
3619*700637cbSDimitry Andric
3620*700637cbSDimitry Andric if (isa_and_nonnull<ImplicitValueInitExpr>(DynamicInit) &&
3621*700637cbSDimitry Andric DynamicInit->getType()->isArrayType()) {
3622*700637cbSDimitry Andric QualType ElemType =
3623*700637cbSDimitry Andric DynamicInit->getType()->getAsArrayTypeUnsafe()->getElementType();
3624*700637cbSDimitry Andric PrimType InitT = classifyPrim(ElemType);
3625*700637cbSDimitry Andric if (!this->visitZeroInitializer(InitT, ElemType, E))
3626*700637cbSDimitry Andric return false;
3627*700637cbSDimitry Andric if (!this->emitStorePop(InitT, E))
3628*700637cbSDimitry Andric return false;
3629*700637cbSDimitry Andric } else if (DynamicInit) {
3630*700637cbSDimitry Andric if (std::optional<PrimType> InitT = classify(DynamicInit)) {
3631*700637cbSDimitry Andric if (!this->visit(DynamicInit))
3632*700637cbSDimitry Andric return false;
3633*700637cbSDimitry Andric if (!this->emitStorePop(*InitT, E))
3634*700637cbSDimitry Andric return false;
3635*700637cbSDimitry Andric } else {
3636*700637cbSDimitry Andric if (!this->visitInitializer(DynamicInit))
3637*700637cbSDimitry Andric return false;
3638*700637cbSDimitry Andric if (!this->emitPopPtr(E))
3639*700637cbSDimitry Andric return false;
3640*700637cbSDimitry Andric }
3641*700637cbSDimitry Andric } else {
3642*700637cbSDimitry Andric assert(CtorFunc);
3643*700637cbSDimitry Andric if (!this->emitCall(CtorFunc, 0, E))
3644*700637cbSDimitry Andric return false;
3645*700637cbSDimitry Andric }
3646*700637cbSDimitry Andric
3647*700637cbSDimitry Andric // ++Iter;
3648*700637cbSDimitry Andric if (!this->emitGetPtrLocal(Iter, E))
3649*700637cbSDimitry Andric return false;
3650*700637cbSDimitry Andric if (!this->emitIncPop(SizeT, false, E))
3651*700637cbSDimitry Andric return false;
3652*700637cbSDimitry Andric
3653*700637cbSDimitry Andric if (!this->jump(StartLabel))
3654*700637cbSDimitry Andric return false;
3655*700637cbSDimitry Andric
3656*700637cbSDimitry Andric this->fallthrough(EndLabel);
3657*700637cbSDimitry Andric this->emitLabel(EndLabel);
3658*700637cbSDimitry Andric }
3659*700637cbSDimitry Andric }
3660*700637cbSDimitry Andric } else { // Non-array.
3661*700637cbSDimitry Andric if (PlacementDest) {
3662*700637cbSDimitry Andric if (!this->visit(PlacementDest))
3663*700637cbSDimitry Andric return false;
3664*700637cbSDimitry Andric if (!this->emitStartLifetime(E))
3665*700637cbSDimitry Andric return false;
3666*700637cbSDimitry Andric if (!this->emitCheckNewTypeMismatch(E, E))
3667*700637cbSDimitry Andric return false;
3668*700637cbSDimitry Andric } else {
3669*700637cbSDimitry Andric // Allocate just one element.
3670*700637cbSDimitry Andric if (!this->emitAlloc(Desc, E))
3671*700637cbSDimitry Andric return false;
3672*700637cbSDimitry Andric }
3673*700637cbSDimitry Andric
3674*700637cbSDimitry Andric if (Init) {
3675*700637cbSDimitry Andric if (ElemT) {
3676*700637cbSDimitry Andric if (!this->visit(Init))
3677*700637cbSDimitry Andric return false;
3678*700637cbSDimitry Andric
3679*700637cbSDimitry Andric if (!this->emitInit(*ElemT, E))
3680*700637cbSDimitry Andric return false;
3681*700637cbSDimitry Andric } else {
3682*700637cbSDimitry Andric // Composite.
3683*700637cbSDimitry Andric if (!this->visitInitializer(Init))
3684*700637cbSDimitry Andric return false;
3685*700637cbSDimitry Andric }
3686*700637cbSDimitry Andric }
3687*700637cbSDimitry Andric }
3688*700637cbSDimitry Andric
3689*700637cbSDimitry Andric if (DiscardResult)
3690*700637cbSDimitry Andric return this->emitPopPtr(E);
3691*700637cbSDimitry Andric
3692*700637cbSDimitry Andric return true;
3693*700637cbSDimitry Andric }
3694*700637cbSDimitry Andric
3695*700637cbSDimitry Andric template <class Emitter>
VisitCXXDeleteExpr(const CXXDeleteExpr * E)3696*700637cbSDimitry Andric bool Compiler<Emitter>::VisitCXXDeleteExpr(const CXXDeleteExpr *E) {
3697*700637cbSDimitry Andric const Expr *Arg = E->getArgument();
3698*700637cbSDimitry Andric
3699*700637cbSDimitry Andric const FunctionDecl *OperatorDelete = E->getOperatorDelete();
3700*700637cbSDimitry Andric
3701*700637cbSDimitry Andric if (!OperatorDelete->isUsableAsGlobalAllocationFunctionInConstantEvaluation())
3702*700637cbSDimitry Andric return this->emitInvalidNewDeleteExpr(E, E);
3703*700637cbSDimitry Andric
3704*700637cbSDimitry Andric // Arg must be an lvalue.
3705*700637cbSDimitry Andric if (!this->visit(Arg))
3706*700637cbSDimitry Andric return false;
3707*700637cbSDimitry Andric
3708*700637cbSDimitry Andric return this->emitFree(E->isArrayForm(), E->isGlobalDelete(), E);
3709*700637cbSDimitry Andric }
3710*700637cbSDimitry Andric
3711*700637cbSDimitry Andric template <class Emitter>
VisitBlockExpr(const BlockExpr * E)3712*700637cbSDimitry Andric bool Compiler<Emitter>::VisitBlockExpr(const BlockExpr *E) {
3713*700637cbSDimitry Andric if (DiscardResult)
3714*700637cbSDimitry Andric return true;
3715*700637cbSDimitry Andric
3716*700637cbSDimitry Andric const Function *Func = nullptr;
3717*700637cbSDimitry Andric if (auto F = Ctx.getOrCreateObjCBlock(E))
3718*700637cbSDimitry Andric Func = F;
3719*700637cbSDimitry Andric
3720*700637cbSDimitry Andric if (!Func)
3721*700637cbSDimitry Andric return false;
3722*700637cbSDimitry Andric return this->emitGetFnPtr(Func, E);
3723*700637cbSDimitry Andric }
3724*700637cbSDimitry Andric
3725*700637cbSDimitry Andric template <class Emitter>
VisitCXXTypeidExpr(const CXXTypeidExpr * E)3726*700637cbSDimitry Andric bool Compiler<Emitter>::VisitCXXTypeidExpr(const CXXTypeidExpr *E) {
3727*700637cbSDimitry Andric const Type *TypeInfoType = E->getType().getTypePtr();
3728*700637cbSDimitry Andric
3729*700637cbSDimitry Andric auto canonType = [](const Type *T) {
3730*700637cbSDimitry Andric return T->getCanonicalTypeUnqualified().getTypePtr();
3731*700637cbSDimitry Andric };
3732*700637cbSDimitry Andric
3733*700637cbSDimitry Andric if (!E->isPotentiallyEvaluated()) {
3734*700637cbSDimitry Andric if (DiscardResult)
3735*700637cbSDimitry Andric return true;
3736*700637cbSDimitry Andric
3737*700637cbSDimitry Andric if (E->isTypeOperand())
3738*700637cbSDimitry Andric return this->emitGetTypeid(
3739*700637cbSDimitry Andric canonType(E->getTypeOperand(Ctx.getASTContext()).getTypePtr()),
3740*700637cbSDimitry Andric TypeInfoType, E);
3741*700637cbSDimitry Andric
3742*700637cbSDimitry Andric return this->emitGetTypeid(
3743*700637cbSDimitry Andric canonType(E->getExprOperand()->getType().getTypePtr()), TypeInfoType,
3744*700637cbSDimitry Andric E);
3745*700637cbSDimitry Andric }
3746*700637cbSDimitry Andric
3747*700637cbSDimitry Andric // Otherwise, we need to evaluate the expression operand.
3748*700637cbSDimitry Andric assert(E->getExprOperand());
3749*700637cbSDimitry Andric assert(E->getExprOperand()->isLValue());
3750*700637cbSDimitry Andric
3751*700637cbSDimitry Andric if (!Ctx.getLangOpts().CPlusPlus20 && !this->emitDiagTypeid(E))
3752*700637cbSDimitry Andric return false;
3753*700637cbSDimitry Andric
3754*700637cbSDimitry Andric if (!this->visit(E->getExprOperand()))
3755*700637cbSDimitry Andric return false;
3756*700637cbSDimitry Andric
3757*700637cbSDimitry Andric if (!this->emitGetTypeidPtr(TypeInfoType, E))
3758*700637cbSDimitry Andric return false;
3759*700637cbSDimitry Andric if (DiscardResult)
3760*700637cbSDimitry Andric return this->emitPopPtr(E);
3761*700637cbSDimitry Andric return true;
3762*700637cbSDimitry Andric }
3763*700637cbSDimitry Andric
3764*700637cbSDimitry Andric template <class Emitter>
VisitExpressionTraitExpr(const ExpressionTraitExpr * E)3765*700637cbSDimitry Andric bool Compiler<Emitter>::VisitExpressionTraitExpr(const ExpressionTraitExpr *E) {
3766*700637cbSDimitry Andric assert(Ctx.getLangOpts().CPlusPlus);
3767*700637cbSDimitry Andric return this->emitConstBool(E->getValue(), E);
3768*700637cbSDimitry Andric }
3769*700637cbSDimitry Andric
3770*700637cbSDimitry Andric template <class Emitter>
VisitCXXUuidofExpr(const CXXUuidofExpr * E)3771*700637cbSDimitry Andric bool Compiler<Emitter>::VisitCXXUuidofExpr(const CXXUuidofExpr *E) {
3772*700637cbSDimitry Andric if (DiscardResult)
3773*700637cbSDimitry Andric return true;
3774*700637cbSDimitry Andric assert(!Initializing);
3775*700637cbSDimitry Andric
3776*700637cbSDimitry Andric const MSGuidDecl *GuidDecl = E->getGuidDecl();
3777*700637cbSDimitry Andric const RecordDecl *RD = GuidDecl->getType()->getAsRecordDecl();
3778*700637cbSDimitry Andric assert(RD);
3779*700637cbSDimitry Andric // If the definiton of the result type is incomplete, just return a dummy.
3780*700637cbSDimitry Andric // If (and when) that is read from, we will fail, but not now.
3781*700637cbSDimitry Andric if (!RD->isCompleteDefinition())
3782*700637cbSDimitry Andric return this->emitDummyPtr(GuidDecl, E);
3783*700637cbSDimitry Andric
3784*700637cbSDimitry Andric std::optional<unsigned> GlobalIndex = P.getOrCreateGlobal(GuidDecl);
3785*700637cbSDimitry Andric if (!GlobalIndex)
3786*700637cbSDimitry Andric return false;
3787*700637cbSDimitry Andric if (!this->emitGetPtrGlobal(*GlobalIndex, E))
3788*700637cbSDimitry Andric return false;
3789*700637cbSDimitry Andric
3790*700637cbSDimitry Andric assert(this->getRecord(E->getType()));
3791*700637cbSDimitry Andric
3792*700637cbSDimitry Andric const APValue &V = GuidDecl->getAsAPValue();
3793*700637cbSDimitry Andric if (V.getKind() == APValue::None)
3794*700637cbSDimitry Andric return true;
3795*700637cbSDimitry Andric
3796*700637cbSDimitry Andric assert(V.isStruct());
3797*700637cbSDimitry Andric assert(V.getStructNumBases() == 0);
3798*700637cbSDimitry Andric if (!this->visitAPValueInitializer(V, E, E->getType()))
3799*700637cbSDimitry Andric return false;
3800*700637cbSDimitry Andric
3801*700637cbSDimitry Andric return this->emitFinishInit(E);
3802*700637cbSDimitry Andric }
3803*700637cbSDimitry Andric
3804*700637cbSDimitry Andric template <class Emitter>
VisitRequiresExpr(const RequiresExpr * E)3805*700637cbSDimitry Andric bool Compiler<Emitter>::VisitRequiresExpr(const RequiresExpr *E) {
3806*700637cbSDimitry Andric assert(classifyPrim(E->getType()) == PT_Bool);
3807*700637cbSDimitry Andric if (DiscardResult)
3808*700637cbSDimitry Andric return true;
3809*700637cbSDimitry Andric return this->emitConstBool(E->isSatisfied(), E);
3810*700637cbSDimitry Andric }
3811*700637cbSDimitry Andric
3812*700637cbSDimitry Andric template <class Emitter>
VisitConceptSpecializationExpr(const ConceptSpecializationExpr * E)3813*700637cbSDimitry Andric bool Compiler<Emitter>::VisitConceptSpecializationExpr(
3814*700637cbSDimitry Andric const ConceptSpecializationExpr *E) {
3815*700637cbSDimitry Andric assert(classifyPrim(E->getType()) == PT_Bool);
3816*700637cbSDimitry Andric if (DiscardResult)
3817*700637cbSDimitry Andric return true;
3818*700637cbSDimitry Andric return this->emitConstBool(E->isSatisfied(), E);
3819*700637cbSDimitry Andric }
3820*700637cbSDimitry Andric
3821*700637cbSDimitry Andric template <class Emitter>
VisitCXXRewrittenBinaryOperator(const CXXRewrittenBinaryOperator * E)3822*700637cbSDimitry Andric bool Compiler<Emitter>::VisitCXXRewrittenBinaryOperator(
3823*700637cbSDimitry Andric const CXXRewrittenBinaryOperator *E) {
3824*700637cbSDimitry Andric return this->delegate(E->getSemanticForm());
3825*700637cbSDimitry Andric }
3826*700637cbSDimitry Andric
3827*700637cbSDimitry Andric template <class Emitter>
VisitPseudoObjectExpr(const PseudoObjectExpr * E)3828*700637cbSDimitry Andric bool Compiler<Emitter>::VisitPseudoObjectExpr(const PseudoObjectExpr *E) {
3829*700637cbSDimitry Andric
3830*700637cbSDimitry Andric for (const Expr *SemE : E->semantics()) {
3831*700637cbSDimitry Andric if (auto *OVE = dyn_cast<OpaqueValueExpr>(SemE)) {
3832*700637cbSDimitry Andric if (SemE == E->getResultExpr())
3833*700637cbSDimitry Andric return false;
3834*700637cbSDimitry Andric
3835*700637cbSDimitry Andric if (OVE->isUnique())
3836*700637cbSDimitry Andric continue;
3837*700637cbSDimitry Andric
3838*700637cbSDimitry Andric if (!this->discard(OVE))
3839*700637cbSDimitry Andric return false;
3840*700637cbSDimitry Andric } else if (SemE == E->getResultExpr()) {
3841*700637cbSDimitry Andric if (!this->delegate(SemE))
3842*700637cbSDimitry Andric return false;
3843*700637cbSDimitry Andric } else {
3844*700637cbSDimitry Andric if (!this->discard(SemE))
3845*700637cbSDimitry Andric return false;
3846*700637cbSDimitry Andric }
3847*700637cbSDimitry Andric }
3848*700637cbSDimitry Andric return true;
3849*700637cbSDimitry Andric }
3850*700637cbSDimitry Andric
3851*700637cbSDimitry Andric template <class Emitter>
VisitPackIndexingExpr(const PackIndexingExpr * E)3852*700637cbSDimitry Andric bool Compiler<Emitter>::VisitPackIndexingExpr(const PackIndexingExpr *E) {
3853*700637cbSDimitry Andric return this->delegate(E->getSelectedExpr());
3854*700637cbSDimitry Andric }
3855*700637cbSDimitry Andric
3856*700637cbSDimitry Andric template <class Emitter>
VisitRecoveryExpr(const RecoveryExpr * E)3857*700637cbSDimitry Andric bool Compiler<Emitter>::VisitRecoveryExpr(const RecoveryExpr *E) {
3858*700637cbSDimitry Andric return this->emitError(E);
3859*700637cbSDimitry Andric }
3860*700637cbSDimitry Andric
3861*700637cbSDimitry Andric template <class Emitter>
VisitAddrLabelExpr(const AddrLabelExpr * E)3862*700637cbSDimitry Andric bool Compiler<Emitter>::VisitAddrLabelExpr(const AddrLabelExpr *E) {
3863*700637cbSDimitry Andric assert(E->getType()->isVoidPointerType());
3864*700637cbSDimitry Andric
3865*700637cbSDimitry Andric unsigned Offset =
3866*700637cbSDimitry Andric allocateLocalPrimitive(E->getLabel(), PT_Ptr, /*IsConst=*/true);
3867*700637cbSDimitry Andric
3868*700637cbSDimitry Andric return this->emitGetLocal(PT_Ptr, Offset, E);
3869*700637cbSDimitry Andric }
3870*700637cbSDimitry Andric
3871*700637cbSDimitry Andric template <class Emitter>
VisitConvertVectorExpr(const ConvertVectorExpr * E)3872*700637cbSDimitry Andric bool Compiler<Emitter>::VisitConvertVectorExpr(const ConvertVectorExpr *E) {
3873*700637cbSDimitry Andric assert(Initializing);
3874*700637cbSDimitry Andric const auto *VT = E->getType()->castAs<VectorType>();
3875*700637cbSDimitry Andric QualType ElemType = VT->getElementType();
3876*700637cbSDimitry Andric PrimType ElemT = classifyPrim(ElemType);
3877*700637cbSDimitry Andric const Expr *Src = E->getSrcExpr();
3878*700637cbSDimitry Andric QualType SrcType = Src->getType();
3879*700637cbSDimitry Andric PrimType SrcElemT = classifyVectorElementType(SrcType);
3880*700637cbSDimitry Andric
3881*700637cbSDimitry Andric unsigned SrcOffset =
3882*700637cbSDimitry Andric this->allocateLocalPrimitive(Src, PT_Ptr, /*IsConst=*/true);
3883*700637cbSDimitry Andric if (!this->visit(Src))
3884*700637cbSDimitry Andric return false;
3885*700637cbSDimitry Andric if (!this->emitSetLocal(PT_Ptr, SrcOffset, E))
3886*700637cbSDimitry Andric return false;
3887*700637cbSDimitry Andric
3888*700637cbSDimitry Andric for (unsigned I = 0; I != VT->getNumElements(); ++I) {
3889*700637cbSDimitry Andric if (!this->emitGetLocal(PT_Ptr, SrcOffset, E))
3890*700637cbSDimitry Andric return false;
3891*700637cbSDimitry Andric if (!this->emitArrayElemPop(SrcElemT, I, E))
3892*700637cbSDimitry Andric return false;
3893*700637cbSDimitry Andric
3894*700637cbSDimitry Andric // Cast to the desired result element type.
3895*700637cbSDimitry Andric if (SrcElemT != ElemT) {
3896*700637cbSDimitry Andric if (!this->emitPrimCast(SrcElemT, ElemT, ElemType, E))
3897*700637cbSDimitry Andric return false;
3898*700637cbSDimitry Andric } else if (ElemType->isFloatingType() && SrcType != ElemType) {
3899*700637cbSDimitry Andric const auto *TargetSemantics = &Ctx.getFloatSemantics(ElemType);
3900*700637cbSDimitry Andric if (!this->emitCastFP(TargetSemantics, getRoundingMode(E), E))
3901*700637cbSDimitry Andric return false;
3902*700637cbSDimitry Andric }
3903*700637cbSDimitry Andric if (!this->emitInitElem(ElemT, I, E))
3904*700637cbSDimitry Andric return false;
3905*700637cbSDimitry Andric }
3906*700637cbSDimitry Andric
3907*700637cbSDimitry Andric return true;
3908*700637cbSDimitry Andric }
3909*700637cbSDimitry Andric
3910*700637cbSDimitry Andric template <class Emitter>
VisitShuffleVectorExpr(const ShuffleVectorExpr * E)3911*700637cbSDimitry Andric bool Compiler<Emitter>::VisitShuffleVectorExpr(const ShuffleVectorExpr *E) {
3912*700637cbSDimitry Andric assert(Initializing);
3913*700637cbSDimitry Andric assert(E->getNumSubExprs() > 2);
3914*700637cbSDimitry Andric
3915*700637cbSDimitry Andric const Expr *Vecs[] = {E->getExpr(0), E->getExpr(1)};
3916*700637cbSDimitry Andric const VectorType *VT = Vecs[0]->getType()->castAs<VectorType>();
3917*700637cbSDimitry Andric PrimType ElemT = classifyPrim(VT->getElementType());
3918*700637cbSDimitry Andric unsigned NumInputElems = VT->getNumElements();
3919*700637cbSDimitry Andric unsigned NumOutputElems = E->getNumSubExprs() - 2;
3920*700637cbSDimitry Andric assert(NumOutputElems > 0);
3921*700637cbSDimitry Andric
3922*700637cbSDimitry Andric // Save both input vectors to a local variable.
3923*700637cbSDimitry Andric unsigned VectorOffsets[2];
3924*700637cbSDimitry Andric for (unsigned I = 0; I != 2; ++I) {
3925*700637cbSDimitry Andric VectorOffsets[I] =
3926*700637cbSDimitry Andric this->allocateLocalPrimitive(Vecs[I], PT_Ptr, /*IsConst=*/true);
3927*700637cbSDimitry Andric if (!this->visit(Vecs[I]))
3928*700637cbSDimitry Andric return false;
3929*700637cbSDimitry Andric if (!this->emitSetLocal(PT_Ptr, VectorOffsets[I], E))
3930*700637cbSDimitry Andric return false;
3931*700637cbSDimitry Andric }
3932*700637cbSDimitry Andric for (unsigned I = 0; I != NumOutputElems; ++I) {
3933*700637cbSDimitry Andric APSInt ShuffleIndex = E->getShuffleMaskIdx(I);
3934*700637cbSDimitry Andric assert(ShuffleIndex >= -1);
3935*700637cbSDimitry Andric if (ShuffleIndex == -1)
3936*700637cbSDimitry Andric return this->emitInvalidShuffleVectorIndex(I, E);
3937*700637cbSDimitry Andric
3938*700637cbSDimitry Andric assert(ShuffleIndex < (NumInputElems * 2));
3939*700637cbSDimitry Andric if (!this->emitGetLocal(PT_Ptr,
3940*700637cbSDimitry Andric VectorOffsets[ShuffleIndex >= NumInputElems], E))
3941*700637cbSDimitry Andric return false;
3942*700637cbSDimitry Andric unsigned InputVectorIndex = ShuffleIndex.getZExtValue() % NumInputElems;
3943*700637cbSDimitry Andric if (!this->emitArrayElemPop(ElemT, InputVectorIndex, E))
3944*700637cbSDimitry Andric return false;
3945*700637cbSDimitry Andric
3946*700637cbSDimitry Andric if (!this->emitInitElem(ElemT, I, E))
3947*700637cbSDimitry Andric return false;
3948*700637cbSDimitry Andric }
3949*700637cbSDimitry Andric
3950*700637cbSDimitry Andric return true;
3951*700637cbSDimitry Andric }
3952*700637cbSDimitry Andric
3953*700637cbSDimitry Andric template <class Emitter>
VisitExtVectorElementExpr(const ExtVectorElementExpr * E)3954*700637cbSDimitry Andric bool Compiler<Emitter>::VisitExtVectorElementExpr(
3955*700637cbSDimitry Andric const ExtVectorElementExpr *E) {
3956*700637cbSDimitry Andric const Expr *Base = E->getBase();
3957*700637cbSDimitry Andric assert(
3958*700637cbSDimitry Andric Base->getType()->isVectorType() ||
3959*700637cbSDimitry Andric Base->getType()->getAs<PointerType>()->getPointeeType()->isVectorType());
3960*700637cbSDimitry Andric
3961*700637cbSDimitry Andric SmallVector<uint32_t, 4> Indices;
3962*700637cbSDimitry Andric E->getEncodedElementAccess(Indices);
3963*700637cbSDimitry Andric
3964*700637cbSDimitry Andric if (Indices.size() == 1) {
3965*700637cbSDimitry Andric if (!this->visit(Base))
3966*700637cbSDimitry Andric return false;
3967*700637cbSDimitry Andric
3968*700637cbSDimitry Andric if (E->isGLValue()) {
3969*700637cbSDimitry Andric if (!this->emitConstUint32(Indices[0], E))
3970*700637cbSDimitry Andric return false;
3971*700637cbSDimitry Andric return this->emitArrayElemPtrPop(PT_Uint32, E);
3972*700637cbSDimitry Andric }
3973*700637cbSDimitry Andric // Else, also load the value.
3974*700637cbSDimitry Andric return this->emitArrayElemPop(classifyPrim(E->getType()), Indices[0], E);
3975*700637cbSDimitry Andric }
3976*700637cbSDimitry Andric
3977*700637cbSDimitry Andric // Create a local variable for the base.
3978*700637cbSDimitry Andric unsigned BaseOffset = allocateLocalPrimitive(Base, PT_Ptr, /*IsConst=*/true);
3979*700637cbSDimitry Andric if (!this->visit(Base))
3980*700637cbSDimitry Andric return false;
3981*700637cbSDimitry Andric if (!this->emitSetLocal(PT_Ptr, BaseOffset, E))
3982*700637cbSDimitry Andric return false;
3983*700637cbSDimitry Andric
3984*700637cbSDimitry Andric // Now the vector variable for the return value.
3985*700637cbSDimitry Andric if (!Initializing) {
3986*700637cbSDimitry Andric std::optional<unsigned> ResultIndex;
3987*700637cbSDimitry Andric ResultIndex = allocateLocal(E);
3988*700637cbSDimitry Andric if (!ResultIndex)
3989*700637cbSDimitry Andric return false;
3990*700637cbSDimitry Andric if (!this->emitGetPtrLocal(*ResultIndex, E))
3991*700637cbSDimitry Andric return false;
3992*700637cbSDimitry Andric }
3993*700637cbSDimitry Andric
3994*700637cbSDimitry Andric assert(Indices.size() == E->getType()->getAs<VectorType>()->getNumElements());
3995*700637cbSDimitry Andric
3996*700637cbSDimitry Andric PrimType ElemT =
3997*700637cbSDimitry Andric classifyPrim(E->getType()->getAs<VectorType>()->getElementType());
3998*700637cbSDimitry Andric uint32_t DstIndex = 0;
3999*700637cbSDimitry Andric for (uint32_t I : Indices) {
4000*700637cbSDimitry Andric if (!this->emitGetLocal(PT_Ptr, BaseOffset, E))
4001*700637cbSDimitry Andric return false;
4002*700637cbSDimitry Andric if (!this->emitArrayElemPop(ElemT, I, E))
4003*700637cbSDimitry Andric return false;
4004*700637cbSDimitry Andric if (!this->emitInitElem(ElemT, DstIndex, E))
4005*700637cbSDimitry Andric return false;
4006*700637cbSDimitry Andric ++DstIndex;
4007*700637cbSDimitry Andric }
4008*700637cbSDimitry Andric
4009*700637cbSDimitry Andric // Leave the result pointer on the stack.
4010*700637cbSDimitry Andric assert(!DiscardResult);
4011*700637cbSDimitry Andric return true;
4012*700637cbSDimitry Andric }
4013*700637cbSDimitry Andric
4014*700637cbSDimitry Andric template <class Emitter>
VisitObjCBoxedExpr(const ObjCBoxedExpr * E)4015*700637cbSDimitry Andric bool Compiler<Emitter>::VisitObjCBoxedExpr(const ObjCBoxedExpr *E) {
4016*700637cbSDimitry Andric const Expr *SubExpr = E->getSubExpr();
4017*700637cbSDimitry Andric if (!E->isExpressibleAsConstantInitializer())
4018*700637cbSDimitry Andric return this->discard(SubExpr) && this->emitInvalid(E);
4019*700637cbSDimitry Andric
4020*700637cbSDimitry Andric if (DiscardResult)
4021*700637cbSDimitry Andric return true;
4022*700637cbSDimitry Andric
4023*700637cbSDimitry Andric assert(classifyPrim(E) == PT_Ptr);
4024*700637cbSDimitry Andric return this->emitDummyPtr(E, E);
4025*700637cbSDimitry Andric }
4026*700637cbSDimitry Andric
4027*700637cbSDimitry Andric template <class Emitter>
VisitCXXStdInitializerListExpr(const CXXStdInitializerListExpr * E)4028*700637cbSDimitry Andric bool Compiler<Emitter>::VisitCXXStdInitializerListExpr(
4029*700637cbSDimitry Andric const CXXStdInitializerListExpr *E) {
4030*700637cbSDimitry Andric const Expr *SubExpr = E->getSubExpr();
4031*700637cbSDimitry Andric const ConstantArrayType *ArrayType =
4032*700637cbSDimitry Andric Ctx.getASTContext().getAsConstantArrayType(SubExpr->getType());
4033*700637cbSDimitry Andric const Record *R = getRecord(E->getType());
4034*700637cbSDimitry Andric assert(Initializing);
4035*700637cbSDimitry Andric assert(SubExpr->isGLValue());
4036*700637cbSDimitry Andric
4037*700637cbSDimitry Andric if (!this->visit(SubExpr))
4038*700637cbSDimitry Andric return false;
4039*700637cbSDimitry Andric if (!this->emitConstUint8(0, E))
4040*700637cbSDimitry Andric return false;
4041*700637cbSDimitry Andric if (!this->emitArrayElemPtrPopUint8(E))
4042*700637cbSDimitry Andric return false;
4043*700637cbSDimitry Andric if (!this->emitInitFieldPtr(R->getField(0u)->Offset, E))
4044*700637cbSDimitry Andric return false;
4045*700637cbSDimitry Andric
4046*700637cbSDimitry Andric PrimType SecondFieldT = classifyPrim(R->getField(1u)->Decl->getType());
4047*700637cbSDimitry Andric if (isIntegralType(SecondFieldT)) {
4048*700637cbSDimitry Andric if (!this->emitConst(static_cast<APSInt>(ArrayType->getSize()),
4049*700637cbSDimitry Andric SecondFieldT, E))
4050*700637cbSDimitry Andric return false;
4051*700637cbSDimitry Andric return this->emitInitField(SecondFieldT, R->getField(1u)->Offset, E);
4052*700637cbSDimitry Andric }
4053*700637cbSDimitry Andric assert(SecondFieldT == PT_Ptr);
4054*700637cbSDimitry Andric
4055*700637cbSDimitry Andric if (!this->emitGetFieldPtr(R->getField(0u)->Offset, E))
4056*700637cbSDimitry Andric return false;
4057*700637cbSDimitry Andric if (!this->emitExpandPtr(E))
4058*700637cbSDimitry Andric return false;
4059*700637cbSDimitry Andric if (!this->emitConst(static_cast<APSInt>(ArrayType->getSize()), PT_Uint64, E))
4060*700637cbSDimitry Andric return false;
4061*700637cbSDimitry Andric if (!this->emitArrayElemPtrPop(PT_Uint64, E))
4062*700637cbSDimitry Andric return false;
4063*700637cbSDimitry Andric return this->emitInitFieldPtr(R->getField(1u)->Offset, E);
4064*700637cbSDimitry Andric }
4065*700637cbSDimitry Andric
4066*700637cbSDimitry Andric template <class Emitter>
VisitStmtExpr(const StmtExpr * E)4067*700637cbSDimitry Andric bool Compiler<Emitter>::VisitStmtExpr(const StmtExpr *E) {
4068*700637cbSDimitry Andric BlockScope<Emitter> BS(this);
4069*700637cbSDimitry Andric StmtExprScope<Emitter> SS(this);
4070*700637cbSDimitry Andric
4071*700637cbSDimitry Andric const CompoundStmt *CS = E->getSubStmt();
4072*700637cbSDimitry Andric const Stmt *Result = CS->getStmtExprResult();
4073*700637cbSDimitry Andric for (const Stmt *S : CS->body()) {
4074*700637cbSDimitry Andric if (S != Result) {
4075*700637cbSDimitry Andric if (!this->visitStmt(S))
4076*700637cbSDimitry Andric return false;
4077*700637cbSDimitry Andric continue;
4078*700637cbSDimitry Andric }
4079*700637cbSDimitry Andric
4080*700637cbSDimitry Andric assert(S == Result);
4081*700637cbSDimitry Andric if (const Expr *ResultExpr = dyn_cast<Expr>(S))
4082*700637cbSDimitry Andric return this->delegate(ResultExpr);
4083*700637cbSDimitry Andric return this->emitUnsupported(E);
4084*700637cbSDimitry Andric }
4085*700637cbSDimitry Andric
4086*700637cbSDimitry Andric return BS.destroyLocals();
4087*700637cbSDimitry Andric }
4088*700637cbSDimitry Andric
discard(const Expr * E)4089*700637cbSDimitry Andric template <class Emitter> bool Compiler<Emitter>::discard(const Expr *E) {
4090*700637cbSDimitry Andric OptionScope<Emitter> Scope(this, /*NewDiscardResult=*/true,
4091*700637cbSDimitry Andric /*NewInitializing=*/false);
4092*700637cbSDimitry Andric return this->Visit(E);
4093*700637cbSDimitry Andric }
4094*700637cbSDimitry Andric
delegate(const Expr * E)4095*700637cbSDimitry Andric template <class Emitter> bool Compiler<Emitter>::delegate(const Expr *E) {
4096*700637cbSDimitry Andric // We're basically doing:
4097*700637cbSDimitry Andric // OptionScope<Emitter> Scope(this, DicardResult, Initializing);
4098*700637cbSDimitry Andric // but that's unnecessary of course.
4099*700637cbSDimitry Andric return this->Visit(E);
4100*700637cbSDimitry Andric }
4101*700637cbSDimitry Andric
visit(const Expr * E)4102*700637cbSDimitry Andric template <class Emitter> bool Compiler<Emitter>::visit(const Expr *E) {
4103*700637cbSDimitry Andric if (E->getType().isNull())
4104*700637cbSDimitry Andric return false;
4105*700637cbSDimitry Andric
4106*700637cbSDimitry Andric if (E->getType()->isVoidType())
4107*700637cbSDimitry Andric return this->discard(E);
4108*700637cbSDimitry Andric
4109*700637cbSDimitry Andric // Create local variable to hold the return value.
4110*700637cbSDimitry Andric if (!E->isGLValue() && !E->getType()->isAnyComplexType() &&
4111*700637cbSDimitry Andric !classify(E->getType())) {
4112*700637cbSDimitry Andric std::optional<unsigned> LocalIndex = allocateLocal(E);
4113*700637cbSDimitry Andric if (!LocalIndex)
4114*700637cbSDimitry Andric return false;
4115*700637cbSDimitry Andric
4116*700637cbSDimitry Andric if (!this->emitGetPtrLocal(*LocalIndex, E))
4117*700637cbSDimitry Andric return false;
4118*700637cbSDimitry Andric InitLinkScope<Emitter> ILS(this, InitLink::Temp(*LocalIndex));
4119*700637cbSDimitry Andric return this->visitInitializer(E);
4120*700637cbSDimitry Andric }
4121*700637cbSDimitry Andric
4122*700637cbSDimitry Andric // Otherwise,we have a primitive return value, produce the value directly
4123*700637cbSDimitry Andric // and push it on the stack.
4124*700637cbSDimitry Andric OptionScope<Emitter> Scope(this, /*NewDiscardResult=*/false,
4125*700637cbSDimitry Andric /*NewInitializing=*/false);
4126*700637cbSDimitry Andric return this->Visit(E);
4127*700637cbSDimitry Andric }
4128*700637cbSDimitry Andric
4129*700637cbSDimitry Andric template <class Emitter>
visitInitializer(const Expr * E)4130*700637cbSDimitry Andric bool Compiler<Emitter>::visitInitializer(const Expr *E) {
4131*700637cbSDimitry Andric assert(!classify(E->getType()));
4132*700637cbSDimitry Andric
4133*700637cbSDimitry Andric OptionScope<Emitter> Scope(this, /*NewDiscardResult=*/false,
4134*700637cbSDimitry Andric /*NewInitializing=*/true);
4135*700637cbSDimitry Andric return this->Visit(E);
4136*700637cbSDimitry Andric }
4137*700637cbSDimitry Andric
visitBool(const Expr * E)4138*700637cbSDimitry Andric template <class Emitter> bool Compiler<Emitter>::visitBool(const Expr *E) {
4139*700637cbSDimitry Andric std::optional<PrimType> T = classify(E->getType());
4140*700637cbSDimitry Andric if (!T) {
4141*700637cbSDimitry Andric // Convert complex values to bool.
4142*700637cbSDimitry Andric if (E->getType()->isAnyComplexType()) {
4143*700637cbSDimitry Andric if (!this->visit(E))
4144*700637cbSDimitry Andric return false;
4145*700637cbSDimitry Andric return this->emitComplexBoolCast(E);
4146*700637cbSDimitry Andric }
4147*700637cbSDimitry Andric return false;
4148*700637cbSDimitry Andric }
4149*700637cbSDimitry Andric
4150*700637cbSDimitry Andric if (!this->visit(E))
4151*700637cbSDimitry Andric return false;
4152*700637cbSDimitry Andric
4153*700637cbSDimitry Andric if (T == PT_Bool)
4154*700637cbSDimitry Andric return true;
4155*700637cbSDimitry Andric
4156*700637cbSDimitry Andric // Convert pointers to bool.
4157*700637cbSDimitry Andric if (T == PT_Ptr)
4158*700637cbSDimitry Andric return this->emitIsNonNullPtr(E);
4159*700637cbSDimitry Andric
4160*700637cbSDimitry Andric // Or Floats.
4161*700637cbSDimitry Andric if (T == PT_Float)
4162*700637cbSDimitry Andric return this->emitCastFloatingIntegralBool(getFPOptions(E), E);
4163*700637cbSDimitry Andric
4164*700637cbSDimitry Andric // Or anything else we can.
4165*700637cbSDimitry Andric return this->emitCast(*T, PT_Bool, E);
4166*700637cbSDimitry Andric }
4167*700637cbSDimitry Andric
4168*700637cbSDimitry Andric template <class Emitter>
visitZeroInitializer(PrimType T,QualType QT,const Expr * E)4169*700637cbSDimitry Andric bool Compiler<Emitter>::visitZeroInitializer(PrimType T, QualType QT,
4170*700637cbSDimitry Andric const Expr *E) {
4171*700637cbSDimitry Andric if (const auto *AT = QT->getAs<AtomicType>())
4172*700637cbSDimitry Andric QT = AT->getValueType();
4173*700637cbSDimitry Andric
4174*700637cbSDimitry Andric switch (T) {
4175*700637cbSDimitry Andric case PT_Bool:
4176*700637cbSDimitry Andric return this->emitZeroBool(E);
4177*700637cbSDimitry Andric case PT_Sint8:
4178*700637cbSDimitry Andric return this->emitZeroSint8(E);
4179*700637cbSDimitry Andric case PT_Uint8:
4180*700637cbSDimitry Andric return this->emitZeroUint8(E);
4181*700637cbSDimitry Andric case PT_Sint16:
4182*700637cbSDimitry Andric return this->emitZeroSint16(E);
4183*700637cbSDimitry Andric case PT_Uint16:
4184*700637cbSDimitry Andric return this->emitZeroUint16(E);
4185*700637cbSDimitry Andric case PT_Sint32:
4186*700637cbSDimitry Andric return this->emitZeroSint32(E);
4187*700637cbSDimitry Andric case PT_Uint32:
4188*700637cbSDimitry Andric return this->emitZeroUint32(E);
4189*700637cbSDimitry Andric case PT_Sint64:
4190*700637cbSDimitry Andric return this->emitZeroSint64(E);
4191*700637cbSDimitry Andric case PT_Uint64:
4192*700637cbSDimitry Andric return this->emitZeroUint64(E);
4193*700637cbSDimitry Andric case PT_IntAP:
4194*700637cbSDimitry Andric return this->emitZeroIntAP(Ctx.getBitWidth(QT), E);
4195*700637cbSDimitry Andric case PT_IntAPS:
4196*700637cbSDimitry Andric return this->emitZeroIntAPS(Ctx.getBitWidth(QT), E);
4197*700637cbSDimitry Andric case PT_Ptr:
4198*700637cbSDimitry Andric return this->emitNullPtr(Ctx.getASTContext().getTargetNullPointerValue(QT),
4199*700637cbSDimitry Andric nullptr, E);
4200*700637cbSDimitry Andric case PT_MemberPtr:
4201*700637cbSDimitry Andric return this->emitNullMemberPtr(0, nullptr, E);
4202*700637cbSDimitry Andric case PT_Float: {
4203*700637cbSDimitry Andric APFloat F = APFloat::getZero(Ctx.getFloatSemantics(QT));
4204*700637cbSDimitry Andric return this->emitFloat(F, E);
4205*700637cbSDimitry Andric }
4206*700637cbSDimitry Andric case PT_FixedPoint: {
4207*700637cbSDimitry Andric auto Sem = Ctx.getASTContext().getFixedPointSemantics(E->getType());
4208*700637cbSDimitry Andric return this->emitConstFixedPoint(FixedPoint::zero(Sem), E);
4209*700637cbSDimitry Andric }
4210*700637cbSDimitry Andric }
4211*700637cbSDimitry Andric llvm_unreachable("unknown primitive type");
4212*700637cbSDimitry Andric }
4213*700637cbSDimitry Andric
4214*700637cbSDimitry Andric template <class Emitter>
visitZeroRecordInitializer(const Record * R,const Expr * E)4215*700637cbSDimitry Andric bool Compiler<Emitter>::visitZeroRecordInitializer(const Record *R,
4216*700637cbSDimitry Andric const Expr *E) {
4217*700637cbSDimitry Andric assert(E);
4218*700637cbSDimitry Andric assert(R);
4219*700637cbSDimitry Andric // Fields
4220*700637cbSDimitry Andric for (const Record::Field &Field : R->fields()) {
4221*700637cbSDimitry Andric if (Field.isUnnamedBitField())
4222*700637cbSDimitry Andric continue;
4223*700637cbSDimitry Andric
4224*700637cbSDimitry Andric const Descriptor *D = Field.Desc;
4225*700637cbSDimitry Andric if (D->isPrimitive()) {
4226*700637cbSDimitry Andric QualType QT = D->getType();
4227*700637cbSDimitry Andric PrimType T = classifyPrim(D->getType());
4228*700637cbSDimitry Andric if (!this->visitZeroInitializer(T, QT, E))
4229*700637cbSDimitry Andric return false;
4230*700637cbSDimitry Andric if (!this->emitInitField(T, Field.Offset, E))
4231*700637cbSDimitry Andric return false;
4232*700637cbSDimitry Andric if (R->isUnion())
4233*700637cbSDimitry Andric break;
4234*700637cbSDimitry Andric continue;
4235*700637cbSDimitry Andric }
4236*700637cbSDimitry Andric
4237*700637cbSDimitry Andric if (!this->emitGetPtrField(Field.Offset, E))
4238*700637cbSDimitry Andric return false;
4239*700637cbSDimitry Andric
4240*700637cbSDimitry Andric if (D->isPrimitiveArray()) {
4241*700637cbSDimitry Andric QualType ET = D->getElemQualType();
4242*700637cbSDimitry Andric PrimType T = classifyPrim(ET);
4243*700637cbSDimitry Andric for (uint32_t I = 0, N = D->getNumElems(); I != N; ++I) {
4244*700637cbSDimitry Andric if (!this->visitZeroInitializer(T, ET, E))
4245*700637cbSDimitry Andric return false;
4246*700637cbSDimitry Andric if (!this->emitInitElem(T, I, E))
4247*700637cbSDimitry Andric return false;
4248*700637cbSDimitry Andric }
4249*700637cbSDimitry Andric } else if (D->isCompositeArray()) {
4250*700637cbSDimitry Andric // Can't be a vector or complex field.
4251*700637cbSDimitry Andric if (!this->visitZeroArrayInitializer(D->getType(), E))
4252*700637cbSDimitry Andric return false;
4253*700637cbSDimitry Andric } else if (D->isRecord()) {
4254*700637cbSDimitry Andric if (!this->visitZeroRecordInitializer(D->ElemRecord, E))
4255*700637cbSDimitry Andric return false;
4256*700637cbSDimitry Andric } else
4257*700637cbSDimitry Andric return false;
4258*700637cbSDimitry Andric
4259*700637cbSDimitry Andric if (!this->emitFinishInitPop(E))
4260*700637cbSDimitry Andric return false;
4261*700637cbSDimitry Andric
4262*700637cbSDimitry Andric // C++11 [dcl.init]p5: If T is a (possibly cv-qualified) union type, the
4263*700637cbSDimitry Andric // object's first non-static named data member is zero-initialized
4264*700637cbSDimitry Andric if (R->isUnion())
4265*700637cbSDimitry Andric break;
4266*700637cbSDimitry Andric }
4267*700637cbSDimitry Andric
4268*700637cbSDimitry Andric for (const Record::Base &B : R->bases()) {
4269*700637cbSDimitry Andric if (!this->emitGetPtrBase(B.Offset, E))
4270*700637cbSDimitry Andric return false;
4271*700637cbSDimitry Andric if (!this->visitZeroRecordInitializer(B.R, E))
4272*700637cbSDimitry Andric return false;
4273*700637cbSDimitry Andric if (!this->emitFinishInitPop(E))
4274*700637cbSDimitry Andric return false;
4275*700637cbSDimitry Andric }
4276*700637cbSDimitry Andric
4277*700637cbSDimitry Andric // FIXME: Virtual bases.
4278*700637cbSDimitry Andric
4279*700637cbSDimitry Andric return true;
4280*700637cbSDimitry Andric }
4281*700637cbSDimitry Andric
4282*700637cbSDimitry Andric template <class Emitter>
visitZeroArrayInitializer(QualType T,const Expr * E)4283*700637cbSDimitry Andric bool Compiler<Emitter>::visitZeroArrayInitializer(QualType T, const Expr *E) {
4284*700637cbSDimitry Andric assert(T->isArrayType() || T->isAnyComplexType() || T->isVectorType());
4285*700637cbSDimitry Andric const ArrayType *AT = T->getAsArrayTypeUnsafe();
4286*700637cbSDimitry Andric QualType ElemType = AT->getElementType();
4287*700637cbSDimitry Andric size_t NumElems = cast<ConstantArrayType>(AT)->getZExtSize();
4288*700637cbSDimitry Andric
4289*700637cbSDimitry Andric if (std::optional<PrimType> ElemT = classify(ElemType)) {
4290*700637cbSDimitry Andric for (size_t I = 0; I != NumElems; ++I) {
4291*700637cbSDimitry Andric if (!this->visitZeroInitializer(*ElemT, ElemType, E))
4292*700637cbSDimitry Andric return false;
4293*700637cbSDimitry Andric if (!this->emitInitElem(*ElemT, I, E))
4294*700637cbSDimitry Andric return false;
4295*700637cbSDimitry Andric }
4296*700637cbSDimitry Andric return true;
4297*700637cbSDimitry Andric } else if (ElemType->isRecordType()) {
4298*700637cbSDimitry Andric const Record *R = getRecord(ElemType);
4299*700637cbSDimitry Andric
4300*700637cbSDimitry Andric for (size_t I = 0; I != NumElems; ++I) {
4301*700637cbSDimitry Andric if (!this->emitConstUint32(I, E))
4302*700637cbSDimitry Andric return false;
4303*700637cbSDimitry Andric if (!this->emitArrayElemPtr(PT_Uint32, E))
4304*700637cbSDimitry Andric return false;
4305*700637cbSDimitry Andric if (!this->visitZeroRecordInitializer(R, E))
4306*700637cbSDimitry Andric return false;
4307*700637cbSDimitry Andric if (!this->emitPopPtr(E))
4308*700637cbSDimitry Andric return false;
4309*700637cbSDimitry Andric }
4310*700637cbSDimitry Andric return true;
4311*700637cbSDimitry Andric } else if (ElemType->isArrayType()) {
4312*700637cbSDimitry Andric for (size_t I = 0; I != NumElems; ++I) {
4313*700637cbSDimitry Andric if (!this->emitConstUint32(I, E))
4314*700637cbSDimitry Andric return false;
4315*700637cbSDimitry Andric if (!this->emitArrayElemPtr(PT_Uint32, E))
4316*700637cbSDimitry Andric return false;
4317*700637cbSDimitry Andric if (!this->visitZeroArrayInitializer(ElemType, E))
4318*700637cbSDimitry Andric return false;
4319*700637cbSDimitry Andric if (!this->emitPopPtr(E))
4320*700637cbSDimitry Andric return false;
4321*700637cbSDimitry Andric }
4322*700637cbSDimitry Andric return true;
4323*700637cbSDimitry Andric }
4324*700637cbSDimitry Andric
4325*700637cbSDimitry Andric return false;
4326*700637cbSDimitry Andric }
4327*700637cbSDimitry Andric
4328*700637cbSDimitry Andric template <class Emitter>
4329*700637cbSDimitry Andric template <typename T>
emitConst(T Value,PrimType Ty,const Expr * E)4330*700637cbSDimitry Andric bool Compiler<Emitter>::emitConst(T Value, PrimType Ty, const Expr *E) {
4331*700637cbSDimitry Andric switch (Ty) {
4332*700637cbSDimitry Andric case PT_Sint8:
4333*700637cbSDimitry Andric return this->emitConstSint8(Value, E);
4334*700637cbSDimitry Andric case PT_Uint8:
4335*700637cbSDimitry Andric return this->emitConstUint8(Value, E);
4336*700637cbSDimitry Andric case PT_Sint16:
4337*700637cbSDimitry Andric return this->emitConstSint16(Value, E);
4338*700637cbSDimitry Andric case PT_Uint16:
4339*700637cbSDimitry Andric return this->emitConstUint16(Value, E);
4340*700637cbSDimitry Andric case PT_Sint32:
4341*700637cbSDimitry Andric return this->emitConstSint32(Value, E);
4342*700637cbSDimitry Andric case PT_Uint32:
4343*700637cbSDimitry Andric return this->emitConstUint32(Value, E);
4344*700637cbSDimitry Andric case PT_Sint64:
4345*700637cbSDimitry Andric return this->emitConstSint64(Value, E);
4346*700637cbSDimitry Andric case PT_Uint64:
4347*700637cbSDimitry Andric return this->emitConstUint64(Value, E);
4348*700637cbSDimitry Andric case PT_Bool:
4349*700637cbSDimitry Andric return this->emitConstBool(Value, E);
4350*700637cbSDimitry Andric case PT_Ptr:
4351*700637cbSDimitry Andric case PT_MemberPtr:
4352*700637cbSDimitry Andric case PT_Float:
4353*700637cbSDimitry Andric case PT_IntAP:
4354*700637cbSDimitry Andric case PT_IntAPS:
4355*700637cbSDimitry Andric case PT_FixedPoint:
4356*700637cbSDimitry Andric llvm_unreachable("Invalid integral type");
4357*700637cbSDimitry Andric break;
4358*700637cbSDimitry Andric }
4359*700637cbSDimitry Andric llvm_unreachable("unknown primitive type");
4360*700637cbSDimitry Andric }
4361*700637cbSDimitry Andric
4362*700637cbSDimitry Andric template <class Emitter>
4363*700637cbSDimitry Andric template <typename T>
emitConst(T Value,const Expr * E)4364*700637cbSDimitry Andric bool Compiler<Emitter>::emitConst(T Value, const Expr *E) {
4365*700637cbSDimitry Andric return this->emitConst(Value, classifyPrim(E->getType()), E);
4366*700637cbSDimitry Andric }
4367*700637cbSDimitry Andric
4368*700637cbSDimitry Andric template <class Emitter>
emitConst(const APSInt & Value,PrimType Ty,const Expr * E)4369*700637cbSDimitry Andric bool Compiler<Emitter>::emitConst(const APSInt &Value, PrimType Ty,
4370*700637cbSDimitry Andric const Expr *E) {
4371*700637cbSDimitry Andric if (Ty == PT_IntAPS)
4372*700637cbSDimitry Andric return this->emitConstIntAPS(Value, E);
4373*700637cbSDimitry Andric if (Ty == PT_IntAP)
4374*700637cbSDimitry Andric return this->emitConstIntAP(Value, E);
4375*700637cbSDimitry Andric
4376*700637cbSDimitry Andric if (Value.isSigned())
4377*700637cbSDimitry Andric return this->emitConst(Value.getSExtValue(), Ty, E);
4378*700637cbSDimitry Andric return this->emitConst(Value.getZExtValue(), Ty, E);
4379*700637cbSDimitry Andric }
4380*700637cbSDimitry Andric
4381*700637cbSDimitry Andric template <class Emitter>
emitConst(const APSInt & Value,const Expr * E)4382*700637cbSDimitry Andric bool Compiler<Emitter>::emitConst(const APSInt &Value, const Expr *E) {
4383*700637cbSDimitry Andric return this->emitConst(Value, classifyPrim(E->getType()), E);
4384*700637cbSDimitry Andric }
4385*700637cbSDimitry Andric
4386*700637cbSDimitry Andric template <class Emitter>
allocateLocalPrimitive(DeclTy && Src,PrimType Ty,bool IsConst,const ValueDecl * ExtendingDecl,ScopeKind SC,bool IsConstexprUnknown)4387*700637cbSDimitry Andric unsigned Compiler<Emitter>::allocateLocalPrimitive(
4388*700637cbSDimitry Andric DeclTy &&Src, PrimType Ty, bool IsConst, const ValueDecl *ExtendingDecl,
4389*700637cbSDimitry Andric ScopeKind SC, bool IsConstexprUnknown) {
4390*700637cbSDimitry Andric // Make sure we don't accidentally register the same decl twice.
4391*700637cbSDimitry Andric if (const auto *VD =
4392*700637cbSDimitry Andric dyn_cast_if_present<ValueDecl>(Src.dyn_cast<const Decl *>())) {
4393*700637cbSDimitry Andric assert(!P.getGlobal(VD));
4394*700637cbSDimitry Andric assert(!Locals.contains(VD));
4395*700637cbSDimitry Andric (void)VD;
4396*700637cbSDimitry Andric }
4397*700637cbSDimitry Andric
4398*700637cbSDimitry Andric // FIXME: There are cases where Src.is<Expr*>() is wrong, e.g.
4399*700637cbSDimitry Andric // (int){12} in C. Consider using Expr::isTemporaryObject() instead
4400*700637cbSDimitry Andric // or isa<MaterializeTemporaryExpr>().
4401*700637cbSDimitry Andric Descriptor *D = P.createDescriptor(Src, Ty, nullptr, Descriptor::InlineDescMD,
4402*700637cbSDimitry Andric IsConst, isa<const Expr *>(Src));
4403*700637cbSDimitry Andric D->IsConstexprUnknown = IsConstexprUnknown;
4404*700637cbSDimitry Andric Scope::Local Local = this->createLocal(D);
4405*700637cbSDimitry Andric if (auto *VD = dyn_cast_if_present<ValueDecl>(Src.dyn_cast<const Decl *>()))
4406*700637cbSDimitry Andric Locals.insert({VD, Local});
4407*700637cbSDimitry Andric if (ExtendingDecl)
4408*700637cbSDimitry Andric VarScope->addExtended(Local, ExtendingDecl);
4409*700637cbSDimitry Andric else
4410*700637cbSDimitry Andric VarScope->addForScopeKind(Local, SC);
4411*700637cbSDimitry Andric return Local.Offset;
4412*700637cbSDimitry Andric }
4413*700637cbSDimitry Andric
4414*700637cbSDimitry Andric template <class Emitter>
4415*700637cbSDimitry Andric std::optional<unsigned>
allocateLocal(DeclTy && Src,QualType Ty,const ValueDecl * ExtendingDecl,ScopeKind SC,bool IsConstexprUnknown)4416*700637cbSDimitry Andric Compiler<Emitter>::allocateLocal(DeclTy &&Src, QualType Ty,
4417*700637cbSDimitry Andric const ValueDecl *ExtendingDecl, ScopeKind SC,
4418*700637cbSDimitry Andric bool IsConstexprUnknown) {
4419*700637cbSDimitry Andric // Make sure we don't accidentally register the same decl twice.
4420*700637cbSDimitry Andric if ([[maybe_unused]] const auto *VD =
4421*700637cbSDimitry Andric dyn_cast_if_present<ValueDecl>(Src.dyn_cast<const Decl *>())) {
4422*700637cbSDimitry Andric assert(!P.getGlobal(VD));
4423*700637cbSDimitry Andric assert(!Locals.contains(VD));
4424*700637cbSDimitry Andric }
4425*700637cbSDimitry Andric
4426*700637cbSDimitry Andric const ValueDecl *Key = nullptr;
4427*700637cbSDimitry Andric const Expr *Init = nullptr;
4428*700637cbSDimitry Andric bool IsTemporary = false;
4429*700637cbSDimitry Andric if (auto *VD = dyn_cast_if_present<ValueDecl>(Src.dyn_cast<const Decl *>())) {
4430*700637cbSDimitry Andric Key = VD;
4431*700637cbSDimitry Andric Ty = VD->getType();
4432*700637cbSDimitry Andric
4433*700637cbSDimitry Andric if (const auto *VarD = dyn_cast<VarDecl>(VD))
4434*700637cbSDimitry Andric Init = VarD->getInit();
4435*700637cbSDimitry Andric }
4436*700637cbSDimitry Andric if (auto *E = Src.dyn_cast<const Expr *>()) {
4437*700637cbSDimitry Andric IsTemporary = true;
4438*700637cbSDimitry Andric if (Ty.isNull())
4439*700637cbSDimitry Andric Ty = E->getType();
4440*700637cbSDimitry Andric }
4441*700637cbSDimitry Andric
4442*700637cbSDimitry Andric Descriptor *D = P.createDescriptor(
4443*700637cbSDimitry Andric Src, Ty.getTypePtr(), Descriptor::InlineDescMD, Ty.isConstQualified(),
4444*700637cbSDimitry Andric IsTemporary, /*IsMutable=*/false, /*IsVolatile=*/false, Init);
4445*700637cbSDimitry Andric if (!D)
4446*700637cbSDimitry Andric return std::nullopt;
4447*700637cbSDimitry Andric D->IsConstexprUnknown = IsConstexprUnknown;
4448*700637cbSDimitry Andric
4449*700637cbSDimitry Andric Scope::Local Local = this->createLocal(D);
4450*700637cbSDimitry Andric if (Key)
4451*700637cbSDimitry Andric Locals.insert({Key, Local});
4452*700637cbSDimitry Andric if (ExtendingDecl)
4453*700637cbSDimitry Andric VarScope->addExtended(Local, ExtendingDecl);
4454*700637cbSDimitry Andric else
4455*700637cbSDimitry Andric VarScope->addForScopeKind(Local, SC);
4456*700637cbSDimitry Andric return Local.Offset;
4457*700637cbSDimitry Andric }
4458*700637cbSDimitry Andric
4459*700637cbSDimitry Andric template <class Emitter>
allocateTemporary(const Expr * E)4460*700637cbSDimitry Andric std::optional<unsigned> Compiler<Emitter>::allocateTemporary(const Expr *E) {
4461*700637cbSDimitry Andric QualType Ty = E->getType();
4462*700637cbSDimitry Andric assert(!Ty->isRecordType());
4463*700637cbSDimitry Andric
4464*700637cbSDimitry Andric Descriptor *D = P.createDescriptor(
4465*700637cbSDimitry Andric E, Ty.getTypePtr(), Descriptor::InlineDescMD, Ty.isConstQualified(),
4466*700637cbSDimitry Andric /*IsTemporary=*/true);
4467*700637cbSDimitry Andric
4468*700637cbSDimitry Andric if (!D)
4469*700637cbSDimitry Andric return std::nullopt;
4470*700637cbSDimitry Andric
4471*700637cbSDimitry Andric Scope::Local Local = this->createLocal(D);
4472*700637cbSDimitry Andric VariableScope<Emitter> *S = VarScope;
4473*700637cbSDimitry Andric assert(S);
4474*700637cbSDimitry Andric // Attach to topmost scope.
4475*700637cbSDimitry Andric while (S->getParent())
4476*700637cbSDimitry Andric S = S->getParent();
4477*700637cbSDimitry Andric assert(S && !S->getParent());
4478*700637cbSDimitry Andric S->addLocal(Local);
4479*700637cbSDimitry Andric return Local.Offset;
4480*700637cbSDimitry Andric }
4481*700637cbSDimitry Andric
4482*700637cbSDimitry Andric template <class Emitter>
getRecordTy(QualType Ty)4483*700637cbSDimitry Andric const RecordType *Compiler<Emitter>::getRecordTy(QualType Ty) {
4484*700637cbSDimitry Andric if (const PointerType *PT = dyn_cast<PointerType>(Ty))
4485*700637cbSDimitry Andric return PT->getPointeeType()->getAs<RecordType>();
4486*700637cbSDimitry Andric return Ty->getAs<RecordType>();
4487*700637cbSDimitry Andric }
4488*700637cbSDimitry Andric
getRecord(QualType Ty)4489*700637cbSDimitry Andric template <class Emitter> Record *Compiler<Emitter>::getRecord(QualType Ty) {
4490*700637cbSDimitry Andric if (const auto *RecordTy = getRecordTy(Ty))
4491*700637cbSDimitry Andric return getRecord(RecordTy->getDecl());
4492*700637cbSDimitry Andric return nullptr;
4493*700637cbSDimitry Andric }
4494*700637cbSDimitry Andric
4495*700637cbSDimitry Andric template <class Emitter>
getRecord(const RecordDecl * RD)4496*700637cbSDimitry Andric Record *Compiler<Emitter>::getRecord(const RecordDecl *RD) {
4497*700637cbSDimitry Andric return P.getOrCreateRecord(RD);
4498*700637cbSDimitry Andric }
4499*700637cbSDimitry Andric
4500*700637cbSDimitry Andric template <class Emitter>
getFunction(const FunctionDecl * FD)4501*700637cbSDimitry Andric const Function *Compiler<Emitter>::getFunction(const FunctionDecl *FD) {
4502*700637cbSDimitry Andric return Ctx.getOrCreateFunction(FD);
4503*700637cbSDimitry Andric }
4504*700637cbSDimitry Andric
4505*700637cbSDimitry Andric template <class Emitter>
visitExpr(const Expr * E,bool DestroyToplevelScope)4506*700637cbSDimitry Andric bool Compiler<Emitter>::visitExpr(const Expr *E, bool DestroyToplevelScope) {
4507*700637cbSDimitry Andric LocalScope<Emitter> RootScope(this);
4508*700637cbSDimitry Andric
4509*700637cbSDimitry Andric // If we won't destroy the toplevel scope, check for memory leaks first.
4510*700637cbSDimitry Andric if (!DestroyToplevelScope) {
4511*700637cbSDimitry Andric if (!this->emitCheckAllocations(E))
4512*700637cbSDimitry Andric return false;
4513*700637cbSDimitry Andric }
4514*700637cbSDimitry Andric
4515*700637cbSDimitry Andric auto maybeDestroyLocals = [&]() -> bool {
4516*700637cbSDimitry Andric if (DestroyToplevelScope)
4517*700637cbSDimitry Andric return RootScope.destroyLocals() && this->emitCheckAllocations(E);
4518*700637cbSDimitry Andric return this->emitCheckAllocations(E);
4519*700637cbSDimitry Andric };
4520*700637cbSDimitry Andric
4521*700637cbSDimitry Andric // Void expressions.
4522*700637cbSDimitry Andric if (E->getType()->isVoidType()) {
4523*700637cbSDimitry Andric if (!visit(E))
4524*700637cbSDimitry Andric return false;
4525*700637cbSDimitry Andric return this->emitRetVoid(E) && maybeDestroyLocals();
4526*700637cbSDimitry Andric }
4527*700637cbSDimitry Andric
4528*700637cbSDimitry Andric // Expressions with a primitive return type.
4529*700637cbSDimitry Andric if (std::optional<PrimType> T = classify(E)) {
4530*700637cbSDimitry Andric if (!visit(E))
4531*700637cbSDimitry Andric return false;
4532*700637cbSDimitry Andric
4533*700637cbSDimitry Andric return this->emitRet(*T, E) && maybeDestroyLocals();
4534*700637cbSDimitry Andric }
4535*700637cbSDimitry Andric
4536*700637cbSDimitry Andric // Expressions with a composite return type.
4537*700637cbSDimitry Andric // For us, that means everything we don't
4538*700637cbSDimitry Andric // have a PrimType for.
4539*700637cbSDimitry Andric if (std::optional<unsigned> LocalOffset = this->allocateLocal(E)) {
4540*700637cbSDimitry Andric InitLinkScope<Emitter> ILS(this, InitLink::Temp(*LocalOffset));
4541*700637cbSDimitry Andric if (!this->emitGetPtrLocal(*LocalOffset, E))
4542*700637cbSDimitry Andric return false;
4543*700637cbSDimitry Andric
4544*700637cbSDimitry Andric if (!visitInitializer(E))
4545*700637cbSDimitry Andric return false;
4546*700637cbSDimitry Andric
4547*700637cbSDimitry Andric if (!this->emitFinishInit(E))
4548*700637cbSDimitry Andric return false;
4549*700637cbSDimitry Andric // We are destroying the locals AFTER the Ret op.
4550*700637cbSDimitry Andric // The Ret op needs to copy the (alive) values, but the
4551*700637cbSDimitry Andric // destructors may still turn the entire expression invalid.
4552*700637cbSDimitry Andric return this->emitRetValue(E) && maybeDestroyLocals();
4553*700637cbSDimitry Andric }
4554*700637cbSDimitry Andric
4555*700637cbSDimitry Andric return maybeDestroyLocals() && this->emitCheckAllocations(E) && false;
4556*700637cbSDimitry Andric }
4557*700637cbSDimitry Andric
4558*700637cbSDimitry Andric template <class Emitter>
visitDecl(const VarDecl * VD,bool IsConstexprUnknown)4559*700637cbSDimitry Andric VarCreationState Compiler<Emitter>::visitDecl(const VarDecl *VD,
4560*700637cbSDimitry Andric bool IsConstexprUnknown) {
4561*700637cbSDimitry Andric
4562*700637cbSDimitry Andric auto R = this->visitVarDecl(VD, /*Toplevel=*/true, IsConstexprUnknown);
4563*700637cbSDimitry Andric
4564*700637cbSDimitry Andric if (R.notCreated())
4565*700637cbSDimitry Andric return R;
4566*700637cbSDimitry Andric
4567*700637cbSDimitry Andric if (R)
4568*700637cbSDimitry Andric return true;
4569*700637cbSDimitry Andric
4570*700637cbSDimitry Andric if (!R && Context::shouldBeGloballyIndexed(VD)) {
4571*700637cbSDimitry Andric if (auto GlobalIndex = P.getGlobal(VD)) {
4572*700637cbSDimitry Andric Block *GlobalBlock = P.getGlobal(*GlobalIndex);
4573*700637cbSDimitry Andric GlobalInlineDescriptor &GD =
4574*700637cbSDimitry Andric *reinterpret_cast<GlobalInlineDescriptor *>(GlobalBlock->rawData());
4575*700637cbSDimitry Andric
4576*700637cbSDimitry Andric GD.InitState = GlobalInitState::InitializerFailed;
4577*700637cbSDimitry Andric GlobalBlock->invokeDtor();
4578*700637cbSDimitry Andric }
4579*700637cbSDimitry Andric }
4580*700637cbSDimitry Andric
4581*700637cbSDimitry Andric return R;
4582*700637cbSDimitry Andric }
4583*700637cbSDimitry Andric
4584*700637cbSDimitry Andric /// Toplevel visitDeclAndReturn().
4585*700637cbSDimitry Andric /// We get here from evaluateAsInitializer().
4586*700637cbSDimitry Andric /// We need to evaluate the initializer and return its value.
4587*700637cbSDimitry Andric template <class Emitter>
visitDeclAndReturn(const VarDecl * VD,bool ConstantContext)4588*700637cbSDimitry Andric bool Compiler<Emitter>::visitDeclAndReturn(const VarDecl *VD,
4589*700637cbSDimitry Andric bool ConstantContext) {
4590*700637cbSDimitry Andric
4591*700637cbSDimitry Andric // We only create variables if we're evaluating in a constant context.
4592*700637cbSDimitry Andric // Otherwise, just evaluate the initializer and return it.
4593*700637cbSDimitry Andric if (!ConstantContext) {
4594*700637cbSDimitry Andric DeclScope<Emitter> LS(this, VD);
4595*700637cbSDimitry Andric const Expr *Init = VD->getInit();
4596*700637cbSDimitry Andric if (!this->visit(Init))
4597*700637cbSDimitry Andric return false;
4598*700637cbSDimitry Andric return this->emitRet(classify(Init).value_or(PT_Ptr), VD) &&
4599*700637cbSDimitry Andric LS.destroyLocals() && this->emitCheckAllocations(VD);
4600*700637cbSDimitry Andric }
4601*700637cbSDimitry Andric
4602*700637cbSDimitry Andric LocalScope<Emitter> VDScope(this, VD);
4603*700637cbSDimitry Andric if (!this->visitVarDecl(VD, /*Toplevel=*/true))
4604*700637cbSDimitry Andric return false;
4605*700637cbSDimitry Andric
4606*700637cbSDimitry Andric std::optional<PrimType> VarT = classify(VD->getType());
4607*700637cbSDimitry Andric if (Context::shouldBeGloballyIndexed(VD)) {
4608*700637cbSDimitry Andric auto GlobalIndex = P.getGlobal(VD);
4609*700637cbSDimitry Andric assert(GlobalIndex); // visitVarDecl() didn't return false.
4610*700637cbSDimitry Andric if (VarT) {
4611*700637cbSDimitry Andric if (!this->emitGetGlobalUnchecked(*VarT, *GlobalIndex, VD))
4612*700637cbSDimitry Andric return false;
4613*700637cbSDimitry Andric } else {
4614*700637cbSDimitry Andric if (!this->emitGetPtrGlobal(*GlobalIndex, VD))
4615*700637cbSDimitry Andric return false;
4616*700637cbSDimitry Andric }
4617*700637cbSDimitry Andric } else {
4618*700637cbSDimitry Andric auto Local = Locals.find(VD);
4619*700637cbSDimitry Andric assert(Local != Locals.end()); // Same here.
4620*700637cbSDimitry Andric if (VarT) {
4621*700637cbSDimitry Andric if (!this->emitGetLocal(*VarT, Local->second.Offset, VD))
4622*700637cbSDimitry Andric return false;
4623*700637cbSDimitry Andric } else {
4624*700637cbSDimitry Andric if (!this->emitGetPtrLocal(Local->second.Offset, VD))
4625*700637cbSDimitry Andric return false;
4626*700637cbSDimitry Andric }
4627*700637cbSDimitry Andric }
4628*700637cbSDimitry Andric
4629*700637cbSDimitry Andric // Return the value.
4630*700637cbSDimitry Andric if (!this->emitRet(VarT.value_or(PT_Ptr), VD)) {
4631*700637cbSDimitry Andric // If the Ret above failed and this is a global variable, mark it as
4632*700637cbSDimitry Andric // uninitialized, even everything else succeeded.
4633*700637cbSDimitry Andric if (Context::shouldBeGloballyIndexed(VD)) {
4634*700637cbSDimitry Andric auto GlobalIndex = P.getGlobal(VD);
4635*700637cbSDimitry Andric assert(GlobalIndex);
4636*700637cbSDimitry Andric Block *GlobalBlock = P.getGlobal(*GlobalIndex);
4637*700637cbSDimitry Andric GlobalInlineDescriptor &GD =
4638*700637cbSDimitry Andric *reinterpret_cast<GlobalInlineDescriptor *>(GlobalBlock->rawData());
4639*700637cbSDimitry Andric
4640*700637cbSDimitry Andric GD.InitState = GlobalInitState::InitializerFailed;
4641*700637cbSDimitry Andric GlobalBlock->invokeDtor();
4642*700637cbSDimitry Andric }
4643*700637cbSDimitry Andric return false;
4644*700637cbSDimitry Andric }
4645*700637cbSDimitry Andric
4646*700637cbSDimitry Andric return VDScope.destroyLocals() && this->emitCheckAllocations(VD);
4647*700637cbSDimitry Andric }
4648*700637cbSDimitry Andric
4649*700637cbSDimitry Andric template <class Emitter>
visitVarDecl(const VarDecl * VD,bool Toplevel,bool IsConstexprUnknown)4650*700637cbSDimitry Andric VarCreationState Compiler<Emitter>::visitVarDecl(const VarDecl *VD,
4651*700637cbSDimitry Andric bool Toplevel,
4652*700637cbSDimitry Andric bool IsConstexprUnknown) {
4653*700637cbSDimitry Andric // We don't know what to do with these, so just return false.
4654*700637cbSDimitry Andric if (VD->getType().isNull())
4655*700637cbSDimitry Andric return false;
4656*700637cbSDimitry Andric
4657*700637cbSDimitry Andric // This case is EvalEmitter-only. If we won't create any instructions for the
4658*700637cbSDimitry Andric // initializer anyway, don't bother creating the variable in the first place.
4659*700637cbSDimitry Andric if (!this->isActive())
4660*700637cbSDimitry Andric return VarCreationState::NotCreated();
4661*700637cbSDimitry Andric
4662*700637cbSDimitry Andric const Expr *Init = VD->getInit();
4663*700637cbSDimitry Andric std::optional<PrimType> VarT = classify(VD->getType());
4664*700637cbSDimitry Andric
4665*700637cbSDimitry Andric if (Init && Init->isValueDependent())
4666*700637cbSDimitry Andric return false;
4667*700637cbSDimitry Andric
4668*700637cbSDimitry Andric if (Context::shouldBeGloballyIndexed(VD)) {
4669*700637cbSDimitry Andric auto checkDecl = [&]() -> bool {
4670*700637cbSDimitry Andric bool NeedsOp = !Toplevel && VD->isLocalVarDecl() && VD->isStaticLocal();
4671*700637cbSDimitry Andric return !NeedsOp || this->emitCheckDecl(VD, VD);
4672*700637cbSDimitry Andric };
4673*700637cbSDimitry Andric
4674*700637cbSDimitry Andric auto initGlobal = [&](unsigned GlobalIndex) -> bool {
4675*700637cbSDimitry Andric assert(Init);
4676*700637cbSDimitry Andric
4677*700637cbSDimitry Andric if (VarT) {
4678*700637cbSDimitry Andric if (!this->visit(Init))
4679*700637cbSDimitry Andric return checkDecl() && false;
4680*700637cbSDimitry Andric
4681*700637cbSDimitry Andric return checkDecl() && this->emitInitGlobal(*VarT, GlobalIndex, VD);
4682*700637cbSDimitry Andric }
4683*700637cbSDimitry Andric
4684*700637cbSDimitry Andric if (!checkDecl())
4685*700637cbSDimitry Andric return false;
4686*700637cbSDimitry Andric
4687*700637cbSDimitry Andric if (!this->emitGetPtrGlobal(GlobalIndex, Init))
4688*700637cbSDimitry Andric return false;
4689*700637cbSDimitry Andric
4690*700637cbSDimitry Andric if (!visitInitializer(Init))
4691*700637cbSDimitry Andric return false;
4692*700637cbSDimitry Andric
4693*700637cbSDimitry Andric return this->emitFinishInitGlobal(Init);
4694*700637cbSDimitry Andric };
4695*700637cbSDimitry Andric
4696*700637cbSDimitry Andric DeclScope<Emitter> LocalScope(this, VD);
4697*700637cbSDimitry Andric
4698*700637cbSDimitry Andric // We've already seen and initialized this global.
4699*700637cbSDimitry Andric if (std::optional<unsigned> GlobalIndex = P.getGlobal(VD)) {
4700*700637cbSDimitry Andric if (P.getPtrGlobal(*GlobalIndex).isInitialized())
4701*700637cbSDimitry Andric return checkDecl();
4702*700637cbSDimitry Andric
4703*700637cbSDimitry Andric // The previous attempt at initialization might've been unsuccessful,
4704*700637cbSDimitry Andric // so let's try this one.
4705*700637cbSDimitry Andric return Init && checkDecl() && initGlobal(*GlobalIndex);
4706*700637cbSDimitry Andric }
4707*700637cbSDimitry Andric
4708*700637cbSDimitry Andric std::optional<unsigned> GlobalIndex = P.createGlobal(VD, Init);
4709*700637cbSDimitry Andric
4710*700637cbSDimitry Andric if (!GlobalIndex)
4711*700637cbSDimitry Andric return false;
4712*700637cbSDimitry Andric
4713*700637cbSDimitry Andric return !Init || (checkDecl() && initGlobal(*GlobalIndex));
4714*700637cbSDimitry Andric }
4715*700637cbSDimitry Andric // Local variables.
4716*700637cbSDimitry Andric InitLinkScope<Emitter> ILS(this, InitLink::Decl(VD));
4717*700637cbSDimitry Andric
4718*700637cbSDimitry Andric if (VarT) {
4719*700637cbSDimitry Andric unsigned Offset = this->allocateLocalPrimitive(
4720*700637cbSDimitry Andric VD, *VarT, VD->getType().isConstQualified(), nullptr, ScopeKind::Block,
4721*700637cbSDimitry Andric IsConstexprUnknown);
4722*700637cbSDimitry Andric if (Init) {
4723*700637cbSDimitry Andric // If this is a toplevel declaration, create a scope for the
4724*700637cbSDimitry Andric // initializer.
4725*700637cbSDimitry Andric if (Toplevel) {
4726*700637cbSDimitry Andric LocalScope<Emitter> Scope(this);
4727*700637cbSDimitry Andric if (!this->visit(Init))
4728*700637cbSDimitry Andric return false;
4729*700637cbSDimitry Andric return this->emitSetLocal(*VarT, Offset, VD) && Scope.destroyLocals();
4730*700637cbSDimitry Andric } else {
4731*700637cbSDimitry Andric if (!this->visit(Init))
4732*700637cbSDimitry Andric return false;
4733*700637cbSDimitry Andric return this->emitSetLocal(*VarT, Offset, VD);
4734*700637cbSDimitry Andric }
4735*700637cbSDimitry Andric }
4736*700637cbSDimitry Andric } else {
4737*700637cbSDimitry Andric if (std::optional<unsigned> Offset = this->allocateLocal(
4738*700637cbSDimitry Andric VD, VD->getType(), nullptr, ScopeKind::Block, IsConstexprUnknown)) {
4739*700637cbSDimitry Andric if (!Init)
4740*700637cbSDimitry Andric return true;
4741*700637cbSDimitry Andric
4742*700637cbSDimitry Andric if (!this->emitGetPtrLocal(*Offset, Init))
4743*700637cbSDimitry Andric return false;
4744*700637cbSDimitry Andric
4745*700637cbSDimitry Andric if (!visitInitializer(Init))
4746*700637cbSDimitry Andric return false;
4747*700637cbSDimitry Andric
4748*700637cbSDimitry Andric return this->emitFinishInitPop(Init);
4749*700637cbSDimitry Andric }
4750*700637cbSDimitry Andric return false;
4751*700637cbSDimitry Andric }
4752*700637cbSDimitry Andric return true;
4753*700637cbSDimitry Andric }
4754*700637cbSDimitry Andric
4755*700637cbSDimitry Andric template <class Emitter>
visitAPValue(const APValue & Val,PrimType ValType,const Expr * E)4756*700637cbSDimitry Andric bool Compiler<Emitter>::visitAPValue(const APValue &Val, PrimType ValType,
4757*700637cbSDimitry Andric const Expr *E) {
4758*700637cbSDimitry Andric assert(!DiscardResult);
4759*700637cbSDimitry Andric if (Val.isInt())
4760*700637cbSDimitry Andric return this->emitConst(Val.getInt(), ValType, E);
4761*700637cbSDimitry Andric else if (Val.isFloat()) {
4762*700637cbSDimitry Andric APFloat F = Val.getFloat();
4763*700637cbSDimitry Andric return this->emitFloat(F, E);
4764*700637cbSDimitry Andric }
4765*700637cbSDimitry Andric
4766*700637cbSDimitry Andric if (Val.isLValue()) {
4767*700637cbSDimitry Andric if (Val.isNullPointer())
4768*700637cbSDimitry Andric return this->emitNull(ValType, 0, nullptr, E);
4769*700637cbSDimitry Andric APValue::LValueBase Base = Val.getLValueBase();
4770*700637cbSDimitry Andric if (const Expr *BaseExpr = Base.dyn_cast<const Expr *>())
4771*700637cbSDimitry Andric return this->visit(BaseExpr);
4772*700637cbSDimitry Andric else if (const auto *VD = Base.dyn_cast<const ValueDecl *>()) {
4773*700637cbSDimitry Andric return this->visitDeclRef(VD, E);
4774*700637cbSDimitry Andric }
4775*700637cbSDimitry Andric } else if (Val.isMemberPointer()) {
4776*700637cbSDimitry Andric if (const ValueDecl *MemberDecl = Val.getMemberPointerDecl())
4777*700637cbSDimitry Andric return this->emitGetMemberPtr(MemberDecl, E);
4778*700637cbSDimitry Andric return this->emitNullMemberPtr(0, nullptr, E);
4779*700637cbSDimitry Andric }
4780*700637cbSDimitry Andric
4781*700637cbSDimitry Andric return false;
4782*700637cbSDimitry Andric }
4783*700637cbSDimitry Andric
4784*700637cbSDimitry Andric template <class Emitter>
visitAPValueInitializer(const APValue & Val,const Expr * E,QualType T)4785*700637cbSDimitry Andric bool Compiler<Emitter>::visitAPValueInitializer(const APValue &Val,
4786*700637cbSDimitry Andric const Expr *E, QualType T) {
4787*700637cbSDimitry Andric if (Val.isStruct()) {
4788*700637cbSDimitry Andric const Record *R = this->getRecord(T);
4789*700637cbSDimitry Andric assert(R);
4790*700637cbSDimitry Andric for (unsigned I = 0, N = Val.getStructNumFields(); I != N; ++I) {
4791*700637cbSDimitry Andric const APValue &F = Val.getStructField(I);
4792*700637cbSDimitry Andric const Record::Field *RF = R->getField(I);
4793*700637cbSDimitry Andric QualType FieldType = RF->Decl->getType();
4794*700637cbSDimitry Andric
4795*700637cbSDimitry Andric if (std::optional<PrimType> PT = classify(FieldType)) {
4796*700637cbSDimitry Andric if (!this->visitAPValue(F, *PT, E))
4797*700637cbSDimitry Andric return false;
4798*700637cbSDimitry Andric if (!this->emitInitField(*PT, RF->Offset, E))
4799*700637cbSDimitry Andric return false;
4800*700637cbSDimitry Andric } else {
4801*700637cbSDimitry Andric if (!this->emitGetPtrField(RF->Offset, E))
4802*700637cbSDimitry Andric return false;
4803*700637cbSDimitry Andric if (!this->visitAPValueInitializer(F, E, FieldType))
4804*700637cbSDimitry Andric return false;
4805*700637cbSDimitry Andric if (!this->emitPopPtr(E))
4806*700637cbSDimitry Andric return false;
4807*700637cbSDimitry Andric }
4808*700637cbSDimitry Andric }
4809*700637cbSDimitry Andric return true;
4810*700637cbSDimitry Andric } else if (Val.isUnion()) {
4811*700637cbSDimitry Andric const FieldDecl *UnionField = Val.getUnionField();
4812*700637cbSDimitry Andric const Record *R = this->getRecord(UnionField->getParent());
4813*700637cbSDimitry Andric assert(R);
4814*700637cbSDimitry Andric const APValue &F = Val.getUnionValue();
4815*700637cbSDimitry Andric const Record::Field *RF = R->getField(UnionField);
4816*700637cbSDimitry Andric PrimType T = classifyPrim(RF->Decl->getType());
4817*700637cbSDimitry Andric if (!this->visitAPValue(F, T, E))
4818*700637cbSDimitry Andric return false;
4819*700637cbSDimitry Andric return this->emitInitField(T, RF->Offset, E);
4820*700637cbSDimitry Andric } else if (Val.isArray()) {
4821*700637cbSDimitry Andric const auto *ArrType = T->getAsArrayTypeUnsafe();
4822*700637cbSDimitry Andric QualType ElemType = ArrType->getElementType();
4823*700637cbSDimitry Andric for (unsigned A = 0, AN = Val.getArraySize(); A != AN; ++A) {
4824*700637cbSDimitry Andric const APValue &Elem = Val.getArrayInitializedElt(A);
4825*700637cbSDimitry Andric if (std::optional<PrimType> ElemT = classify(ElemType)) {
4826*700637cbSDimitry Andric if (!this->visitAPValue(Elem, *ElemT, E))
4827*700637cbSDimitry Andric return false;
4828*700637cbSDimitry Andric if (!this->emitInitElem(*ElemT, A, E))
4829*700637cbSDimitry Andric return false;
4830*700637cbSDimitry Andric } else {
4831*700637cbSDimitry Andric if (!this->emitConstUint32(A, E))
4832*700637cbSDimitry Andric return false;
4833*700637cbSDimitry Andric if (!this->emitArrayElemPtrUint32(E))
4834*700637cbSDimitry Andric return false;
4835*700637cbSDimitry Andric if (!this->visitAPValueInitializer(Elem, E, ElemType))
4836*700637cbSDimitry Andric return false;
4837*700637cbSDimitry Andric if (!this->emitPopPtr(E))
4838*700637cbSDimitry Andric return false;
4839*700637cbSDimitry Andric }
4840*700637cbSDimitry Andric }
4841*700637cbSDimitry Andric return true;
4842*700637cbSDimitry Andric }
4843*700637cbSDimitry Andric // TODO: Other types.
4844*700637cbSDimitry Andric
4845*700637cbSDimitry Andric return false;
4846*700637cbSDimitry Andric }
4847*700637cbSDimitry Andric
4848*700637cbSDimitry Andric template <class Emitter>
VisitBuiltinCallExpr(const CallExpr * E,unsigned BuiltinID)4849*700637cbSDimitry Andric bool Compiler<Emitter>::VisitBuiltinCallExpr(const CallExpr *E,
4850*700637cbSDimitry Andric unsigned BuiltinID) {
4851*700637cbSDimitry Andric
4852*700637cbSDimitry Andric if (BuiltinID == Builtin::BI__builtin_constant_p) {
4853*700637cbSDimitry Andric // Void argument is always invalid and harder to handle later.
4854*700637cbSDimitry Andric if (E->getArg(0)->getType()->isVoidType()) {
4855*700637cbSDimitry Andric if (DiscardResult)
4856*700637cbSDimitry Andric return true;
4857*700637cbSDimitry Andric return this->emitConst(0, E);
4858*700637cbSDimitry Andric }
4859*700637cbSDimitry Andric
4860*700637cbSDimitry Andric if (!this->emitStartSpeculation(E))
4861*700637cbSDimitry Andric return false;
4862*700637cbSDimitry Andric LabelTy EndLabel = this->getLabel();
4863*700637cbSDimitry Andric if (!this->speculate(E, EndLabel))
4864*700637cbSDimitry Andric return false;
4865*700637cbSDimitry Andric this->fallthrough(EndLabel);
4866*700637cbSDimitry Andric if (!this->emitEndSpeculation(E))
4867*700637cbSDimitry Andric return false;
4868*700637cbSDimitry Andric if (DiscardResult)
4869*700637cbSDimitry Andric return this->emitPop(classifyPrim(E), E);
4870*700637cbSDimitry Andric return true;
4871*700637cbSDimitry Andric }
4872*700637cbSDimitry Andric
4873*700637cbSDimitry Andric // For these, we're expected to ultimately return an APValue pointing
4874*700637cbSDimitry Andric // to the CallExpr. This is needed to get the correct codegen.
4875*700637cbSDimitry Andric if (BuiltinID == Builtin::BI__builtin___CFStringMakeConstantString ||
4876*700637cbSDimitry Andric BuiltinID == Builtin::BI__builtin___NSStringMakeConstantString ||
4877*700637cbSDimitry Andric BuiltinID == Builtin::BI__builtin_ptrauth_sign_constant ||
4878*700637cbSDimitry Andric BuiltinID == Builtin::BI__builtin_function_start) {
4879*700637cbSDimitry Andric if (DiscardResult)
4880*700637cbSDimitry Andric return true;
4881*700637cbSDimitry Andric return this->emitDummyPtr(E, E);
4882*700637cbSDimitry Andric }
4883*700637cbSDimitry Andric
4884*700637cbSDimitry Andric QualType ReturnType = E->getType();
4885*700637cbSDimitry Andric std::optional<PrimType> ReturnT = classify(E);
4886*700637cbSDimitry Andric
4887*700637cbSDimitry Andric // Non-primitive return type. Prepare storage.
4888*700637cbSDimitry Andric if (!Initializing && !ReturnT && !ReturnType->isVoidType()) {
4889*700637cbSDimitry Andric std::optional<unsigned> LocalIndex = allocateLocal(E);
4890*700637cbSDimitry Andric if (!LocalIndex)
4891*700637cbSDimitry Andric return false;
4892*700637cbSDimitry Andric if (!this->emitGetPtrLocal(*LocalIndex, E))
4893*700637cbSDimitry Andric return false;
4894*700637cbSDimitry Andric }
4895*700637cbSDimitry Andric
4896*700637cbSDimitry Andric if (!Context::isUnevaluatedBuiltin(BuiltinID)) {
4897*700637cbSDimitry Andric // Put arguments on the stack.
4898*700637cbSDimitry Andric for (const auto *Arg : E->arguments()) {
4899*700637cbSDimitry Andric if (!this->visit(Arg))
4900*700637cbSDimitry Andric return false;
4901*700637cbSDimitry Andric }
4902*700637cbSDimitry Andric }
4903*700637cbSDimitry Andric
4904*700637cbSDimitry Andric if (!this->emitCallBI(E, BuiltinID, E))
4905*700637cbSDimitry Andric return false;
4906*700637cbSDimitry Andric
4907*700637cbSDimitry Andric if (DiscardResult && !ReturnType->isVoidType()) {
4908*700637cbSDimitry Andric assert(ReturnT);
4909*700637cbSDimitry Andric return this->emitPop(*ReturnT, E);
4910*700637cbSDimitry Andric }
4911*700637cbSDimitry Andric
4912*700637cbSDimitry Andric return true;
4913*700637cbSDimitry Andric }
4914*700637cbSDimitry Andric
stripDerivedToBaseCasts(const Expr * E)4915*700637cbSDimitry Andric static const Expr *stripDerivedToBaseCasts(const Expr *E) {
4916*700637cbSDimitry Andric if (const auto *PE = dyn_cast<ParenExpr>(E))
4917*700637cbSDimitry Andric return stripDerivedToBaseCasts(PE->getSubExpr());
4918*700637cbSDimitry Andric
4919*700637cbSDimitry Andric if (const auto *CE = dyn_cast<CastExpr>(E);
4920*700637cbSDimitry Andric CE &&
4921*700637cbSDimitry Andric (CE->getCastKind() == CK_DerivedToBase || CE->getCastKind() == CK_NoOp))
4922*700637cbSDimitry Andric return stripDerivedToBaseCasts(CE->getSubExpr());
4923*700637cbSDimitry Andric
4924*700637cbSDimitry Andric return E;
4925*700637cbSDimitry Andric }
4926*700637cbSDimitry Andric
4927*700637cbSDimitry Andric template <class Emitter>
VisitCallExpr(const CallExpr * E)4928*700637cbSDimitry Andric bool Compiler<Emitter>::VisitCallExpr(const CallExpr *E) {
4929*700637cbSDimitry Andric const FunctionDecl *FuncDecl = E->getDirectCallee();
4930*700637cbSDimitry Andric
4931*700637cbSDimitry Andric if (FuncDecl) {
4932*700637cbSDimitry Andric if (unsigned BuiltinID = FuncDecl->getBuiltinID())
4933*700637cbSDimitry Andric return VisitBuiltinCallExpr(E, BuiltinID);
4934*700637cbSDimitry Andric
4935*700637cbSDimitry Andric // Calls to replaceable operator new/operator delete.
4936*700637cbSDimitry Andric if (FuncDecl->isUsableAsGlobalAllocationFunctionInConstantEvaluation()) {
4937*700637cbSDimitry Andric if (FuncDecl->getDeclName().isAnyOperatorNew()) {
4938*700637cbSDimitry Andric return VisitBuiltinCallExpr(E, Builtin::BI__builtin_operator_new);
4939*700637cbSDimitry Andric } else {
4940*700637cbSDimitry Andric assert(FuncDecl->getDeclName().getCXXOverloadedOperator() == OO_Delete);
4941*700637cbSDimitry Andric return VisitBuiltinCallExpr(E, Builtin::BI__builtin_operator_delete);
4942*700637cbSDimitry Andric }
4943*700637cbSDimitry Andric }
4944*700637cbSDimitry Andric
4945*700637cbSDimitry Andric // Explicit calls to trivial destructors
4946*700637cbSDimitry Andric if (const auto *DD = dyn_cast<CXXDestructorDecl>(FuncDecl);
4947*700637cbSDimitry Andric DD && DD->isTrivial()) {
4948*700637cbSDimitry Andric const auto *MemberCall = cast<CXXMemberCallExpr>(E);
4949*700637cbSDimitry Andric if (!this->visit(MemberCall->getImplicitObjectArgument()))
4950*700637cbSDimitry Andric return false;
4951*700637cbSDimitry Andric return this->emitCheckDestruction(E) && this->emitEndLifetime(E) &&
4952*700637cbSDimitry Andric this->emitPopPtr(E);
4953*700637cbSDimitry Andric }
4954*700637cbSDimitry Andric }
4955*700637cbSDimitry Andric
4956*700637cbSDimitry Andric BlockScope<Emitter> CallScope(this, ScopeKind::Call);
4957*700637cbSDimitry Andric
4958*700637cbSDimitry Andric QualType ReturnType = E->getCallReturnType(Ctx.getASTContext());
4959*700637cbSDimitry Andric std::optional<PrimType> T = classify(ReturnType);
4960*700637cbSDimitry Andric bool HasRVO = !ReturnType->isVoidType() && !T;
4961*700637cbSDimitry Andric
4962*700637cbSDimitry Andric if (HasRVO) {
4963*700637cbSDimitry Andric if (DiscardResult) {
4964*700637cbSDimitry Andric // If we need to discard the return value but the function returns its
4965*700637cbSDimitry Andric // value via an RVO pointer, we need to create one such pointer just
4966*700637cbSDimitry Andric // for this call.
4967*700637cbSDimitry Andric if (std::optional<unsigned> LocalIndex = allocateLocal(E)) {
4968*700637cbSDimitry Andric if (!this->emitGetPtrLocal(*LocalIndex, E))
4969*700637cbSDimitry Andric return false;
4970*700637cbSDimitry Andric }
4971*700637cbSDimitry Andric } else {
4972*700637cbSDimitry Andric // We need the result. Prepare a pointer to return or
4973*700637cbSDimitry Andric // dup the current one.
4974*700637cbSDimitry Andric if (!Initializing) {
4975*700637cbSDimitry Andric if (std::optional<unsigned> LocalIndex = allocateLocal(E)) {
4976*700637cbSDimitry Andric if (!this->emitGetPtrLocal(*LocalIndex, E))
4977*700637cbSDimitry Andric return false;
4978*700637cbSDimitry Andric }
4979*700637cbSDimitry Andric }
4980*700637cbSDimitry Andric if (!this->emitDupPtr(E))
4981*700637cbSDimitry Andric return false;
4982*700637cbSDimitry Andric }
4983*700637cbSDimitry Andric }
4984*700637cbSDimitry Andric
4985*700637cbSDimitry Andric SmallVector<const Expr *, 8> Args(ArrayRef(E->getArgs(), E->getNumArgs()));
4986*700637cbSDimitry Andric
4987*700637cbSDimitry Andric bool IsAssignmentOperatorCall = false;
4988*700637cbSDimitry Andric if (const auto *OCE = dyn_cast<CXXOperatorCallExpr>(E);
4989*700637cbSDimitry Andric OCE && OCE->isAssignmentOp()) {
4990*700637cbSDimitry Andric // Just like with regular assignments, we need to special-case assignment
4991*700637cbSDimitry Andric // operators here and evaluate the RHS (the second arg) before the LHS (the
4992*700637cbSDimitry Andric // first arg). We fix this by using a Flip op later.
4993*700637cbSDimitry Andric assert(Args.size() == 2);
4994*700637cbSDimitry Andric IsAssignmentOperatorCall = true;
4995*700637cbSDimitry Andric std::reverse(Args.begin(), Args.end());
4996*700637cbSDimitry Andric }
4997*700637cbSDimitry Andric // Calling a static operator will still
4998*700637cbSDimitry Andric // pass the instance, but we don't need it.
4999*700637cbSDimitry Andric // Discard it here.
5000*700637cbSDimitry Andric if (isa<CXXOperatorCallExpr>(E)) {
5001*700637cbSDimitry Andric if (const auto *MD = dyn_cast_if_present<CXXMethodDecl>(FuncDecl);
5002*700637cbSDimitry Andric MD && MD->isStatic()) {
5003*700637cbSDimitry Andric if (!this->discard(E->getArg(0)))
5004*700637cbSDimitry Andric return false;
5005*700637cbSDimitry Andric // Drop first arg.
5006*700637cbSDimitry Andric Args.erase(Args.begin());
5007*700637cbSDimitry Andric }
5008*700637cbSDimitry Andric }
5009*700637cbSDimitry Andric
5010*700637cbSDimitry Andric bool Devirtualized = false;
5011*700637cbSDimitry Andric std::optional<unsigned> CalleeOffset;
5012*700637cbSDimitry Andric // Add the (optional, implicit) This pointer.
5013*700637cbSDimitry Andric if (const auto *MC = dyn_cast<CXXMemberCallExpr>(E)) {
5014*700637cbSDimitry Andric if (!FuncDecl && classifyPrim(E->getCallee()) == PT_MemberPtr) {
5015*700637cbSDimitry Andric // If we end up creating a CallPtr op for this, we need the base of the
5016*700637cbSDimitry Andric // member pointer as the instance pointer, and later extract the function
5017*700637cbSDimitry Andric // decl as the function pointer.
5018*700637cbSDimitry Andric const Expr *Callee = E->getCallee();
5019*700637cbSDimitry Andric CalleeOffset =
5020*700637cbSDimitry Andric this->allocateLocalPrimitive(Callee, PT_MemberPtr, /*IsConst=*/true);
5021*700637cbSDimitry Andric if (!this->visit(Callee))
5022*700637cbSDimitry Andric return false;
5023*700637cbSDimitry Andric if (!this->emitSetLocal(PT_MemberPtr, *CalleeOffset, E))
5024*700637cbSDimitry Andric return false;
5025*700637cbSDimitry Andric if (!this->emitGetLocal(PT_MemberPtr, *CalleeOffset, E))
5026*700637cbSDimitry Andric return false;
5027*700637cbSDimitry Andric if (!this->emitGetMemberPtrBase(E))
5028*700637cbSDimitry Andric return false;
5029*700637cbSDimitry Andric } else {
5030*700637cbSDimitry Andric const auto *InstancePtr = MC->getImplicitObjectArgument();
5031*700637cbSDimitry Andric if (isa_and_nonnull<CXXDestructorDecl>(CompilingFunction) ||
5032*700637cbSDimitry Andric isa_and_nonnull<CXXConstructorDecl>(CompilingFunction)) {
5033*700637cbSDimitry Andric const auto *Stripped = stripDerivedToBaseCasts(InstancePtr);
5034*700637cbSDimitry Andric if (isa<CXXThisExpr>(Stripped)) {
5035*700637cbSDimitry Andric FuncDecl =
5036*700637cbSDimitry Andric cast<CXXMethodDecl>(FuncDecl)->getCorrespondingMethodInClass(
5037*700637cbSDimitry Andric Stripped->getType()->getPointeeType()->getAsCXXRecordDecl());
5038*700637cbSDimitry Andric Devirtualized = true;
5039*700637cbSDimitry Andric if (!this->visit(Stripped))
5040*700637cbSDimitry Andric return false;
5041*700637cbSDimitry Andric } else {
5042*700637cbSDimitry Andric if (!this->visit(InstancePtr))
5043*700637cbSDimitry Andric return false;
5044*700637cbSDimitry Andric }
5045*700637cbSDimitry Andric } else {
5046*700637cbSDimitry Andric if (!this->visit(InstancePtr))
5047*700637cbSDimitry Andric return false;
5048*700637cbSDimitry Andric }
5049*700637cbSDimitry Andric }
5050*700637cbSDimitry Andric } else if (const auto *PD =
5051*700637cbSDimitry Andric dyn_cast<CXXPseudoDestructorExpr>(E->getCallee())) {
5052*700637cbSDimitry Andric if (!this->emitCheckPseudoDtor(E))
5053*700637cbSDimitry Andric return false;
5054*700637cbSDimitry Andric const Expr *Base = PD->getBase();
5055*700637cbSDimitry Andric if (!Base->isGLValue())
5056*700637cbSDimitry Andric return this->discard(Base);
5057*700637cbSDimitry Andric if (!this->visit(Base))
5058*700637cbSDimitry Andric return false;
5059*700637cbSDimitry Andric return this->emitEndLifetimePop(E);
5060*700637cbSDimitry Andric } else if (!FuncDecl) {
5061*700637cbSDimitry Andric const Expr *Callee = E->getCallee();
5062*700637cbSDimitry Andric CalleeOffset =
5063*700637cbSDimitry Andric this->allocateLocalPrimitive(Callee, PT_Ptr, /*IsConst=*/true);
5064*700637cbSDimitry Andric if (!this->visit(Callee))
5065*700637cbSDimitry Andric return false;
5066*700637cbSDimitry Andric if (!this->emitSetLocal(PT_Ptr, *CalleeOffset, E))
5067*700637cbSDimitry Andric return false;
5068*700637cbSDimitry Andric }
5069*700637cbSDimitry Andric
5070*700637cbSDimitry Andric if (!this->visitCallArgs(Args, FuncDecl))
5071*700637cbSDimitry Andric return false;
5072*700637cbSDimitry Andric
5073*700637cbSDimitry Andric // Undo the argument reversal we did earlier.
5074*700637cbSDimitry Andric if (IsAssignmentOperatorCall) {
5075*700637cbSDimitry Andric assert(Args.size() == 2);
5076*700637cbSDimitry Andric PrimType Arg1T = classify(Args[0]).value_or(PT_Ptr);
5077*700637cbSDimitry Andric PrimType Arg2T = classify(Args[1]).value_or(PT_Ptr);
5078*700637cbSDimitry Andric if (!this->emitFlip(Arg2T, Arg1T, E))
5079*700637cbSDimitry Andric return false;
5080*700637cbSDimitry Andric }
5081*700637cbSDimitry Andric
5082*700637cbSDimitry Andric if (FuncDecl) {
5083*700637cbSDimitry Andric const Function *Func = getFunction(FuncDecl);
5084*700637cbSDimitry Andric if (!Func)
5085*700637cbSDimitry Andric return false;
5086*700637cbSDimitry Andric assert(HasRVO == Func->hasRVO());
5087*700637cbSDimitry Andric
5088*700637cbSDimitry Andric bool HasQualifier = false;
5089*700637cbSDimitry Andric if (const auto *ME = dyn_cast<MemberExpr>(E->getCallee()))
5090*700637cbSDimitry Andric HasQualifier = ME->hasQualifier();
5091*700637cbSDimitry Andric
5092*700637cbSDimitry Andric bool IsVirtual = false;
5093*700637cbSDimitry Andric if (const auto *MD = dyn_cast<CXXMethodDecl>(FuncDecl))
5094*700637cbSDimitry Andric IsVirtual = !Devirtualized && MD->isVirtual();
5095*700637cbSDimitry Andric
5096*700637cbSDimitry Andric // In any case call the function. The return value will end up on the stack
5097*700637cbSDimitry Andric // and if the function has RVO, we already have the pointer on the stack to
5098*700637cbSDimitry Andric // write the result into.
5099*700637cbSDimitry Andric if (IsVirtual && !HasQualifier) {
5100*700637cbSDimitry Andric uint32_t VarArgSize = 0;
5101*700637cbSDimitry Andric unsigned NumParams =
5102*700637cbSDimitry Andric Func->getNumWrittenParams() + isa<CXXOperatorCallExpr>(E);
5103*700637cbSDimitry Andric for (unsigned I = NumParams, N = E->getNumArgs(); I != N; ++I)
5104*700637cbSDimitry Andric VarArgSize += align(primSize(classify(E->getArg(I)).value_or(PT_Ptr)));
5105*700637cbSDimitry Andric
5106*700637cbSDimitry Andric if (!this->emitCallVirt(Func, VarArgSize, E))
5107*700637cbSDimitry Andric return false;
5108*700637cbSDimitry Andric } else if (Func->isVariadic()) {
5109*700637cbSDimitry Andric uint32_t VarArgSize = 0;
5110*700637cbSDimitry Andric unsigned NumParams =
5111*700637cbSDimitry Andric Func->getNumWrittenParams() + isa<CXXOperatorCallExpr>(E);
5112*700637cbSDimitry Andric for (unsigned I = NumParams, N = E->getNumArgs(); I != N; ++I)
5113*700637cbSDimitry Andric VarArgSize += align(primSize(classify(E->getArg(I)).value_or(PT_Ptr)));
5114*700637cbSDimitry Andric if (!this->emitCallVar(Func, VarArgSize, E))
5115*700637cbSDimitry Andric return false;
5116*700637cbSDimitry Andric } else {
5117*700637cbSDimitry Andric if (!this->emitCall(Func, 0, E))
5118*700637cbSDimitry Andric return false;
5119*700637cbSDimitry Andric }
5120*700637cbSDimitry Andric } else {
5121*700637cbSDimitry Andric // Indirect call. Visit the callee, which will leave a FunctionPointer on
5122*700637cbSDimitry Andric // the stack. Cleanup of the returned value if necessary will be done after
5123*700637cbSDimitry Andric // the function call completed.
5124*700637cbSDimitry Andric
5125*700637cbSDimitry Andric // Sum the size of all args from the call expr.
5126*700637cbSDimitry Andric uint32_t ArgSize = 0;
5127*700637cbSDimitry Andric for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I)
5128*700637cbSDimitry Andric ArgSize += align(primSize(classify(E->getArg(I)).value_or(PT_Ptr)));
5129*700637cbSDimitry Andric
5130*700637cbSDimitry Andric // Get the callee, either from a member pointer or function pointer saved in
5131*700637cbSDimitry Andric // CalleeOffset.
5132*700637cbSDimitry Andric if (isa<CXXMemberCallExpr>(E) && CalleeOffset) {
5133*700637cbSDimitry Andric if (!this->emitGetLocal(PT_MemberPtr, *CalleeOffset, E))
5134*700637cbSDimitry Andric return false;
5135*700637cbSDimitry Andric if (!this->emitGetMemberPtrDecl(E))
5136*700637cbSDimitry Andric return false;
5137*700637cbSDimitry Andric } else {
5138*700637cbSDimitry Andric if (!this->emitGetLocal(PT_Ptr, *CalleeOffset, E))
5139*700637cbSDimitry Andric return false;
5140*700637cbSDimitry Andric }
5141*700637cbSDimitry Andric if (!this->emitCallPtr(ArgSize, E, E))
5142*700637cbSDimitry Andric return false;
5143*700637cbSDimitry Andric }
5144*700637cbSDimitry Andric
5145*700637cbSDimitry Andric // Cleanup for discarded return values.
5146*700637cbSDimitry Andric if (DiscardResult && !ReturnType->isVoidType() && T)
5147*700637cbSDimitry Andric return this->emitPop(*T, E) && CallScope.destroyLocals();
5148*700637cbSDimitry Andric
5149*700637cbSDimitry Andric return CallScope.destroyLocals();
5150*700637cbSDimitry Andric }
5151*700637cbSDimitry Andric
5152*700637cbSDimitry Andric template <class Emitter>
VisitCXXDefaultInitExpr(const CXXDefaultInitExpr * E)5153*700637cbSDimitry Andric bool Compiler<Emitter>::VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *E) {
5154*700637cbSDimitry Andric SourceLocScope<Emitter> SLS(this, E);
5155*700637cbSDimitry Andric
5156*700637cbSDimitry Andric return this->delegate(E->getExpr());
5157*700637cbSDimitry Andric }
5158*700637cbSDimitry Andric
5159*700637cbSDimitry Andric template <class Emitter>
VisitCXXDefaultArgExpr(const CXXDefaultArgExpr * E)5160*700637cbSDimitry Andric bool Compiler<Emitter>::VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *E) {
5161*700637cbSDimitry Andric SourceLocScope<Emitter> SLS(this, E);
5162*700637cbSDimitry Andric
5163*700637cbSDimitry Andric return this->delegate(E->getExpr());
5164*700637cbSDimitry Andric }
5165*700637cbSDimitry Andric
5166*700637cbSDimitry Andric template <class Emitter>
VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr * E)5167*700637cbSDimitry Andric bool Compiler<Emitter>::VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *E) {
5168*700637cbSDimitry Andric if (DiscardResult)
5169*700637cbSDimitry Andric return true;
5170*700637cbSDimitry Andric
5171*700637cbSDimitry Andric return this->emitConstBool(E->getValue(), E);
5172*700637cbSDimitry Andric }
5173*700637cbSDimitry Andric
5174*700637cbSDimitry Andric template <class Emitter>
VisitCXXNullPtrLiteralExpr(const CXXNullPtrLiteralExpr * E)5175*700637cbSDimitry Andric bool Compiler<Emitter>::VisitCXXNullPtrLiteralExpr(
5176*700637cbSDimitry Andric const CXXNullPtrLiteralExpr *E) {
5177*700637cbSDimitry Andric if (DiscardResult)
5178*700637cbSDimitry Andric return true;
5179*700637cbSDimitry Andric
5180*700637cbSDimitry Andric uint64_t Val = Ctx.getASTContext().getTargetNullPointerValue(E->getType());
5181*700637cbSDimitry Andric return this->emitNullPtr(Val, nullptr, E);
5182*700637cbSDimitry Andric }
5183*700637cbSDimitry Andric
5184*700637cbSDimitry Andric template <class Emitter>
VisitGNUNullExpr(const GNUNullExpr * E)5185*700637cbSDimitry Andric bool Compiler<Emitter>::VisitGNUNullExpr(const GNUNullExpr *E) {
5186*700637cbSDimitry Andric if (DiscardResult)
5187*700637cbSDimitry Andric return true;
5188*700637cbSDimitry Andric
5189*700637cbSDimitry Andric assert(E->getType()->isIntegerType());
5190*700637cbSDimitry Andric
5191*700637cbSDimitry Andric PrimType T = classifyPrim(E->getType());
5192*700637cbSDimitry Andric return this->emitZero(T, E);
5193*700637cbSDimitry Andric }
5194*700637cbSDimitry Andric
5195*700637cbSDimitry Andric template <class Emitter>
VisitCXXThisExpr(const CXXThisExpr * E)5196*700637cbSDimitry Andric bool Compiler<Emitter>::VisitCXXThisExpr(const CXXThisExpr *E) {
5197*700637cbSDimitry Andric if (DiscardResult)
5198*700637cbSDimitry Andric return true;
5199*700637cbSDimitry Andric
5200*700637cbSDimitry Andric if (this->LambdaThisCapture.Offset > 0) {
5201*700637cbSDimitry Andric if (this->LambdaThisCapture.IsPtr)
5202*700637cbSDimitry Andric return this->emitGetThisFieldPtr(this->LambdaThisCapture.Offset, E);
5203*700637cbSDimitry Andric return this->emitGetPtrThisField(this->LambdaThisCapture.Offset, E);
5204*700637cbSDimitry Andric }
5205*700637cbSDimitry Andric
5206*700637cbSDimitry Andric // In some circumstances, the 'this' pointer does not actually refer to the
5207*700637cbSDimitry Andric // instance pointer of the current function frame, but e.g. to the declaration
5208*700637cbSDimitry Andric // currently being initialized. Here we emit the necessary instruction(s) for
5209*700637cbSDimitry Andric // this scenario.
5210*700637cbSDimitry Andric if (!InitStackActive)
5211*700637cbSDimitry Andric return this->emitThis(E);
5212*700637cbSDimitry Andric
5213*700637cbSDimitry Andric if (!InitStack.empty()) {
5214*700637cbSDimitry Andric // If our init stack is, for example:
5215*700637cbSDimitry Andric // 0 Stack: 3 (decl)
5216*700637cbSDimitry Andric // 1 Stack: 6 (init list)
5217*700637cbSDimitry Andric // 2 Stack: 1 (field)
5218*700637cbSDimitry Andric // 3 Stack: 6 (init list)
5219*700637cbSDimitry Andric // 4 Stack: 1 (field)
5220*700637cbSDimitry Andric //
5221*700637cbSDimitry Andric // We want to find the LAST element in it that's an init list,
5222*700637cbSDimitry Andric // which is marked with the K_InitList marker. The index right
5223*700637cbSDimitry Andric // before that points to an init list. We need to find the
5224*700637cbSDimitry Andric // elements before the K_InitList element that point to a base
5225*700637cbSDimitry Andric // (e.g. a decl or This), optionally followed by field, elem, etc.
5226*700637cbSDimitry Andric // In the example above, we want to emit elements [0..2].
5227*700637cbSDimitry Andric unsigned StartIndex = 0;
5228*700637cbSDimitry Andric unsigned EndIndex = 0;
5229*700637cbSDimitry Andric // Find the init list.
5230*700637cbSDimitry Andric for (StartIndex = InitStack.size() - 1; StartIndex > 0; --StartIndex) {
5231*700637cbSDimitry Andric if (InitStack[StartIndex].Kind == InitLink::K_InitList ||
5232*700637cbSDimitry Andric InitStack[StartIndex].Kind == InitLink::K_This) {
5233*700637cbSDimitry Andric EndIndex = StartIndex;
5234*700637cbSDimitry Andric --StartIndex;
5235*700637cbSDimitry Andric break;
5236*700637cbSDimitry Andric }
5237*700637cbSDimitry Andric }
5238*700637cbSDimitry Andric
5239*700637cbSDimitry Andric // Walk backwards to find the base.
5240*700637cbSDimitry Andric for (; StartIndex > 0; --StartIndex) {
5241*700637cbSDimitry Andric if (InitStack[StartIndex].Kind == InitLink::K_InitList)
5242*700637cbSDimitry Andric continue;
5243*700637cbSDimitry Andric
5244*700637cbSDimitry Andric if (InitStack[StartIndex].Kind != InitLink::K_Field &&
5245*700637cbSDimitry Andric InitStack[StartIndex].Kind != InitLink::K_Elem)
5246*700637cbSDimitry Andric break;
5247*700637cbSDimitry Andric }
5248*700637cbSDimitry Andric
5249*700637cbSDimitry Andric // Emit the instructions.
5250*700637cbSDimitry Andric for (unsigned I = StartIndex; I != EndIndex; ++I) {
5251*700637cbSDimitry Andric if (InitStack[I].Kind == InitLink::K_InitList)
5252*700637cbSDimitry Andric continue;
5253*700637cbSDimitry Andric if (!InitStack[I].template emit<Emitter>(this, E))
5254*700637cbSDimitry Andric return false;
5255*700637cbSDimitry Andric }
5256*700637cbSDimitry Andric return true;
5257*700637cbSDimitry Andric }
5258*700637cbSDimitry Andric return this->emitThis(E);
5259*700637cbSDimitry Andric }
5260*700637cbSDimitry Andric
visitStmt(const Stmt * S)5261*700637cbSDimitry Andric template <class Emitter> bool Compiler<Emitter>::visitStmt(const Stmt *S) {
5262*700637cbSDimitry Andric switch (S->getStmtClass()) {
5263*700637cbSDimitry Andric case Stmt::CompoundStmtClass:
5264*700637cbSDimitry Andric return visitCompoundStmt(cast<CompoundStmt>(S));
5265*700637cbSDimitry Andric case Stmt::DeclStmtClass:
5266*700637cbSDimitry Andric return visitDeclStmt(cast<DeclStmt>(S), /*EvaluateConditionDecl=*/true);
5267*700637cbSDimitry Andric case Stmt::ReturnStmtClass:
5268*700637cbSDimitry Andric return visitReturnStmt(cast<ReturnStmt>(S));
5269*700637cbSDimitry Andric case Stmt::IfStmtClass:
5270*700637cbSDimitry Andric return visitIfStmt(cast<IfStmt>(S));
5271*700637cbSDimitry Andric case Stmt::WhileStmtClass:
5272*700637cbSDimitry Andric return visitWhileStmt(cast<WhileStmt>(S));
5273*700637cbSDimitry Andric case Stmt::DoStmtClass:
5274*700637cbSDimitry Andric return visitDoStmt(cast<DoStmt>(S));
5275*700637cbSDimitry Andric case Stmt::ForStmtClass:
5276*700637cbSDimitry Andric return visitForStmt(cast<ForStmt>(S));
5277*700637cbSDimitry Andric case Stmt::CXXForRangeStmtClass:
5278*700637cbSDimitry Andric return visitCXXForRangeStmt(cast<CXXForRangeStmt>(S));
5279*700637cbSDimitry Andric case Stmt::BreakStmtClass:
5280*700637cbSDimitry Andric return visitBreakStmt(cast<BreakStmt>(S));
5281*700637cbSDimitry Andric case Stmt::ContinueStmtClass:
5282*700637cbSDimitry Andric return visitContinueStmt(cast<ContinueStmt>(S));
5283*700637cbSDimitry Andric case Stmt::SwitchStmtClass:
5284*700637cbSDimitry Andric return visitSwitchStmt(cast<SwitchStmt>(S));
5285*700637cbSDimitry Andric case Stmt::CaseStmtClass:
5286*700637cbSDimitry Andric return visitCaseStmt(cast<CaseStmt>(S));
5287*700637cbSDimitry Andric case Stmt::DefaultStmtClass:
5288*700637cbSDimitry Andric return visitDefaultStmt(cast<DefaultStmt>(S));
5289*700637cbSDimitry Andric case Stmt::AttributedStmtClass:
5290*700637cbSDimitry Andric return visitAttributedStmt(cast<AttributedStmt>(S));
5291*700637cbSDimitry Andric case Stmt::CXXTryStmtClass:
5292*700637cbSDimitry Andric return visitCXXTryStmt(cast<CXXTryStmt>(S));
5293*700637cbSDimitry Andric case Stmt::NullStmtClass:
5294*700637cbSDimitry Andric return true;
5295*700637cbSDimitry Andric // Always invalid statements.
5296*700637cbSDimitry Andric case Stmt::GCCAsmStmtClass:
5297*700637cbSDimitry Andric case Stmt::MSAsmStmtClass:
5298*700637cbSDimitry Andric case Stmt::GotoStmtClass:
5299*700637cbSDimitry Andric return this->emitInvalid(S);
5300*700637cbSDimitry Andric case Stmt::LabelStmtClass:
5301*700637cbSDimitry Andric return this->visitStmt(cast<LabelStmt>(S)->getSubStmt());
5302*700637cbSDimitry Andric default: {
5303*700637cbSDimitry Andric if (const auto *E = dyn_cast<Expr>(S))
5304*700637cbSDimitry Andric return this->discard(E);
5305*700637cbSDimitry Andric return false;
5306*700637cbSDimitry Andric }
5307*700637cbSDimitry Andric }
5308*700637cbSDimitry Andric }
5309*700637cbSDimitry Andric
5310*700637cbSDimitry Andric template <class Emitter>
visitCompoundStmt(const CompoundStmt * S)5311*700637cbSDimitry Andric bool Compiler<Emitter>::visitCompoundStmt(const CompoundStmt *S) {
5312*700637cbSDimitry Andric BlockScope<Emitter> Scope(this);
5313*700637cbSDimitry Andric for (const auto *InnerStmt : S->body())
5314*700637cbSDimitry Andric if (!visitStmt(InnerStmt))
5315*700637cbSDimitry Andric return false;
5316*700637cbSDimitry Andric return Scope.destroyLocals();
5317*700637cbSDimitry Andric }
5318*700637cbSDimitry Andric
5319*700637cbSDimitry Andric template <class Emitter>
maybeEmitDeferredVarInit(const VarDecl * VD)5320*700637cbSDimitry Andric bool Compiler<Emitter>::maybeEmitDeferredVarInit(const VarDecl *VD) {
5321*700637cbSDimitry Andric if (auto *DD = dyn_cast_if_present<DecompositionDecl>(VD)) {
5322*700637cbSDimitry Andric for (auto *BD : DD->flat_bindings())
5323*700637cbSDimitry Andric if (auto *KD = BD->getHoldingVar(); KD && !this->visitVarDecl(KD))
5324*700637cbSDimitry Andric return false;
5325*700637cbSDimitry Andric }
5326*700637cbSDimitry Andric return true;
5327*700637cbSDimitry Andric }
5328*700637cbSDimitry Andric
5329*700637cbSDimitry Andric template <class Emitter>
visitDeclStmt(const DeclStmt * DS,bool EvaluateConditionDecl)5330*700637cbSDimitry Andric bool Compiler<Emitter>::visitDeclStmt(const DeclStmt *DS,
5331*700637cbSDimitry Andric bool EvaluateConditionDecl) {
5332*700637cbSDimitry Andric for (const auto *D : DS->decls()) {
5333*700637cbSDimitry Andric if (isa<StaticAssertDecl, TagDecl, TypedefNameDecl, BaseUsingDecl,
5334*700637cbSDimitry Andric FunctionDecl, NamespaceAliasDecl, UsingDirectiveDecl>(D))
5335*700637cbSDimitry Andric continue;
5336*700637cbSDimitry Andric
5337*700637cbSDimitry Andric const auto *VD = dyn_cast<VarDecl>(D);
5338*700637cbSDimitry Andric if (!VD)
5339*700637cbSDimitry Andric return false;
5340*700637cbSDimitry Andric if (!this->visitVarDecl(VD))
5341*700637cbSDimitry Andric return false;
5342*700637cbSDimitry Andric
5343*700637cbSDimitry Andric // Register decomposition decl holding vars.
5344*700637cbSDimitry Andric if (EvaluateConditionDecl && !this->maybeEmitDeferredVarInit(VD))
5345*700637cbSDimitry Andric return false;
5346*700637cbSDimitry Andric }
5347*700637cbSDimitry Andric
5348*700637cbSDimitry Andric return true;
5349*700637cbSDimitry Andric }
5350*700637cbSDimitry Andric
5351*700637cbSDimitry Andric template <class Emitter>
visitReturnStmt(const ReturnStmt * RS)5352*700637cbSDimitry Andric bool Compiler<Emitter>::visitReturnStmt(const ReturnStmt *RS) {
5353*700637cbSDimitry Andric if (this->InStmtExpr)
5354*700637cbSDimitry Andric return this->emitUnsupported(RS);
5355*700637cbSDimitry Andric
5356*700637cbSDimitry Andric if (const Expr *RE = RS->getRetValue()) {
5357*700637cbSDimitry Andric LocalScope<Emitter> RetScope(this);
5358*700637cbSDimitry Andric if (ReturnType) {
5359*700637cbSDimitry Andric // Primitive types are simply returned.
5360*700637cbSDimitry Andric if (!this->visit(RE))
5361*700637cbSDimitry Andric return false;
5362*700637cbSDimitry Andric this->emitCleanup();
5363*700637cbSDimitry Andric return this->emitRet(*ReturnType, RS);
5364*700637cbSDimitry Andric } else if (RE->getType()->isVoidType()) {
5365*700637cbSDimitry Andric if (!this->visit(RE))
5366*700637cbSDimitry Andric return false;
5367*700637cbSDimitry Andric } else {
5368*700637cbSDimitry Andric InitLinkScope<Emitter> ILS(this, InitLink::RVO());
5369*700637cbSDimitry Andric // RVO - construct the value in the return location.
5370*700637cbSDimitry Andric if (!this->emitRVOPtr(RE))
5371*700637cbSDimitry Andric return false;
5372*700637cbSDimitry Andric if (!this->visitInitializer(RE))
5373*700637cbSDimitry Andric return false;
5374*700637cbSDimitry Andric if (!this->emitPopPtr(RE))
5375*700637cbSDimitry Andric return false;
5376*700637cbSDimitry Andric
5377*700637cbSDimitry Andric this->emitCleanup();
5378*700637cbSDimitry Andric return this->emitRetVoid(RS);
5379*700637cbSDimitry Andric }
5380*700637cbSDimitry Andric }
5381*700637cbSDimitry Andric
5382*700637cbSDimitry Andric // Void return.
5383*700637cbSDimitry Andric this->emitCleanup();
5384*700637cbSDimitry Andric return this->emitRetVoid(RS);
5385*700637cbSDimitry Andric }
5386*700637cbSDimitry Andric
visitIfStmt(const IfStmt * IS)5387*700637cbSDimitry Andric template <class Emitter> bool Compiler<Emitter>::visitIfStmt(const IfStmt *IS) {
5388*700637cbSDimitry Andric auto visitChildStmt = [&](const Stmt *S) -> bool {
5389*700637cbSDimitry Andric LocalScope<Emitter> SScope(this);
5390*700637cbSDimitry Andric if (!visitStmt(S))
5391*700637cbSDimitry Andric return false;
5392*700637cbSDimitry Andric return SScope.destroyLocals();
5393*700637cbSDimitry Andric };
5394*700637cbSDimitry Andric if (auto *CondInit = IS->getInit())
5395*700637cbSDimitry Andric if (!visitStmt(CondInit))
5396*700637cbSDimitry Andric return false;
5397*700637cbSDimitry Andric
5398*700637cbSDimitry Andric if (const DeclStmt *CondDecl = IS->getConditionVariableDeclStmt())
5399*700637cbSDimitry Andric if (!visitDeclStmt(CondDecl))
5400*700637cbSDimitry Andric return false;
5401*700637cbSDimitry Andric
5402*700637cbSDimitry Andric // Save ourselves compiling some code and the jumps, etc. if the condition is
5403*700637cbSDimitry Andric // stataically known to be either true or false. We could look at more cases
5404*700637cbSDimitry Andric // here, but I think all the ones that actually happen are using a
5405*700637cbSDimitry Andric // ConstantExpr.
5406*700637cbSDimitry Andric if (std::optional<bool> BoolValue = getBoolValue(IS->getCond())) {
5407*700637cbSDimitry Andric if (*BoolValue)
5408*700637cbSDimitry Andric return visitChildStmt(IS->getThen());
5409*700637cbSDimitry Andric else if (const Stmt *Else = IS->getElse())
5410*700637cbSDimitry Andric return visitChildStmt(Else);
5411*700637cbSDimitry Andric return true;
5412*700637cbSDimitry Andric }
5413*700637cbSDimitry Andric
5414*700637cbSDimitry Andric // Otherwise, compile the condition.
5415*700637cbSDimitry Andric if (IS->isNonNegatedConsteval()) {
5416*700637cbSDimitry Andric if (!this->emitIsConstantContext(IS))
5417*700637cbSDimitry Andric return false;
5418*700637cbSDimitry Andric } else if (IS->isNegatedConsteval()) {
5419*700637cbSDimitry Andric if (!this->emitIsConstantContext(IS))
5420*700637cbSDimitry Andric return false;
5421*700637cbSDimitry Andric if (!this->emitInv(IS))
5422*700637cbSDimitry Andric return false;
5423*700637cbSDimitry Andric } else {
5424*700637cbSDimitry Andric if (!this->visitBool(IS->getCond()))
5425*700637cbSDimitry Andric return false;
5426*700637cbSDimitry Andric }
5427*700637cbSDimitry Andric
5428*700637cbSDimitry Andric if (!this->maybeEmitDeferredVarInit(IS->getConditionVariable()))
5429*700637cbSDimitry Andric return false;
5430*700637cbSDimitry Andric
5431*700637cbSDimitry Andric if (const Stmt *Else = IS->getElse()) {
5432*700637cbSDimitry Andric LabelTy LabelElse = this->getLabel();
5433*700637cbSDimitry Andric LabelTy LabelEnd = this->getLabel();
5434*700637cbSDimitry Andric if (!this->jumpFalse(LabelElse))
5435*700637cbSDimitry Andric return false;
5436*700637cbSDimitry Andric if (!visitChildStmt(IS->getThen()))
5437*700637cbSDimitry Andric return false;
5438*700637cbSDimitry Andric if (!this->jump(LabelEnd))
5439*700637cbSDimitry Andric return false;
5440*700637cbSDimitry Andric this->emitLabel(LabelElse);
5441*700637cbSDimitry Andric if (!visitChildStmt(Else))
5442*700637cbSDimitry Andric return false;
5443*700637cbSDimitry Andric this->emitLabel(LabelEnd);
5444*700637cbSDimitry Andric } else {
5445*700637cbSDimitry Andric LabelTy LabelEnd = this->getLabel();
5446*700637cbSDimitry Andric if (!this->jumpFalse(LabelEnd))
5447*700637cbSDimitry Andric return false;
5448*700637cbSDimitry Andric if (!visitChildStmt(IS->getThen()))
5449*700637cbSDimitry Andric return false;
5450*700637cbSDimitry Andric this->emitLabel(LabelEnd);
5451*700637cbSDimitry Andric }
5452*700637cbSDimitry Andric
5453*700637cbSDimitry Andric return true;
5454*700637cbSDimitry Andric }
5455*700637cbSDimitry Andric
5456*700637cbSDimitry Andric template <class Emitter>
visitWhileStmt(const WhileStmt * S)5457*700637cbSDimitry Andric bool Compiler<Emitter>::visitWhileStmt(const WhileStmt *S) {
5458*700637cbSDimitry Andric const Expr *Cond = S->getCond();
5459*700637cbSDimitry Andric const Stmt *Body = S->getBody();
5460*700637cbSDimitry Andric
5461*700637cbSDimitry Andric LabelTy CondLabel = this->getLabel(); // Label before the condition.
5462*700637cbSDimitry Andric LabelTy EndLabel = this->getLabel(); // Label after the loop.
5463*700637cbSDimitry Andric LoopScope<Emitter> LS(this, EndLabel, CondLabel);
5464*700637cbSDimitry Andric
5465*700637cbSDimitry Andric this->fallthrough(CondLabel);
5466*700637cbSDimitry Andric this->emitLabel(CondLabel);
5467*700637cbSDimitry Andric
5468*700637cbSDimitry Andric {
5469*700637cbSDimitry Andric LocalScope<Emitter> CondScope(this);
5470*700637cbSDimitry Andric if (const DeclStmt *CondDecl = S->getConditionVariableDeclStmt())
5471*700637cbSDimitry Andric if (!visitDeclStmt(CondDecl))
5472*700637cbSDimitry Andric return false;
5473*700637cbSDimitry Andric
5474*700637cbSDimitry Andric if (!this->visitBool(Cond))
5475*700637cbSDimitry Andric return false;
5476*700637cbSDimitry Andric
5477*700637cbSDimitry Andric if (!this->maybeEmitDeferredVarInit(S->getConditionVariable()))
5478*700637cbSDimitry Andric return false;
5479*700637cbSDimitry Andric
5480*700637cbSDimitry Andric if (!this->jumpFalse(EndLabel))
5481*700637cbSDimitry Andric return false;
5482*700637cbSDimitry Andric
5483*700637cbSDimitry Andric if (!this->visitStmt(Body))
5484*700637cbSDimitry Andric return false;
5485*700637cbSDimitry Andric
5486*700637cbSDimitry Andric if (!CondScope.destroyLocals())
5487*700637cbSDimitry Andric return false;
5488*700637cbSDimitry Andric }
5489*700637cbSDimitry Andric if (!this->jump(CondLabel))
5490*700637cbSDimitry Andric return false;
5491*700637cbSDimitry Andric this->fallthrough(EndLabel);
5492*700637cbSDimitry Andric this->emitLabel(EndLabel);
5493*700637cbSDimitry Andric
5494*700637cbSDimitry Andric return true;
5495*700637cbSDimitry Andric }
5496*700637cbSDimitry Andric
visitDoStmt(const DoStmt * S)5497*700637cbSDimitry Andric template <class Emitter> bool Compiler<Emitter>::visitDoStmt(const DoStmt *S) {
5498*700637cbSDimitry Andric const Expr *Cond = S->getCond();
5499*700637cbSDimitry Andric const Stmt *Body = S->getBody();
5500*700637cbSDimitry Andric
5501*700637cbSDimitry Andric LabelTy StartLabel = this->getLabel();
5502*700637cbSDimitry Andric LabelTy EndLabel = this->getLabel();
5503*700637cbSDimitry Andric LabelTy CondLabel = this->getLabel();
5504*700637cbSDimitry Andric LoopScope<Emitter> LS(this, EndLabel, CondLabel);
5505*700637cbSDimitry Andric
5506*700637cbSDimitry Andric this->fallthrough(StartLabel);
5507*700637cbSDimitry Andric this->emitLabel(StartLabel);
5508*700637cbSDimitry Andric
5509*700637cbSDimitry Andric {
5510*700637cbSDimitry Andric LocalScope<Emitter> CondScope(this);
5511*700637cbSDimitry Andric if (!this->visitStmt(Body))
5512*700637cbSDimitry Andric return false;
5513*700637cbSDimitry Andric this->fallthrough(CondLabel);
5514*700637cbSDimitry Andric this->emitLabel(CondLabel);
5515*700637cbSDimitry Andric if (!this->visitBool(Cond))
5516*700637cbSDimitry Andric return false;
5517*700637cbSDimitry Andric
5518*700637cbSDimitry Andric if (!CondScope.destroyLocals())
5519*700637cbSDimitry Andric return false;
5520*700637cbSDimitry Andric }
5521*700637cbSDimitry Andric if (!this->jumpTrue(StartLabel))
5522*700637cbSDimitry Andric return false;
5523*700637cbSDimitry Andric
5524*700637cbSDimitry Andric this->fallthrough(EndLabel);
5525*700637cbSDimitry Andric this->emitLabel(EndLabel);
5526*700637cbSDimitry Andric return true;
5527*700637cbSDimitry Andric }
5528*700637cbSDimitry Andric
5529*700637cbSDimitry Andric template <class Emitter>
visitForStmt(const ForStmt * S)5530*700637cbSDimitry Andric bool Compiler<Emitter>::visitForStmt(const ForStmt *S) {
5531*700637cbSDimitry Andric // for (Init; Cond; Inc) { Body }
5532*700637cbSDimitry Andric const Stmt *Init = S->getInit();
5533*700637cbSDimitry Andric const Expr *Cond = S->getCond();
5534*700637cbSDimitry Andric const Expr *Inc = S->getInc();
5535*700637cbSDimitry Andric const Stmt *Body = S->getBody();
5536*700637cbSDimitry Andric
5537*700637cbSDimitry Andric LabelTy EndLabel = this->getLabel();
5538*700637cbSDimitry Andric LabelTy CondLabel = this->getLabel();
5539*700637cbSDimitry Andric LabelTy IncLabel = this->getLabel();
5540*700637cbSDimitry Andric LoopScope<Emitter> LS(this, EndLabel, IncLabel);
5541*700637cbSDimitry Andric
5542*700637cbSDimitry Andric if (Init && !this->visitStmt(Init))
5543*700637cbSDimitry Andric return false;
5544*700637cbSDimitry Andric
5545*700637cbSDimitry Andric this->fallthrough(CondLabel);
5546*700637cbSDimitry Andric this->emitLabel(CondLabel);
5547*700637cbSDimitry Andric
5548*700637cbSDimitry Andric // Start of loop body.
5549*700637cbSDimitry Andric LocalScope<Emitter> CondScope(this);
5550*700637cbSDimitry Andric if (const DeclStmt *CondDecl = S->getConditionVariableDeclStmt())
5551*700637cbSDimitry Andric if (!visitDeclStmt(CondDecl))
5552*700637cbSDimitry Andric return false;
5553*700637cbSDimitry Andric
5554*700637cbSDimitry Andric if (Cond) {
5555*700637cbSDimitry Andric if (!this->visitBool(Cond))
5556*700637cbSDimitry Andric return false;
5557*700637cbSDimitry Andric if (!this->jumpFalse(EndLabel))
5558*700637cbSDimitry Andric return false;
5559*700637cbSDimitry Andric }
5560*700637cbSDimitry Andric if (!this->maybeEmitDeferredVarInit(S->getConditionVariable()))
5561*700637cbSDimitry Andric return false;
5562*700637cbSDimitry Andric
5563*700637cbSDimitry Andric if (Body && !this->visitStmt(Body))
5564*700637cbSDimitry Andric return false;
5565*700637cbSDimitry Andric
5566*700637cbSDimitry Andric this->fallthrough(IncLabel);
5567*700637cbSDimitry Andric this->emitLabel(IncLabel);
5568*700637cbSDimitry Andric if (Inc && !this->discard(Inc))
5569*700637cbSDimitry Andric return false;
5570*700637cbSDimitry Andric
5571*700637cbSDimitry Andric if (!CondScope.destroyLocals())
5572*700637cbSDimitry Andric return false;
5573*700637cbSDimitry Andric if (!this->jump(CondLabel))
5574*700637cbSDimitry Andric return false;
5575*700637cbSDimitry Andric // End of loop body.
5576*700637cbSDimitry Andric
5577*700637cbSDimitry Andric this->emitLabel(EndLabel);
5578*700637cbSDimitry Andric // If we jumped out of the loop above, we still need to clean up the condition
5579*700637cbSDimitry Andric // scope.
5580*700637cbSDimitry Andric return CondScope.destroyLocals();
5581*700637cbSDimitry Andric }
5582*700637cbSDimitry Andric
5583*700637cbSDimitry Andric template <class Emitter>
visitCXXForRangeStmt(const CXXForRangeStmt * S)5584*700637cbSDimitry Andric bool Compiler<Emitter>::visitCXXForRangeStmt(const CXXForRangeStmt *S) {
5585*700637cbSDimitry Andric const Stmt *Init = S->getInit();
5586*700637cbSDimitry Andric const Expr *Cond = S->getCond();
5587*700637cbSDimitry Andric const Expr *Inc = S->getInc();
5588*700637cbSDimitry Andric const Stmt *Body = S->getBody();
5589*700637cbSDimitry Andric const Stmt *BeginStmt = S->getBeginStmt();
5590*700637cbSDimitry Andric const Stmt *RangeStmt = S->getRangeStmt();
5591*700637cbSDimitry Andric const Stmt *EndStmt = S->getEndStmt();
5592*700637cbSDimitry Andric
5593*700637cbSDimitry Andric LabelTy EndLabel = this->getLabel();
5594*700637cbSDimitry Andric LabelTy CondLabel = this->getLabel();
5595*700637cbSDimitry Andric LabelTy IncLabel = this->getLabel();
5596*700637cbSDimitry Andric LoopScope<Emitter> LS(this, EndLabel, IncLabel);
5597*700637cbSDimitry Andric
5598*700637cbSDimitry Andric // Emit declarations needed in the loop.
5599*700637cbSDimitry Andric if (Init && !this->visitStmt(Init))
5600*700637cbSDimitry Andric return false;
5601*700637cbSDimitry Andric if (!this->visitStmt(RangeStmt))
5602*700637cbSDimitry Andric return false;
5603*700637cbSDimitry Andric if (!this->visitStmt(BeginStmt))
5604*700637cbSDimitry Andric return false;
5605*700637cbSDimitry Andric if (!this->visitStmt(EndStmt))
5606*700637cbSDimitry Andric return false;
5607*700637cbSDimitry Andric
5608*700637cbSDimitry Andric // Now the condition as well as the loop variable assignment.
5609*700637cbSDimitry Andric this->fallthrough(CondLabel);
5610*700637cbSDimitry Andric this->emitLabel(CondLabel);
5611*700637cbSDimitry Andric if (!this->visitBool(Cond))
5612*700637cbSDimitry Andric return false;
5613*700637cbSDimitry Andric if (!this->jumpFalse(EndLabel))
5614*700637cbSDimitry Andric return false;
5615*700637cbSDimitry Andric
5616*700637cbSDimitry Andric if (!this->visitDeclStmt(S->getLoopVarStmt(), /*EvaluateConditionDecl=*/true))
5617*700637cbSDimitry Andric return false;
5618*700637cbSDimitry Andric
5619*700637cbSDimitry Andric // Body.
5620*700637cbSDimitry Andric {
5621*700637cbSDimitry Andric if (!this->visitStmt(Body))
5622*700637cbSDimitry Andric return false;
5623*700637cbSDimitry Andric
5624*700637cbSDimitry Andric this->fallthrough(IncLabel);
5625*700637cbSDimitry Andric this->emitLabel(IncLabel);
5626*700637cbSDimitry Andric if (!this->discard(Inc))
5627*700637cbSDimitry Andric return false;
5628*700637cbSDimitry Andric }
5629*700637cbSDimitry Andric
5630*700637cbSDimitry Andric if (!this->jump(CondLabel))
5631*700637cbSDimitry Andric return false;
5632*700637cbSDimitry Andric
5633*700637cbSDimitry Andric this->fallthrough(EndLabel);
5634*700637cbSDimitry Andric this->emitLabel(EndLabel);
5635*700637cbSDimitry Andric return true;
5636*700637cbSDimitry Andric }
5637*700637cbSDimitry Andric
5638*700637cbSDimitry Andric template <class Emitter>
visitBreakStmt(const BreakStmt * S)5639*700637cbSDimitry Andric bool Compiler<Emitter>::visitBreakStmt(const BreakStmt *S) {
5640*700637cbSDimitry Andric if (!BreakLabel)
5641*700637cbSDimitry Andric return false;
5642*700637cbSDimitry Andric
5643*700637cbSDimitry Andric for (VariableScope<Emitter> *C = VarScope; C != BreakVarScope;
5644*700637cbSDimitry Andric C = C->getParent())
5645*700637cbSDimitry Andric C->emitDestruction();
5646*700637cbSDimitry Andric return this->jump(*BreakLabel);
5647*700637cbSDimitry Andric }
5648*700637cbSDimitry Andric
5649*700637cbSDimitry Andric template <class Emitter>
visitContinueStmt(const ContinueStmt * S)5650*700637cbSDimitry Andric bool Compiler<Emitter>::visitContinueStmt(const ContinueStmt *S) {
5651*700637cbSDimitry Andric if (!ContinueLabel)
5652*700637cbSDimitry Andric return false;
5653*700637cbSDimitry Andric
5654*700637cbSDimitry Andric for (VariableScope<Emitter> *C = VarScope;
5655*700637cbSDimitry Andric C && C->getParent() != ContinueVarScope; C = C->getParent())
5656*700637cbSDimitry Andric C->emitDestruction();
5657*700637cbSDimitry Andric return this->jump(*ContinueLabel);
5658*700637cbSDimitry Andric }
5659*700637cbSDimitry Andric
5660*700637cbSDimitry Andric template <class Emitter>
visitSwitchStmt(const SwitchStmt * S)5661*700637cbSDimitry Andric bool Compiler<Emitter>::visitSwitchStmt(const SwitchStmt *S) {
5662*700637cbSDimitry Andric const Expr *Cond = S->getCond();
5663*700637cbSDimitry Andric if (Cond->containsErrors())
5664*700637cbSDimitry Andric return false;
5665*700637cbSDimitry Andric
5666*700637cbSDimitry Andric PrimType CondT = this->classifyPrim(Cond->getType());
5667*700637cbSDimitry Andric LocalScope<Emitter> LS(this);
5668*700637cbSDimitry Andric
5669*700637cbSDimitry Andric LabelTy EndLabel = this->getLabel();
5670*700637cbSDimitry Andric OptLabelTy DefaultLabel = std::nullopt;
5671*700637cbSDimitry Andric unsigned CondVar =
5672*700637cbSDimitry Andric this->allocateLocalPrimitive(Cond, CondT, /*IsConst=*/true);
5673*700637cbSDimitry Andric
5674*700637cbSDimitry Andric if (const auto *CondInit = S->getInit())
5675*700637cbSDimitry Andric if (!visitStmt(CondInit))
5676*700637cbSDimitry Andric return false;
5677*700637cbSDimitry Andric
5678*700637cbSDimitry Andric if (const DeclStmt *CondDecl = S->getConditionVariableDeclStmt())
5679*700637cbSDimitry Andric if (!visitDeclStmt(CondDecl))
5680*700637cbSDimitry Andric return false;
5681*700637cbSDimitry Andric
5682*700637cbSDimitry Andric // Initialize condition variable.
5683*700637cbSDimitry Andric if (!this->visit(Cond))
5684*700637cbSDimitry Andric return false;
5685*700637cbSDimitry Andric if (!this->emitSetLocal(CondT, CondVar, S))
5686*700637cbSDimitry Andric return false;
5687*700637cbSDimitry Andric
5688*700637cbSDimitry Andric if (!this->maybeEmitDeferredVarInit(S->getConditionVariable()))
5689*700637cbSDimitry Andric return false;
5690*700637cbSDimitry Andric
5691*700637cbSDimitry Andric CaseMap CaseLabels;
5692*700637cbSDimitry Andric // Create labels and comparison ops for all case statements.
5693*700637cbSDimitry Andric for (const SwitchCase *SC = S->getSwitchCaseList(); SC;
5694*700637cbSDimitry Andric SC = SC->getNextSwitchCase()) {
5695*700637cbSDimitry Andric if (const auto *CS = dyn_cast<CaseStmt>(SC)) {
5696*700637cbSDimitry Andric // FIXME: Implement ranges.
5697*700637cbSDimitry Andric if (CS->caseStmtIsGNURange())
5698*700637cbSDimitry Andric return false;
5699*700637cbSDimitry Andric CaseLabels[SC] = this->getLabel();
5700*700637cbSDimitry Andric
5701*700637cbSDimitry Andric const Expr *Value = CS->getLHS();
5702*700637cbSDimitry Andric PrimType ValueT = this->classifyPrim(Value->getType());
5703*700637cbSDimitry Andric
5704*700637cbSDimitry Andric // Compare the case statement's value to the switch condition.
5705*700637cbSDimitry Andric if (!this->emitGetLocal(CondT, CondVar, CS))
5706*700637cbSDimitry Andric return false;
5707*700637cbSDimitry Andric if (!this->visit(Value))
5708*700637cbSDimitry Andric return false;
5709*700637cbSDimitry Andric
5710*700637cbSDimitry Andric // Compare and jump to the case label.
5711*700637cbSDimitry Andric if (!this->emitEQ(ValueT, S))
5712*700637cbSDimitry Andric return false;
5713*700637cbSDimitry Andric if (!this->jumpTrue(CaseLabels[CS]))
5714*700637cbSDimitry Andric return false;
5715*700637cbSDimitry Andric } else {
5716*700637cbSDimitry Andric assert(!DefaultLabel);
5717*700637cbSDimitry Andric DefaultLabel = this->getLabel();
5718*700637cbSDimitry Andric }
5719*700637cbSDimitry Andric }
5720*700637cbSDimitry Andric
5721*700637cbSDimitry Andric // If none of the conditions above were true, fall through to the default
5722*700637cbSDimitry Andric // statement or jump after the switch statement.
5723*700637cbSDimitry Andric if (DefaultLabel) {
5724*700637cbSDimitry Andric if (!this->jump(*DefaultLabel))
5725*700637cbSDimitry Andric return false;
5726*700637cbSDimitry Andric } else {
5727*700637cbSDimitry Andric if (!this->jump(EndLabel))
5728*700637cbSDimitry Andric return false;
5729*700637cbSDimitry Andric }
5730*700637cbSDimitry Andric
5731*700637cbSDimitry Andric SwitchScope<Emitter> SS(this, std::move(CaseLabels), EndLabel, DefaultLabel);
5732*700637cbSDimitry Andric if (!this->visitStmt(S->getBody()))
5733*700637cbSDimitry Andric return false;
5734*700637cbSDimitry Andric this->emitLabel(EndLabel);
5735*700637cbSDimitry Andric
5736*700637cbSDimitry Andric return LS.destroyLocals();
5737*700637cbSDimitry Andric }
5738*700637cbSDimitry Andric
5739*700637cbSDimitry Andric template <class Emitter>
visitCaseStmt(const CaseStmt * S)5740*700637cbSDimitry Andric bool Compiler<Emitter>::visitCaseStmt(const CaseStmt *S) {
5741*700637cbSDimitry Andric this->emitLabel(CaseLabels[S]);
5742*700637cbSDimitry Andric return this->visitStmt(S->getSubStmt());
5743*700637cbSDimitry Andric }
5744*700637cbSDimitry Andric
5745*700637cbSDimitry Andric template <class Emitter>
visitDefaultStmt(const DefaultStmt * S)5746*700637cbSDimitry Andric bool Compiler<Emitter>::visitDefaultStmt(const DefaultStmt *S) {
5747*700637cbSDimitry Andric this->emitLabel(*DefaultLabel);
5748*700637cbSDimitry Andric return this->visitStmt(S->getSubStmt());
5749*700637cbSDimitry Andric }
5750*700637cbSDimitry Andric
5751*700637cbSDimitry Andric template <class Emitter>
visitAttributedStmt(const AttributedStmt * S)5752*700637cbSDimitry Andric bool Compiler<Emitter>::visitAttributedStmt(const AttributedStmt *S) {
5753*700637cbSDimitry Andric if (this->Ctx.getLangOpts().CXXAssumptions &&
5754*700637cbSDimitry Andric !this->Ctx.getLangOpts().MSVCCompat) {
5755*700637cbSDimitry Andric for (const Attr *A : S->getAttrs()) {
5756*700637cbSDimitry Andric auto *AA = dyn_cast<CXXAssumeAttr>(A);
5757*700637cbSDimitry Andric if (!AA)
5758*700637cbSDimitry Andric continue;
5759*700637cbSDimitry Andric
5760*700637cbSDimitry Andric assert(isa<NullStmt>(S->getSubStmt()));
5761*700637cbSDimitry Andric
5762*700637cbSDimitry Andric const Expr *Assumption = AA->getAssumption();
5763*700637cbSDimitry Andric if (Assumption->isValueDependent())
5764*700637cbSDimitry Andric return false;
5765*700637cbSDimitry Andric
5766*700637cbSDimitry Andric if (Assumption->HasSideEffects(this->Ctx.getASTContext()))
5767*700637cbSDimitry Andric continue;
5768*700637cbSDimitry Andric
5769*700637cbSDimitry Andric // Evaluate assumption.
5770*700637cbSDimitry Andric if (!this->visitBool(Assumption))
5771*700637cbSDimitry Andric return false;
5772*700637cbSDimitry Andric
5773*700637cbSDimitry Andric if (!this->emitAssume(Assumption))
5774*700637cbSDimitry Andric return false;
5775*700637cbSDimitry Andric }
5776*700637cbSDimitry Andric }
5777*700637cbSDimitry Andric
5778*700637cbSDimitry Andric // Ignore other attributes.
5779*700637cbSDimitry Andric return this->visitStmt(S->getSubStmt());
5780*700637cbSDimitry Andric }
5781*700637cbSDimitry Andric
5782*700637cbSDimitry Andric template <class Emitter>
visitCXXTryStmt(const CXXTryStmt * S)5783*700637cbSDimitry Andric bool Compiler<Emitter>::visitCXXTryStmt(const CXXTryStmt *S) {
5784*700637cbSDimitry Andric // Ignore all handlers.
5785*700637cbSDimitry Andric return this->visitStmt(S->getTryBlock());
5786*700637cbSDimitry Andric }
5787*700637cbSDimitry Andric
5788*700637cbSDimitry Andric template <class Emitter>
emitLambdaStaticInvokerBody(const CXXMethodDecl * MD)5789*700637cbSDimitry Andric bool Compiler<Emitter>::emitLambdaStaticInvokerBody(const CXXMethodDecl *MD) {
5790*700637cbSDimitry Andric assert(MD->isLambdaStaticInvoker());
5791*700637cbSDimitry Andric assert(MD->hasBody());
5792*700637cbSDimitry Andric assert(cast<CompoundStmt>(MD->getBody())->body_empty());
5793*700637cbSDimitry Andric
5794*700637cbSDimitry Andric const CXXRecordDecl *ClosureClass = MD->getParent();
5795*700637cbSDimitry Andric const CXXMethodDecl *LambdaCallOp = ClosureClass->getLambdaCallOperator();
5796*700637cbSDimitry Andric assert(ClosureClass->captures_begin() == ClosureClass->captures_end());
5797*700637cbSDimitry Andric const Function *Func = this->getFunction(LambdaCallOp);
5798*700637cbSDimitry Andric if (!Func)
5799*700637cbSDimitry Andric return false;
5800*700637cbSDimitry Andric assert(Func->hasThisPointer());
5801*700637cbSDimitry Andric assert(Func->getNumParams() == (MD->getNumParams() + 1 + Func->hasRVO()));
5802*700637cbSDimitry Andric
5803*700637cbSDimitry Andric if (Func->hasRVO()) {
5804*700637cbSDimitry Andric if (!this->emitRVOPtr(MD))
5805*700637cbSDimitry Andric return false;
5806*700637cbSDimitry Andric }
5807*700637cbSDimitry Andric
5808*700637cbSDimitry Andric // The lambda call operator needs an instance pointer, but we don't have
5809*700637cbSDimitry Andric // one here, and we don't need one either because the lambda cannot have
5810*700637cbSDimitry Andric // any captures, as verified above. Emit a null pointer. This is then
5811*700637cbSDimitry Andric // special-cased when interpreting to not emit any misleading diagnostics.
5812*700637cbSDimitry Andric if (!this->emitNullPtr(0, nullptr, MD))
5813*700637cbSDimitry Andric return false;
5814*700637cbSDimitry Andric
5815*700637cbSDimitry Andric // Forward all arguments from the static invoker to the lambda call operator.
5816*700637cbSDimitry Andric for (const ParmVarDecl *PVD : MD->parameters()) {
5817*700637cbSDimitry Andric auto It = this->Params.find(PVD);
5818*700637cbSDimitry Andric assert(It != this->Params.end());
5819*700637cbSDimitry Andric
5820*700637cbSDimitry Andric // We do the lvalue-to-rvalue conversion manually here, so no need
5821*700637cbSDimitry Andric // to care about references.
5822*700637cbSDimitry Andric PrimType ParamType = this->classify(PVD->getType()).value_or(PT_Ptr);
5823*700637cbSDimitry Andric if (!this->emitGetParam(ParamType, It->second.Offset, MD))
5824*700637cbSDimitry Andric return false;
5825*700637cbSDimitry Andric }
5826*700637cbSDimitry Andric
5827*700637cbSDimitry Andric if (!this->emitCall(Func, 0, LambdaCallOp))
5828*700637cbSDimitry Andric return false;
5829*700637cbSDimitry Andric
5830*700637cbSDimitry Andric this->emitCleanup();
5831*700637cbSDimitry Andric if (ReturnType)
5832*700637cbSDimitry Andric return this->emitRet(*ReturnType, MD);
5833*700637cbSDimitry Andric
5834*700637cbSDimitry Andric // Nothing to do, since we emitted the RVO pointer above.
5835*700637cbSDimitry Andric return this->emitRetVoid(MD);
5836*700637cbSDimitry Andric }
5837*700637cbSDimitry Andric
5838*700637cbSDimitry Andric template <class Emitter>
checkLiteralType(const Expr * E)5839*700637cbSDimitry Andric bool Compiler<Emitter>::checkLiteralType(const Expr *E) {
5840*700637cbSDimitry Andric if (Ctx.getLangOpts().CPlusPlus23)
5841*700637cbSDimitry Andric return true;
5842*700637cbSDimitry Andric
5843*700637cbSDimitry Andric if (!E->isPRValue() || E->getType()->isLiteralType(Ctx.getASTContext()))
5844*700637cbSDimitry Andric return true;
5845*700637cbSDimitry Andric
5846*700637cbSDimitry Andric return this->emitCheckLiteralType(E->getType().getTypePtr(), E);
5847*700637cbSDimitry Andric }
5848*700637cbSDimitry Andric
5849*700637cbSDimitry Andric template <class Emitter>
compileConstructor(const CXXConstructorDecl * Ctor)5850*700637cbSDimitry Andric bool Compiler<Emitter>::compileConstructor(const CXXConstructorDecl *Ctor) {
5851*700637cbSDimitry Andric assert(!ReturnType);
5852*700637cbSDimitry Andric
5853*700637cbSDimitry Andric auto emitFieldInitializer = [&](const Record::Field *F, unsigned FieldOffset,
5854*700637cbSDimitry Andric const Expr *InitExpr) -> bool {
5855*700637cbSDimitry Andric // We don't know what to do with these, so just return false.
5856*700637cbSDimitry Andric if (InitExpr->getType().isNull())
5857*700637cbSDimitry Andric return false;
5858*700637cbSDimitry Andric
5859*700637cbSDimitry Andric if (std::optional<PrimType> T = this->classify(InitExpr)) {
5860*700637cbSDimitry Andric if (!this->visit(InitExpr))
5861*700637cbSDimitry Andric return false;
5862*700637cbSDimitry Andric
5863*700637cbSDimitry Andric if (F->isBitField())
5864*700637cbSDimitry Andric return this->emitInitThisBitField(*T, F, FieldOffset, InitExpr);
5865*700637cbSDimitry Andric return this->emitInitThisField(*T, FieldOffset, InitExpr);
5866*700637cbSDimitry Andric }
5867*700637cbSDimitry Andric // Non-primitive case. Get a pointer to the field-to-initialize
5868*700637cbSDimitry Andric // on the stack and call visitInitialzer() for it.
5869*700637cbSDimitry Andric InitLinkScope<Emitter> FieldScope(this, InitLink::Field(F->Offset));
5870*700637cbSDimitry Andric if (!this->emitGetPtrThisField(FieldOffset, InitExpr))
5871*700637cbSDimitry Andric return false;
5872*700637cbSDimitry Andric
5873*700637cbSDimitry Andric if (!this->visitInitializer(InitExpr))
5874*700637cbSDimitry Andric return false;
5875*700637cbSDimitry Andric
5876*700637cbSDimitry Andric return this->emitFinishInitPop(InitExpr);
5877*700637cbSDimitry Andric };
5878*700637cbSDimitry Andric
5879*700637cbSDimitry Andric const RecordDecl *RD = Ctor->getParent();
5880*700637cbSDimitry Andric const Record *R = this->getRecord(RD);
5881*700637cbSDimitry Andric if (!R)
5882*700637cbSDimitry Andric return false;
5883*700637cbSDimitry Andric
5884*700637cbSDimitry Andric if (R->isUnion() && Ctor->isCopyOrMoveConstructor()) {
5885*700637cbSDimitry Andric if (R->getNumFields() == 0)
5886*700637cbSDimitry Andric return this->emitRetVoid(Ctor);
5887*700637cbSDimitry Andric // union copy and move ctors are special.
5888*700637cbSDimitry Andric assert(cast<CompoundStmt>(Ctor->getBody())->body_empty());
5889*700637cbSDimitry Andric if (!this->emitThis(Ctor))
5890*700637cbSDimitry Andric return false;
5891*700637cbSDimitry Andric
5892*700637cbSDimitry Andric auto PVD = Ctor->getParamDecl(0);
5893*700637cbSDimitry Andric ParamOffset PO = this->Params[PVD]; // Must exist.
5894*700637cbSDimitry Andric
5895*700637cbSDimitry Andric if (!this->emitGetParam(PT_Ptr, PO.Offset, Ctor))
5896*700637cbSDimitry Andric return false;
5897*700637cbSDimitry Andric
5898*700637cbSDimitry Andric return this->emitMemcpy(Ctor) && this->emitPopPtr(Ctor) &&
5899*700637cbSDimitry Andric this->emitRetVoid(Ctor);
5900*700637cbSDimitry Andric }
5901*700637cbSDimitry Andric
5902*700637cbSDimitry Andric InitLinkScope<Emitter> InitScope(this, InitLink::This());
5903*700637cbSDimitry Andric for (const auto *Init : Ctor->inits()) {
5904*700637cbSDimitry Andric // Scope needed for the initializers.
5905*700637cbSDimitry Andric BlockScope<Emitter> Scope(this);
5906*700637cbSDimitry Andric
5907*700637cbSDimitry Andric const Expr *InitExpr = Init->getInit();
5908*700637cbSDimitry Andric if (const FieldDecl *Member = Init->getMember()) {
5909*700637cbSDimitry Andric const Record::Field *F = R->getField(Member);
5910*700637cbSDimitry Andric
5911*700637cbSDimitry Andric if (!emitFieldInitializer(F, F->Offset, InitExpr))
5912*700637cbSDimitry Andric return false;
5913*700637cbSDimitry Andric } else if (const Type *Base = Init->getBaseClass()) {
5914*700637cbSDimitry Andric const auto *BaseDecl = Base->getAsCXXRecordDecl();
5915*700637cbSDimitry Andric assert(BaseDecl);
5916*700637cbSDimitry Andric
5917*700637cbSDimitry Andric if (Init->isBaseVirtual()) {
5918*700637cbSDimitry Andric assert(R->getVirtualBase(BaseDecl));
5919*700637cbSDimitry Andric if (!this->emitGetPtrThisVirtBase(BaseDecl, InitExpr))
5920*700637cbSDimitry Andric return false;
5921*700637cbSDimitry Andric
5922*700637cbSDimitry Andric } else {
5923*700637cbSDimitry Andric // Base class initializer.
5924*700637cbSDimitry Andric // Get This Base and call initializer on it.
5925*700637cbSDimitry Andric const Record::Base *B = R->getBase(BaseDecl);
5926*700637cbSDimitry Andric assert(B);
5927*700637cbSDimitry Andric if (!this->emitGetPtrThisBase(B->Offset, InitExpr))
5928*700637cbSDimitry Andric return false;
5929*700637cbSDimitry Andric }
5930*700637cbSDimitry Andric
5931*700637cbSDimitry Andric if (!this->visitInitializer(InitExpr))
5932*700637cbSDimitry Andric return false;
5933*700637cbSDimitry Andric if (!this->emitFinishInitPop(InitExpr))
5934*700637cbSDimitry Andric return false;
5935*700637cbSDimitry Andric } else if (const IndirectFieldDecl *IFD = Init->getIndirectMember()) {
5936*700637cbSDimitry Andric assert(IFD->getChainingSize() >= 2);
5937*700637cbSDimitry Andric
5938*700637cbSDimitry Andric unsigned NestedFieldOffset = 0;
5939*700637cbSDimitry Andric const Record::Field *NestedField = nullptr;
5940*700637cbSDimitry Andric for (const NamedDecl *ND : IFD->chain()) {
5941*700637cbSDimitry Andric const auto *FD = cast<FieldDecl>(ND);
5942*700637cbSDimitry Andric const Record *FieldRecord = this->P.getOrCreateRecord(FD->getParent());
5943*700637cbSDimitry Andric assert(FieldRecord);
5944*700637cbSDimitry Andric
5945*700637cbSDimitry Andric NestedField = FieldRecord->getField(FD);
5946*700637cbSDimitry Andric assert(NestedField);
5947*700637cbSDimitry Andric
5948*700637cbSDimitry Andric NestedFieldOffset += NestedField->Offset;
5949*700637cbSDimitry Andric }
5950*700637cbSDimitry Andric assert(NestedField);
5951*700637cbSDimitry Andric
5952*700637cbSDimitry Andric if (!emitFieldInitializer(NestedField, NestedFieldOffset, InitExpr))
5953*700637cbSDimitry Andric return false;
5954*700637cbSDimitry Andric
5955*700637cbSDimitry Andric // Mark all chain links as initialized.
5956*700637cbSDimitry Andric unsigned InitFieldOffset = 0;
5957*700637cbSDimitry Andric for (const NamedDecl *ND : IFD->chain().drop_back()) {
5958*700637cbSDimitry Andric const auto *FD = cast<FieldDecl>(ND);
5959*700637cbSDimitry Andric const Record *FieldRecord = this->P.getOrCreateRecord(FD->getParent());
5960*700637cbSDimitry Andric assert(FieldRecord);
5961*700637cbSDimitry Andric NestedField = FieldRecord->getField(FD);
5962*700637cbSDimitry Andric InitFieldOffset += NestedField->Offset;
5963*700637cbSDimitry Andric assert(NestedField);
5964*700637cbSDimitry Andric if (!this->emitGetPtrThisField(InitFieldOffset, InitExpr))
5965*700637cbSDimitry Andric return false;
5966*700637cbSDimitry Andric if (!this->emitFinishInitPop(InitExpr))
5967*700637cbSDimitry Andric return false;
5968*700637cbSDimitry Andric }
5969*700637cbSDimitry Andric
5970*700637cbSDimitry Andric } else {
5971*700637cbSDimitry Andric assert(Init->isDelegatingInitializer());
5972*700637cbSDimitry Andric if (!this->emitThis(InitExpr))
5973*700637cbSDimitry Andric return false;
5974*700637cbSDimitry Andric if (!this->visitInitializer(Init->getInit()))
5975*700637cbSDimitry Andric return false;
5976*700637cbSDimitry Andric if (!this->emitPopPtr(InitExpr))
5977*700637cbSDimitry Andric return false;
5978*700637cbSDimitry Andric }
5979*700637cbSDimitry Andric
5980*700637cbSDimitry Andric if (!Scope.destroyLocals())
5981*700637cbSDimitry Andric return false;
5982*700637cbSDimitry Andric }
5983*700637cbSDimitry Andric
5984*700637cbSDimitry Andric if (const auto *Body = Ctor->getBody())
5985*700637cbSDimitry Andric if (!visitStmt(Body))
5986*700637cbSDimitry Andric return false;
5987*700637cbSDimitry Andric
5988*700637cbSDimitry Andric return this->emitRetVoid(SourceInfo{});
5989*700637cbSDimitry Andric }
5990*700637cbSDimitry Andric
5991*700637cbSDimitry Andric template <class Emitter>
compileDestructor(const CXXDestructorDecl * Dtor)5992*700637cbSDimitry Andric bool Compiler<Emitter>::compileDestructor(const CXXDestructorDecl *Dtor) {
5993*700637cbSDimitry Andric const RecordDecl *RD = Dtor->getParent();
5994*700637cbSDimitry Andric const Record *R = this->getRecord(RD);
5995*700637cbSDimitry Andric if (!R)
5996*700637cbSDimitry Andric return false;
5997*700637cbSDimitry Andric
5998*700637cbSDimitry Andric if (!Dtor->isTrivial() && Dtor->getBody()) {
5999*700637cbSDimitry Andric if (!this->visitStmt(Dtor->getBody()))
6000*700637cbSDimitry Andric return false;
6001*700637cbSDimitry Andric }
6002*700637cbSDimitry Andric
6003*700637cbSDimitry Andric if (!this->emitThis(Dtor))
6004*700637cbSDimitry Andric return false;
6005*700637cbSDimitry Andric
6006*700637cbSDimitry Andric if (!this->emitCheckDestruction(Dtor))
6007*700637cbSDimitry Andric return false;
6008*700637cbSDimitry Andric
6009*700637cbSDimitry Andric assert(R);
6010*700637cbSDimitry Andric if (!R->isUnion()) {
6011*700637cbSDimitry Andric // First, destroy all fields.
6012*700637cbSDimitry Andric for (const Record::Field &Field : llvm::reverse(R->fields())) {
6013*700637cbSDimitry Andric const Descriptor *D = Field.Desc;
6014*700637cbSDimitry Andric if (!D->isPrimitive() && !D->isPrimitiveArray()) {
6015*700637cbSDimitry Andric if (!this->emitGetPtrField(Field.Offset, SourceInfo{}))
6016*700637cbSDimitry Andric return false;
6017*700637cbSDimitry Andric if (!this->emitDestruction(D, SourceInfo{}))
6018*700637cbSDimitry Andric return false;
6019*700637cbSDimitry Andric if (!this->emitPopPtr(SourceInfo{}))
6020*700637cbSDimitry Andric return false;
6021*700637cbSDimitry Andric }
6022*700637cbSDimitry Andric }
6023*700637cbSDimitry Andric }
6024*700637cbSDimitry Andric
6025*700637cbSDimitry Andric for (const Record::Base &Base : llvm::reverse(R->bases())) {
6026*700637cbSDimitry Andric if (Base.R->isAnonymousUnion())
6027*700637cbSDimitry Andric continue;
6028*700637cbSDimitry Andric
6029*700637cbSDimitry Andric if (!this->emitGetPtrBase(Base.Offset, SourceInfo{}))
6030*700637cbSDimitry Andric return false;
6031*700637cbSDimitry Andric if (!this->emitRecordDestruction(Base.R, {}))
6032*700637cbSDimitry Andric return false;
6033*700637cbSDimitry Andric if (!this->emitPopPtr(SourceInfo{}))
6034*700637cbSDimitry Andric return false;
6035*700637cbSDimitry Andric }
6036*700637cbSDimitry Andric
6037*700637cbSDimitry Andric // FIXME: Virtual bases.
6038*700637cbSDimitry Andric return this->emitPopPtr(Dtor) && this->emitRetVoid(Dtor);
6039*700637cbSDimitry Andric }
6040*700637cbSDimitry Andric
6041*700637cbSDimitry Andric template <class Emitter>
compileUnionAssignmentOperator(const CXXMethodDecl * MD)6042*700637cbSDimitry Andric bool Compiler<Emitter>::compileUnionAssignmentOperator(
6043*700637cbSDimitry Andric const CXXMethodDecl *MD) {
6044*700637cbSDimitry Andric if (!this->emitThis(MD))
6045*700637cbSDimitry Andric return false;
6046*700637cbSDimitry Andric
6047*700637cbSDimitry Andric auto PVD = MD->getParamDecl(0);
6048*700637cbSDimitry Andric ParamOffset PO = this->Params[PVD]; // Must exist.
6049*700637cbSDimitry Andric
6050*700637cbSDimitry Andric if (!this->emitGetParam(PT_Ptr, PO.Offset, MD))
6051*700637cbSDimitry Andric return false;
6052*700637cbSDimitry Andric
6053*700637cbSDimitry Andric return this->emitMemcpy(MD) && this->emitRet(PT_Ptr, MD);
6054*700637cbSDimitry Andric }
6055*700637cbSDimitry Andric
6056*700637cbSDimitry Andric template <class Emitter>
visitFunc(const FunctionDecl * F)6057*700637cbSDimitry Andric bool Compiler<Emitter>::visitFunc(const FunctionDecl *F) {
6058*700637cbSDimitry Andric // Classify the return type.
6059*700637cbSDimitry Andric ReturnType = this->classify(F->getReturnType());
6060*700637cbSDimitry Andric
6061*700637cbSDimitry Andric this->CompilingFunction = F;
6062*700637cbSDimitry Andric
6063*700637cbSDimitry Andric if (const auto *Ctor = dyn_cast<CXXConstructorDecl>(F))
6064*700637cbSDimitry Andric return this->compileConstructor(Ctor);
6065*700637cbSDimitry Andric if (const auto *Dtor = dyn_cast<CXXDestructorDecl>(F))
6066*700637cbSDimitry Andric return this->compileDestructor(Dtor);
6067*700637cbSDimitry Andric
6068*700637cbSDimitry Andric // Emit custom code if this is a lambda static invoker.
6069*700637cbSDimitry Andric if (const auto *MD = dyn_cast<CXXMethodDecl>(F)) {
6070*700637cbSDimitry Andric const RecordDecl *RD = MD->getParent();
6071*700637cbSDimitry Andric
6072*700637cbSDimitry Andric if (RD->isUnion() &&
6073*700637cbSDimitry Andric (MD->isCopyAssignmentOperator() || MD->isMoveAssignmentOperator()))
6074*700637cbSDimitry Andric return this->compileUnionAssignmentOperator(MD);
6075*700637cbSDimitry Andric
6076*700637cbSDimitry Andric if (MD->isLambdaStaticInvoker())
6077*700637cbSDimitry Andric return this->emitLambdaStaticInvokerBody(MD);
6078*700637cbSDimitry Andric }
6079*700637cbSDimitry Andric
6080*700637cbSDimitry Andric // Regular functions.
6081*700637cbSDimitry Andric if (const auto *Body = F->getBody())
6082*700637cbSDimitry Andric if (!visitStmt(Body))
6083*700637cbSDimitry Andric return false;
6084*700637cbSDimitry Andric
6085*700637cbSDimitry Andric // Emit a guard return to protect against a code path missing one.
6086*700637cbSDimitry Andric if (F->getReturnType()->isVoidType())
6087*700637cbSDimitry Andric return this->emitRetVoid(SourceInfo{});
6088*700637cbSDimitry Andric return this->emitNoRet(SourceInfo{});
6089*700637cbSDimitry Andric }
6090*700637cbSDimitry Andric
6091*700637cbSDimitry Andric template <class Emitter>
VisitUnaryOperator(const UnaryOperator * E)6092*700637cbSDimitry Andric bool Compiler<Emitter>::VisitUnaryOperator(const UnaryOperator *E) {
6093*700637cbSDimitry Andric const Expr *SubExpr = E->getSubExpr();
6094*700637cbSDimitry Andric if (SubExpr->getType()->isAnyComplexType())
6095*700637cbSDimitry Andric return this->VisitComplexUnaryOperator(E);
6096*700637cbSDimitry Andric if (SubExpr->getType()->isVectorType())
6097*700637cbSDimitry Andric return this->VisitVectorUnaryOperator(E);
6098*700637cbSDimitry Andric if (SubExpr->getType()->isFixedPointType())
6099*700637cbSDimitry Andric return this->VisitFixedPointUnaryOperator(E);
6100*700637cbSDimitry Andric std::optional<PrimType> T = classify(SubExpr->getType());
6101*700637cbSDimitry Andric
6102*700637cbSDimitry Andric switch (E->getOpcode()) {
6103*700637cbSDimitry Andric case UO_PostInc: { // x++
6104*700637cbSDimitry Andric if (!Ctx.getLangOpts().CPlusPlus14)
6105*700637cbSDimitry Andric return this->emitInvalid(E);
6106*700637cbSDimitry Andric if (!T)
6107*700637cbSDimitry Andric return this->emitError(E);
6108*700637cbSDimitry Andric
6109*700637cbSDimitry Andric if (!this->visit(SubExpr))
6110*700637cbSDimitry Andric return false;
6111*700637cbSDimitry Andric
6112*700637cbSDimitry Andric if (T == PT_Ptr) {
6113*700637cbSDimitry Andric if (!this->emitIncPtr(E))
6114*700637cbSDimitry Andric return false;
6115*700637cbSDimitry Andric
6116*700637cbSDimitry Andric return DiscardResult ? this->emitPopPtr(E) : true;
6117*700637cbSDimitry Andric }
6118*700637cbSDimitry Andric
6119*700637cbSDimitry Andric if (T == PT_Float) {
6120*700637cbSDimitry Andric return DiscardResult ? this->emitIncfPop(getFPOptions(E), E)
6121*700637cbSDimitry Andric : this->emitIncf(getFPOptions(E), E);
6122*700637cbSDimitry Andric }
6123*700637cbSDimitry Andric
6124*700637cbSDimitry Andric return DiscardResult ? this->emitIncPop(*T, E->canOverflow(), E)
6125*700637cbSDimitry Andric : this->emitInc(*T, E->canOverflow(), E);
6126*700637cbSDimitry Andric }
6127*700637cbSDimitry Andric case UO_PostDec: { // x--
6128*700637cbSDimitry Andric if (!Ctx.getLangOpts().CPlusPlus14)
6129*700637cbSDimitry Andric return this->emitInvalid(E);
6130*700637cbSDimitry Andric if (!T)
6131*700637cbSDimitry Andric return this->emitError(E);
6132*700637cbSDimitry Andric
6133*700637cbSDimitry Andric if (!this->visit(SubExpr))
6134*700637cbSDimitry Andric return false;
6135*700637cbSDimitry Andric
6136*700637cbSDimitry Andric if (T == PT_Ptr) {
6137*700637cbSDimitry Andric if (!this->emitDecPtr(E))
6138*700637cbSDimitry Andric return false;
6139*700637cbSDimitry Andric
6140*700637cbSDimitry Andric return DiscardResult ? this->emitPopPtr(E) : true;
6141*700637cbSDimitry Andric }
6142*700637cbSDimitry Andric
6143*700637cbSDimitry Andric if (T == PT_Float) {
6144*700637cbSDimitry Andric return DiscardResult ? this->emitDecfPop(getFPOptions(E), E)
6145*700637cbSDimitry Andric : this->emitDecf(getFPOptions(E), E);
6146*700637cbSDimitry Andric }
6147*700637cbSDimitry Andric
6148*700637cbSDimitry Andric return DiscardResult ? this->emitDecPop(*T, E->canOverflow(), E)
6149*700637cbSDimitry Andric : this->emitDec(*T, E->canOverflow(), E);
6150*700637cbSDimitry Andric }
6151*700637cbSDimitry Andric case UO_PreInc: { // ++x
6152*700637cbSDimitry Andric if (!Ctx.getLangOpts().CPlusPlus14)
6153*700637cbSDimitry Andric return this->emitInvalid(E);
6154*700637cbSDimitry Andric if (!T)
6155*700637cbSDimitry Andric return this->emitError(E);
6156*700637cbSDimitry Andric
6157*700637cbSDimitry Andric if (!this->visit(SubExpr))
6158*700637cbSDimitry Andric return false;
6159*700637cbSDimitry Andric
6160*700637cbSDimitry Andric if (T == PT_Ptr) {
6161*700637cbSDimitry Andric if (!this->emitLoadPtr(E))
6162*700637cbSDimitry Andric return false;
6163*700637cbSDimitry Andric if (!this->emitConstUint8(1, E))
6164*700637cbSDimitry Andric return false;
6165*700637cbSDimitry Andric if (!this->emitAddOffsetUint8(E))
6166*700637cbSDimitry Andric return false;
6167*700637cbSDimitry Andric return DiscardResult ? this->emitStorePopPtr(E) : this->emitStorePtr(E);
6168*700637cbSDimitry Andric }
6169*700637cbSDimitry Andric
6170*700637cbSDimitry Andric // Post-inc and pre-inc are the same if the value is to be discarded.
6171*700637cbSDimitry Andric if (DiscardResult) {
6172*700637cbSDimitry Andric if (T == PT_Float)
6173*700637cbSDimitry Andric return this->emitIncfPop(getFPOptions(E), E);
6174*700637cbSDimitry Andric return this->emitIncPop(*T, E->canOverflow(), E);
6175*700637cbSDimitry Andric }
6176*700637cbSDimitry Andric
6177*700637cbSDimitry Andric if (T == PT_Float) {
6178*700637cbSDimitry Andric const auto &TargetSemantics = Ctx.getFloatSemantics(E->getType());
6179*700637cbSDimitry Andric if (!this->emitLoadFloat(E))
6180*700637cbSDimitry Andric return false;
6181*700637cbSDimitry Andric APFloat F(TargetSemantics, 1);
6182*700637cbSDimitry Andric if (!this->emitFloat(F, E))
6183*700637cbSDimitry Andric return false;
6184*700637cbSDimitry Andric
6185*700637cbSDimitry Andric if (!this->emitAddf(getFPOptions(E), E))
6186*700637cbSDimitry Andric return false;
6187*700637cbSDimitry Andric if (!this->emitStoreFloat(E))
6188*700637cbSDimitry Andric return false;
6189*700637cbSDimitry Andric } else {
6190*700637cbSDimitry Andric assert(isIntegralType(*T));
6191*700637cbSDimitry Andric if (!this->emitPreInc(*T, E->canOverflow(), E))
6192*700637cbSDimitry Andric return false;
6193*700637cbSDimitry Andric }
6194*700637cbSDimitry Andric return E->isGLValue() || this->emitLoadPop(*T, E);
6195*700637cbSDimitry Andric }
6196*700637cbSDimitry Andric case UO_PreDec: { // --x
6197*700637cbSDimitry Andric if (!Ctx.getLangOpts().CPlusPlus14)
6198*700637cbSDimitry Andric return this->emitInvalid(E);
6199*700637cbSDimitry Andric if (!T)
6200*700637cbSDimitry Andric return this->emitError(E);
6201*700637cbSDimitry Andric
6202*700637cbSDimitry Andric if (!this->visit(SubExpr))
6203*700637cbSDimitry Andric return false;
6204*700637cbSDimitry Andric
6205*700637cbSDimitry Andric if (T == PT_Ptr) {
6206*700637cbSDimitry Andric if (!this->emitLoadPtr(E))
6207*700637cbSDimitry Andric return false;
6208*700637cbSDimitry Andric if (!this->emitConstUint8(1, E))
6209*700637cbSDimitry Andric return false;
6210*700637cbSDimitry Andric if (!this->emitSubOffsetUint8(E))
6211*700637cbSDimitry Andric return false;
6212*700637cbSDimitry Andric return DiscardResult ? this->emitStorePopPtr(E) : this->emitStorePtr(E);
6213*700637cbSDimitry Andric }
6214*700637cbSDimitry Andric
6215*700637cbSDimitry Andric // Post-dec and pre-dec are the same if the value is to be discarded.
6216*700637cbSDimitry Andric if (DiscardResult) {
6217*700637cbSDimitry Andric if (T == PT_Float)
6218*700637cbSDimitry Andric return this->emitDecfPop(getFPOptions(E), E);
6219*700637cbSDimitry Andric return this->emitDecPop(*T, E->canOverflow(), E);
6220*700637cbSDimitry Andric }
6221*700637cbSDimitry Andric
6222*700637cbSDimitry Andric if (T == PT_Float) {
6223*700637cbSDimitry Andric const auto &TargetSemantics = Ctx.getFloatSemantics(E->getType());
6224*700637cbSDimitry Andric if (!this->emitLoadFloat(E))
6225*700637cbSDimitry Andric return false;
6226*700637cbSDimitry Andric APFloat F(TargetSemantics, 1);
6227*700637cbSDimitry Andric if (!this->emitFloat(F, E))
6228*700637cbSDimitry Andric return false;
6229*700637cbSDimitry Andric
6230*700637cbSDimitry Andric if (!this->emitSubf(getFPOptions(E), E))
6231*700637cbSDimitry Andric return false;
6232*700637cbSDimitry Andric if (!this->emitStoreFloat(E))
6233*700637cbSDimitry Andric return false;
6234*700637cbSDimitry Andric } else {
6235*700637cbSDimitry Andric assert(isIntegralType(*T));
6236*700637cbSDimitry Andric if (!this->emitPreDec(*T, E->canOverflow(), E))
6237*700637cbSDimitry Andric return false;
6238*700637cbSDimitry Andric }
6239*700637cbSDimitry Andric return E->isGLValue() || this->emitLoadPop(*T, E);
6240*700637cbSDimitry Andric }
6241*700637cbSDimitry Andric case UO_LNot: // !x
6242*700637cbSDimitry Andric if (!T)
6243*700637cbSDimitry Andric return this->emitError(E);
6244*700637cbSDimitry Andric
6245*700637cbSDimitry Andric if (DiscardResult)
6246*700637cbSDimitry Andric return this->discard(SubExpr);
6247*700637cbSDimitry Andric
6248*700637cbSDimitry Andric if (!this->visitBool(SubExpr))
6249*700637cbSDimitry Andric return false;
6250*700637cbSDimitry Andric
6251*700637cbSDimitry Andric if (!this->emitInv(E))
6252*700637cbSDimitry Andric return false;
6253*700637cbSDimitry Andric
6254*700637cbSDimitry Andric if (PrimType ET = classifyPrim(E->getType()); ET != PT_Bool)
6255*700637cbSDimitry Andric return this->emitCast(PT_Bool, ET, E);
6256*700637cbSDimitry Andric return true;
6257*700637cbSDimitry Andric case UO_Minus: // -x
6258*700637cbSDimitry Andric if (!T)
6259*700637cbSDimitry Andric return this->emitError(E);
6260*700637cbSDimitry Andric
6261*700637cbSDimitry Andric if (!this->visit(SubExpr))
6262*700637cbSDimitry Andric return false;
6263*700637cbSDimitry Andric return DiscardResult ? this->emitPop(*T, E) : this->emitNeg(*T, E);
6264*700637cbSDimitry Andric case UO_Plus: // +x
6265*700637cbSDimitry Andric if (!T)
6266*700637cbSDimitry Andric return this->emitError(E);
6267*700637cbSDimitry Andric
6268*700637cbSDimitry Andric if (!this->visit(SubExpr)) // noop
6269*700637cbSDimitry Andric return false;
6270*700637cbSDimitry Andric return DiscardResult ? this->emitPop(*T, E) : true;
6271*700637cbSDimitry Andric case UO_AddrOf: // &x
6272*700637cbSDimitry Andric if (E->getType()->isMemberPointerType()) {
6273*700637cbSDimitry Andric // C++11 [expr.unary.op]p3 has very strict rules on how the address of a
6274*700637cbSDimitry Andric // member can be formed.
6275*700637cbSDimitry Andric return this->emitGetMemberPtr(cast<DeclRefExpr>(SubExpr)->getDecl(), E);
6276*700637cbSDimitry Andric }
6277*700637cbSDimitry Andric // We should already have a pointer when we get here.
6278*700637cbSDimitry Andric return this->delegate(SubExpr);
6279*700637cbSDimitry Andric case UO_Deref: // *x
6280*700637cbSDimitry Andric if (DiscardResult)
6281*700637cbSDimitry Andric return this->discard(SubExpr);
6282*700637cbSDimitry Andric
6283*700637cbSDimitry Andric if (!this->visit(SubExpr))
6284*700637cbSDimitry Andric return false;
6285*700637cbSDimitry Andric
6286*700637cbSDimitry Andric if (classifyPrim(SubExpr) == PT_Ptr)
6287*700637cbSDimitry Andric return this->emitNarrowPtr(E);
6288*700637cbSDimitry Andric return true;
6289*700637cbSDimitry Andric
6290*700637cbSDimitry Andric case UO_Not: // ~x
6291*700637cbSDimitry Andric if (!T)
6292*700637cbSDimitry Andric return this->emitError(E);
6293*700637cbSDimitry Andric
6294*700637cbSDimitry Andric if (!this->visit(SubExpr))
6295*700637cbSDimitry Andric return false;
6296*700637cbSDimitry Andric return DiscardResult ? this->emitPop(*T, E) : this->emitComp(*T, E);
6297*700637cbSDimitry Andric case UO_Real: // __real x
6298*700637cbSDimitry Andric assert(T);
6299*700637cbSDimitry Andric return this->delegate(SubExpr);
6300*700637cbSDimitry Andric case UO_Imag: { // __imag x
6301*700637cbSDimitry Andric assert(T);
6302*700637cbSDimitry Andric if (!this->discard(SubExpr))
6303*700637cbSDimitry Andric return false;
6304*700637cbSDimitry Andric return this->visitZeroInitializer(*T, SubExpr->getType(), SubExpr);
6305*700637cbSDimitry Andric }
6306*700637cbSDimitry Andric case UO_Extension:
6307*700637cbSDimitry Andric return this->delegate(SubExpr);
6308*700637cbSDimitry Andric case UO_Coawait:
6309*700637cbSDimitry Andric assert(false && "Unhandled opcode");
6310*700637cbSDimitry Andric }
6311*700637cbSDimitry Andric
6312*700637cbSDimitry Andric return false;
6313*700637cbSDimitry Andric }
6314*700637cbSDimitry Andric
6315*700637cbSDimitry Andric template <class Emitter>
VisitComplexUnaryOperator(const UnaryOperator * E)6316*700637cbSDimitry Andric bool Compiler<Emitter>::VisitComplexUnaryOperator(const UnaryOperator *E) {
6317*700637cbSDimitry Andric const Expr *SubExpr = E->getSubExpr();
6318*700637cbSDimitry Andric assert(SubExpr->getType()->isAnyComplexType());
6319*700637cbSDimitry Andric
6320*700637cbSDimitry Andric if (DiscardResult)
6321*700637cbSDimitry Andric return this->discard(SubExpr);
6322*700637cbSDimitry Andric
6323*700637cbSDimitry Andric std::optional<PrimType> ResT = classify(E);
6324*700637cbSDimitry Andric auto prepareResult = [=]() -> bool {
6325*700637cbSDimitry Andric if (!ResT && !Initializing) {
6326*700637cbSDimitry Andric std::optional<unsigned> LocalIndex = allocateLocal(SubExpr);
6327*700637cbSDimitry Andric if (!LocalIndex)
6328*700637cbSDimitry Andric return false;
6329*700637cbSDimitry Andric return this->emitGetPtrLocal(*LocalIndex, E);
6330*700637cbSDimitry Andric }
6331*700637cbSDimitry Andric
6332*700637cbSDimitry Andric return true;
6333*700637cbSDimitry Andric };
6334*700637cbSDimitry Andric
6335*700637cbSDimitry Andric // The offset of the temporary, if we created one.
6336*700637cbSDimitry Andric unsigned SubExprOffset = ~0u;
6337*700637cbSDimitry Andric auto createTemp = [=, &SubExprOffset]() -> bool {
6338*700637cbSDimitry Andric SubExprOffset =
6339*700637cbSDimitry Andric this->allocateLocalPrimitive(SubExpr, PT_Ptr, /*IsConst=*/true);
6340*700637cbSDimitry Andric if (!this->visit(SubExpr))
6341*700637cbSDimitry Andric return false;
6342*700637cbSDimitry Andric return this->emitSetLocal(PT_Ptr, SubExprOffset, E);
6343*700637cbSDimitry Andric };
6344*700637cbSDimitry Andric
6345*700637cbSDimitry Andric PrimType ElemT = classifyComplexElementType(SubExpr->getType());
6346*700637cbSDimitry Andric auto getElem = [=](unsigned Offset, unsigned Index) -> bool {
6347*700637cbSDimitry Andric if (!this->emitGetLocal(PT_Ptr, Offset, E))
6348*700637cbSDimitry Andric return false;
6349*700637cbSDimitry Andric return this->emitArrayElemPop(ElemT, Index, E);
6350*700637cbSDimitry Andric };
6351*700637cbSDimitry Andric
6352*700637cbSDimitry Andric switch (E->getOpcode()) {
6353*700637cbSDimitry Andric case UO_Minus:
6354*700637cbSDimitry Andric if (!prepareResult())
6355*700637cbSDimitry Andric return false;
6356*700637cbSDimitry Andric if (!createTemp())
6357*700637cbSDimitry Andric return false;
6358*700637cbSDimitry Andric for (unsigned I = 0; I != 2; ++I) {
6359*700637cbSDimitry Andric if (!getElem(SubExprOffset, I))
6360*700637cbSDimitry Andric return false;
6361*700637cbSDimitry Andric if (!this->emitNeg(ElemT, E))
6362*700637cbSDimitry Andric return false;
6363*700637cbSDimitry Andric if (!this->emitInitElem(ElemT, I, E))
6364*700637cbSDimitry Andric return false;
6365*700637cbSDimitry Andric }
6366*700637cbSDimitry Andric break;
6367*700637cbSDimitry Andric
6368*700637cbSDimitry Andric case UO_Plus: // +x
6369*700637cbSDimitry Andric case UO_AddrOf: // &x
6370*700637cbSDimitry Andric case UO_Deref: // *x
6371*700637cbSDimitry Andric return this->delegate(SubExpr);
6372*700637cbSDimitry Andric
6373*700637cbSDimitry Andric case UO_LNot:
6374*700637cbSDimitry Andric if (!this->visit(SubExpr))
6375*700637cbSDimitry Andric return false;
6376*700637cbSDimitry Andric if (!this->emitComplexBoolCast(SubExpr))
6377*700637cbSDimitry Andric return false;
6378*700637cbSDimitry Andric if (!this->emitInv(E))
6379*700637cbSDimitry Andric return false;
6380*700637cbSDimitry Andric if (PrimType ET = classifyPrim(E->getType()); ET != PT_Bool)
6381*700637cbSDimitry Andric return this->emitCast(PT_Bool, ET, E);
6382*700637cbSDimitry Andric return true;
6383*700637cbSDimitry Andric
6384*700637cbSDimitry Andric case UO_Real:
6385*700637cbSDimitry Andric return this->emitComplexReal(SubExpr);
6386*700637cbSDimitry Andric
6387*700637cbSDimitry Andric case UO_Imag:
6388*700637cbSDimitry Andric if (!this->visit(SubExpr))
6389*700637cbSDimitry Andric return false;
6390*700637cbSDimitry Andric
6391*700637cbSDimitry Andric if (SubExpr->isLValue()) {
6392*700637cbSDimitry Andric if (!this->emitConstUint8(1, E))
6393*700637cbSDimitry Andric return false;
6394*700637cbSDimitry Andric return this->emitArrayElemPtrPopUint8(E);
6395*700637cbSDimitry Andric }
6396*700637cbSDimitry Andric
6397*700637cbSDimitry Andric // Since our _Complex implementation does not map to a primitive type,
6398*700637cbSDimitry Andric // we sometimes have to do the lvalue-to-rvalue conversion here manually.
6399*700637cbSDimitry Andric return this->emitArrayElemPop(classifyPrim(E->getType()), 1, E);
6400*700637cbSDimitry Andric
6401*700637cbSDimitry Andric case UO_Not: // ~x
6402*700637cbSDimitry Andric if (!this->visit(SubExpr))
6403*700637cbSDimitry Andric return false;
6404*700637cbSDimitry Andric // Negate the imaginary component.
6405*700637cbSDimitry Andric if (!this->emitArrayElem(ElemT, 1, E))
6406*700637cbSDimitry Andric return false;
6407*700637cbSDimitry Andric if (!this->emitNeg(ElemT, E))
6408*700637cbSDimitry Andric return false;
6409*700637cbSDimitry Andric if (!this->emitInitElem(ElemT, 1, E))
6410*700637cbSDimitry Andric return false;
6411*700637cbSDimitry Andric return DiscardResult ? this->emitPopPtr(E) : true;
6412*700637cbSDimitry Andric
6413*700637cbSDimitry Andric case UO_Extension:
6414*700637cbSDimitry Andric return this->delegate(SubExpr);
6415*700637cbSDimitry Andric
6416*700637cbSDimitry Andric default:
6417*700637cbSDimitry Andric return this->emitInvalid(E);
6418*700637cbSDimitry Andric }
6419*700637cbSDimitry Andric
6420*700637cbSDimitry Andric return true;
6421*700637cbSDimitry Andric }
6422*700637cbSDimitry Andric
6423*700637cbSDimitry Andric template <class Emitter>
VisitVectorUnaryOperator(const UnaryOperator * E)6424*700637cbSDimitry Andric bool Compiler<Emitter>::VisitVectorUnaryOperator(const UnaryOperator *E) {
6425*700637cbSDimitry Andric const Expr *SubExpr = E->getSubExpr();
6426*700637cbSDimitry Andric assert(SubExpr->getType()->isVectorType());
6427*700637cbSDimitry Andric
6428*700637cbSDimitry Andric if (DiscardResult)
6429*700637cbSDimitry Andric return this->discard(SubExpr);
6430*700637cbSDimitry Andric
6431*700637cbSDimitry Andric auto UnaryOp = E->getOpcode();
6432*700637cbSDimitry Andric if (UnaryOp == UO_Extension)
6433*700637cbSDimitry Andric return this->delegate(SubExpr);
6434*700637cbSDimitry Andric
6435*700637cbSDimitry Andric if (UnaryOp != UO_Plus && UnaryOp != UO_Minus && UnaryOp != UO_LNot &&
6436*700637cbSDimitry Andric UnaryOp != UO_Not && UnaryOp != UO_AddrOf)
6437*700637cbSDimitry Andric return this->emitInvalid(E);
6438*700637cbSDimitry Andric
6439*700637cbSDimitry Andric // Nothing to do here.
6440*700637cbSDimitry Andric if (UnaryOp == UO_Plus || UnaryOp == UO_AddrOf)
6441*700637cbSDimitry Andric return this->delegate(SubExpr);
6442*700637cbSDimitry Andric
6443*700637cbSDimitry Andric if (!Initializing) {
6444*700637cbSDimitry Andric std::optional<unsigned> LocalIndex = allocateLocal(SubExpr);
6445*700637cbSDimitry Andric if (!LocalIndex)
6446*700637cbSDimitry Andric return false;
6447*700637cbSDimitry Andric if (!this->emitGetPtrLocal(*LocalIndex, E))
6448*700637cbSDimitry Andric return false;
6449*700637cbSDimitry Andric }
6450*700637cbSDimitry Andric
6451*700637cbSDimitry Andric // The offset of the temporary, if we created one.
6452*700637cbSDimitry Andric unsigned SubExprOffset =
6453*700637cbSDimitry Andric this->allocateLocalPrimitive(SubExpr, PT_Ptr, /*IsConst=*/true);
6454*700637cbSDimitry Andric if (!this->visit(SubExpr))
6455*700637cbSDimitry Andric return false;
6456*700637cbSDimitry Andric if (!this->emitSetLocal(PT_Ptr, SubExprOffset, E))
6457*700637cbSDimitry Andric return false;
6458*700637cbSDimitry Andric
6459*700637cbSDimitry Andric const auto *VecTy = SubExpr->getType()->getAs<VectorType>();
6460*700637cbSDimitry Andric PrimType ElemT = classifyVectorElementType(SubExpr->getType());
6461*700637cbSDimitry Andric auto getElem = [=](unsigned Offset, unsigned Index) -> bool {
6462*700637cbSDimitry Andric if (!this->emitGetLocal(PT_Ptr, Offset, E))
6463*700637cbSDimitry Andric return false;
6464*700637cbSDimitry Andric return this->emitArrayElemPop(ElemT, Index, E);
6465*700637cbSDimitry Andric };
6466*700637cbSDimitry Andric
6467*700637cbSDimitry Andric switch (UnaryOp) {
6468*700637cbSDimitry Andric case UO_Minus:
6469*700637cbSDimitry Andric for (unsigned I = 0; I != VecTy->getNumElements(); ++I) {
6470*700637cbSDimitry Andric if (!getElem(SubExprOffset, I))
6471*700637cbSDimitry Andric return false;
6472*700637cbSDimitry Andric if (!this->emitNeg(ElemT, E))
6473*700637cbSDimitry Andric return false;
6474*700637cbSDimitry Andric if (!this->emitInitElem(ElemT, I, E))
6475*700637cbSDimitry Andric return false;
6476*700637cbSDimitry Andric }
6477*700637cbSDimitry Andric break;
6478*700637cbSDimitry Andric case UO_LNot: { // !x
6479*700637cbSDimitry Andric // In C++, the logic operators !, &&, || are available for vectors. !v is
6480*700637cbSDimitry Andric // equivalent to v == 0.
6481*700637cbSDimitry Andric //
6482*700637cbSDimitry Andric // The result of the comparison is a vector of the same width and number of
6483*700637cbSDimitry Andric // elements as the comparison operands with a signed integral element type.
6484*700637cbSDimitry Andric //
6485*700637cbSDimitry Andric // https://gcc.gnu.org/onlinedocs/gcc/Vector-Extensions.html
6486*700637cbSDimitry Andric QualType ResultVecTy = E->getType();
6487*700637cbSDimitry Andric PrimType ResultVecElemT =
6488*700637cbSDimitry Andric classifyPrim(ResultVecTy->getAs<VectorType>()->getElementType());
6489*700637cbSDimitry Andric for (unsigned I = 0; I != VecTy->getNumElements(); ++I) {
6490*700637cbSDimitry Andric if (!getElem(SubExprOffset, I))
6491*700637cbSDimitry Andric return false;
6492*700637cbSDimitry Andric // operator ! on vectors returns -1 for 'truth', so negate it.
6493*700637cbSDimitry Andric if (!this->emitPrimCast(ElemT, PT_Bool, Ctx.getASTContext().BoolTy, E))
6494*700637cbSDimitry Andric return false;
6495*700637cbSDimitry Andric if (!this->emitInv(E))
6496*700637cbSDimitry Andric return false;
6497*700637cbSDimitry Andric if (!this->emitPrimCast(PT_Bool, ElemT, VecTy->getElementType(), E))
6498*700637cbSDimitry Andric return false;
6499*700637cbSDimitry Andric if (!this->emitNeg(ElemT, E))
6500*700637cbSDimitry Andric return false;
6501*700637cbSDimitry Andric if (ElemT != ResultVecElemT &&
6502*700637cbSDimitry Andric !this->emitPrimCast(ElemT, ResultVecElemT, ResultVecTy, E))
6503*700637cbSDimitry Andric return false;
6504*700637cbSDimitry Andric if (!this->emitInitElem(ResultVecElemT, I, E))
6505*700637cbSDimitry Andric return false;
6506*700637cbSDimitry Andric }
6507*700637cbSDimitry Andric break;
6508*700637cbSDimitry Andric }
6509*700637cbSDimitry Andric case UO_Not: // ~x
6510*700637cbSDimitry Andric for (unsigned I = 0; I != VecTy->getNumElements(); ++I) {
6511*700637cbSDimitry Andric if (!getElem(SubExprOffset, I))
6512*700637cbSDimitry Andric return false;
6513*700637cbSDimitry Andric if (ElemT == PT_Bool) {
6514*700637cbSDimitry Andric if (!this->emitInv(E))
6515*700637cbSDimitry Andric return false;
6516*700637cbSDimitry Andric } else {
6517*700637cbSDimitry Andric if (!this->emitComp(ElemT, E))
6518*700637cbSDimitry Andric return false;
6519*700637cbSDimitry Andric }
6520*700637cbSDimitry Andric if (!this->emitInitElem(ElemT, I, E))
6521*700637cbSDimitry Andric return false;
6522*700637cbSDimitry Andric }
6523*700637cbSDimitry Andric break;
6524*700637cbSDimitry Andric default:
6525*700637cbSDimitry Andric llvm_unreachable("Unsupported unary operators should be handled up front");
6526*700637cbSDimitry Andric }
6527*700637cbSDimitry Andric return true;
6528*700637cbSDimitry Andric }
6529*700637cbSDimitry Andric
6530*700637cbSDimitry Andric template <class Emitter>
visitDeclRef(const ValueDecl * D,const Expr * E)6531*700637cbSDimitry Andric bool Compiler<Emitter>::visitDeclRef(const ValueDecl *D, const Expr *E) {
6532*700637cbSDimitry Andric if (DiscardResult)
6533*700637cbSDimitry Andric return true;
6534*700637cbSDimitry Andric
6535*700637cbSDimitry Andric if (const auto *ECD = dyn_cast<EnumConstantDecl>(D))
6536*700637cbSDimitry Andric return this->emitConst(ECD->getInitVal(), E);
6537*700637cbSDimitry Andric if (const auto *FuncDecl = dyn_cast<FunctionDecl>(D)) {
6538*700637cbSDimitry Andric const Function *F = getFunction(FuncDecl);
6539*700637cbSDimitry Andric return F && this->emitGetFnPtr(F, E);
6540*700637cbSDimitry Andric }
6541*700637cbSDimitry Andric if (const auto *TPOD = dyn_cast<TemplateParamObjectDecl>(D)) {
6542*700637cbSDimitry Andric if (std::optional<unsigned> Index = P.getOrCreateGlobal(D)) {
6543*700637cbSDimitry Andric if (!this->emitGetPtrGlobal(*Index, E))
6544*700637cbSDimitry Andric return false;
6545*700637cbSDimitry Andric if (std::optional<PrimType> T = classify(E->getType())) {
6546*700637cbSDimitry Andric if (!this->visitAPValue(TPOD->getValue(), *T, E))
6547*700637cbSDimitry Andric return false;
6548*700637cbSDimitry Andric return this->emitInitGlobal(*T, *Index, E);
6549*700637cbSDimitry Andric }
6550*700637cbSDimitry Andric return this->visitAPValueInitializer(TPOD->getValue(), E,
6551*700637cbSDimitry Andric TPOD->getType());
6552*700637cbSDimitry Andric }
6553*700637cbSDimitry Andric return false;
6554*700637cbSDimitry Andric }
6555*700637cbSDimitry Andric
6556*700637cbSDimitry Andric // References are implemented via pointers, so when we see a DeclRefExpr
6557*700637cbSDimitry Andric // pointing to a reference, we need to get its value directly (i.e. the
6558*700637cbSDimitry Andric // pointer to the actual value) instead of a pointer to the pointer to the
6559*700637cbSDimitry Andric // value.
6560*700637cbSDimitry Andric bool IsReference = D->getType()->isReferenceType();
6561*700637cbSDimitry Andric
6562*700637cbSDimitry Andric // Local variables.
6563*700637cbSDimitry Andric if (auto It = Locals.find(D); It != Locals.end()) {
6564*700637cbSDimitry Andric const unsigned Offset = It->second.Offset;
6565*700637cbSDimitry Andric if (IsReference)
6566*700637cbSDimitry Andric return this->emitGetLocal(classifyPrim(E), Offset, E);
6567*700637cbSDimitry Andric return this->emitGetPtrLocal(Offset, E);
6568*700637cbSDimitry Andric }
6569*700637cbSDimitry Andric // Global variables.
6570*700637cbSDimitry Andric if (auto GlobalIndex = P.getGlobal(D)) {
6571*700637cbSDimitry Andric if (IsReference) {
6572*700637cbSDimitry Andric if (!Ctx.getLangOpts().CPlusPlus11)
6573*700637cbSDimitry Andric return this->emitGetGlobal(classifyPrim(E), *GlobalIndex, E);
6574*700637cbSDimitry Andric return this->emitGetGlobalUnchecked(classifyPrim(E), *GlobalIndex, E);
6575*700637cbSDimitry Andric }
6576*700637cbSDimitry Andric
6577*700637cbSDimitry Andric return this->emitGetPtrGlobal(*GlobalIndex, E);
6578*700637cbSDimitry Andric }
6579*700637cbSDimitry Andric // Function parameters.
6580*700637cbSDimitry Andric if (const auto *PVD = dyn_cast<ParmVarDecl>(D)) {
6581*700637cbSDimitry Andric if (auto It = this->Params.find(PVD); It != this->Params.end()) {
6582*700637cbSDimitry Andric if (IsReference || !It->second.IsPtr)
6583*700637cbSDimitry Andric return this->emitGetParam(classifyPrim(E), It->second.Offset, E);
6584*700637cbSDimitry Andric
6585*700637cbSDimitry Andric return this->emitGetPtrParam(It->second.Offset, E);
6586*700637cbSDimitry Andric }
6587*700637cbSDimitry Andric }
6588*700637cbSDimitry Andric
6589*700637cbSDimitry Andric // In case we need to re-visit a declaration.
6590*700637cbSDimitry Andric auto revisit = [&](const VarDecl *VD) -> bool {
6591*700637cbSDimitry Andric if (!this->emitPushCC(VD->hasConstantInitialization(), E))
6592*700637cbSDimitry Andric return false;
6593*700637cbSDimitry Andric auto VarState = this->visitDecl(VD, /*IsConstexprUnknown=*/true);
6594*700637cbSDimitry Andric
6595*700637cbSDimitry Andric if (!this->emitPopCC(E))
6596*700637cbSDimitry Andric return false;
6597*700637cbSDimitry Andric
6598*700637cbSDimitry Andric if (VarState.notCreated())
6599*700637cbSDimitry Andric return true;
6600*700637cbSDimitry Andric if (!VarState)
6601*700637cbSDimitry Andric return false;
6602*700637cbSDimitry Andric // Retry.
6603*700637cbSDimitry Andric return this->visitDeclRef(D, E);
6604*700637cbSDimitry Andric };
6605*700637cbSDimitry Andric
6606*700637cbSDimitry Andric // Lambda captures.
6607*700637cbSDimitry Andric if (auto It = this->LambdaCaptures.find(D);
6608*700637cbSDimitry Andric It != this->LambdaCaptures.end()) {
6609*700637cbSDimitry Andric auto [Offset, IsPtr] = It->second;
6610*700637cbSDimitry Andric
6611*700637cbSDimitry Andric if (IsPtr)
6612*700637cbSDimitry Andric return this->emitGetThisFieldPtr(Offset, E);
6613*700637cbSDimitry Andric return this->emitGetPtrThisField(Offset, E);
6614*700637cbSDimitry Andric }
6615*700637cbSDimitry Andric
6616*700637cbSDimitry Andric if (const auto *DRE = dyn_cast<DeclRefExpr>(E);
6617*700637cbSDimitry Andric DRE && DRE->refersToEnclosingVariableOrCapture()) {
6618*700637cbSDimitry Andric if (const auto *VD = dyn_cast<VarDecl>(D); VD && VD->isInitCapture())
6619*700637cbSDimitry Andric return revisit(VD);
6620*700637cbSDimitry Andric }
6621*700637cbSDimitry Andric
6622*700637cbSDimitry Andric if (const auto *BD = dyn_cast<BindingDecl>(D))
6623*700637cbSDimitry Andric return this->visit(BD->getBinding());
6624*700637cbSDimitry Andric
6625*700637cbSDimitry Andric // Avoid infinite recursion.
6626*700637cbSDimitry Andric if (D == InitializingDecl)
6627*700637cbSDimitry Andric return this->emitDummyPtr(D, E);
6628*700637cbSDimitry Andric
6629*700637cbSDimitry Andric // Try to lazily visit (or emit dummy pointers for) declarations
6630*700637cbSDimitry Andric // we haven't seen yet.
6631*700637cbSDimitry Andric // For C.
6632*700637cbSDimitry Andric if (!Ctx.getLangOpts().CPlusPlus) {
6633*700637cbSDimitry Andric if (const auto *VD = dyn_cast<VarDecl>(D);
6634*700637cbSDimitry Andric VD && VD->getAnyInitializer() &&
6635*700637cbSDimitry Andric VD->getType().isConstant(Ctx.getASTContext()) && !VD->isWeak())
6636*700637cbSDimitry Andric return revisit(VD);
6637*700637cbSDimitry Andric return this->emitDummyPtr(D, E);
6638*700637cbSDimitry Andric }
6639*700637cbSDimitry Andric
6640*700637cbSDimitry Andric // ... and C++.
6641*700637cbSDimitry Andric const auto *VD = dyn_cast<VarDecl>(D);
6642*700637cbSDimitry Andric if (!VD)
6643*700637cbSDimitry Andric return this->emitDummyPtr(D, E);
6644*700637cbSDimitry Andric
6645*700637cbSDimitry Andric const auto typeShouldBeVisited = [&](QualType T) -> bool {
6646*700637cbSDimitry Andric if (T.isConstant(Ctx.getASTContext()))
6647*700637cbSDimitry Andric return true;
6648*700637cbSDimitry Andric return T->isReferenceType();
6649*700637cbSDimitry Andric };
6650*700637cbSDimitry Andric
6651*700637cbSDimitry Andric if ((VD->hasGlobalStorage() || VD->isStaticDataMember()) &&
6652*700637cbSDimitry Andric typeShouldBeVisited(VD->getType())) {
6653*700637cbSDimitry Andric if (const Expr *Init = VD->getAnyInitializer();
6654*700637cbSDimitry Andric Init && !Init->isValueDependent()) {
6655*700637cbSDimitry Andric // Whether or not the evaluation is successul doesn't really matter
6656*700637cbSDimitry Andric // here -- we will create a global variable in any case, and that
6657*700637cbSDimitry Andric // will have the state of initializer evaluation attached.
6658*700637cbSDimitry Andric APValue V;
6659*700637cbSDimitry Andric SmallVector<PartialDiagnosticAt> Notes;
6660*700637cbSDimitry Andric (void)Init->EvaluateAsInitializer(V, Ctx.getASTContext(), VD, Notes,
6661*700637cbSDimitry Andric true);
6662*700637cbSDimitry Andric return this->visitDeclRef(D, E);
6663*700637cbSDimitry Andric }
6664*700637cbSDimitry Andric return revisit(VD);
6665*700637cbSDimitry Andric }
6666*700637cbSDimitry Andric
6667*700637cbSDimitry Andric // FIXME: The evaluateValue() check here is a little ridiculous, since
6668*700637cbSDimitry Andric // it will ultimately call into Context::evaluateAsInitializer(). In
6669*700637cbSDimitry Andric // other words, we're evaluating the initializer, just to know if we can
6670*700637cbSDimitry Andric // evaluate the initializer.
6671*700637cbSDimitry Andric if (VD->isLocalVarDecl() && typeShouldBeVisited(VD->getType()) &&
6672*700637cbSDimitry Andric VD->getInit() && !VD->getInit()->isValueDependent()) {
6673*700637cbSDimitry Andric
6674*700637cbSDimitry Andric if (VD->evaluateValue())
6675*700637cbSDimitry Andric return revisit(VD);
6676*700637cbSDimitry Andric
6677*700637cbSDimitry Andric if (!IsReference)
6678*700637cbSDimitry Andric return this->emitDummyPtr(D, E);
6679*700637cbSDimitry Andric
6680*700637cbSDimitry Andric return this->emitInvalidDeclRef(cast<DeclRefExpr>(E),
6681*700637cbSDimitry Andric /*InitializerFailed=*/true, E);
6682*700637cbSDimitry Andric }
6683*700637cbSDimitry Andric
6684*700637cbSDimitry Andric return this->emitDummyPtr(D, E);
6685*700637cbSDimitry Andric }
6686*700637cbSDimitry Andric
6687*700637cbSDimitry Andric template <class Emitter>
VisitDeclRefExpr(const DeclRefExpr * E)6688*700637cbSDimitry Andric bool Compiler<Emitter>::VisitDeclRefExpr(const DeclRefExpr *E) {
6689*700637cbSDimitry Andric const auto *D = E->getDecl();
6690*700637cbSDimitry Andric return this->visitDeclRef(D, E);
6691*700637cbSDimitry Andric }
6692*700637cbSDimitry Andric
emitCleanup()6693*700637cbSDimitry Andric template <class Emitter> void Compiler<Emitter>::emitCleanup() {
6694*700637cbSDimitry Andric for (VariableScope<Emitter> *C = VarScope; C; C = C->getParent())
6695*700637cbSDimitry Andric C->emitDestruction();
6696*700637cbSDimitry Andric }
6697*700637cbSDimitry Andric
6698*700637cbSDimitry Andric template <class Emitter>
collectBaseOffset(const QualType BaseType,const QualType DerivedType)6699*700637cbSDimitry Andric unsigned Compiler<Emitter>::collectBaseOffset(const QualType BaseType,
6700*700637cbSDimitry Andric const QualType DerivedType) {
6701*700637cbSDimitry Andric const auto extractRecordDecl = [](QualType Ty) -> const CXXRecordDecl * {
6702*700637cbSDimitry Andric if (const auto *R = Ty->getPointeeCXXRecordDecl())
6703*700637cbSDimitry Andric return R;
6704*700637cbSDimitry Andric return Ty->getAsCXXRecordDecl();
6705*700637cbSDimitry Andric };
6706*700637cbSDimitry Andric const CXXRecordDecl *BaseDecl = extractRecordDecl(BaseType);
6707*700637cbSDimitry Andric const CXXRecordDecl *DerivedDecl = extractRecordDecl(DerivedType);
6708*700637cbSDimitry Andric
6709*700637cbSDimitry Andric return Ctx.collectBaseOffset(BaseDecl, DerivedDecl);
6710*700637cbSDimitry Andric }
6711*700637cbSDimitry Andric
6712*700637cbSDimitry Andric /// Emit casts from a PrimType to another PrimType.
6713*700637cbSDimitry Andric template <class Emitter>
emitPrimCast(PrimType FromT,PrimType ToT,QualType ToQT,const Expr * E)6714*700637cbSDimitry Andric bool Compiler<Emitter>::emitPrimCast(PrimType FromT, PrimType ToT,
6715*700637cbSDimitry Andric QualType ToQT, const Expr *E) {
6716*700637cbSDimitry Andric
6717*700637cbSDimitry Andric if (FromT == PT_Float) {
6718*700637cbSDimitry Andric // Floating to floating.
6719*700637cbSDimitry Andric if (ToT == PT_Float) {
6720*700637cbSDimitry Andric const llvm::fltSemantics *ToSem = &Ctx.getFloatSemantics(ToQT);
6721*700637cbSDimitry Andric return this->emitCastFP(ToSem, getRoundingMode(E), E);
6722*700637cbSDimitry Andric }
6723*700637cbSDimitry Andric
6724*700637cbSDimitry Andric if (ToT == PT_IntAP)
6725*700637cbSDimitry Andric return this->emitCastFloatingIntegralAP(Ctx.getBitWidth(ToQT),
6726*700637cbSDimitry Andric getFPOptions(E), E);
6727*700637cbSDimitry Andric if (ToT == PT_IntAPS)
6728*700637cbSDimitry Andric return this->emitCastFloatingIntegralAPS(Ctx.getBitWidth(ToQT),
6729*700637cbSDimitry Andric getFPOptions(E), E);
6730*700637cbSDimitry Andric
6731*700637cbSDimitry Andric // Float to integral.
6732*700637cbSDimitry Andric if (isIntegralType(ToT) || ToT == PT_Bool)
6733*700637cbSDimitry Andric return this->emitCastFloatingIntegral(ToT, getFPOptions(E), E);
6734*700637cbSDimitry Andric }
6735*700637cbSDimitry Andric
6736*700637cbSDimitry Andric if (isIntegralType(FromT) || FromT == PT_Bool) {
6737*700637cbSDimitry Andric if (ToT == PT_IntAP)
6738*700637cbSDimitry Andric return this->emitCastAP(FromT, Ctx.getBitWidth(ToQT), E);
6739*700637cbSDimitry Andric if (ToT == PT_IntAPS)
6740*700637cbSDimitry Andric return this->emitCastAPS(FromT, Ctx.getBitWidth(ToQT), E);
6741*700637cbSDimitry Andric
6742*700637cbSDimitry Andric // Integral to integral.
6743*700637cbSDimitry Andric if (isIntegralType(ToT) || ToT == PT_Bool)
6744*700637cbSDimitry Andric return FromT != ToT ? this->emitCast(FromT, ToT, E) : true;
6745*700637cbSDimitry Andric
6746*700637cbSDimitry Andric if (ToT == PT_Float) {
6747*700637cbSDimitry Andric // Integral to floating.
6748*700637cbSDimitry Andric const llvm::fltSemantics *ToSem = &Ctx.getFloatSemantics(ToQT);
6749*700637cbSDimitry Andric return this->emitCastIntegralFloating(FromT, ToSem, getFPOptions(E), E);
6750*700637cbSDimitry Andric }
6751*700637cbSDimitry Andric }
6752*700637cbSDimitry Andric
6753*700637cbSDimitry Andric return false;
6754*700637cbSDimitry Andric }
6755*700637cbSDimitry Andric
6756*700637cbSDimitry Andric /// Emits __real(SubExpr)
6757*700637cbSDimitry Andric template <class Emitter>
emitComplexReal(const Expr * SubExpr)6758*700637cbSDimitry Andric bool Compiler<Emitter>::emitComplexReal(const Expr *SubExpr) {
6759*700637cbSDimitry Andric assert(SubExpr->getType()->isAnyComplexType());
6760*700637cbSDimitry Andric
6761*700637cbSDimitry Andric if (DiscardResult)
6762*700637cbSDimitry Andric return this->discard(SubExpr);
6763*700637cbSDimitry Andric
6764*700637cbSDimitry Andric if (!this->visit(SubExpr))
6765*700637cbSDimitry Andric return false;
6766*700637cbSDimitry Andric if (SubExpr->isLValue()) {
6767*700637cbSDimitry Andric if (!this->emitConstUint8(0, SubExpr))
6768*700637cbSDimitry Andric return false;
6769*700637cbSDimitry Andric return this->emitArrayElemPtrPopUint8(SubExpr);
6770*700637cbSDimitry Andric }
6771*700637cbSDimitry Andric
6772*700637cbSDimitry Andric // Rvalue, load the actual element.
6773*700637cbSDimitry Andric return this->emitArrayElemPop(classifyComplexElementType(SubExpr->getType()),
6774*700637cbSDimitry Andric 0, SubExpr);
6775*700637cbSDimitry Andric }
6776*700637cbSDimitry Andric
6777*700637cbSDimitry Andric template <class Emitter>
emitComplexBoolCast(const Expr * E)6778*700637cbSDimitry Andric bool Compiler<Emitter>::emitComplexBoolCast(const Expr *E) {
6779*700637cbSDimitry Andric assert(!DiscardResult);
6780*700637cbSDimitry Andric PrimType ElemT = classifyComplexElementType(E->getType());
6781*700637cbSDimitry Andric // We emit the expression (__real(E) != 0 || __imag(E) != 0)
6782*700637cbSDimitry Andric // for us, that means (bool)E[0] || (bool)E[1]
6783*700637cbSDimitry Andric if (!this->emitArrayElem(ElemT, 0, E))
6784*700637cbSDimitry Andric return false;
6785*700637cbSDimitry Andric if (ElemT == PT_Float) {
6786*700637cbSDimitry Andric if (!this->emitCastFloatingIntegral(PT_Bool, getFPOptions(E), E))
6787*700637cbSDimitry Andric return false;
6788*700637cbSDimitry Andric } else {
6789*700637cbSDimitry Andric if (!this->emitCast(ElemT, PT_Bool, E))
6790*700637cbSDimitry Andric return false;
6791*700637cbSDimitry Andric }
6792*700637cbSDimitry Andric
6793*700637cbSDimitry Andric // We now have the bool value of E[0] on the stack.
6794*700637cbSDimitry Andric LabelTy LabelTrue = this->getLabel();
6795*700637cbSDimitry Andric if (!this->jumpTrue(LabelTrue))
6796*700637cbSDimitry Andric return false;
6797*700637cbSDimitry Andric
6798*700637cbSDimitry Andric if (!this->emitArrayElemPop(ElemT, 1, E))
6799*700637cbSDimitry Andric return false;
6800*700637cbSDimitry Andric if (ElemT == PT_Float) {
6801*700637cbSDimitry Andric if (!this->emitCastFloatingIntegral(PT_Bool, getFPOptions(E), E))
6802*700637cbSDimitry Andric return false;
6803*700637cbSDimitry Andric } else {
6804*700637cbSDimitry Andric if (!this->emitCast(ElemT, PT_Bool, E))
6805*700637cbSDimitry Andric return false;
6806*700637cbSDimitry Andric }
6807*700637cbSDimitry Andric // Leave the boolean value of E[1] on the stack.
6808*700637cbSDimitry Andric LabelTy EndLabel = this->getLabel();
6809*700637cbSDimitry Andric this->jump(EndLabel);
6810*700637cbSDimitry Andric
6811*700637cbSDimitry Andric this->emitLabel(LabelTrue);
6812*700637cbSDimitry Andric if (!this->emitPopPtr(E))
6813*700637cbSDimitry Andric return false;
6814*700637cbSDimitry Andric if (!this->emitConstBool(true, E))
6815*700637cbSDimitry Andric return false;
6816*700637cbSDimitry Andric
6817*700637cbSDimitry Andric this->fallthrough(EndLabel);
6818*700637cbSDimitry Andric this->emitLabel(EndLabel);
6819*700637cbSDimitry Andric
6820*700637cbSDimitry Andric return true;
6821*700637cbSDimitry Andric }
6822*700637cbSDimitry Andric
6823*700637cbSDimitry Andric template <class Emitter>
emitComplexComparison(const Expr * LHS,const Expr * RHS,const BinaryOperator * E)6824*700637cbSDimitry Andric bool Compiler<Emitter>::emitComplexComparison(const Expr *LHS, const Expr *RHS,
6825*700637cbSDimitry Andric const BinaryOperator *E) {
6826*700637cbSDimitry Andric assert(E->isComparisonOp());
6827*700637cbSDimitry Andric assert(!Initializing);
6828*700637cbSDimitry Andric assert(!DiscardResult);
6829*700637cbSDimitry Andric
6830*700637cbSDimitry Andric PrimType ElemT;
6831*700637cbSDimitry Andric bool LHSIsComplex;
6832*700637cbSDimitry Andric unsigned LHSOffset;
6833*700637cbSDimitry Andric if (LHS->getType()->isAnyComplexType()) {
6834*700637cbSDimitry Andric LHSIsComplex = true;
6835*700637cbSDimitry Andric ElemT = classifyComplexElementType(LHS->getType());
6836*700637cbSDimitry Andric LHSOffset = allocateLocalPrimitive(LHS, PT_Ptr, /*IsConst=*/true);
6837*700637cbSDimitry Andric if (!this->visit(LHS))
6838*700637cbSDimitry Andric return false;
6839*700637cbSDimitry Andric if (!this->emitSetLocal(PT_Ptr, LHSOffset, E))
6840*700637cbSDimitry Andric return false;
6841*700637cbSDimitry Andric } else {
6842*700637cbSDimitry Andric LHSIsComplex = false;
6843*700637cbSDimitry Andric PrimType LHST = classifyPrim(LHS->getType());
6844*700637cbSDimitry Andric LHSOffset = this->allocateLocalPrimitive(LHS, LHST, /*IsConst=*/true);
6845*700637cbSDimitry Andric if (!this->visit(LHS))
6846*700637cbSDimitry Andric return false;
6847*700637cbSDimitry Andric if (!this->emitSetLocal(LHST, LHSOffset, E))
6848*700637cbSDimitry Andric return false;
6849*700637cbSDimitry Andric }
6850*700637cbSDimitry Andric
6851*700637cbSDimitry Andric bool RHSIsComplex;
6852*700637cbSDimitry Andric unsigned RHSOffset;
6853*700637cbSDimitry Andric if (RHS->getType()->isAnyComplexType()) {
6854*700637cbSDimitry Andric RHSIsComplex = true;
6855*700637cbSDimitry Andric ElemT = classifyComplexElementType(RHS->getType());
6856*700637cbSDimitry Andric RHSOffset = allocateLocalPrimitive(RHS, PT_Ptr, /*IsConst=*/true);
6857*700637cbSDimitry Andric if (!this->visit(RHS))
6858*700637cbSDimitry Andric return false;
6859*700637cbSDimitry Andric if (!this->emitSetLocal(PT_Ptr, RHSOffset, E))
6860*700637cbSDimitry Andric return false;
6861*700637cbSDimitry Andric } else {
6862*700637cbSDimitry Andric RHSIsComplex = false;
6863*700637cbSDimitry Andric PrimType RHST = classifyPrim(RHS->getType());
6864*700637cbSDimitry Andric RHSOffset = this->allocateLocalPrimitive(RHS, RHST, /*IsConst=*/true);
6865*700637cbSDimitry Andric if (!this->visit(RHS))
6866*700637cbSDimitry Andric return false;
6867*700637cbSDimitry Andric if (!this->emitSetLocal(RHST, RHSOffset, E))
6868*700637cbSDimitry Andric return false;
6869*700637cbSDimitry Andric }
6870*700637cbSDimitry Andric
6871*700637cbSDimitry Andric auto getElem = [&](unsigned LocalOffset, unsigned Index,
6872*700637cbSDimitry Andric bool IsComplex) -> bool {
6873*700637cbSDimitry Andric if (IsComplex) {
6874*700637cbSDimitry Andric if (!this->emitGetLocal(PT_Ptr, LocalOffset, E))
6875*700637cbSDimitry Andric return false;
6876*700637cbSDimitry Andric return this->emitArrayElemPop(ElemT, Index, E);
6877*700637cbSDimitry Andric }
6878*700637cbSDimitry Andric return this->emitGetLocal(ElemT, LocalOffset, E);
6879*700637cbSDimitry Andric };
6880*700637cbSDimitry Andric
6881*700637cbSDimitry Andric for (unsigned I = 0; I != 2; ++I) {
6882*700637cbSDimitry Andric // Get both values.
6883*700637cbSDimitry Andric if (!getElem(LHSOffset, I, LHSIsComplex))
6884*700637cbSDimitry Andric return false;
6885*700637cbSDimitry Andric if (!getElem(RHSOffset, I, RHSIsComplex))
6886*700637cbSDimitry Andric return false;
6887*700637cbSDimitry Andric // And compare them.
6888*700637cbSDimitry Andric if (!this->emitEQ(ElemT, E))
6889*700637cbSDimitry Andric return false;
6890*700637cbSDimitry Andric
6891*700637cbSDimitry Andric if (!this->emitCastBoolUint8(E))
6892*700637cbSDimitry Andric return false;
6893*700637cbSDimitry Andric }
6894*700637cbSDimitry Andric
6895*700637cbSDimitry Andric // We now have two bool values on the stack. Compare those.
6896*700637cbSDimitry Andric if (!this->emitAddUint8(E))
6897*700637cbSDimitry Andric return false;
6898*700637cbSDimitry Andric if (!this->emitConstUint8(2, E))
6899*700637cbSDimitry Andric return false;
6900*700637cbSDimitry Andric
6901*700637cbSDimitry Andric if (E->getOpcode() == BO_EQ) {
6902*700637cbSDimitry Andric if (!this->emitEQUint8(E))
6903*700637cbSDimitry Andric return false;
6904*700637cbSDimitry Andric } else if (E->getOpcode() == BO_NE) {
6905*700637cbSDimitry Andric if (!this->emitNEUint8(E))
6906*700637cbSDimitry Andric return false;
6907*700637cbSDimitry Andric } else
6908*700637cbSDimitry Andric return false;
6909*700637cbSDimitry Andric
6910*700637cbSDimitry Andric // In C, this returns an int.
6911*700637cbSDimitry Andric if (PrimType ResT = classifyPrim(E->getType()); ResT != PT_Bool)
6912*700637cbSDimitry Andric return this->emitCast(PT_Bool, ResT, E);
6913*700637cbSDimitry Andric return true;
6914*700637cbSDimitry Andric }
6915*700637cbSDimitry Andric
6916*700637cbSDimitry Andric /// When calling this, we have a pointer of the local-to-destroy
6917*700637cbSDimitry Andric /// on the stack.
6918*700637cbSDimitry Andric /// Emit destruction of record types (or arrays of record types).
6919*700637cbSDimitry Andric template <class Emitter>
emitRecordDestruction(const Record * R,SourceInfo Loc)6920*700637cbSDimitry Andric bool Compiler<Emitter>::emitRecordDestruction(const Record *R, SourceInfo Loc) {
6921*700637cbSDimitry Andric assert(R);
6922*700637cbSDimitry Andric assert(!R->isAnonymousUnion());
6923*700637cbSDimitry Andric const CXXDestructorDecl *Dtor = R->getDestructor();
6924*700637cbSDimitry Andric if (!Dtor || Dtor->isTrivial())
6925*700637cbSDimitry Andric return true;
6926*700637cbSDimitry Andric
6927*700637cbSDimitry Andric assert(Dtor);
6928*700637cbSDimitry Andric const Function *DtorFunc = getFunction(Dtor);
6929*700637cbSDimitry Andric if (!DtorFunc)
6930*700637cbSDimitry Andric return false;
6931*700637cbSDimitry Andric assert(DtorFunc->hasThisPointer());
6932*700637cbSDimitry Andric assert(DtorFunc->getNumParams() == 1);
6933*700637cbSDimitry Andric if (!this->emitDupPtr(Loc))
6934*700637cbSDimitry Andric return false;
6935*700637cbSDimitry Andric return this->emitCall(DtorFunc, 0, Loc);
6936*700637cbSDimitry Andric }
6937*700637cbSDimitry Andric /// When calling this, we have a pointer of the local-to-destroy
6938*700637cbSDimitry Andric /// on the stack.
6939*700637cbSDimitry Andric /// Emit destruction of record types (or arrays of record types).
6940*700637cbSDimitry Andric template <class Emitter>
emitDestruction(const Descriptor * Desc,SourceInfo Loc)6941*700637cbSDimitry Andric bool Compiler<Emitter>::emitDestruction(const Descriptor *Desc,
6942*700637cbSDimitry Andric SourceInfo Loc) {
6943*700637cbSDimitry Andric assert(Desc);
6944*700637cbSDimitry Andric assert(!Desc->isPrimitive());
6945*700637cbSDimitry Andric assert(!Desc->isPrimitiveArray());
6946*700637cbSDimitry Andric
6947*700637cbSDimitry Andric // Can happen if the decl is invalid.
6948*700637cbSDimitry Andric if (Desc->isDummy())
6949*700637cbSDimitry Andric return true;
6950*700637cbSDimitry Andric
6951*700637cbSDimitry Andric // Arrays.
6952*700637cbSDimitry Andric if (Desc->isArray()) {
6953*700637cbSDimitry Andric const Descriptor *ElemDesc = Desc->ElemDesc;
6954*700637cbSDimitry Andric assert(ElemDesc);
6955*700637cbSDimitry Andric
6956*700637cbSDimitry Andric // Don't need to do anything for these.
6957*700637cbSDimitry Andric if (ElemDesc->isPrimitiveArray())
6958*700637cbSDimitry Andric return true;
6959*700637cbSDimitry Andric
6960*700637cbSDimitry Andric // If this is an array of record types, check if we need
6961*700637cbSDimitry Andric // to call the element destructors at all. If not, try
6962*700637cbSDimitry Andric // to save the work.
6963*700637cbSDimitry Andric if (const Record *ElemRecord = ElemDesc->ElemRecord) {
6964*700637cbSDimitry Andric if (const CXXDestructorDecl *Dtor = ElemRecord->getDestructor();
6965*700637cbSDimitry Andric !Dtor || Dtor->isTrivial())
6966*700637cbSDimitry Andric return true;
6967*700637cbSDimitry Andric }
6968*700637cbSDimitry Andric
6969*700637cbSDimitry Andric if (unsigned N = Desc->getNumElems()) {
6970*700637cbSDimitry Andric for (ssize_t I = N - 1; I >= 0; --I) {
6971*700637cbSDimitry Andric if (!this->emitConstUint64(I, Loc))
6972*700637cbSDimitry Andric return false;
6973*700637cbSDimitry Andric if (!this->emitArrayElemPtrUint64(Loc))
6974*700637cbSDimitry Andric return false;
6975*700637cbSDimitry Andric if (!this->emitDestruction(ElemDesc, Loc))
6976*700637cbSDimitry Andric return false;
6977*700637cbSDimitry Andric if (!this->emitPopPtr(Loc))
6978*700637cbSDimitry Andric return false;
6979*700637cbSDimitry Andric }
6980*700637cbSDimitry Andric }
6981*700637cbSDimitry Andric return true;
6982*700637cbSDimitry Andric }
6983*700637cbSDimitry Andric
6984*700637cbSDimitry Andric assert(Desc->ElemRecord);
6985*700637cbSDimitry Andric if (Desc->ElemRecord->isAnonymousUnion())
6986*700637cbSDimitry Andric return true;
6987*700637cbSDimitry Andric
6988*700637cbSDimitry Andric return this->emitRecordDestruction(Desc->ElemRecord, Loc);
6989*700637cbSDimitry Andric }
6990*700637cbSDimitry Andric
6991*700637cbSDimitry Andric /// Create a dummy pointer for the given decl (or expr) and
6992*700637cbSDimitry Andric /// push a pointer to it on the stack.
6993*700637cbSDimitry Andric template <class Emitter>
emitDummyPtr(const DeclTy & D,const Expr * E)6994*700637cbSDimitry Andric bool Compiler<Emitter>::emitDummyPtr(const DeclTy &D, const Expr *E) {
6995*700637cbSDimitry Andric assert(!DiscardResult && "Should've been checked before");
6996*700637cbSDimitry Andric
6997*700637cbSDimitry Andric unsigned DummyID = P.getOrCreateDummy(D);
6998*700637cbSDimitry Andric
6999*700637cbSDimitry Andric if (!this->emitGetPtrGlobal(DummyID, E))
7000*700637cbSDimitry Andric return false;
7001*700637cbSDimitry Andric if (E->getType()->isVoidType())
7002*700637cbSDimitry Andric return true;
7003*700637cbSDimitry Andric
7004*700637cbSDimitry Andric // Convert the dummy pointer to another pointer type if we have to.
7005*700637cbSDimitry Andric if (PrimType PT = classifyPrim(E); PT != PT_Ptr) {
7006*700637cbSDimitry Andric if (isPtrType(PT))
7007*700637cbSDimitry Andric return this->emitDecayPtr(PT_Ptr, PT, E);
7008*700637cbSDimitry Andric return false;
7009*700637cbSDimitry Andric }
7010*700637cbSDimitry Andric return true;
7011*700637cbSDimitry Andric }
7012*700637cbSDimitry Andric
7013*700637cbSDimitry Andric template <class Emitter>
emitFloat(const APFloat & F,const Expr * E)7014*700637cbSDimitry Andric bool Compiler<Emitter>::emitFloat(const APFloat &F, const Expr *E) {
7015*700637cbSDimitry Andric assert(!DiscardResult && "Should've been checked before");
7016*700637cbSDimitry Andric
7017*700637cbSDimitry Andric if (Floating::singleWord(F.getSemantics()))
7018*700637cbSDimitry Andric return this->emitConstFloat(Floating(F), E);
7019*700637cbSDimitry Andric
7020*700637cbSDimitry Andric APInt I = F.bitcastToAPInt();
7021*700637cbSDimitry Andric return this->emitConstFloat(
7022*700637cbSDimitry Andric Floating(const_cast<uint64_t *>(I.getRawData()),
7023*700637cbSDimitry Andric llvm::APFloatBase::SemanticsToEnum(F.getSemantics())),
7024*700637cbSDimitry Andric E);
7025*700637cbSDimitry Andric }
7026*700637cbSDimitry Andric
7027*700637cbSDimitry Andric // This function is constexpr if and only if To, From, and the types of
7028*700637cbSDimitry Andric // all subobjects of To and From are types T such that...
7029*700637cbSDimitry Andric // (3.1) - is_union_v<T> is false;
7030*700637cbSDimitry Andric // (3.2) - is_pointer_v<T> is false;
7031*700637cbSDimitry Andric // (3.3) - is_member_pointer_v<T> is false;
7032*700637cbSDimitry Andric // (3.4) - is_volatile_v<T> is false; and
7033*700637cbSDimitry Andric // (3.5) - T has no non-static data members of reference type
7034*700637cbSDimitry Andric template <class Emitter>
emitBuiltinBitCast(const CastExpr * E)7035*700637cbSDimitry Andric bool Compiler<Emitter>::emitBuiltinBitCast(const CastExpr *E) {
7036*700637cbSDimitry Andric const Expr *SubExpr = E->getSubExpr();
7037*700637cbSDimitry Andric QualType FromType = SubExpr->getType();
7038*700637cbSDimitry Andric QualType ToType = E->getType();
7039*700637cbSDimitry Andric std::optional<PrimType> ToT = classify(ToType);
7040*700637cbSDimitry Andric
7041*700637cbSDimitry Andric assert(!ToType->isReferenceType());
7042*700637cbSDimitry Andric
7043*700637cbSDimitry Andric // Prepare storage for the result in case we discard.
7044*700637cbSDimitry Andric if (DiscardResult && !Initializing && !ToT) {
7045*700637cbSDimitry Andric std::optional<unsigned> LocalIndex = allocateLocal(E);
7046*700637cbSDimitry Andric if (!LocalIndex)
7047*700637cbSDimitry Andric return false;
7048*700637cbSDimitry Andric if (!this->emitGetPtrLocal(*LocalIndex, E))
7049*700637cbSDimitry Andric return false;
7050*700637cbSDimitry Andric }
7051*700637cbSDimitry Andric
7052*700637cbSDimitry Andric // Get a pointer to the value-to-cast on the stack.
7053*700637cbSDimitry Andric // For CK_LValueToRValueBitCast, this is always an lvalue and
7054*700637cbSDimitry Andric // we later assume it to be one (i.e. a PT_Ptr). However,
7055*700637cbSDimitry Andric // we call this function for other utility methods where
7056*700637cbSDimitry Andric // a bitcast might be useful, so convert it to a PT_Ptr in that case.
7057*700637cbSDimitry Andric if (SubExpr->isGLValue() || FromType->isVectorType()) {
7058*700637cbSDimitry Andric if (!this->visit(SubExpr))
7059*700637cbSDimitry Andric return false;
7060*700637cbSDimitry Andric } else if (std::optional<PrimType> FromT = classify(SubExpr)) {
7061*700637cbSDimitry Andric unsigned TempOffset =
7062*700637cbSDimitry Andric allocateLocalPrimitive(SubExpr, *FromT, /*IsConst=*/true);
7063*700637cbSDimitry Andric if (!this->visit(SubExpr))
7064*700637cbSDimitry Andric return false;
7065*700637cbSDimitry Andric if (!this->emitSetLocal(*FromT, TempOffset, E))
7066*700637cbSDimitry Andric return false;
7067*700637cbSDimitry Andric if (!this->emitGetPtrLocal(TempOffset, E))
7068*700637cbSDimitry Andric return false;
7069*700637cbSDimitry Andric } else {
7070*700637cbSDimitry Andric return false;
7071*700637cbSDimitry Andric }
7072*700637cbSDimitry Andric
7073*700637cbSDimitry Andric if (!ToT) {
7074*700637cbSDimitry Andric if (!this->emitBitCast(E))
7075*700637cbSDimitry Andric return false;
7076*700637cbSDimitry Andric return DiscardResult ? this->emitPopPtr(E) : true;
7077*700637cbSDimitry Andric }
7078*700637cbSDimitry Andric assert(ToT);
7079*700637cbSDimitry Andric
7080*700637cbSDimitry Andric const llvm::fltSemantics *TargetSemantics = nullptr;
7081*700637cbSDimitry Andric if (ToT == PT_Float)
7082*700637cbSDimitry Andric TargetSemantics = &Ctx.getFloatSemantics(ToType);
7083*700637cbSDimitry Andric
7084*700637cbSDimitry Andric // Conversion to a primitive type. FromType can be another
7085*700637cbSDimitry Andric // primitive type, or a record/array.
7086*700637cbSDimitry Andric bool ToTypeIsUChar = (ToType->isSpecificBuiltinType(BuiltinType::UChar) ||
7087*700637cbSDimitry Andric ToType->isSpecificBuiltinType(BuiltinType::Char_U));
7088*700637cbSDimitry Andric uint32_t ResultBitWidth = std::max(Ctx.getBitWidth(ToType), 8u);
7089*700637cbSDimitry Andric
7090*700637cbSDimitry Andric if (!this->emitBitCastPrim(*ToT, ToTypeIsUChar || ToType->isStdByteType(),
7091*700637cbSDimitry Andric ResultBitWidth, TargetSemantics, E))
7092*700637cbSDimitry Andric return false;
7093*700637cbSDimitry Andric
7094*700637cbSDimitry Andric if (DiscardResult)
7095*700637cbSDimitry Andric return this->emitPop(*ToT, E);
7096*700637cbSDimitry Andric
7097*700637cbSDimitry Andric return true;
7098*700637cbSDimitry Andric }
7099*700637cbSDimitry Andric
7100*700637cbSDimitry Andric namespace clang {
7101*700637cbSDimitry Andric namespace interp {
7102*700637cbSDimitry Andric
7103*700637cbSDimitry Andric template class Compiler<ByteCodeEmitter>;
7104*700637cbSDimitry Andric template class Compiler<EvalEmitter>;
7105*700637cbSDimitry Andric
7106*700637cbSDimitry Andric } // namespace interp
7107*700637cbSDimitry Andric } // namespace clang
7108