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