1950b70dcSNandor Licker //===--- ByteCodeExprGen.cpp - Code generator for expressions ---*- C++ -*-===//
2950b70dcSNandor Licker //
3950b70dcSNandor Licker // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4950b70dcSNandor Licker // See https://llvm.org/LICENSE.txt for license information.
5950b70dcSNandor Licker // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6950b70dcSNandor Licker //
7950b70dcSNandor Licker //===----------------------------------------------------------------------===//
8950b70dcSNandor Licker
9950b70dcSNandor Licker #include "ByteCodeExprGen.h"
10950b70dcSNandor Licker #include "ByteCodeEmitter.h"
11950b70dcSNandor Licker #include "ByteCodeGenError.h"
12950b70dcSNandor Licker #include "Context.h"
13950b70dcSNandor Licker #include "Function.h"
14950b70dcSNandor Licker #include "PrimType.h"
15950b70dcSNandor Licker #include "Program.h"
16950b70dcSNandor Licker #include "State.h"
17950b70dcSNandor Licker
18950b70dcSNandor Licker using namespace clang;
19950b70dcSNandor Licker using namespace clang::interp;
20950b70dcSNandor Licker
21950b70dcSNandor Licker using APSInt = llvm::APSInt;
22950b70dcSNandor Licker template <typename T> using Expected = llvm::Expected<T>;
23950b70dcSNandor Licker template <typename T> using Optional = llvm::Optional<T>;
24950b70dcSNandor Licker
25950b70dcSNandor Licker namespace clang {
26950b70dcSNandor Licker namespace interp {
27950b70dcSNandor Licker
28950b70dcSNandor Licker /// Scope used to handle temporaries in toplevel variable declarations.
29950b70dcSNandor Licker template <class Emitter> class DeclScope final : public LocalScope<Emitter> {
30950b70dcSNandor Licker public:
DeclScope(ByteCodeExprGen<Emitter> * Ctx,const VarDecl * VD)31950b70dcSNandor Licker DeclScope(ByteCodeExprGen<Emitter> *Ctx, const VarDecl *VD)
32950b70dcSNandor Licker : LocalScope<Emitter>(Ctx), Scope(Ctx->P, VD) {}
33950b70dcSNandor Licker
addExtended(const Scope::Local & Local)34950b70dcSNandor Licker void addExtended(const Scope::Local &Local) override {
35950b70dcSNandor Licker return this->addLocal(Local);
36950b70dcSNandor Licker }
37950b70dcSNandor Licker
38950b70dcSNandor Licker private:
39950b70dcSNandor Licker Program::DeclScope Scope;
40950b70dcSNandor Licker };
41950b70dcSNandor Licker
42950b70dcSNandor Licker /// Scope used to handle initialization methods.
43950b70dcSNandor Licker template <class Emitter> class OptionScope {
44950b70dcSNandor Licker public:
45950b70dcSNandor Licker using InitFnRef = typename ByteCodeExprGen<Emitter>::InitFnRef;
46950b70dcSNandor Licker using ChainedInitFnRef = std::function<bool(InitFnRef)>;
47950b70dcSNandor Licker
48950b70dcSNandor Licker /// Root constructor, compiling or discarding primitives.
OptionScope(ByteCodeExprGen<Emitter> * Ctx,bool NewDiscardResult)49950b70dcSNandor Licker OptionScope(ByteCodeExprGen<Emitter> *Ctx, bool NewDiscardResult)
50950b70dcSNandor Licker : Ctx(Ctx), OldDiscardResult(Ctx->DiscardResult),
51950b70dcSNandor Licker OldInitFn(std::move(Ctx->InitFn)) {
52950b70dcSNandor Licker Ctx->DiscardResult = NewDiscardResult;
53950b70dcSNandor Licker Ctx->InitFn = llvm::Optional<InitFnRef>{};
54950b70dcSNandor Licker }
55950b70dcSNandor Licker
56950b70dcSNandor Licker /// Root constructor, setting up compilation state.
OptionScope(ByteCodeExprGen<Emitter> * Ctx,InitFnRef NewInitFn)57950b70dcSNandor Licker OptionScope(ByteCodeExprGen<Emitter> *Ctx, InitFnRef NewInitFn)
58950b70dcSNandor Licker : Ctx(Ctx), OldDiscardResult(Ctx->DiscardResult),
59950b70dcSNandor Licker OldInitFn(std::move(Ctx->InitFn)) {
60950b70dcSNandor Licker Ctx->DiscardResult = true;
61950b70dcSNandor Licker Ctx->InitFn = NewInitFn;
62950b70dcSNandor Licker }
63950b70dcSNandor Licker
64950b70dcSNandor Licker /// Extends the chain of initialisation pointers.
OptionScope(ByteCodeExprGen<Emitter> * Ctx,ChainedInitFnRef NewInitFn)65950b70dcSNandor Licker OptionScope(ByteCodeExprGen<Emitter> *Ctx, ChainedInitFnRef NewInitFn)
66950b70dcSNandor Licker : Ctx(Ctx), OldDiscardResult(Ctx->DiscardResult),
67950b70dcSNandor Licker OldInitFn(std::move(Ctx->InitFn)) {
68950b70dcSNandor Licker assert(OldInitFn && "missing initializer");
69950b70dcSNandor Licker Ctx->InitFn = [this, NewInitFn] { return NewInitFn(*OldInitFn); };
70950b70dcSNandor Licker }
71950b70dcSNandor Licker
~OptionScope()72950b70dcSNandor Licker ~OptionScope() {
73950b70dcSNandor Licker Ctx->DiscardResult = OldDiscardResult;
74950b70dcSNandor Licker Ctx->InitFn = std::move(OldInitFn);
75950b70dcSNandor Licker }
76950b70dcSNandor Licker
77950b70dcSNandor Licker private:
78950b70dcSNandor Licker /// Parent context.
79950b70dcSNandor Licker ByteCodeExprGen<Emitter> *Ctx;
80950b70dcSNandor Licker /// Old discard flag to restore.
81950b70dcSNandor Licker bool OldDiscardResult;
82950b70dcSNandor Licker /// Old pointer emitter to restore.
83950b70dcSNandor Licker llvm::Optional<InitFnRef> OldInitFn;
84950b70dcSNandor Licker };
85950b70dcSNandor Licker
86950b70dcSNandor Licker } // namespace interp
87950b70dcSNandor Licker } // namespace clang
88950b70dcSNandor Licker
89950b70dcSNandor Licker template <class Emitter>
VisitCastExpr(const CastExpr * CE)90950b70dcSNandor Licker bool ByteCodeExprGen<Emitter>::VisitCastExpr(const CastExpr *CE) {
91950b70dcSNandor Licker auto *SubExpr = CE->getSubExpr();
92950b70dcSNandor Licker switch (CE->getCastKind()) {
93950b70dcSNandor Licker
94950b70dcSNandor Licker case CK_LValueToRValue: {
95950b70dcSNandor Licker return dereference(
96950b70dcSNandor Licker CE->getSubExpr(), DerefKind::Read,
97950b70dcSNandor Licker [](PrimType) {
98950b70dcSNandor Licker // Value loaded - nothing to do here.
99950b70dcSNandor Licker return true;
100950b70dcSNandor Licker },
101950b70dcSNandor Licker [this, CE](PrimType T) {
102950b70dcSNandor Licker // Pointer on stack - dereference it.
103950b70dcSNandor Licker if (!this->emitLoadPop(T, CE))
104950b70dcSNandor Licker return false;
105950b70dcSNandor Licker return DiscardResult ? this->emitPop(T, CE) : true;
106950b70dcSNandor Licker });
107950b70dcSNandor Licker }
108950b70dcSNandor Licker
109950b70dcSNandor Licker case CK_ArrayToPointerDecay:
110950b70dcSNandor Licker case CK_AtomicToNonAtomic:
111950b70dcSNandor Licker case CK_ConstructorConversion:
112950b70dcSNandor Licker case CK_FunctionToPointerDecay:
113950b70dcSNandor Licker case CK_NonAtomicToAtomic:
114950b70dcSNandor Licker case CK_NoOp:
115950b70dcSNandor Licker case CK_UserDefinedConversion:
116950b70dcSNandor Licker return this->Visit(SubExpr);
117950b70dcSNandor Licker
118950b70dcSNandor Licker case CK_ToVoid:
119950b70dcSNandor Licker return discard(SubExpr);
120950b70dcSNandor Licker
121950b70dcSNandor Licker default: {
122950b70dcSNandor Licker // TODO: implement other casts.
123950b70dcSNandor Licker return this->bail(CE);
124950b70dcSNandor Licker }
125950b70dcSNandor Licker }
126950b70dcSNandor Licker }
127950b70dcSNandor Licker
128950b70dcSNandor Licker template <class Emitter>
VisitIntegerLiteral(const IntegerLiteral * LE)129950b70dcSNandor Licker bool ByteCodeExprGen<Emitter>::VisitIntegerLiteral(const IntegerLiteral *LE) {
130950b70dcSNandor Licker if (DiscardResult)
131950b70dcSNandor Licker return true;
132950b70dcSNandor Licker
133950b70dcSNandor Licker auto Val = LE->getValue();
134950b70dcSNandor Licker QualType LitTy = LE->getType();
135950b70dcSNandor Licker if (Optional<PrimType> T = classify(LitTy))
136950b70dcSNandor Licker return emitConst(*T, getIntWidth(LitTy), LE->getValue(), LE);
137950b70dcSNandor Licker return this->bail(LE);
138950b70dcSNandor Licker }
139950b70dcSNandor Licker
140950b70dcSNandor Licker template <class Emitter>
VisitParenExpr(const ParenExpr * PE)141950b70dcSNandor Licker bool ByteCodeExprGen<Emitter>::VisitParenExpr(const ParenExpr *PE) {
142950b70dcSNandor Licker return this->Visit(PE->getSubExpr());
143950b70dcSNandor Licker }
144950b70dcSNandor Licker
145950b70dcSNandor Licker template <class Emitter>
VisitBinaryOperator(const BinaryOperator * BO)146950b70dcSNandor Licker bool ByteCodeExprGen<Emitter>::VisitBinaryOperator(const BinaryOperator *BO) {
147950b70dcSNandor Licker const Expr *LHS = BO->getLHS();
148950b70dcSNandor Licker const Expr *RHS = BO->getRHS();
149950b70dcSNandor Licker
150950b70dcSNandor Licker // Deal with operations which have composite or void types.
151950b70dcSNandor Licker switch (BO->getOpcode()) {
152950b70dcSNandor Licker case BO_Comma:
153950b70dcSNandor Licker if (!discard(LHS))
154950b70dcSNandor Licker return false;
155950b70dcSNandor Licker if (!this->Visit(RHS))
156950b70dcSNandor Licker return false;
157950b70dcSNandor Licker return true;
158950b70dcSNandor Licker default:
159950b70dcSNandor Licker break;
160950b70dcSNandor Licker }
161950b70dcSNandor Licker
162950b70dcSNandor Licker // Typecheck the args.
163950b70dcSNandor Licker Optional<PrimType> LT = classify(LHS->getType());
164950b70dcSNandor Licker Optional<PrimType> RT = classify(RHS->getType());
165950b70dcSNandor Licker if (!LT || !RT) {
166950b70dcSNandor Licker return this->bail(BO);
167950b70dcSNandor Licker }
168950b70dcSNandor Licker
169950b70dcSNandor Licker if (Optional<PrimType> T = classify(BO->getType())) {
170950b70dcSNandor Licker if (!visit(LHS))
171950b70dcSNandor Licker return false;
172950b70dcSNandor Licker if (!visit(RHS))
173950b70dcSNandor Licker return false;
174950b70dcSNandor Licker
175950b70dcSNandor Licker auto Discard = [this, T, BO](bool Result) {
176950b70dcSNandor Licker if (!Result)
177950b70dcSNandor Licker return false;
178950b70dcSNandor Licker return DiscardResult ? this->emitPop(*T, BO) : true;
179950b70dcSNandor Licker };
180950b70dcSNandor Licker
181950b70dcSNandor Licker switch (BO->getOpcode()) {
182950b70dcSNandor Licker case BO_EQ:
183950b70dcSNandor Licker return Discard(this->emitEQ(*LT, BO));
184950b70dcSNandor Licker case BO_NE:
185950b70dcSNandor Licker return Discard(this->emitNE(*LT, BO));
186950b70dcSNandor Licker case BO_LT:
187950b70dcSNandor Licker return Discard(this->emitLT(*LT, BO));
188950b70dcSNandor Licker case BO_LE:
189950b70dcSNandor Licker return Discard(this->emitLE(*LT, BO));
190950b70dcSNandor Licker case BO_GT:
191950b70dcSNandor Licker return Discard(this->emitGT(*LT, BO));
192950b70dcSNandor Licker case BO_GE:
193950b70dcSNandor Licker return Discard(this->emitGE(*LT, BO));
194950b70dcSNandor Licker case BO_Sub:
195950b70dcSNandor Licker return Discard(this->emitSub(*T, BO));
196950b70dcSNandor Licker case BO_Add:
197950b70dcSNandor Licker return Discard(this->emitAdd(*T, BO));
198950b70dcSNandor Licker case BO_Mul:
199950b70dcSNandor Licker return Discard(this->emitMul(*T, BO));
200950b70dcSNandor Licker default:
201950b70dcSNandor Licker return this->bail(BO);
202950b70dcSNandor Licker }
203950b70dcSNandor Licker }
204950b70dcSNandor Licker
205950b70dcSNandor Licker return this->bail(BO);
206950b70dcSNandor Licker }
207950b70dcSNandor Licker
208950b70dcSNandor Licker template <class Emitter>
discard(const Expr * E)209950b70dcSNandor Licker bool ByteCodeExprGen<Emitter>::discard(const Expr *E) {
21017d4bd3dSKazu Hirata OptionScope<Emitter> Scope(this, /*NewDiscardResult=*/true);
211950b70dcSNandor Licker return this->Visit(E);
212950b70dcSNandor Licker }
213950b70dcSNandor Licker
214950b70dcSNandor Licker template <class Emitter>
visit(const Expr * E)215950b70dcSNandor Licker bool ByteCodeExprGen<Emitter>::visit(const Expr *E) {
21617d4bd3dSKazu Hirata OptionScope<Emitter> Scope(this, /*NewDiscardResult=*/false);
217950b70dcSNandor Licker return this->Visit(E);
218950b70dcSNandor Licker }
219950b70dcSNandor Licker
220950b70dcSNandor Licker template <class Emitter>
visitBool(const Expr * E)221950b70dcSNandor Licker bool ByteCodeExprGen<Emitter>::visitBool(const Expr *E) {
222950b70dcSNandor Licker if (Optional<PrimType> T = classify(E->getType())) {
223950b70dcSNandor Licker return visit(E);
224950b70dcSNandor Licker } else {
225950b70dcSNandor Licker return this->bail(E);
226950b70dcSNandor Licker }
227950b70dcSNandor Licker }
228950b70dcSNandor Licker
229950b70dcSNandor Licker template <class Emitter>
visitZeroInitializer(PrimType T,const Expr * E)230950b70dcSNandor Licker bool ByteCodeExprGen<Emitter>::visitZeroInitializer(PrimType T, const Expr *E) {
231950b70dcSNandor Licker switch (T) {
232950b70dcSNandor Licker case PT_Bool:
233950b70dcSNandor Licker return this->emitZeroBool(E);
234950b70dcSNandor Licker case PT_Sint8:
235950b70dcSNandor Licker return this->emitZeroSint8(E);
236950b70dcSNandor Licker case PT_Uint8:
237950b70dcSNandor Licker return this->emitZeroUint8(E);
238950b70dcSNandor Licker case PT_Sint16:
239950b70dcSNandor Licker return this->emitZeroSint16(E);
240950b70dcSNandor Licker case PT_Uint16:
241950b70dcSNandor Licker return this->emitZeroUint16(E);
242950b70dcSNandor Licker case PT_Sint32:
243950b70dcSNandor Licker return this->emitZeroSint32(E);
244950b70dcSNandor Licker case PT_Uint32:
245950b70dcSNandor Licker return this->emitZeroUint32(E);
246950b70dcSNandor Licker case PT_Sint64:
247950b70dcSNandor Licker return this->emitZeroSint64(E);
248950b70dcSNandor Licker case PT_Uint64:
249950b70dcSNandor Licker return this->emitZeroUint64(E);
250950b70dcSNandor Licker case PT_Ptr:
251950b70dcSNandor Licker return this->emitNullPtr(E);
252950b70dcSNandor Licker }
253950b70dcSNandor Licker llvm_unreachable("unknown primitive type");
254950b70dcSNandor Licker }
255950b70dcSNandor Licker
256950b70dcSNandor Licker template <class Emitter>
dereference(const Expr * LV,DerefKind AK,llvm::function_ref<bool (PrimType)> Direct,llvm::function_ref<bool (PrimType)> Indirect)257950b70dcSNandor Licker bool ByteCodeExprGen<Emitter>::dereference(
258950b70dcSNandor Licker const Expr *LV, DerefKind AK, llvm::function_ref<bool(PrimType)> Direct,
259950b70dcSNandor Licker llvm::function_ref<bool(PrimType)> Indirect) {
260950b70dcSNandor Licker if (Optional<PrimType> T = classify(LV->getType())) {
261950b70dcSNandor Licker if (!LV->refersToBitField()) {
262950b70dcSNandor Licker // Only primitive, non bit-field types can be dereferenced directly.
263950b70dcSNandor Licker if (auto *DE = dyn_cast<DeclRefExpr>(LV)) {
264950b70dcSNandor Licker if (!DE->getDecl()->getType()->isReferenceType()) {
265950b70dcSNandor Licker if (auto *PD = dyn_cast<ParmVarDecl>(DE->getDecl()))
266950b70dcSNandor Licker return dereferenceParam(LV, *T, PD, AK, Direct, Indirect);
267950b70dcSNandor Licker if (auto *VD = dyn_cast<VarDecl>(DE->getDecl()))
268950b70dcSNandor Licker return dereferenceVar(LV, *T, VD, AK, Direct, Indirect);
269950b70dcSNandor Licker }
270950b70dcSNandor Licker }
271950b70dcSNandor Licker }
272950b70dcSNandor Licker
273950b70dcSNandor Licker if (!visit(LV))
274950b70dcSNandor Licker return false;
275950b70dcSNandor Licker return Indirect(*T);
276950b70dcSNandor Licker }
277950b70dcSNandor Licker
278950b70dcSNandor Licker return false;
279950b70dcSNandor Licker }
280950b70dcSNandor Licker
281950b70dcSNandor Licker template <class Emitter>
dereferenceParam(const Expr * LV,PrimType T,const ParmVarDecl * PD,DerefKind AK,llvm::function_ref<bool (PrimType)> Direct,llvm::function_ref<bool (PrimType)> Indirect)282950b70dcSNandor Licker bool ByteCodeExprGen<Emitter>::dereferenceParam(
283950b70dcSNandor Licker const Expr *LV, PrimType T, const ParmVarDecl *PD, DerefKind AK,
284950b70dcSNandor Licker llvm::function_ref<bool(PrimType)> Direct,
285950b70dcSNandor Licker llvm::function_ref<bool(PrimType)> Indirect) {
286950b70dcSNandor Licker auto It = this->Params.find(PD);
287950b70dcSNandor Licker if (It != this->Params.end()) {
288950b70dcSNandor Licker unsigned Idx = It->second;
289950b70dcSNandor Licker switch (AK) {
290950b70dcSNandor Licker case DerefKind::Read:
291950b70dcSNandor Licker return DiscardResult ? true : this->emitGetParam(T, Idx, LV);
292950b70dcSNandor Licker
293950b70dcSNandor Licker case DerefKind::Write:
294950b70dcSNandor Licker if (!Direct(T))
295950b70dcSNandor Licker return false;
296950b70dcSNandor Licker if (!this->emitSetParam(T, Idx, LV))
297950b70dcSNandor Licker return false;
298950b70dcSNandor Licker return DiscardResult ? true : this->emitGetPtrParam(Idx, LV);
299950b70dcSNandor Licker
300950b70dcSNandor Licker case DerefKind::ReadWrite:
301950b70dcSNandor Licker if (!this->emitGetParam(T, Idx, LV))
302950b70dcSNandor Licker return false;
303950b70dcSNandor Licker if (!Direct(T))
304950b70dcSNandor Licker return false;
305950b70dcSNandor Licker if (!this->emitSetParam(T, Idx, LV))
306950b70dcSNandor Licker return false;
307950b70dcSNandor Licker return DiscardResult ? true : this->emitGetPtrParam(Idx, LV);
308950b70dcSNandor Licker }
309950b70dcSNandor Licker return true;
310950b70dcSNandor Licker }
311950b70dcSNandor Licker
312950b70dcSNandor Licker // If the param is a pointer, we can dereference a dummy value.
313950b70dcSNandor Licker if (!DiscardResult && T == PT_Ptr && AK == DerefKind::Read) {
314950b70dcSNandor Licker if (auto Idx = P.getOrCreateDummy(PD))
315950b70dcSNandor Licker return this->emitGetPtrGlobal(*Idx, PD);
316950b70dcSNandor Licker return false;
317950b70dcSNandor Licker }
318950b70dcSNandor Licker
319950b70dcSNandor Licker // Value cannot be produced - try to emit pointer and do stuff with it.
320950b70dcSNandor Licker return visit(LV) && Indirect(T);
321950b70dcSNandor Licker }
322950b70dcSNandor Licker
323950b70dcSNandor Licker template <class Emitter>
dereferenceVar(const Expr * LV,PrimType T,const VarDecl * VD,DerefKind AK,llvm::function_ref<bool (PrimType)> Direct,llvm::function_ref<bool (PrimType)> Indirect)324950b70dcSNandor Licker bool ByteCodeExprGen<Emitter>::dereferenceVar(
325950b70dcSNandor Licker const Expr *LV, PrimType T, const VarDecl *VD, DerefKind AK,
326950b70dcSNandor Licker llvm::function_ref<bool(PrimType)> Direct,
327950b70dcSNandor Licker llvm::function_ref<bool(PrimType)> Indirect) {
328950b70dcSNandor Licker auto It = Locals.find(VD);
329950b70dcSNandor Licker if (It != Locals.end()) {
330950b70dcSNandor Licker const auto &L = It->second;
331950b70dcSNandor Licker switch (AK) {
332950b70dcSNandor Licker case DerefKind::Read:
333950b70dcSNandor Licker if (!this->emitGetLocal(T, L.Offset, LV))
334950b70dcSNandor Licker return false;
335950b70dcSNandor Licker return DiscardResult ? this->emitPop(T, LV) : true;
336950b70dcSNandor Licker
337950b70dcSNandor Licker case DerefKind::Write:
338950b70dcSNandor Licker if (!Direct(T))
339950b70dcSNandor Licker return false;
340950b70dcSNandor Licker if (!this->emitSetLocal(T, L.Offset, LV))
341950b70dcSNandor Licker return false;
342950b70dcSNandor Licker return DiscardResult ? true : this->emitGetPtrLocal(L.Offset, LV);
343950b70dcSNandor Licker
344950b70dcSNandor Licker case DerefKind::ReadWrite:
345950b70dcSNandor Licker if (!this->emitGetLocal(T, L.Offset, LV))
346950b70dcSNandor Licker return false;
347950b70dcSNandor Licker if (!Direct(T))
348950b70dcSNandor Licker return false;
349950b70dcSNandor Licker if (!this->emitSetLocal(T, L.Offset, LV))
350950b70dcSNandor Licker return false;
351950b70dcSNandor Licker return DiscardResult ? true : this->emitGetPtrLocal(L.Offset, LV);
352950b70dcSNandor Licker }
353950b70dcSNandor Licker } else if (auto Idx = getGlobalIdx(VD)) {
354950b70dcSNandor Licker switch (AK) {
355950b70dcSNandor Licker case DerefKind::Read:
356950b70dcSNandor Licker if (!this->emitGetGlobal(T, *Idx, LV))
357950b70dcSNandor Licker return false;
358950b70dcSNandor Licker return DiscardResult ? this->emitPop(T, LV) : true;
359950b70dcSNandor Licker
360950b70dcSNandor Licker case DerefKind::Write:
361950b70dcSNandor Licker if (!Direct(T))
362950b70dcSNandor Licker return false;
363950b70dcSNandor Licker if (!this->emitSetGlobal(T, *Idx, LV))
364950b70dcSNandor Licker return false;
365950b70dcSNandor Licker return DiscardResult ? true : this->emitGetPtrGlobal(*Idx, LV);
366950b70dcSNandor Licker
367950b70dcSNandor Licker case DerefKind::ReadWrite:
368950b70dcSNandor Licker if (!this->emitGetGlobal(T, *Idx, LV))
369950b70dcSNandor Licker return false;
370950b70dcSNandor Licker if (!Direct(T))
371950b70dcSNandor Licker return false;
372950b70dcSNandor Licker if (!this->emitSetGlobal(T, *Idx, LV))
373950b70dcSNandor Licker return false;
374950b70dcSNandor Licker return DiscardResult ? true : this->emitGetPtrGlobal(*Idx, LV);
375950b70dcSNandor Licker }
376950b70dcSNandor Licker }
377950b70dcSNandor Licker
378950b70dcSNandor Licker // If the declaration is a constant value, emit it here even
379950b70dcSNandor Licker // though the declaration was not evaluated in the current scope.
380950b70dcSNandor Licker // The access mode can only be read in this case.
381950b70dcSNandor Licker if (!DiscardResult && AK == DerefKind::Read) {
382950b70dcSNandor Licker if (VD->hasLocalStorage() && VD->hasInit() && !VD->isConstexpr()) {
383950b70dcSNandor Licker QualType VT = VD->getType();
384950b70dcSNandor Licker if (VT.isConstQualified() && VT->isFundamentalType())
385950b70dcSNandor Licker return this->Visit(VD->getInit());
386950b70dcSNandor Licker }
387950b70dcSNandor Licker }
388950b70dcSNandor Licker
389950b70dcSNandor Licker // Value cannot be produced - try to emit pointer.
390950b70dcSNandor Licker return visit(LV) && Indirect(T);
391950b70dcSNandor Licker }
392950b70dcSNandor Licker
393950b70dcSNandor Licker template <class Emitter>
emitConst(PrimType T,unsigned NumBits,const APInt & Value,const Expr * E)394950b70dcSNandor Licker bool ByteCodeExprGen<Emitter>::emitConst(PrimType T, unsigned NumBits,
395950b70dcSNandor Licker const APInt &Value, const Expr *E) {
396950b70dcSNandor Licker switch (T) {
397950b70dcSNandor Licker case PT_Sint8:
398950b70dcSNandor Licker return this->emitConstSint8(Value.getSExtValue(), E);
399950b70dcSNandor Licker case PT_Uint8:
400950b70dcSNandor Licker return this->emitConstUint8(Value.getZExtValue(), E);
401950b70dcSNandor Licker case PT_Sint16:
402950b70dcSNandor Licker return this->emitConstSint16(Value.getSExtValue(), E);
403950b70dcSNandor Licker case PT_Uint16:
404950b70dcSNandor Licker return this->emitConstUint16(Value.getZExtValue(), E);
405950b70dcSNandor Licker case PT_Sint32:
406950b70dcSNandor Licker return this->emitConstSint32(Value.getSExtValue(), E);
407950b70dcSNandor Licker case PT_Uint32:
408950b70dcSNandor Licker return this->emitConstUint32(Value.getZExtValue(), E);
409950b70dcSNandor Licker case PT_Sint64:
410950b70dcSNandor Licker return this->emitConstSint64(Value.getSExtValue(), E);
411950b70dcSNandor Licker case PT_Uint64:
412950b70dcSNandor Licker return this->emitConstUint64(Value.getZExtValue(), E);
413950b70dcSNandor Licker case PT_Bool:
414950b70dcSNandor Licker return this->emitConstBool(Value.getBoolValue(), E);
415950b70dcSNandor Licker case PT_Ptr:
416950b70dcSNandor Licker llvm_unreachable("Invalid integral type");
417950b70dcSNandor Licker break;
418950b70dcSNandor Licker }
419950b70dcSNandor Licker llvm_unreachable("unknown primitive type");
420950b70dcSNandor Licker }
421950b70dcSNandor Licker
422950b70dcSNandor Licker template <class Emitter>
allocateLocalPrimitive(DeclTy && Src,PrimType Ty,bool IsConst,bool IsExtended)423950b70dcSNandor Licker unsigned ByteCodeExprGen<Emitter>::allocateLocalPrimitive(DeclTy &&Src,
424950b70dcSNandor Licker PrimType Ty,
425950b70dcSNandor Licker bool IsConst,
426950b70dcSNandor Licker bool IsExtended) {
427950b70dcSNandor Licker Descriptor *D = P.createDescriptor(Src, Ty, IsConst, Src.is<const Expr *>());
428950b70dcSNandor Licker Scope::Local Local = this->createLocal(D);
429950b70dcSNandor Licker if (auto *VD = dyn_cast_or_null<ValueDecl>(Src.dyn_cast<const Decl *>()))
430950b70dcSNandor Licker Locals.insert({VD, Local});
431950b70dcSNandor Licker VarScope->add(Local, IsExtended);
432950b70dcSNandor Licker return Local.Offset;
433950b70dcSNandor Licker }
434950b70dcSNandor Licker
435950b70dcSNandor Licker template <class Emitter>
436950b70dcSNandor Licker llvm::Optional<unsigned>
allocateLocal(DeclTy && Src,bool IsExtended)437950b70dcSNandor Licker ByteCodeExprGen<Emitter>::allocateLocal(DeclTy &&Src, bool IsExtended) {
438950b70dcSNandor Licker QualType Ty;
439950b70dcSNandor Licker
440950b70dcSNandor Licker const ValueDecl *Key = nullptr;
441950b70dcSNandor Licker bool IsTemporary = false;
442950b70dcSNandor Licker if (auto *VD = dyn_cast_or_null<ValueDecl>(Src.dyn_cast<const Decl *>())) {
443950b70dcSNandor Licker Key = VD;
444950b70dcSNandor Licker Ty = VD->getType();
445950b70dcSNandor Licker }
446950b70dcSNandor Licker if (auto *E = Src.dyn_cast<const Expr *>()) {
447950b70dcSNandor Licker IsTemporary = true;
448950b70dcSNandor Licker Ty = E->getType();
449950b70dcSNandor Licker }
450950b70dcSNandor Licker
451950b70dcSNandor Licker Descriptor *D = P.createDescriptor(Src, Ty.getTypePtr(),
452950b70dcSNandor Licker Ty.isConstQualified(), IsTemporary);
453950b70dcSNandor Licker if (!D)
454950b70dcSNandor Licker return {};
455950b70dcSNandor Licker
456950b70dcSNandor Licker Scope::Local Local = this->createLocal(D);
457950b70dcSNandor Licker if (Key)
458950b70dcSNandor Licker Locals.insert({Key, Local});
459950b70dcSNandor Licker VarScope->add(Local, IsExtended);
460950b70dcSNandor Licker return Local.Offset;
461950b70dcSNandor Licker }
462950b70dcSNandor Licker
463950b70dcSNandor Licker template <class Emitter>
visitInitializer(const Expr * Init,InitFnRef InitFn)464950b70dcSNandor Licker bool ByteCodeExprGen<Emitter>::visitInitializer(
465950b70dcSNandor Licker const Expr *Init, InitFnRef InitFn) {
466950b70dcSNandor Licker OptionScope<Emitter> Scope(this, InitFn);
467950b70dcSNandor Licker return this->Visit(Init);
468950b70dcSNandor Licker }
469950b70dcSNandor Licker
470950b70dcSNandor Licker template <class Emitter>
getPtrVarDecl(const VarDecl * VD,const Expr * E)471950b70dcSNandor Licker bool ByteCodeExprGen<Emitter>::getPtrVarDecl(const VarDecl *VD, const Expr *E) {
472950b70dcSNandor Licker // Generate a pointer to the local, loading refs.
473950b70dcSNandor Licker if (Optional<unsigned> Idx = getGlobalIdx(VD)) {
474950b70dcSNandor Licker if (VD->getType()->isReferenceType())
475950b70dcSNandor Licker return this->emitGetGlobalPtr(*Idx, E);
476950b70dcSNandor Licker else
477950b70dcSNandor Licker return this->emitGetPtrGlobal(*Idx, E);
478950b70dcSNandor Licker }
479950b70dcSNandor Licker return this->bail(VD);
480950b70dcSNandor Licker }
481950b70dcSNandor Licker
482950b70dcSNandor Licker template <class Emitter>
483950b70dcSNandor Licker llvm::Optional<unsigned>
getGlobalIdx(const VarDecl * VD)484950b70dcSNandor Licker ByteCodeExprGen<Emitter>::getGlobalIdx(const VarDecl *VD) {
485950b70dcSNandor Licker if (VD->isConstexpr()) {
486950b70dcSNandor Licker // Constexpr decl - it must have already been defined.
487950b70dcSNandor Licker return P.getGlobal(VD);
488950b70dcSNandor Licker }
489950b70dcSNandor Licker if (!VD->hasLocalStorage()) {
490950b70dcSNandor Licker // Not constexpr, but a global var - can have pointer taken.
491950b70dcSNandor Licker Program::DeclScope Scope(P, VD);
492950b70dcSNandor Licker return P.getOrCreateGlobal(VD);
493950b70dcSNandor Licker }
494950b70dcSNandor Licker return {};
495950b70dcSNandor Licker }
496950b70dcSNandor Licker
497950b70dcSNandor Licker template <class Emitter>
getRecordTy(QualType Ty)498950b70dcSNandor Licker const RecordType *ByteCodeExprGen<Emitter>::getRecordTy(QualType Ty) {
499*13436320SSunho Kim if (const PointerType *PT = dyn_cast<PointerType>(Ty))
500950b70dcSNandor Licker return PT->getPointeeType()->getAs<RecordType>();
501950b70dcSNandor Licker else
502950b70dcSNandor Licker return Ty->getAs<RecordType>();
503950b70dcSNandor Licker }
504950b70dcSNandor Licker
505950b70dcSNandor Licker template <class Emitter>
getRecord(QualType Ty)506950b70dcSNandor Licker Record *ByteCodeExprGen<Emitter>::getRecord(QualType Ty) {
507950b70dcSNandor Licker if (auto *RecordTy = getRecordTy(Ty)) {
508950b70dcSNandor Licker return getRecord(RecordTy->getDecl());
509950b70dcSNandor Licker }
510950b70dcSNandor Licker return nullptr;
511950b70dcSNandor Licker }
512950b70dcSNandor Licker
513950b70dcSNandor Licker template <class Emitter>
getRecord(const RecordDecl * RD)514950b70dcSNandor Licker Record *ByteCodeExprGen<Emitter>::getRecord(const RecordDecl *RD) {
515950b70dcSNandor Licker return P.getOrCreateRecord(RD);
516950b70dcSNandor Licker }
517950b70dcSNandor Licker
518950b70dcSNandor Licker template <class Emitter>
visitExpr(const Expr * Exp)519950b70dcSNandor Licker bool ByteCodeExprGen<Emitter>::visitExpr(const Expr *Exp) {
520950b70dcSNandor Licker ExprScope<Emitter> RootScope(this);
521950b70dcSNandor Licker if (!visit(Exp))
522950b70dcSNandor Licker return false;
523950b70dcSNandor Licker
524950b70dcSNandor Licker if (Optional<PrimType> T = classify(Exp))
525950b70dcSNandor Licker return this->emitRet(*T, Exp);
526950b70dcSNandor Licker else
527950b70dcSNandor Licker return this->emitRetValue(Exp);
528950b70dcSNandor Licker }
529950b70dcSNandor Licker
530950b70dcSNandor Licker template <class Emitter>
visitDecl(const VarDecl * VD)531950b70dcSNandor Licker bool ByteCodeExprGen<Emitter>::visitDecl(const VarDecl *VD) {
532950b70dcSNandor Licker const Expr *Init = VD->getInit();
533950b70dcSNandor Licker
534950b70dcSNandor Licker if (Optional<unsigned> I = P.createGlobal(VD)) {
535950b70dcSNandor Licker if (Optional<PrimType> T = classify(VD->getType())) {
536950b70dcSNandor Licker {
537950b70dcSNandor Licker // Primitive declarations - compute the value and set it.
538950b70dcSNandor Licker DeclScope<Emitter> LocalScope(this, VD);
539950b70dcSNandor Licker if (!visit(Init))
540950b70dcSNandor Licker return false;
541950b70dcSNandor Licker }
542950b70dcSNandor Licker
543950b70dcSNandor Licker // If the declaration is global, save the value for later use.
544950b70dcSNandor Licker if (!this->emitDup(*T, VD))
545950b70dcSNandor Licker return false;
546950b70dcSNandor Licker if (!this->emitInitGlobal(*T, *I, VD))
547950b70dcSNandor Licker return false;
548950b70dcSNandor Licker return this->emitRet(*T, VD);
549950b70dcSNandor Licker } else {
550950b70dcSNandor Licker {
551950b70dcSNandor Licker // Composite declarations - allocate storage and initialize it.
552950b70dcSNandor Licker DeclScope<Emitter> LocalScope(this, VD);
553950b70dcSNandor Licker if (!visitGlobalInitializer(Init, *I))
554950b70dcSNandor Licker return false;
555950b70dcSNandor Licker }
556950b70dcSNandor Licker
557950b70dcSNandor Licker // Return a pointer to the global.
558950b70dcSNandor Licker if (!this->emitGetPtrGlobal(*I, VD))
559950b70dcSNandor Licker return false;
560950b70dcSNandor Licker return this->emitRetValue(VD);
561950b70dcSNandor Licker }
562950b70dcSNandor Licker }
563950b70dcSNandor Licker
564950b70dcSNandor Licker return this->bail(VD);
565950b70dcSNandor Licker }
566950b70dcSNandor Licker
567950b70dcSNandor Licker template <class Emitter>
emitCleanup()568950b70dcSNandor Licker void ByteCodeExprGen<Emitter>::emitCleanup() {
569950b70dcSNandor Licker for (VariableScope<Emitter> *C = VarScope; C; C = C->getParent())
570950b70dcSNandor Licker C->emitDestruction();
571950b70dcSNandor Licker }
572950b70dcSNandor Licker
573950b70dcSNandor Licker namespace clang {
574950b70dcSNandor Licker namespace interp {
575950b70dcSNandor Licker
576950b70dcSNandor Licker template class ByteCodeExprGen<ByteCodeEmitter>;
577950b70dcSNandor Licker template class ByteCodeExprGen<EvalEmitter>;
578950b70dcSNandor Licker
579950b70dcSNandor Licker } // namespace interp
580950b70dcSNandor Licker } // namespace clang
581