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