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 bool ConvertResultToRValue = false); 39 EvaluationResult interpretDecl(const VarDecl *VD, bool CheckFullyInitialized); 40 41 /// Clean up all resources. 42 void cleanup(); 43 44 InterpState &getState() { return S; } 45 46 protected: 47 EvalEmitter(Context &Ctx, Program &P, State &Parent, InterpStack &Stk); 48 49 virtual ~EvalEmitter(); 50 51 /// Define a label. 52 void emitLabel(LabelTy Label); 53 /// Create a label. 54 LabelTy getLabel(); 55 56 /// Methods implemented by the compiler. 57 virtual bool visitExpr(const Expr *E) = 0; 58 virtual bool visitDeclAndReturn(const VarDecl *VD, bool ConstantContext) = 0; 59 virtual bool visitFunc(const FunctionDecl *F) = 0; 60 61 /// Emits jumps. 62 bool jumpTrue(const LabelTy &Label); 63 bool jumpFalse(const LabelTy &Label); 64 bool jump(const LabelTy &Label); 65 bool fallthrough(const LabelTy &Label); 66 67 /// Since expressions can only jump forward, predicated execution is 68 /// used to deal with if-else statements. 69 bool isActive() const { return CurrentLabel == ActiveLabel; } 70 71 /// Callback for registering a local. 72 Local createLocal(Descriptor *D); 73 74 /// Returns the source location of the current opcode. 75 SourceInfo getSource(const Function *F, CodePtr PC) const override { 76 return (F && F->hasBody()) ? F->getSource(PC) : CurrentSource; 77 } 78 79 /// Parameter indices. 80 llvm::DenseMap<const ParmVarDecl *, ParamOffset> Params; 81 /// Lambda captures. 82 llvm::DenseMap<const ValueDecl *, ParamOffset> LambdaCaptures; 83 /// Offset of the This parameter in a lambda record. 84 ParamOffset LambdaThisCapture{0, false}; 85 /// Local descriptors. 86 llvm::SmallVector<SmallVector<Local, 8>, 2> Descriptors; 87 88 private: 89 /// Current compilation context. 90 Context &Ctx; 91 /// Current program. 92 Program &P; 93 /// Callee evaluation state. 94 InterpState S; 95 /// Location to write the result to. 96 EvaluationResult EvalResult; 97 /// Whether the result should be converted to an RValue. 98 bool ConvertResultToRValue = false; 99 /// Whether we should check if the result has been fully 100 /// initialized. 101 bool CheckFullyInitialized = false; 102 103 /// Temporaries which require storage. 104 llvm::DenseMap<unsigned, std::unique_ptr<char[]>> Locals; 105 106 Block *getLocal(unsigned Index) const { 107 auto It = Locals.find(Index); 108 assert(It != Locals.end() && "Missing local variable"); 109 return reinterpret_cast<Block *>(It->second.get()); 110 } 111 112 void updateGlobalTemporaries(); 113 114 // The emitter always tracks the current instruction and sets OpPC to a token 115 // value which is mapped to the location of the opcode being evaluated. 116 CodePtr OpPC; 117 /// Location of the current instruction. 118 SourceInfo CurrentSource; 119 120 /// Next label ID to generate - first label is 1. 121 LabelTy NextLabel = 1; 122 /// Label being executed - 0 is the entry label. 123 LabelTy CurrentLabel = 0; 124 /// Active block which should be executed. 125 LabelTy ActiveLabel = 0; 126 127 protected: 128 #define GET_EVAL_PROTO 129 #include "Opcodes.inc" 130 #undef GET_EVAL_PROTO 131 }; 132 133 } // namespace interp 134 } // namespace clang 135 136 #endif 137