• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "PrimType.h"
15 #include "Program.h"
16 #include "State.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:
DeclScope(ByteCodeExprGen<Emitter> * Ctx,const VarDecl * VD)31   DeclScope(ByteCodeExprGen<Emitter> *Ctx, const VarDecl *VD)
32       : LocalScope<Emitter>(Ctx), Scope(Ctx->P, VD) {}
33 
addExtended(const Scope::Local & Local)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.
OptionScope(ByteCodeExprGen<Emitter> * Ctx,bool NewDiscardResult)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.
OptionScope(ByteCodeExprGen<Emitter> * Ctx,InitFnRef NewInitFn)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.
OptionScope(ByteCodeExprGen<Emitter> * Ctx,ChainedInitFnRef NewInitFn)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 
~OptionScope()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>
VisitCastExpr(const CastExpr * CE)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>
VisitIntegerLiteral(const IntegerLiteral * LE)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>
VisitParenExpr(const ParenExpr * PE)141 bool ByteCodeExprGen<Emitter>::VisitParenExpr(const ParenExpr *PE) {
142   return this->Visit(PE->getSubExpr());
143 }
144 
145 template <class Emitter>
VisitBinaryOperator(const BinaryOperator * BO)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>
discard(const Expr * E)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>
visit(const Expr * E)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>
visitBool(const Expr * E)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>
visitZeroInitializer(PrimType T,const Expr * E)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   llvm_unreachable("unknown primitive type");
254 }
255 
256 template <class Emitter>
dereference(const Expr * LV,DerefKind AK,llvm::function_ref<bool (PrimType)> Direct,llvm::function_ref<bool (PrimType)> Indirect)257 bool ByteCodeExprGen<Emitter>::dereference(
258     const Expr *LV, DerefKind AK, llvm::function_ref<bool(PrimType)> Direct,
259     llvm::function_ref<bool(PrimType)> Indirect) {
260   if (Optional<PrimType> T = classify(LV->getType())) {
261     if (!LV->refersToBitField()) {
262       // Only primitive, non bit-field types can be dereferenced directly.
263       if (auto *DE = dyn_cast<DeclRefExpr>(LV)) {
264         if (!DE->getDecl()->getType()->isReferenceType()) {
265           if (auto *PD = dyn_cast<ParmVarDecl>(DE->getDecl()))
266             return dereferenceParam(LV, *T, PD, AK, Direct, Indirect);
267           if (auto *VD = dyn_cast<VarDecl>(DE->getDecl()))
268             return dereferenceVar(LV, *T, VD, AK, Direct, Indirect);
269         }
270       }
271     }
272 
273     if (!visit(LV))
274       return false;
275     return Indirect(*T);
276   }
277 
278   return false;
279 }
280 
281 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)282 bool ByteCodeExprGen<Emitter>::dereferenceParam(
283     const Expr *LV, PrimType T, const ParmVarDecl *PD, DerefKind AK,
284     llvm::function_ref<bool(PrimType)> Direct,
285     llvm::function_ref<bool(PrimType)> Indirect) {
286   auto It = this->Params.find(PD);
287   if (It != this->Params.end()) {
288     unsigned Idx = It->second;
289     switch (AK) {
290     case DerefKind::Read:
291       return DiscardResult ? true : this->emitGetParam(T, Idx, LV);
292 
293     case DerefKind::Write:
294       if (!Direct(T))
295         return false;
296       if (!this->emitSetParam(T, Idx, LV))
297         return false;
298       return DiscardResult ? true : this->emitGetPtrParam(Idx, LV);
299 
300     case DerefKind::ReadWrite:
301       if (!this->emitGetParam(T, Idx, LV))
302         return false;
303       if (!Direct(T))
304         return false;
305       if (!this->emitSetParam(T, Idx, LV))
306         return false;
307       return DiscardResult ? true : this->emitGetPtrParam(Idx, LV);
308     }
309     return true;
310   }
311 
312   // If the param is a pointer, we can dereference a dummy value.
313   if (!DiscardResult && T == PT_Ptr && AK == DerefKind::Read) {
314     if (auto Idx = P.getOrCreateDummy(PD))
315       return this->emitGetPtrGlobal(*Idx, PD);
316     return false;
317   }
318 
319   // Value cannot be produced - try to emit pointer and do stuff with it.
320   return visit(LV) && Indirect(T);
321 }
322 
323 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)324 bool ByteCodeExprGen<Emitter>::dereferenceVar(
325     const Expr *LV, PrimType T, const VarDecl *VD, DerefKind AK,
326     llvm::function_ref<bool(PrimType)> Direct,
327     llvm::function_ref<bool(PrimType)> Indirect) {
328   auto It = Locals.find(VD);
329   if (It != Locals.end()) {
330     const auto &L = It->second;
331     switch (AK) {
332     case DerefKind::Read:
333       if (!this->emitGetLocal(T, L.Offset, LV))
334         return false;
335       return DiscardResult ? this->emitPop(T, LV) : true;
336 
337     case DerefKind::Write:
338       if (!Direct(T))
339         return false;
340       if (!this->emitSetLocal(T, L.Offset, LV))
341         return false;
342       return DiscardResult ? true : this->emitGetPtrLocal(L.Offset, LV);
343 
344     case DerefKind::ReadWrite:
345       if (!this->emitGetLocal(T, L.Offset, LV))
346         return false;
347       if (!Direct(T))
348         return false;
349       if (!this->emitSetLocal(T, L.Offset, LV))
350         return false;
351       return DiscardResult ? true : this->emitGetPtrLocal(L.Offset, LV);
352     }
353   } else if (auto Idx = getGlobalIdx(VD)) {
354     switch (AK) {
355     case DerefKind::Read:
356       if (!this->emitGetGlobal(T, *Idx, LV))
357         return false;
358       return DiscardResult ? this->emitPop(T, LV) : true;
359 
360     case DerefKind::Write:
361       if (!Direct(T))
362         return false;
363       if (!this->emitSetGlobal(T, *Idx, LV))
364         return false;
365       return DiscardResult ? true : this->emitGetPtrGlobal(*Idx, LV);
366 
367     case DerefKind::ReadWrite:
368       if (!this->emitGetGlobal(T, *Idx, LV))
369         return false;
370       if (!Direct(T))
371         return false;
372       if (!this->emitSetGlobal(T, *Idx, LV))
373         return false;
374       return DiscardResult ? true : this->emitGetPtrGlobal(*Idx, LV);
375     }
376   }
377 
378   // If the declaration is a constant value, emit it here even
379   // though the declaration was not evaluated in the current scope.
380   // The access mode can only be read in this case.
381   if (!DiscardResult && AK == DerefKind::Read) {
382     if (VD->hasLocalStorage() && VD->hasInit() && !VD->isConstexpr()) {
383       QualType VT = VD->getType();
384       if (VT.isConstQualified() && VT->isFundamentalType())
385         return this->Visit(VD->getInit());
386     }
387   }
388 
389   // Value cannot be produced - try to emit pointer.
390   return visit(LV) && Indirect(T);
391 }
392 
393 template <class Emitter>
emitConst(PrimType T,unsigned NumBits,const APInt & Value,const Expr * E)394 bool ByteCodeExprGen<Emitter>::emitConst(PrimType T, unsigned NumBits,
395                                          const APInt &Value, const Expr *E) {
396   switch (T) {
397   case PT_Sint8:
398     return this->emitConstSint8(Value.getSExtValue(), E);
399   case PT_Uint8:
400     return this->emitConstUint8(Value.getZExtValue(), E);
401   case PT_Sint16:
402     return this->emitConstSint16(Value.getSExtValue(), E);
403   case PT_Uint16:
404     return this->emitConstUint16(Value.getZExtValue(), E);
405   case PT_Sint32:
406     return this->emitConstSint32(Value.getSExtValue(), E);
407   case PT_Uint32:
408     return this->emitConstUint32(Value.getZExtValue(), E);
409   case PT_Sint64:
410     return this->emitConstSint64(Value.getSExtValue(), E);
411   case PT_Uint64:
412     return this->emitConstUint64(Value.getZExtValue(), E);
413   case PT_Bool:
414     return this->emitConstBool(Value.getBoolValue(), E);
415   case PT_Ptr:
416     llvm_unreachable("Invalid integral type");
417     break;
418   }
419   llvm_unreachable("unknown primitive type");
420 }
421 
422 template <class Emitter>
allocateLocalPrimitive(DeclTy && Src,PrimType Ty,bool IsConst,bool IsExtended)423 unsigned ByteCodeExprGen<Emitter>::allocateLocalPrimitive(DeclTy &&Src,
424                                                           PrimType Ty,
425                                                           bool IsConst,
426                                                           bool IsExtended) {
427   Descriptor *D = P.createDescriptor(Src, Ty, IsConst, Src.is<const Expr *>());
428   Scope::Local Local = this->createLocal(D);
429   if (auto *VD = dyn_cast_or_null<ValueDecl>(Src.dyn_cast<const Decl *>()))
430     Locals.insert({VD, Local});
431   VarScope->add(Local, IsExtended);
432   return Local.Offset;
433 }
434 
435 template <class Emitter>
436 llvm::Optional<unsigned>
allocateLocal(DeclTy && Src,bool IsExtended)437 ByteCodeExprGen<Emitter>::allocateLocal(DeclTy &&Src, bool IsExtended) {
438   QualType Ty;
439 
440   const ValueDecl *Key = nullptr;
441   bool IsTemporary = false;
442   if (auto *VD = dyn_cast_or_null<ValueDecl>(Src.dyn_cast<const Decl *>())) {
443     Key = VD;
444     Ty = VD->getType();
445   }
446   if (auto *E = Src.dyn_cast<const Expr *>()) {
447     IsTemporary = true;
448     Ty = E->getType();
449   }
450 
451   Descriptor *D = P.createDescriptor(Src, Ty.getTypePtr(),
452                                      Ty.isConstQualified(), IsTemporary);
453   if (!D)
454     return {};
455 
456   Scope::Local Local = this->createLocal(D);
457   if (Key)
458     Locals.insert({Key, Local});
459   VarScope->add(Local, IsExtended);
460   return Local.Offset;
461 }
462 
463 template <class Emitter>
visitInitializer(const Expr * Init,InitFnRef InitFn)464 bool ByteCodeExprGen<Emitter>::visitInitializer(
465     const Expr *Init, InitFnRef InitFn) {
466   OptionScope<Emitter> Scope(this, InitFn);
467   return this->Visit(Init);
468 }
469 
470 template <class Emitter>
getPtrVarDecl(const VarDecl * VD,const Expr * E)471 bool ByteCodeExprGen<Emitter>::getPtrVarDecl(const VarDecl *VD, const Expr *E) {
472   // Generate a pointer to the local, loading refs.
473   if (Optional<unsigned> Idx = getGlobalIdx(VD)) {
474     if (VD->getType()->isReferenceType())
475       return this->emitGetGlobalPtr(*Idx, E);
476     else
477       return this->emitGetPtrGlobal(*Idx, E);
478   }
479   return this->bail(VD);
480 }
481 
482 template <class Emitter>
483 llvm::Optional<unsigned>
getGlobalIdx(const VarDecl * VD)484 ByteCodeExprGen<Emitter>::getGlobalIdx(const VarDecl *VD) {
485   if (VD->isConstexpr()) {
486     // Constexpr decl - it must have already been defined.
487     return P.getGlobal(VD);
488   }
489   if (!VD->hasLocalStorage()) {
490     // Not constexpr, but a global var - can have pointer taken.
491     Program::DeclScope Scope(P, VD);
492     return P.getOrCreateGlobal(VD);
493   }
494   return {};
495 }
496 
497 template <class Emitter>
getRecordTy(QualType Ty)498 const RecordType *ByteCodeExprGen<Emitter>::getRecordTy(QualType Ty) {
499   if (auto *PT = dyn_cast<PointerType>(Ty))
500     return PT->getPointeeType()->getAs<RecordType>();
501   else
502     return Ty->getAs<RecordType>();
503 }
504 
505 template <class Emitter>
getRecord(QualType Ty)506 Record *ByteCodeExprGen<Emitter>::getRecord(QualType Ty) {
507   if (auto *RecordTy = getRecordTy(Ty)) {
508     return getRecord(RecordTy->getDecl());
509   }
510   return nullptr;
511 }
512 
513 template <class Emitter>
getRecord(const RecordDecl * RD)514 Record *ByteCodeExprGen<Emitter>::getRecord(const RecordDecl *RD) {
515   return P.getOrCreateRecord(RD);
516 }
517 
518 template <class Emitter>
visitExpr(const Expr * Exp)519 bool ByteCodeExprGen<Emitter>::visitExpr(const Expr *Exp) {
520   ExprScope<Emitter> RootScope(this);
521   if (!visit(Exp))
522     return false;
523 
524   if (Optional<PrimType> T = classify(Exp))
525     return this->emitRet(*T, Exp);
526   else
527     return this->emitRetValue(Exp);
528 }
529 
530 template <class Emitter>
visitDecl(const VarDecl * VD)531 bool ByteCodeExprGen<Emitter>::visitDecl(const VarDecl *VD) {
532   const Expr *Init = VD->getInit();
533 
534   if (Optional<unsigned> I = P.createGlobal(VD)) {
535     if (Optional<PrimType> T = classify(VD->getType())) {
536       {
537         // Primitive declarations - compute the value and set it.
538         DeclScope<Emitter> LocalScope(this, VD);
539         if (!visit(Init))
540           return false;
541       }
542 
543       // If the declaration is global, save the value for later use.
544       if (!this->emitDup(*T, VD))
545         return false;
546       if (!this->emitInitGlobal(*T, *I, VD))
547         return false;
548       return this->emitRet(*T, VD);
549     } else {
550       {
551         // Composite declarations - allocate storage and initialize it.
552         DeclScope<Emitter> LocalScope(this, VD);
553         if (!visitGlobalInitializer(Init, *I))
554           return false;
555       }
556 
557       // Return a pointer to the global.
558       if (!this->emitGetPtrGlobal(*I, VD))
559         return false;
560       return this->emitRetValue(VD);
561     }
562   }
563 
564   return this->bail(VD);
565 }
566 
567 template <class Emitter>
emitCleanup()568 void ByteCodeExprGen<Emitter>::emitCleanup() {
569   for (VariableScope<Emitter> *C = VarScope; C; C = C->getParent())
570     C->emitDestruction();
571 }
572 
573 namespace clang {
574 namespace interp {
575 
576 template class ByteCodeExprGen<ByteCodeEmitter>;
577 template class ByteCodeExprGen<EvalEmitter>;
578 
579 } // namespace interp
580 } // namespace clang
581