Home | History | Annotate | Line # | Download | only in Interp
      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:
     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   llvm_unreachable("unknown primitive type");
    254 }
    255 
    256 template <class Emitter>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    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>
    514 Record *ByteCodeExprGen<Emitter>::getRecord(const RecordDecl *RD) {
    515   return P.getOrCreateRecord(RD);
    516 }
    517 
    518 template <class Emitter>
    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>
    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>
    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