Home | History | Annotate | Line # | Download | only in Interp
      1  1.1  joerg //===--- EvalEmitter.cpp - Instruction emitter for the VM -------*- C++ -*-===//
      2  1.1  joerg //
      3  1.1  joerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
      4  1.1  joerg // See https://llvm.org/LICENSE.txt for license information.
      5  1.1  joerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
      6  1.1  joerg //
      7  1.1  joerg //===----------------------------------------------------------------------===//
      8  1.1  joerg 
      9  1.1  joerg #include "EvalEmitter.h"
     10  1.1  joerg #include "Context.h"
     11  1.1  joerg #include "Interp.h"
     12  1.1  joerg #include "Opcode.h"
     13  1.1  joerg #include "Program.h"
     14  1.1  joerg #include "clang/AST/DeclCXX.h"
     15  1.1  joerg 
     16  1.1  joerg using namespace clang;
     17  1.1  joerg using namespace clang::interp;
     18  1.1  joerg 
     19  1.1  joerg using APSInt = llvm::APSInt;
     20  1.1  joerg template <typename T> using Expected = llvm::Expected<T>;
     21  1.1  joerg 
     22  1.1  joerg EvalEmitter::EvalEmitter(Context &Ctx, Program &P, State &Parent,
     23  1.1  joerg                          InterpStack &Stk, APValue &Result)
     24  1.1  joerg     : Ctx(Ctx), P(P), S(Parent, P, Stk, Ctx, this), Result(Result) {
     25  1.1  joerg   // Create a dummy frame for the interpreter which does not have locals.
     26  1.1  joerg   S.Current = new InterpFrame(S, nullptr, nullptr, CodePtr(), Pointer());
     27  1.1  joerg }
     28  1.1  joerg 
     29  1.1  joerg llvm::Expected<bool> EvalEmitter::interpretExpr(const Expr *E) {
     30  1.1  joerg   if (this->visitExpr(E))
     31  1.1  joerg     return true;
     32  1.1  joerg   if (BailLocation)
     33  1.1  joerg     return llvm::make_error<ByteCodeGenError>(*BailLocation);
     34  1.1  joerg   return false;
     35  1.1  joerg }
     36  1.1  joerg 
     37  1.1  joerg llvm::Expected<bool> EvalEmitter::interpretDecl(const VarDecl *VD) {
     38  1.1  joerg   if (this->visitDecl(VD))
     39  1.1  joerg     return true;
     40  1.1  joerg   if (BailLocation)
     41  1.1  joerg     return llvm::make_error<ByteCodeGenError>(*BailLocation);
     42  1.1  joerg   return false;
     43  1.1  joerg }
     44  1.1  joerg 
     45  1.1  joerg void EvalEmitter::emitLabel(LabelTy Label) {
     46  1.1  joerg   CurrentLabel = Label;
     47  1.1  joerg }
     48  1.1  joerg 
     49  1.1  joerg EvalEmitter::LabelTy EvalEmitter::getLabel() { return NextLabel++; }
     50  1.1  joerg 
     51  1.1  joerg Scope::Local EvalEmitter::createLocal(Descriptor *D) {
     52  1.1  joerg   // Allocate memory for a local.
     53  1.1  joerg   auto Memory = std::make_unique<char[]>(sizeof(Block) + D->getAllocSize());
     54  1.1  joerg   auto *B = new (Memory.get()) Block(D, /*isStatic=*/false);
     55  1.1  joerg   B->invokeCtor();
     56  1.1  joerg 
     57  1.1  joerg   // Register the local.
     58  1.1  joerg   unsigned Off = Locals.size();
     59  1.1  joerg   Locals.insert({Off, std::move(Memory)});
     60  1.1  joerg   return {Off, D};
     61  1.1  joerg }
     62  1.1  joerg 
     63  1.1  joerg bool EvalEmitter::bail(const SourceLocation &Loc) {
     64  1.1  joerg   if (!BailLocation)
     65  1.1  joerg     BailLocation = Loc;
     66  1.1  joerg   return false;
     67  1.1  joerg }
     68  1.1  joerg 
     69  1.1  joerg bool EvalEmitter::jumpTrue(const LabelTy &Label) {
     70  1.1  joerg   if (isActive()) {
     71  1.1  joerg     if (S.Stk.pop<bool>())
     72  1.1  joerg       ActiveLabel = Label;
     73  1.1  joerg   }
     74  1.1  joerg   return true;
     75  1.1  joerg }
     76  1.1  joerg 
     77  1.1  joerg bool EvalEmitter::jumpFalse(const LabelTy &Label) {
     78  1.1  joerg   if (isActive()) {
     79  1.1  joerg     if (!S.Stk.pop<bool>())
     80  1.1  joerg       ActiveLabel = Label;
     81  1.1  joerg   }
     82  1.1  joerg   return true;
     83  1.1  joerg }
     84  1.1  joerg 
     85  1.1  joerg bool EvalEmitter::jump(const LabelTy &Label) {
     86  1.1  joerg   if (isActive())
     87  1.1  joerg     CurrentLabel = ActiveLabel = Label;
     88  1.1  joerg   return true;
     89  1.1  joerg }
     90  1.1  joerg 
     91  1.1  joerg bool EvalEmitter::fallthrough(const LabelTy &Label) {
     92  1.1  joerg   if (isActive())
     93  1.1  joerg     ActiveLabel = Label;
     94  1.1  joerg   CurrentLabel = Label;
     95  1.1  joerg   return true;
     96  1.1  joerg }
     97  1.1  joerg 
     98  1.1  joerg template <PrimType OpType> bool EvalEmitter::emitRet(const SourceInfo &Info) {
     99  1.1  joerg   if (!isActive())
    100  1.1  joerg     return true;
    101  1.1  joerg   using T = typename PrimConv<OpType>::T;
    102  1.1  joerg   return ReturnValue<T>(S.Stk.pop<T>(), Result);
    103  1.1  joerg }
    104  1.1  joerg 
    105  1.1  joerg bool EvalEmitter::emitRetVoid(const SourceInfo &Info) { return true; }
    106  1.1  joerg 
    107  1.1  joerg bool EvalEmitter::emitRetValue(const SourceInfo &Info) {
    108  1.1  joerg   // Method to recursively traverse composites.
    109  1.1  joerg   std::function<bool(QualType, const Pointer &, APValue &)> Composite;
    110  1.1  joerg   Composite = [this, &Composite](QualType Ty, const Pointer &Ptr, APValue &R) {
    111  1.1  joerg     if (auto *AT = Ty->getAs<AtomicType>())
    112  1.1  joerg       Ty = AT->getValueType();
    113  1.1  joerg 
    114  1.1  joerg     if (auto *RT = Ty->getAs<RecordType>()) {
    115  1.1  joerg       auto *Record = Ptr.getRecord();
    116  1.1  joerg       assert(Record && "Missing record descriptor");
    117  1.1  joerg 
    118  1.1  joerg       bool Ok = true;
    119  1.1  joerg       if (RT->getDecl()->isUnion()) {
    120  1.1  joerg         const FieldDecl *ActiveField = nullptr;
    121  1.1  joerg         APValue Value;
    122  1.1  joerg         for (auto &F : Record->fields()) {
    123  1.1  joerg           const Pointer &FP = Ptr.atField(F.Offset);
    124  1.1  joerg           QualType FieldTy = F.Decl->getType();
    125  1.1  joerg           if (FP.isActive()) {
    126  1.1  joerg             if (llvm::Optional<PrimType> T = Ctx.classify(FieldTy)) {
    127  1.1  joerg               TYPE_SWITCH(*T, Ok &= ReturnValue<T>(FP.deref<T>(), Value));
    128  1.1  joerg             } else {
    129  1.1  joerg               Ok &= Composite(FieldTy, FP, Value);
    130  1.1  joerg             }
    131  1.1  joerg             break;
    132  1.1  joerg           }
    133  1.1  joerg         }
    134  1.1  joerg         R = APValue(ActiveField, Value);
    135  1.1  joerg       } else {
    136  1.1  joerg         unsigned NF = Record->getNumFields();
    137  1.1  joerg         unsigned NB = Record->getNumBases();
    138  1.1  joerg         unsigned NV = Ptr.isBaseClass() ? 0 : Record->getNumVirtualBases();
    139  1.1  joerg 
    140  1.1  joerg         R = APValue(APValue::UninitStruct(), NB, NF);
    141  1.1  joerg 
    142  1.1  joerg         for (unsigned I = 0; I < NF; ++I) {
    143  1.1  joerg           const Record::Field *FD = Record->getField(I);
    144  1.1  joerg           QualType FieldTy = FD->Decl->getType();
    145  1.1  joerg           const Pointer &FP = Ptr.atField(FD->Offset);
    146  1.1  joerg           APValue &Value = R.getStructField(I);
    147  1.1  joerg 
    148  1.1  joerg           if (llvm::Optional<PrimType> T = Ctx.classify(FieldTy)) {
    149  1.1  joerg             TYPE_SWITCH(*T, Ok &= ReturnValue<T>(FP.deref<T>(), Value));
    150  1.1  joerg           } else {
    151  1.1  joerg             Ok &= Composite(FieldTy, FP, Value);
    152  1.1  joerg           }
    153  1.1  joerg         }
    154  1.1  joerg 
    155  1.1  joerg         for (unsigned I = 0; I < NB; ++I) {
    156  1.1  joerg           const Record::Base *BD = Record->getBase(I);
    157  1.1  joerg           QualType BaseTy = Ctx.getASTContext().getRecordType(BD->Decl);
    158  1.1  joerg           const Pointer &BP = Ptr.atField(BD->Offset);
    159  1.1  joerg           Ok &= Composite(BaseTy, BP, R.getStructBase(I));
    160  1.1  joerg         }
    161  1.1  joerg 
    162  1.1  joerg         for (unsigned I = 0; I < NV; ++I) {
    163  1.1  joerg           const Record::Base *VD = Record->getVirtualBase(I);
    164  1.1  joerg           QualType VirtBaseTy = Ctx.getASTContext().getRecordType(VD->Decl);
    165  1.1  joerg           const Pointer &VP = Ptr.atField(VD->Offset);
    166  1.1  joerg           Ok &= Composite(VirtBaseTy, VP, R.getStructBase(NB + I));
    167  1.1  joerg         }
    168  1.1  joerg       }
    169  1.1  joerg       return Ok;
    170  1.1  joerg     }
    171  1.1  joerg     if (auto *AT = Ty->getAsArrayTypeUnsafe()) {
    172  1.1  joerg       const size_t NumElems = Ptr.getNumElems();
    173  1.1  joerg       QualType ElemTy = AT->getElementType();
    174  1.1  joerg       R = APValue(APValue::UninitArray{}, NumElems, NumElems);
    175  1.1  joerg 
    176  1.1  joerg       bool Ok = true;
    177  1.1  joerg       for (unsigned I = 0; I < NumElems; ++I) {
    178  1.1  joerg         APValue &Slot = R.getArrayInitializedElt(I);
    179  1.1  joerg         const Pointer &EP = Ptr.atIndex(I);
    180  1.1  joerg         if (llvm::Optional<PrimType> T = Ctx.classify(ElemTy)) {
    181  1.1  joerg           TYPE_SWITCH(*T, Ok &= ReturnValue<T>(EP.deref<T>(), Slot));
    182  1.1  joerg         } else {
    183  1.1  joerg           Ok &= Composite(ElemTy, EP.narrow(), Slot);
    184  1.1  joerg         }
    185  1.1  joerg       }
    186  1.1  joerg       return Ok;
    187  1.1  joerg     }
    188  1.1  joerg     llvm_unreachable("invalid value to return");
    189  1.1  joerg   };
    190  1.1  joerg 
    191  1.1  joerg   // Return the composite type.
    192  1.1  joerg   const auto &Ptr = S.Stk.pop<Pointer>();
    193  1.1  joerg   return Composite(Ptr.getType(), Ptr, Result);
    194  1.1  joerg }
    195  1.1  joerg 
    196  1.1  joerg bool EvalEmitter::emitGetPtrLocal(uint32_t I, const SourceInfo &Info) {
    197  1.1  joerg   if (!isActive())
    198  1.1  joerg     return true;
    199  1.1  joerg 
    200  1.1  joerg   auto It = Locals.find(I);
    201  1.1  joerg   assert(It != Locals.end() && "Missing local variable");
    202  1.1  joerg   S.Stk.push<Pointer>(reinterpret_cast<Block *>(It->second.get()));
    203  1.1  joerg   return true;
    204  1.1  joerg }
    205  1.1  joerg 
    206  1.1  joerg template <PrimType OpType>
    207  1.1  joerg bool EvalEmitter::emitGetLocal(uint32_t I, const SourceInfo &Info) {
    208  1.1  joerg   if (!isActive())
    209  1.1  joerg     return true;
    210  1.1  joerg 
    211  1.1  joerg   using T = typename PrimConv<OpType>::T;
    212  1.1  joerg 
    213  1.1  joerg   auto It = Locals.find(I);
    214  1.1  joerg   assert(It != Locals.end() && "Missing local variable");
    215  1.1  joerg   auto *B = reinterpret_cast<Block *>(It->second.get());
    216  1.1  joerg   S.Stk.push<T>(*reinterpret_cast<T *>(B + 1));
    217  1.1  joerg   return true;
    218  1.1  joerg }
    219  1.1  joerg 
    220  1.1  joerg template <PrimType OpType>
    221  1.1  joerg bool EvalEmitter::emitSetLocal(uint32_t I, const SourceInfo &Info) {
    222  1.1  joerg   if (!isActive())
    223  1.1  joerg     return true;
    224  1.1  joerg 
    225  1.1  joerg   using T = typename PrimConv<OpType>::T;
    226  1.1  joerg 
    227  1.1  joerg   auto It = Locals.find(I);
    228  1.1  joerg   assert(It != Locals.end() && "Missing local variable");
    229  1.1  joerg   auto *B = reinterpret_cast<Block *>(It->second.get());
    230  1.1  joerg   *reinterpret_cast<T *>(B + 1) = S.Stk.pop<T>();
    231  1.1  joerg   return true;
    232  1.1  joerg }
    233  1.1  joerg 
    234  1.1  joerg bool EvalEmitter::emitDestroy(uint32_t I, const SourceInfo &Info) {
    235  1.1  joerg   if (!isActive())
    236  1.1  joerg     return true;
    237  1.1  joerg 
    238  1.1  joerg   for (auto &Local : Descriptors[I]) {
    239  1.1  joerg     auto It = Locals.find(Local.Offset);
    240  1.1  joerg     assert(It != Locals.end() && "Missing local variable");
    241  1.1  joerg     S.deallocate(reinterpret_cast<Block *>(It->second.get()));
    242  1.1  joerg   }
    243  1.1  joerg 
    244  1.1  joerg   return true;
    245  1.1  joerg }
    246  1.1  joerg 
    247  1.1  joerg //===----------------------------------------------------------------------===//
    248  1.1  joerg // Opcode evaluators
    249  1.1  joerg //===----------------------------------------------------------------------===//
    250  1.1  joerg 
    251  1.1  joerg #define GET_EVAL_IMPL
    252  1.1  joerg #include "Opcodes.inc"
    253  1.1  joerg #undef GET_EVAL_IMPL
    254