1 //===--- EvalEmitter.h - 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 // Defines the instruction emitters. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #ifndef LLVM_CLANG_AST_INTERP_EVALEMITTER_H 14 #define LLVM_CLANG_AST_INTERP_EVALEMITTER_H 15 16 #include "EvaluationResult.h" 17 #include "InterpState.h" 18 #include "PrimType.h" 19 #include "Source.h" 20 #include "llvm/Support/Error.h" 21 22 namespace clang { 23 namespace interp { 24 class Context; 25 class Function; 26 class InterpStack; 27 class Program; 28 enum Opcode : uint32_t; 29 30 /// An emitter which evaluates opcodes as they are emitted. 31 class EvalEmitter : public SourceMapper { 32 public: 33 using LabelTy = uint32_t; 34 using AddrTy = uintptr_t; 35 using Local = Scope::Local; 36 37 EvaluationResult interpretExpr(const Expr *E); 38 EvaluationResult interpretDecl(const VarDecl *VD); 39 40 InterpState &getState() { return S; } 41 42 protected: 43 EvalEmitter(Context &Ctx, Program &P, State &Parent, InterpStack &Stk, 44 APValue &Result); 45 46 virtual ~EvalEmitter(); 47 48 /// Define a label. 49 void emitLabel(LabelTy Label); 50 /// Create a label. 51 LabelTy getLabel(); 52 53 /// Methods implemented by the compiler. 54 virtual bool visitExpr(const Expr *E) = 0; 55 virtual bool visitDecl(const VarDecl *VD) = 0; 56 57 /// Emits jumps. 58 bool jumpTrue(const LabelTy &Label); 59 bool jumpFalse(const LabelTy &Label); 60 bool jump(const LabelTy &Label); 61 bool fallthrough(const LabelTy &Label); 62 63 /// Callback for registering a local. 64 Local createLocal(Descriptor *D); 65 66 /// Returns the source location of the current opcode. 67 SourceInfo getSource(const Function *F, CodePtr PC) const override { 68 return (F && F->hasBody()) ? F->getSource(PC) : CurrentSource; 69 } 70 71 /// Parameter indices. 72 llvm::DenseMap<const ParmVarDecl *, ParamOffset> Params; 73 /// Lambda captures. 74 llvm::DenseMap<const ValueDecl *, ParamOffset> LambdaCaptures; 75 /// Offset of the This parameter in a lambda record. 76 unsigned LambdaThisCapture = 0; 77 /// Local descriptors. 78 llvm::SmallVector<SmallVector<Local, 8>, 2> Descriptors; 79 80 private: 81 /// Current compilation context. 82 Context &Ctx; 83 /// Current program. 84 Program &P; 85 /// Callee evaluation state. 86 InterpState S; 87 /// Location to write the result to. 88 EvaluationResult EvalResult; 89 90 /// Temporaries which require storage. 91 llvm::DenseMap<unsigned, std::unique_ptr<char[]>> Locals; 92 93 Block *getLocal(unsigned Index) const { 94 auto It = Locals.find(Index); 95 assert(It != Locals.end() && "Missing local variable"); 96 return reinterpret_cast<Block *>(It->second.get()); 97 } 98 99 // The emitter always tracks the current instruction and sets OpPC to a token 100 // value which is mapped to the location of the opcode being evaluated. 101 CodePtr OpPC; 102 /// Location of the current instruction. 103 SourceInfo CurrentSource; 104 105 /// Next label ID to generate - first label is 1. 106 LabelTy NextLabel = 1; 107 /// Label being executed - 0 is the entry label. 108 LabelTy CurrentLabel = 0; 109 /// Active block which should be executed. 110 LabelTy ActiveLabel = 0; 111 112 /// Since expressions can only jump forward, predicated execution is 113 /// used to deal with if-else statements. 114 bool isActive() const { return CurrentLabel == ActiveLabel; } 115 116 protected: 117 #define GET_EVAL_PROTO 118 #include "Opcodes.inc" 119 #undef GET_EVAL_PROTO 120 }; 121 122 } // namespace interp 123 } // namespace clang 124 125 #endif 126