1a7dea167SDimitry Andric //===--- ByteCodeExprGen.cpp - Code generator for expressions ---*- C++ -*-===//
2a7dea167SDimitry Andric //
3a7dea167SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4a7dea167SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5a7dea167SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6a7dea167SDimitry Andric //
7a7dea167SDimitry Andric //===----------------------------------------------------------------------===//
8a7dea167SDimitry Andric 
9a7dea167SDimitry Andric #include "ByteCodeExprGen.h"
10a7dea167SDimitry Andric #include "ByteCodeEmitter.h"
11a7dea167SDimitry Andric #include "ByteCodeGenError.h"
12a7dea167SDimitry Andric #include "Context.h"
13a7dea167SDimitry Andric #include "Function.h"
14a7dea167SDimitry Andric #include "PrimType.h"
15a7dea167SDimitry Andric #include "Program.h"
16a7dea167SDimitry Andric #include "State.h"
17a7dea167SDimitry Andric 
18a7dea167SDimitry Andric using namespace clang;
19a7dea167SDimitry Andric using namespace clang::interp;
20a7dea167SDimitry Andric 
21a7dea167SDimitry Andric using APSInt = llvm::APSInt;
22a7dea167SDimitry Andric template <typename T> using Expected = llvm::Expected<T>;
23a7dea167SDimitry Andric template <typename T> using Optional = llvm::Optional<T>;
24a7dea167SDimitry Andric 
25a7dea167SDimitry Andric namespace clang {
26a7dea167SDimitry Andric namespace interp {
27a7dea167SDimitry Andric 
28a7dea167SDimitry Andric /// Scope used to handle temporaries in toplevel variable declarations.
29a7dea167SDimitry Andric template <class Emitter> class DeclScope final : public LocalScope<Emitter> {
30a7dea167SDimitry Andric public:
31a7dea167SDimitry Andric   DeclScope(ByteCodeExprGen<Emitter> *Ctx, const VarDecl *VD)
32a7dea167SDimitry Andric       : LocalScope<Emitter>(Ctx), Scope(Ctx->P, VD) {}
33a7dea167SDimitry Andric 
34a7dea167SDimitry Andric   void addExtended(const Scope::Local &Local) override {
35a7dea167SDimitry Andric     return this->addLocal(Local);
36a7dea167SDimitry Andric   }
37a7dea167SDimitry Andric 
38a7dea167SDimitry Andric private:
39a7dea167SDimitry Andric   Program::DeclScope Scope;
40a7dea167SDimitry Andric };
41a7dea167SDimitry Andric 
42a7dea167SDimitry Andric /// Scope used to handle initialization methods.
43a7dea167SDimitry Andric template <class Emitter> class OptionScope {
44a7dea167SDimitry Andric public:
45a7dea167SDimitry Andric   using InitFnRef = typename ByteCodeExprGen<Emitter>::InitFnRef;
46a7dea167SDimitry Andric   using ChainedInitFnRef = std::function<bool(InitFnRef)>;
47a7dea167SDimitry Andric 
48a7dea167SDimitry Andric   /// Root constructor, compiling or discarding primitives.
49a7dea167SDimitry Andric   OptionScope(ByteCodeExprGen<Emitter> *Ctx, bool NewDiscardResult)
50a7dea167SDimitry Andric       : Ctx(Ctx), OldDiscardResult(Ctx->DiscardResult),
51a7dea167SDimitry Andric         OldInitFn(std::move(Ctx->InitFn)) {
52a7dea167SDimitry Andric     Ctx->DiscardResult = NewDiscardResult;
53a7dea167SDimitry Andric     Ctx->InitFn = llvm::Optional<InitFnRef>{};
54a7dea167SDimitry Andric   }
55a7dea167SDimitry Andric 
56a7dea167SDimitry Andric   /// Root constructor, setting up compilation state.
57a7dea167SDimitry Andric   OptionScope(ByteCodeExprGen<Emitter> *Ctx, InitFnRef NewInitFn)
58a7dea167SDimitry Andric       : Ctx(Ctx), OldDiscardResult(Ctx->DiscardResult),
59a7dea167SDimitry Andric         OldInitFn(std::move(Ctx->InitFn)) {
60a7dea167SDimitry Andric     Ctx->DiscardResult = true;
61a7dea167SDimitry Andric     Ctx->InitFn = NewInitFn;
62a7dea167SDimitry Andric   }
63a7dea167SDimitry Andric 
64a7dea167SDimitry Andric   /// Extends the chain of initialisation pointers.
65a7dea167SDimitry Andric   OptionScope(ByteCodeExprGen<Emitter> *Ctx, ChainedInitFnRef NewInitFn)
66a7dea167SDimitry Andric       : Ctx(Ctx), OldDiscardResult(Ctx->DiscardResult),
67a7dea167SDimitry Andric         OldInitFn(std::move(Ctx->InitFn)) {
68a7dea167SDimitry Andric     assert(OldInitFn && "missing initializer");
69a7dea167SDimitry Andric     Ctx->InitFn = [this, NewInitFn] { return NewInitFn(*OldInitFn); };
70a7dea167SDimitry Andric   }
71a7dea167SDimitry Andric 
72a7dea167SDimitry Andric   ~OptionScope() {
73a7dea167SDimitry Andric     Ctx->DiscardResult = OldDiscardResult;
74a7dea167SDimitry Andric     Ctx->InitFn = std::move(OldInitFn);
75a7dea167SDimitry Andric   }
76a7dea167SDimitry Andric 
77a7dea167SDimitry Andric private:
78a7dea167SDimitry Andric   /// Parent context.
79a7dea167SDimitry Andric   ByteCodeExprGen<Emitter> *Ctx;
80a7dea167SDimitry Andric   /// Old discard flag to restore.
81a7dea167SDimitry Andric   bool OldDiscardResult;
82a7dea167SDimitry Andric   /// Old pointer emitter to restore.
83a7dea167SDimitry Andric   llvm::Optional<InitFnRef> OldInitFn;
84a7dea167SDimitry Andric };
85a7dea167SDimitry Andric 
86a7dea167SDimitry Andric } // namespace interp
87a7dea167SDimitry Andric } // namespace clang
88a7dea167SDimitry Andric 
89a7dea167SDimitry Andric template <class Emitter>
90a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitCastExpr(const CastExpr *CE) {
91a7dea167SDimitry Andric   auto *SubExpr = CE->getSubExpr();
92a7dea167SDimitry Andric   switch (CE->getCastKind()) {
93a7dea167SDimitry Andric 
94a7dea167SDimitry Andric   case CK_LValueToRValue: {
95a7dea167SDimitry Andric     return dereference(
96a7dea167SDimitry Andric         CE->getSubExpr(), DerefKind::Read,
97a7dea167SDimitry Andric         [](PrimType) {
98a7dea167SDimitry Andric           // Value loaded - nothing to do here.
99a7dea167SDimitry Andric           return true;
100a7dea167SDimitry Andric         },
101a7dea167SDimitry Andric         [this, CE](PrimType T) {
102a7dea167SDimitry Andric           // Pointer on stack - dereference it.
103a7dea167SDimitry Andric           if (!this->emitLoadPop(T, CE))
104a7dea167SDimitry Andric             return false;
105a7dea167SDimitry Andric           return DiscardResult ? this->emitPop(T, CE) : true;
106a7dea167SDimitry Andric         });
107a7dea167SDimitry Andric   }
108a7dea167SDimitry Andric 
109a7dea167SDimitry Andric   case CK_ArrayToPointerDecay:
110a7dea167SDimitry Andric   case CK_AtomicToNonAtomic:
111a7dea167SDimitry Andric   case CK_ConstructorConversion:
112a7dea167SDimitry Andric   case CK_FunctionToPointerDecay:
113a7dea167SDimitry Andric   case CK_NonAtomicToAtomic:
114a7dea167SDimitry Andric   case CK_NoOp:
115a7dea167SDimitry Andric   case CK_UserDefinedConversion:
116a7dea167SDimitry Andric     return this->Visit(SubExpr);
117a7dea167SDimitry Andric 
118a7dea167SDimitry Andric   case CK_ToVoid:
119a7dea167SDimitry Andric     return discard(SubExpr);
120a7dea167SDimitry Andric 
121a7dea167SDimitry Andric   default: {
122a7dea167SDimitry Andric     // TODO: implement other casts.
123a7dea167SDimitry Andric     return this->bail(CE);
124a7dea167SDimitry Andric   }
125a7dea167SDimitry Andric   }
126a7dea167SDimitry Andric }
127a7dea167SDimitry Andric 
128a7dea167SDimitry Andric template <class Emitter>
129a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitIntegerLiteral(const IntegerLiteral *LE) {
130a7dea167SDimitry Andric   if (DiscardResult)
131a7dea167SDimitry Andric     return true;
132a7dea167SDimitry Andric 
133a7dea167SDimitry Andric   auto Val = LE->getValue();
134a7dea167SDimitry Andric   QualType LitTy = LE->getType();
135a7dea167SDimitry Andric   if (Optional<PrimType> T = classify(LitTy))
136a7dea167SDimitry Andric     return emitConst(*T, getIntWidth(LitTy), LE->getValue(), LE);
137a7dea167SDimitry Andric   return this->bail(LE);
138a7dea167SDimitry Andric }
139a7dea167SDimitry Andric 
140a7dea167SDimitry Andric template <class Emitter>
141a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitParenExpr(const ParenExpr *PE) {
142a7dea167SDimitry Andric   return this->Visit(PE->getSubExpr());
143a7dea167SDimitry Andric }
144a7dea167SDimitry Andric 
145a7dea167SDimitry Andric template <class Emitter>
146a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::VisitBinaryOperator(const BinaryOperator *BO) {
147a7dea167SDimitry Andric   const Expr *LHS = BO->getLHS();
148a7dea167SDimitry Andric   const Expr *RHS = BO->getRHS();
149a7dea167SDimitry Andric 
150a7dea167SDimitry Andric   // Deal with operations which have composite or void types.
151a7dea167SDimitry Andric   switch (BO->getOpcode()) {
152a7dea167SDimitry Andric   case BO_Comma:
153a7dea167SDimitry Andric     if (!discard(LHS))
154a7dea167SDimitry Andric       return false;
155a7dea167SDimitry Andric     if (!this->Visit(RHS))
156a7dea167SDimitry Andric       return false;
157a7dea167SDimitry Andric     return true;
158a7dea167SDimitry Andric   default:
159a7dea167SDimitry Andric     break;
160a7dea167SDimitry Andric   }
161a7dea167SDimitry Andric 
162a7dea167SDimitry Andric   // Typecheck the args.
163a7dea167SDimitry Andric   Optional<PrimType> LT = classify(LHS->getType());
164a7dea167SDimitry Andric   Optional<PrimType> RT = classify(RHS->getType());
165a7dea167SDimitry Andric   if (!LT || !RT) {
166a7dea167SDimitry Andric     return this->bail(BO);
167a7dea167SDimitry Andric   }
168a7dea167SDimitry Andric 
169a7dea167SDimitry Andric   if (Optional<PrimType> T = classify(BO->getType())) {
170a7dea167SDimitry Andric     if (!visit(LHS))
171a7dea167SDimitry Andric       return false;
172a7dea167SDimitry Andric     if (!visit(RHS))
173a7dea167SDimitry Andric       return false;
174a7dea167SDimitry Andric 
175a7dea167SDimitry Andric     auto Discard = [this, T, BO](bool Result) {
176a7dea167SDimitry Andric       if (!Result)
177a7dea167SDimitry Andric         return false;
178a7dea167SDimitry Andric       return DiscardResult ? this->emitPop(*T, BO) : true;
179a7dea167SDimitry Andric     };
180a7dea167SDimitry Andric 
181a7dea167SDimitry Andric     switch (BO->getOpcode()) {
182a7dea167SDimitry Andric     case BO_EQ:
183a7dea167SDimitry Andric       return Discard(this->emitEQ(*LT, BO));
184a7dea167SDimitry Andric     case BO_NE:
185a7dea167SDimitry Andric       return Discard(this->emitNE(*LT, BO));
186a7dea167SDimitry Andric     case BO_LT:
187a7dea167SDimitry Andric       return Discard(this->emitLT(*LT, BO));
188a7dea167SDimitry Andric     case BO_LE:
189a7dea167SDimitry Andric       return Discard(this->emitLE(*LT, BO));
190a7dea167SDimitry Andric     case BO_GT:
191a7dea167SDimitry Andric       return Discard(this->emitGT(*LT, BO));
192a7dea167SDimitry Andric     case BO_GE:
193a7dea167SDimitry Andric       return Discard(this->emitGE(*LT, BO));
194a7dea167SDimitry Andric     case BO_Sub:
195a7dea167SDimitry Andric       return Discard(this->emitSub(*T, BO));
196a7dea167SDimitry Andric     case BO_Add:
197a7dea167SDimitry Andric       return Discard(this->emitAdd(*T, BO));
198a7dea167SDimitry Andric     case BO_Mul:
199a7dea167SDimitry Andric       return Discard(this->emitMul(*T, BO));
200a7dea167SDimitry Andric     default:
201a7dea167SDimitry Andric       return this->bail(BO);
202a7dea167SDimitry Andric     }
203a7dea167SDimitry Andric   }
204a7dea167SDimitry Andric 
205a7dea167SDimitry Andric   return this->bail(BO);
206a7dea167SDimitry Andric }
207a7dea167SDimitry Andric 
208a7dea167SDimitry Andric template <class Emitter>
209a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::discard(const Expr *E) {
21004eeddc0SDimitry Andric   OptionScope<Emitter> Scope(this, /*NewDiscardResult=*/true);
211a7dea167SDimitry Andric   return this->Visit(E);
212a7dea167SDimitry Andric }
213a7dea167SDimitry Andric 
214a7dea167SDimitry Andric template <class Emitter>
215a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::visit(const Expr *E) {
21604eeddc0SDimitry Andric   OptionScope<Emitter> Scope(this, /*NewDiscardResult=*/false);
217a7dea167SDimitry Andric   return this->Visit(E);
218a7dea167SDimitry Andric }
219a7dea167SDimitry Andric 
220a7dea167SDimitry Andric template <class Emitter>
221a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::visitBool(const Expr *E) {
222a7dea167SDimitry Andric   if (Optional<PrimType> T = classify(E->getType())) {
223a7dea167SDimitry Andric     return visit(E);
224a7dea167SDimitry Andric   } else {
225a7dea167SDimitry Andric     return this->bail(E);
226a7dea167SDimitry Andric   }
227a7dea167SDimitry Andric }
228a7dea167SDimitry Andric 
229a7dea167SDimitry Andric template <class Emitter>
230a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::visitZeroInitializer(PrimType T, const Expr *E) {
231a7dea167SDimitry Andric   switch (T) {
232a7dea167SDimitry Andric   case PT_Bool:
233a7dea167SDimitry Andric     return this->emitZeroBool(E);
234a7dea167SDimitry Andric   case PT_Sint8:
235a7dea167SDimitry Andric     return this->emitZeroSint8(E);
236a7dea167SDimitry Andric   case PT_Uint8:
237a7dea167SDimitry Andric     return this->emitZeroUint8(E);
238a7dea167SDimitry Andric   case PT_Sint16:
239a7dea167SDimitry Andric     return this->emitZeroSint16(E);
240a7dea167SDimitry Andric   case PT_Uint16:
241a7dea167SDimitry Andric     return this->emitZeroUint16(E);
242a7dea167SDimitry Andric   case PT_Sint32:
243a7dea167SDimitry Andric     return this->emitZeroSint32(E);
244a7dea167SDimitry Andric   case PT_Uint32:
245a7dea167SDimitry Andric     return this->emitZeroUint32(E);
246a7dea167SDimitry Andric   case PT_Sint64:
247a7dea167SDimitry Andric     return this->emitZeroSint64(E);
248a7dea167SDimitry Andric   case PT_Uint64:
249a7dea167SDimitry Andric     return this->emitZeroUint64(E);
250a7dea167SDimitry Andric   case PT_Ptr:
251a7dea167SDimitry Andric     return this->emitNullPtr(E);
252a7dea167SDimitry Andric   }
253a7dea167SDimitry Andric   llvm_unreachable("unknown primitive type");
254a7dea167SDimitry Andric }
255a7dea167SDimitry Andric 
256a7dea167SDimitry Andric template <class Emitter>
257a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::dereference(
258a7dea167SDimitry Andric     const Expr *LV, DerefKind AK, llvm::function_ref<bool(PrimType)> Direct,
259a7dea167SDimitry Andric     llvm::function_ref<bool(PrimType)> Indirect) {
260a7dea167SDimitry Andric   if (Optional<PrimType> T = classify(LV->getType())) {
261a7dea167SDimitry Andric     if (!LV->refersToBitField()) {
262a7dea167SDimitry Andric       // Only primitive, non bit-field types can be dereferenced directly.
263a7dea167SDimitry Andric       if (auto *DE = dyn_cast<DeclRefExpr>(LV)) {
264a7dea167SDimitry Andric         if (!DE->getDecl()->getType()->isReferenceType()) {
265a7dea167SDimitry Andric           if (auto *PD = dyn_cast<ParmVarDecl>(DE->getDecl()))
266a7dea167SDimitry Andric             return dereferenceParam(LV, *T, PD, AK, Direct, Indirect);
267a7dea167SDimitry Andric           if (auto *VD = dyn_cast<VarDecl>(DE->getDecl()))
268a7dea167SDimitry Andric             return dereferenceVar(LV, *T, VD, AK, Direct, Indirect);
269a7dea167SDimitry Andric         }
270a7dea167SDimitry Andric       }
271a7dea167SDimitry Andric     }
272a7dea167SDimitry Andric 
273a7dea167SDimitry Andric     if (!visit(LV))
274a7dea167SDimitry Andric       return false;
275a7dea167SDimitry Andric     return Indirect(*T);
276a7dea167SDimitry Andric   }
277a7dea167SDimitry Andric 
278a7dea167SDimitry Andric   return false;
279a7dea167SDimitry Andric }
280a7dea167SDimitry Andric 
281a7dea167SDimitry Andric template <class Emitter>
282a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::dereferenceParam(
283a7dea167SDimitry Andric     const Expr *LV, PrimType T, const ParmVarDecl *PD, DerefKind AK,
284a7dea167SDimitry Andric     llvm::function_ref<bool(PrimType)> Direct,
285a7dea167SDimitry Andric     llvm::function_ref<bool(PrimType)> Indirect) {
286a7dea167SDimitry Andric   auto It = this->Params.find(PD);
287a7dea167SDimitry Andric   if (It != this->Params.end()) {
288a7dea167SDimitry Andric     unsigned Idx = It->second;
289a7dea167SDimitry Andric     switch (AK) {
290a7dea167SDimitry Andric     case DerefKind::Read:
291a7dea167SDimitry Andric       return DiscardResult ? true : this->emitGetParam(T, Idx, LV);
292a7dea167SDimitry Andric 
293a7dea167SDimitry Andric     case DerefKind::Write:
294a7dea167SDimitry Andric       if (!Direct(T))
295a7dea167SDimitry Andric         return false;
296a7dea167SDimitry Andric       if (!this->emitSetParam(T, Idx, LV))
297a7dea167SDimitry Andric         return false;
298a7dea167SDimitry Andric       return DiscardResult ? true : this->emitGetPtrParam(Idx, LV);
299a7dea167SDimitry Andric 
300a7dea167SDimitry Andric     case DerefKind::ReadWrite:
301a7dea167SDimitry Andric       if (!this->emitGetParam(T, Idx, LV))
302a7dea167SDimitry Andric         return false;
303a7dea167SDimitry Andric       if (!Direct(T))
304a7dea167SDimitry Andric         return false;
305a7dea167SDimitry Andric       if (!this->emitSetParam(T, Idx, LV))
306a7dea167SDimitry Andric         return false;
307a7dea167SDimitry Andric       return DiscardResult ? true : this->emitGetPtrParam(Idx, LV);
308a7dea167SDimitry Andric     }
309a7dea167SDimitry Andric     return true;
310a7dea167SDimitry Andric   }
311a7dea167SDimitry Andric 
312a7dea167SDimitry Andric   // If the param is a pointer, we can dereference a dummy value.
313a7dea167SDimitry Andric   if (!DiscardResult && T == PT_Ptr && AK == DerefKind::Read) {
314a7dea167SDimitry Andric     if (auto Idx = P.getOrCreateDummy(PD))
315a7dea167SDimitry Andric       return this->emitGetPtrGlobal(*Idx, PD);
316a7dea167SDimitry Andric     return false;
317a7dea167SDimitry Andric   }
318a7dea167SDimitry Andric 
319a7dea167SDimitry Andric   // Value cannot be produced - try to emit pointer and do stuff with it.
320a7dea167SDimitry Andric   return visit(LV) && Indirect(T);
321a7dea167SDimitry Andric }
322a7dea167SDimitry Andric 
323a7dea167SDimitry Andric template <class Emitter>
324a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::dereferenceVar(
325a7dea167SDimitry Andric     const Expr *LV, PrimType T, const VarDecl *VD, DerefKind AK,
326a7dea167SDimitry Andric     llvm::function_ref<bool(PrimType)> Direct,
327a7dea167SDimitry Andric     llvm::function_ref<bool(PrimType)> Indirect) {
328a7dea167SDimitry Andric   auto It = Locals.find(VD);
329a7dea167SDimitry Andric   if (It != Locals.end()) {
330a7dea167SDimitry Andric     const auto &L = It->second;
331a7dea167SDimitry Andric     switch (AK) {
332a7dea167SDimitry Andric     case DerefKind::Read:
333a7dea167SDimitry Andric       if (!this->emitGetLocal(T, L.Offset, LV))
334a7dea167SDimitry Andric         return false;
335a7dea167SDimitry Andric       return DiscardResult ? this->emitPop(T, LV) : true;
336a7dea167SDimitry Andric 
337a7dea167SDimitry Andric     case DerefKind::Write:
338a7dea167SDimitry Andric       if (!Direct(T))
339a7dea167SDimitry Andric         return false;
340a7dea167SDimitry Andric       if (!this->emitSetLocal(T, L.Offset, LV))
341a7dea167SDimitry Andric         return false;
342a7dea167SDimitry Andric       return DiscardResult ? true : this->emitGetPtrLocal(L.Offset, LV);
343a7dea167SDimitry Andric 
344a7dea167SDimitry Andric     case DerefKind::ReadWrite:
345a7dea167SDimitry Andric       if (!this->emitGetLocal(T, L.Offset, LV))
346a7dea167SDimitry Andric         return false;
347a7dea167SDimitry Andric       if (!Direct(T))
348a7dea167SDimitry Andric         return false;
349a7dea167SDimitry Andric       if (!this->emitSetLocal(T, L.Offset, LV))
350a7dea167SDimitry Andric         return false;
351a7dea167SDimitry Andric       return DiscardResult ? true : this->emitGetPtrLocal(L.Offset, LV);
352a7dea167SDimitry Andric     }
353a7dea167SDimitry Andric   } else if (auto Idx = getGlobalIdx(VD)) {
354a7dea167SDimitry Andric     switch (AK) {
355a7dea167SDimitry Andric     case DerefKind::Read:
356a7dea167SDimitry Andric       if (!this->emitGetGlobal(T, *Idx, LV))
357a7dea167SDimitry Andric         return false;
358a7dea167SDimitry Andric       return DiscardResult ? this->emitPop(T, LV) : true;
359a7dea167SDimitry Andric 
360a7dea167SDimitry Andric     case DerefKind::Write:
361a7dea167SDimitry Andric       if (!Direct(T))
362a7dea167SDimitry Andric         return false;
363a7dea167SDimitry Andric       if (!this->emitSetGlobal(T, *Idx, LV))
364a7dea167SDimitry Andric         return false;
365a7dea167SDimitry Andric       return DiscardResult ? true : this->emitGetPtrGlobal(*Idx, LV);
366a7dea167SDimitry Andric 
367a7dea167SDimitry Andric     case DerefKind::ReadWrite:
368a7dea167SDimitry Andric       if (!this->emitGetGlobal(T, *Idx, LV))
369a7dea167SDimitry Andric         return false;
370a7dea167SDimitry Andric       if (!Direct(T))
371a7dea167SDimitry Andric         return false;
372a7dea167SDimitry Andric       if (!this->emitSetGlobal(T, *Idx, LV))
373a7dea167SDimitry Andric         return false;
374a7dea167SDimitry Andric       return DiscardResult ? true : this->emitGetPtrGlobal(*Idx, LV);
375a7dea167SDimitry Andric     }
376a7dea167SDimitry Andric   }
377a7dea167SDimitry Andric 
378a7dea167SDimitry Andric   // If the declaration is a constant value, emit it here even
379a7dea167SDimitry Andric   // though the declaration was not evaluated in the current scope.
380a7dea167SDimitry Andric   // The access mode can only be read in this case.
381a7dea167SDimitry Andric   if (!DiscardResult && AK == DerefKind::Read) {
382a7dea167SDimitry Andric     if (VD->hasLocalStorage() && VD->hasInit() && !VD->isConstexpr()) {
383a7dea167SDimitry Andric       QualType VT = VD->getType();
384a7dea167SDimitry Andric       if (VT.isConstQualified() && VT->isFundamentalType())
385a7dea167SDimitry Andric         return this->Visit(VD->getInit());
386a7dea167SDimitry Andric     }
387a7dea167SDimitry Andric   }
388a7dea167SDimitry Andric 
389a7dea167SDimitry Andric   // Value cannot be produced - try to emit pointer.
390a7dea167SDimitry Andric   return visit(LV) && Indirect(T);
391a7dea167SDimitry Andric }
392a7dea167SDimitry Andric 
393a7dea167SDimitry Andric template <class Emitter>
394a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::emitConst(PrimType T, unsigned NumBits,
395a7dea167SDimitry Andric                                          const APInt &Value, const Expr *E) {
396a7dea167SDimitry Andric   switch (T) {
397a7dea167SDimitry Andric   case PT_Sint8:
398a7dea167SDimitry Andric     return this->emitConstSint8(Value.getSExtValue(), E);
399a7dea167SDimitry Andric   case PT_Uint8:
400a7dea167SDimitry Andric     return this->emitConstUint8(Value.getZExtValue(), E);
401a7dea167SDimitry Andric   case PT_Sint16:
402a7dea167SDimitry Andric     return this->emitConstSint16(Value.getSExtValue(), E);
403a7dea167SDimitry Andric   case PT_Uint16:
404a7dea167SDimitry Andric     return this->emitConstUint16(Value.getZExtValue(), E);
405a7dea167SDimitry Andric   case PT_Sint32:
406a7dea167SDimitry Andric     return this->emitConstSint32(Value.getSExtValue(), E);
407a7dea167SDimitry Andric   case PT_Uint32:
408a7dea167SDimitry Andric     return this->emitConstUint32(Value.getZExtValue(), E);
409a7dea167SDimitry Andric   case PT_Sint64:
410a7dea167SDimitry Andric     return this->emitConstSint64(Value.getSExtValue(), E);
411a7dea167SDimitry Andric   case PT_Uint64:
412a7dea167SDimitry Andric     return this->emitConstUint64(Value.getZExtValue(), E);
413a7dea167SDimitry Andric   case PT_Bool:
414a7dea167SDimitry Andric     return this->emitConstBool(Value.getBoolValue(), E);
415a7dea167SDimitry Andric   case PT_Ptr:
416a7dea167SDimitry Andric     llvm_unreachable("Invalid integral type");
417a7dea167SDimitry Andric     break;
418a7dea167SDimitry Andric   }
419a7dea167SDimitry Andric   llvm_unreachable("unknown primitive type");
420a7dea167SDimitry Andric }
421a7dea167SDimitry Andric 
422a7dea167SDimitry Andric template <class Emitter>
423a7dea167SDimitry Andric unsigned ByteCodeExprGen<Emitter>::allocateLocalPrimitive(DeclTy &&Src,
424a7dea167SDimitry Andric                                                           PrimType Ty,
425a7dea167SDimitry Andric                                                           bool IsConst,
426a7dea167SDimitry Andric                                                           bool IsExtended) {
427a7dea167SDimitry Andric   Descriptor *D = P.createDescriptor(Src, Ty, IsConst, Src.is<const Expr *>());
428a7dea167SDimitry Andric   Scope::Local Local = this->createLocal(D);
429a7dea167SDimitry Andric   if (auto *VD = dyn_cast_or_null<ValueDecl>(Src.dyn_cast<const Decl *>()))
430a7dea167SDimitry Andric     Locals.insert({VD, Local});
431a7dea167SDimitry Andric   VarScope->add(Local, IsExtended);
432a7dea167SDimitry Andric   return Local.Offset;
433a7dea167SDimitry Andric }
434a7dea167SDimitry Andric 
435a7dea167SDimitry Andric template <class Emitter>
436a7dea167SDimitry Andric llvm::Optional<unsigned>
437a7dea167SDimitry Andric ByteCodeExprGen<Emitter>::allocateLocal(DeclTy &&Src, bool IsExtended) {
438a7dea167SDimitry Andric   QualType Ty;
439a7dea167SDimitry Andric 
440a7dea167SDimitry Andric   const ValueDecl *Key = nullptr;
441a7dea167SDimitry Andric   bool IsTemporary = false;
442a7dea167SDimitry Andric   if (auto *VD = dyn_cast_or_null<ValueDecl>(Src.dyn_cast<const Decl *>())) {
443a7dea167SDimitry Andric     Key = VD;
444a7dea167SDimitry Andric     Ty = VD->getType();
445a7dea167SDimitry Andric   }
446a7dea167SDimitry Andric   if (auto *E = Src.dyn_cast<const Expr *>()) {
447a7dea167SDimitry Andric     IsTemporary = true;
448a7dea167SDimitry Andric     Ty = E->getType();
449a7dea167SDimitry Andric   }
450a7dea167SDimitry Andric 
451a7dea167SDimitry Andric   Descriptor *D = P.createDescriptor(Src, Ty.getTypePtr(),
452a7dea167SDimitry Andric                                      Ty.isConstQualified(), IsTemporary);
453a7dea167SDimitry Andric   if (!D)
454a7dea167SDimitry Andric     return {};
455a7dea167SDimitry Andric 
456a7dea167SDimitry Andric   Scope::Local Local = this->createLocal(D);
457a7dea167SDimitry Andric   if (Key)
458a7dea167SDimitry Andric     Locals.insert({Key, Local});
459a7dea167SDimitry Andric   VarScope->add(Local, IsExtended);
460a7dea167SDimitry Andric   return Local.Offset;
461a7dea167SDimitry Andric }
462a7dea167SDimitry Andric 
463a7dea167SDimitry Andric template <class Emitter>
464a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::visitInitializer(
465a7dea167SDimitry Andric     const Expr *Init, InitFnRef InitFn) {
466a7dea167SDimitry Andric   OptionScope<Emitter> Scope(this, InitFn);
467a7dea167SDimitry Andric   return this->Visit(Init);
468a7dea167SDimitry Andric }
469a7dea167SDimitry Andric 
470a7dea167SDimitry Andric template <class Emitter>
471a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::getPtrVarDecl(const VarDecl *VD, const Expr *E) {
472a7dea167SDimitry Andric   // Generate a pointer to the local, loading refs.
473a7dea167SDimitry Andric   if (Optional<unsigned> Idx = getGlobalIdx(VD)) {
474a7dea167SDimitry Andric     if (VD->getType()->isReferenceType())
475a7dea167SDimitry Andric       return this->emitGetGlobalPtr(*Idx, E);
476a7dea167SDimitry Andric     else
477a7dea167SDimitry Andric       return this->emitGetPtrGlobal(*Idx, E);
478a7dea167SDimitry Andric   }
479a7dea167SDimitry Andric   return this->bail(VD);
480a7dea167SDimitry Andric }
481a7dea167SDimitry Andric 
482a7dea167SDimitry Andric template <class Emitter>
483a7dea167SDimitry Andric llvm::Optional<unsigned>
484a7dea167SDimitry Andric ByteCodeExprGen<Emitter>::getGlobalIdx(const VarDecl *VD) {
485a7dea167SDimitry Andric   if (VD->isConstexpr()) {
486a7dea167SDimitry Andric     // Constexpr decl - it must have already been defined.
487a7dea167SDimitry Andric     return P.getGlobal(VD);
488a7dea167SDimitry Andric   }
489a7dea167SDimitry Andric   if (!VD->hasLocalStorage()) {
490a7dea167SDimitry Andric     // Not constexpr, but a global var - can have pointer taken.
491a7dea167SDimitry Andric     Program::DeclScope Scope(P, VD);
492a7dea167SDimitry Andric     return P.getOrCreateGlobal(VD);
493a7dea167SDimitry Andric   }
494a7dea167SDimitry Andric   return {};
495a7dea167SDimitry Andric }
496a7dea167SDimitry Andric 
497a7dea167SDimitry Andric template <class Emitter>
498a7dea167SDimitry Andric const RecordType *ByteCodeExprGen<Emitter>::getRecordTy(QualType Ty) {
499a7dea167SDimitry Andric   if (auto *PT = dyn_cast<PointerType>(Ty))
500a7dea167SDimitry Andric     return PT->getPointeeType()->getAs<RecordType>();
501a7dea167SDimitry Andric   else
502a7dea167SDimitry Andric     return Ty->getAs<RecordType>();
503a7dea167SDimitry Andric }
504a7dea167SDimitry Andric 
505a7dea167SDimitry Andric template <class Emitter>
506a7dea167SDimitry Andric Record *ByteCodeExprGen<Emitter>::getRecord(QualType Ty) {
507a7dea167SDimitry Andric   if (auto *RecordTy = getRecordTy(Ty)) {
508a7dea167SDimitry Andric     return getRecord(RecordTy->getDecl());
509a7dea167SDimitry Andric   }
510a7dea167SDimitry Andric   return nullptr;
511a7dea167SDimitry Andric }
512a7dea167SDimitry Andric 
513a7dea167SDimitry Andric template <class Emitter>
514a7dea167SDimitry Andric Record *ByteCodeExprGen<Emitter>::getRecord(const RecordDecl *RD) {
515a7dea167SDimitry Andric   return P.getOrCreateRecord(RD);
516a7dea167SDimitry Andric }
517a7dea167SDimitry Andric 
518a7dea167SDimitry Andric template <class Emitter>
519a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::visitExpr(const Expr *Exp) {
520a7dea167SDimitry Andric   ExprScope<Emitter> RootScope(this);
521a7dea167SDimitry Andric   if (!visit(Exp))
522a7dea167SDimitry Andric     return false;
523a7dea167SDimitry Andric 
524a7dea167SDimitry Andric   if (Optional<PrimType> T = classify(Exp))
525a7dea167SDimitry Andric     return this->emitRet(*T, Exp);
526a7dea167SDimitry Andric   else
527a7dea167SDimitry Andric     return this->emitRetValue(Exp);
528a7dea167SDimitry Andric }
529a7dea167SDimitry Andric 
530a7dea167SDimitry Andric template <class Emitter>
531a7dea167SDimitry Andric bool ByteCodeExprGen<Emitter>::visitDecl(const VarDecl *VD) {
532a7dea167SDimitry Andric   const Expr *Init = VD->getInit();
533a7dea167SDimitry Andric 
534a7dea167SDimitry Andric   if (Optional<unsigned> I = P.createGlobal(VD)) {
535a7dea167SDimitry Andric     if (Optional<PrimType> T = classify(VD->getType())) {
536a7dea167SDimitry Andric       {
537a7dea167SDimitry Andric         // Primitive declarations - compute the value and set it.
538a7dea167SDimitry Andric         DeclScope<Emitter> LocalScope(this, VD);
539a7dea167SDimitry Andric         if (!visit(Init))
540a7dea167SDimitry Andric           return false;
541a7dea167SDimitry Andric       }
542a7dea167SDimitry Andric 
543a7dea167SDimitry Andric       // If the declaration is global, save the value for later use.
544a7dea167SDimitry Andric       if (!this->emitDup(*T, VD))
545a7dea167SDimitry Andric         return false;
546a7dea167SDimitry Andric       if (!this->emitInitGlobal(*T, *I, VD))
547a7dea167SDimitry Andric         return false;
548a7dea167SDimitry Andric       return this->emitRet(*T, VD);
549a7dea167SDimitry Andric     } else {
550a7dea167SDimitry Andric       {
551a7dea167SDimitry Andric         // Composite declarations - allocate storage and initialize it.
552a7dea167SDimitry Andric         DeclScope<Emitter> LocalScope(this, VD);
553a7dea167SDimitry Andric         if (!visitGlobalInitializer(Init, *I))
554a7dea167SDimitry Andric           return false;
555a7dea167SDimitry Andric       }
556a7dea167SDimitry Andric 
557a7dea167SDimitry Andric       // Return a pointer to the global.
558a7dea167SDimitry Andric       if (!this->emitGetPtrGlobal(*I, VD))
559a7dea167SDimitry Andric         return false;
560a7dea167SDimitry Andric       return this->emitRetValue(VD);
561a7dea167SDimitry Andric     }
562a7dea167SDimitry Andric   }
563a7dea167SDimitry Andric 
564a7dea167SDimitry Andric   return this->bail(VD);
565a7dea167SDimitry Andric }
566a7dea167SDimitry Andric 
567a7dea167SDimitry Andric template <class Emitter>
568a7dea167SDimitry Andric void ByteCodeExprGen<Emitter>::emitCleanup() {
569a7dea167SDimitry Andric   for (VariableScope<Emitter> *C = VarScope; C; C = C->getParent())
570a7dea167SDimitry Andric     C->emitDestruction();
571a7dea167SDimitry Andric }
572a7dea167SDimitry Andric 
573a7dea167SDimitry Andric namespace clang {
574a7dea167SDimitry Andric namespace interp {
575a7dea167SDimitry Andric 
576a7dea167SDimitry Andric template class ByteCodeExprGen<ByteCodeEmitter>;
577a7dea167SDimitry Andric template class ByteCodeExprGen<EvalEmitter>;
578a7dea167SDimitry Andric 
579a7dea167SDimitry Andric } // namespace interp
580a7dea167SDimitry Andric } // namespace clang
581