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