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