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