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