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