EvalEmitter.cpp revision 353942
1165982Srwatson//===--- EvalEmitter.cpp - Instruction emitter for the VM -------*- C++ -*-===// 2165982Srwatson// 3165982Srwatson// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4165982Srwatson// See https://llvm.org/LICENSE.txt for license information. 5165982Srwatson// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6165982Srwatson// 7165982Srwatson//===----------------------------------------------------------------------===// 8165982Srwatson 9165982Srwatson#include "EvalEmitter.h" 10165982Srwatson#include "Context.h" 11165982Srwatson#include "Interp.h" 12165982Srwatson#include "Opcode.h" 13165982Srwatson#include "Program.h" 14165982Srwatson#include "clang/AST/DeclCXX.h" 15165982Srwatson 16165982Srwatsonusing namespace clang; 17165982Srwatsonusing namespace clang::interp; 18165982Srwatson 19165982Srwatsonusing APSInt = llvm::APSInt; 20165982Srwatsontemplate <typename T> using Expected = llvm::Expected<T>; 21165982Srwatson 22165982SrwatsonEvalEmitter::EvalEmitter(Context &Ctx, Program &P, State &Parent, 23165982Srwatson InterpStack &Stk, APValue &Result) 24165982Srwatson : Ctx(Ctx), P(P), S(Parent, P, Stk, Ctx, this), Result(Result) { 25165982Srwatson // Create a dummy frame for the interpreter which does not have locals. 26165982Srwatson S.Current = new InterpFrame(S, nullptr, nullptr, CodePtr(), Pointer()); 27165982Srwatson} 28165982Srwatson 29165984Srwatsonllvm::Expected<bool> EvalEmitter::interpretExpr(const Expr *E) { 30165982Srwatson if (this->visitExpr(E)) 31165982Srwatson return true; 32165982Srwatson if (BailLocation) 33165982Srwatson return llvm::make_error<ByteCodeGenError>(*BailLocation); 34165982Srwatson return false; 35165982Srwatson} 36165982Srwatson 37165982Srwatsonllvm::Expected<bool> EvalEmitter::interpretDecl(const VarDecl *VD) { 38165984Srwatson if (this->visitDecl(VD)) 39165982Srwatson return true; 40165982Srwatson if (BailLocation) 41165982Srwatson return llvm::make_error<ByteCodeGenError>(*BailLocation); 42165982Srwatson return false; 43165982Srwatson} 44165982Srwatson 45165982Srwatsonvoid EvalEmitter::emitLabel(LabelTy Label) { 46165982Srwatson CurrentLabel = Label; 47165982Srwatson} 48165982Srwatson 49165982SrwatsonEvalEmitter::LabelTy EvalEmitter::getLabel() { return NextLabel++; } 50165982Srwatson 51165982SrwatsonScope::Local EvalEmitter::createLocal(Descriptor *D) { 52165982Srwatson // Allocate memory for a local. 53165982Srwatson auto Memory = std::make_unique<char[]>(sizeof(Block) + D->getAllocSize()); 54165982Srwatson auto *B = new (Memory.get()) Block(D, /*isStatic=*/false); 55165982Srwatson B->invokeCtor(); 56165982Srwatson 57294485Sngie // Register the local. 58165982Srwatson unsigned Off = Locals.size(); 59294485Sngie Locals.insert({Off, std::move(Memory)}); 60165982Srwatson return {Off, D}; 61165982Srwatson} 62165982Srwatson 63165982Srwatsonbool EvalEmitter::bail(const SourceLocation &Loc) { 64165982Srwatson if (!BailLocation) 65165982Srwatson BailLocation = Loc; 66165982Srwatson return false; 67165982Srwatson} 68165982Srwatson 69165982Srwatsonbool EvalEmitter::jumpTrue(const LabelTy &Label) { 70165982Srwatson if (isActive()) { 71294485Sngie if (S.Stk.pop<bool>()) 72165982Srwatson ActiveLabel = Label; 73294485Sngie } 74165982Srwatson return true; 75165982Srwatson} 76165982Srwatson 77165982Srwatsonbool EvalEmitter::jumpFalse(const LabelTy &Label) { 78165982Srwatson if (isActive()) { 79165982Srwatson if (!S.Stk.pop<bool>()) 80165982Srwatson ActiveLabel = Label; 81165982Srwatson } 82165982Srwatson return true; 83165982Srwatson} 84165982Srwatson 85165982Srwatsonbool EvalEmitter::jump(const LabelTy &Label) { 86165982Srwatson if (isActive()) 87165982Srwatson CurrentLabel = ActiveLabel = Label; 88165982Srwatson return true; 89165982Srwatson} 90294485Sngie 91165982Srwatsonbool EvalEmitter::fallthrough(const LabelTy &Label) { 92294485Sngie if (isActive()) 93165982Srwatson ActiveLabel = Label; 94165982Srwatson CurrentLabel = Label; 95165982Srwatson return true; 96294485Sngie} 97165982Srwatson 98165982Srwatsontemplate <PrimType OpType> bool EvalEmitter::emitRet(const SourceInfo &Info) { 99165982Srwatson if (!isActive()) 100165982Srwatson return true; 101294485Sngie using T = typename PrimConv<OpType>::T; 102165982Srwatson return ReturnValue<T>(S.Stk.pop<T>(), Result); 103294485Sngie} 104165982Srwatson 105165982Srwatsonbool EvalEmitter::emitRetVoid(const SourceInfo &Info) { return true; } 106165982Srwatson 107294485Sngiebool EvalEmitter::emitRetValue(const SourceInfo &Info) { 108165982Srwatson // Method to recursively traverse composites. 109165982Srwatson std::function<bool(QualType, const Pointer &, APValue &)> Composite; 110165982Srwatson Composite = [this, &Composite](QualType Ty, const Pointer &Ptr, APValue &R) { 111165982Srwatson if (auto *AT = Ty->getAs<AtomicType>()) 112165982Srwatson Ty = AT->getValueType(); 113165982Srwatson 114165982Srwatson if (auto *RT = Ty->getAs<RecordType>()) { 115165982Srwatson auto *Record = Ptr.getRecord(); 116165982Srwatson assert(Record && "Missing record descriptor"); 117165984Srwatson 118165982Srwatson bool Ok = true; 119165984Srwatson if (RT->getDecl()->isUnion()) { 120165984Srwatson const FieldDecl *ActiveField = nullptr; 121165982Srwatson APValue Value; 122165982Srwatson for (auto &F : Record->fields()) { 123165982Srwatson const Pointer &FP = Ptr.atField(F.Offset); 124165982Srwatson QualType FieldTy = F.Decl->getType(); 125165982Srwatson if (FP.isActive()) { 126165982Srwatson if (llvm::Optional<PrimType> T = Ctx.classify(FieldTy)) { 127165982Srwatson TYPE_SWITCH(*T, Ok &= ReturnValue<T>(FP.deref<T>(), Value)); 128165982Srwatson } else { 129165982Srwatson Ok &= Composite(FieldTy, FP, Value); 130165982Srwatson } 131165982Srwatson break; 132165982Srwatson } 133294485Sngie } 134165982Srwatson R = APValue(ActiveField, Value); 135294485Sngie } else { 136165982Srwatson unsigned NF = Record->getNumFields(); 137165982Srwatson unsigned NB = Record->getNumBases(); 138294485Sngie unsigned NV = Ptr.isBaseClass() ? 0 : Record->getNumVirtualBases(); 139165982Srwatson 140165982Srwatson R = APValue(APValue::UninitStruct(), NB, NF); 141165982Srwatson 142165982Srwatson for (unsigned I = 0; I < NF; ++I) { 143165982Srwatson const Record::Field *FD = Record->getField(I); 144165982Srwatson QualType FieldTy = FD->Decl->getType(); 145165982Srwatson const Pointer &FP = Ptr.atField(FD->Offset); 146294485Sngie APValue &Value = R.getStructField(I); 147165982Srwatson 148294485Sngie if (llvm::Optional<PrimType> T = Ctx.classify(FieldTy)) { 149165984Srwatson TYPE_SWITCH(*T, Ok &= ReturnValue<T>(FP.deref<T>(), Value)); 150165984Srwatson } else { 151294485Sngie Ok &= Composite(FieldTy, FP, Value); 152165982Srwatson } 153165982Srwatson } 154165982Srwatson 155165982Srwatson for (unsigned I = 0; I < NB; ++I) { 156165982Srwatson const Record::Base *BD = Record->getBase(I); 157165982Srwatson QualType BaseTy = Ctx.getASTContext().getRecordType(BD->Decl); 158294485Sngie const Pointer &BP = Ptr.atField(BD->Offset); 159294485Sngie Ok &= Composite(BaseTy, BP, R.getStructBase(I)); 160165982Srwatson } 161165982Srwatson 162294485Sngie for (unsigned I = 0; I < NV; ++I) { 163294485Sngie const Record::Base *VD = Record->getVirtualBase(I); 164294485Sngie QualType VirtBaseTy = Ctx.getASTContext().getRecordType(VD->Decl); 165165982Srwatson const Pointer &VP = Ptr.atField(VD->Offset); 166165984Srwatson Ok &= Composite(VirtBaseTy, VP, R.getStructBase(NB + I)); 167165984Srwatson } 168165984Srwatson } 169165984Srwatson return Ok; 170165984Srwatson } 171165984Srwatson if (auto *AT = Ty->getAsArrayTypeUnsafe()) { 172165984Srwatson const size_t NumElems = Ptr.getNumElems(); 173165984Srwatson QualType ElemTy = AT->getElementType(); 174294485Sngie R = APValue(APValue::UninitArray{}, NumElems, NumElems); 175165984Srwatson 176294485Sngie bool Ok = true; 177165984Srwatson for (unsigned I = 0; I < NumElems; ++I) { 178294485Sngie APValue &Slot = R.getArrayInitializedElt(I); 179165984Srwatson const Pointer &EP = Ptr.atIndex(I); 180165982Srwatson if (llvm::Optional<PrimType> T = Ctx.classify(ElemTy)) { 181165982Srwatson TYPE_SWITCH(*T, Ok &= ReturnValue<T>(EP.deref<T>(), Slot)); 182165982Srwatson } else { 183165982Srwatson Ok &= Composite(ElemTy, EP.narrow(), Slot); 184165982Srwatson } 185165982Srwatson } 186165982Srwatson return Ok; 187165982Srwatson } 188165982Srwatson llvm_unreachable("invalid value to return"); 189165982Srwatson }; 190294485Sngie 191165982Srwatson // Return the composite type. 192165982Srwatson const auto &Ptr = S.Stk.pop<Pointer>(); 193165982Srwatson return Composite(Ptr.getType(), Ptr, Result); 194165982Srwatson} 195165982Srwatson 196165982Srwatsonbool EvalEmitter::emitGetPtrLocal(uint32_t I, const SourceInfo &Info) { 197165982Srwatson if (!isActive()) 198294485Sngie return true; 199165982Srwatson 200165982Srwatson auto It = Locals.find(I); 201165982Srwatson assert(It != Locals.end() && "Missing local variable"); 202165982Srwatson S.Stk.push<Pointer>(reinterpret_cast<Block *>(It->second.get())); 203165982Srwatson return true; 204165982Srwatson} 205165982Srwatson 206294485Sngietemplate <PrimType OpType> 207165982Srwatsonbool EvalEmitter::emitGetLocal(uint32_t I, const SourceInfo &Info) { 208165982Srwatson if (!isActive()) 209165982Srwatson return true; 210165982Srwatson 211165982Srwatson using T = typename PrimConv<OpType>::T; 212281974Sngie 213165982Srwatson auto It = Locals.find(I); 214165982Srwatson assert(It != Locals.end() && "Missing local variable"); 215281974Sngie auto *B = reinterpret_cast<Block *>(It->second.get()); 216294485Sngie S.Stk.push<T>(*reinterpret_cast<T *>(B + 1)); 217281974Sngie return true; 218165982Srwatson} 219165982Srwatson 220294485Sngietemplate <PrimType OpType> 221165982Srwatsonbool EvalEmitter::emitSetLocal(uint32_t I, const SourceInfo &Info) { 222165982Srwatson if (!isActive()) 223165982Srwatson return true; 224294485Sngie 225165982Srwatson using T = typename PrimConv<OpType>::T; 226165982Srwatson 227165982Srwatson auto It = Locals.find(I); 228294485Sngie assert(It != Locals.end() && "Missing local variable"); 229165982Srwatson auto *B = reinterpret_cast<Block *>(It->second.get()); 230165982Srwatson *reinterpret_cast<T *>(B + 1) = S.Stk.pop<T>(); 231165982Srwatson return true; 232165982Srwatson} 233165982Srwatson 234165982Srwatsonbool EvalEmitter::emitDestroy(uint32_t I, const SourceInfo &Info) { 235165982Srwatson if (!isActive()) 236165982Srwatson return true; 237165982Srwatson 238165982Srwatson for (auto &Local : Descriptors[I]) { 239165982Srwatson auto It = Locals.find(Local.Offset); 240165982Srwatson assert(It != Locals.end() && "Missing local variable"); 241165982Srwatson S.deallocate(reinterpret_cast<Block *>(It->second.get())); 242165982Srwatson } 243165982Srwatson 244165982Srwatson return true; 245294485Sngie} 246165982Srwatson 247165982Srwatson//===----------------------------------------------------------------------===// 248165982Srwatson// Opcode evaluators 249165982Srwatson//===----------------------------------------------------------------------===// 250165982Srwatson 251165982Srwatson#define GET_EVAL_IMPL 252165982Srwatson#include "Opcodes.inc" 253165982Srwatson#undef GET_EVAL_IMPL 254165982Srwatson