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 class FunctionDecl; 27 namespace interp { 28 class Context; 29 class Function; 30 class InterpState; 31 class Program; 32 class SourceInfo; 33 enum Opcode : uint32_t; 34 35 /// An emitter which evaluates opcodes as they are emitted. 36 class EvalEmitter : public SourceMapper { 37 public: 38 using LabelTy = uint32_t; 39 using AddrTy = uintptr_t; 40 using Local = Scope::Local; 41 42 llvm::Expected<bool> interpretExpr(const Expr *E); 43 llvm::Expected<bool> interpretDecl(const VarDecl *VD); 44 45 protected: 46 EvalEmitter(Context &Ctx, Program &P, State &Parent, InterpStack &Stk, 47 APValue &Result); 48 ~EvalEmitter()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 visitDecl(const VarDecl *VD) = 0; 59 bail(const Stmt * S)60 bool bail(const Stmt *S) { return bail(S->getBeginLoc()); } bail(const Decl * D)61 bool bail(const Decl *D) { return bail(D->getBeginLoc()); } 62 bool bail(const SourceLocation &Loc); 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 70 /// Callback for registering a local. 71 Local createLocal(Descriptor *D); 72 73 /// Returns the source location of the current opcode. getSource(Function * F,CodePtr PC)74 SourceInfo getSource(Function *F, CodePtr PC) const override { 75 return F ? F->getSource(PC) : CurrentSource; 76 } 77 78 /// Parameter indices. 79 llvm::DenseMap<const ParmVarDecl *, unsigned> Params; 80 /// Local descriptors. 81 llvm::SmallVector<SmallVector<Local, 8>, 2> Descriptors; 82 83 private: 84 /// Current compilation context. 85 Context &Ctx; 86 /// Current program. 87 Program &P; 88 /// Callee evaluation state. 89 InterpState S; 90 /// Location to write the result to. 91 APValue &Result; 92 93 /// Temporaries which require storage. 94 llvm::DenseMap<unsigned, std::unique_ptr<char[]>> Locals; 95 96 // The emitter always tracks the current instruction and sets OpPC to a token 97 // value which is mapped to the location of the opcode being evaluated. 98 CodePtr OpPC; 99 /// Location of a failure. 100 llvm::Optional<SourceLocation> BailLocation; 101 /// Location of the current instruction. 102 SourceInfo CurrentSource; 103 104 /// Next label ID to generate - first label is 1. 105 LabelTy NextLabel = 1; 106 /// Label being executed - 0 is the entry label. 107 LabelTy CurrentLabel = 0; 108 /// Active block which should be executed. 109 LabelTy ActiveLabel = 0; 110 111 /// Since expressions can only jump forward, predicated execution is 112 /// used to deal with if-else statements. isActive()113 bool isActive() { return CurrentLabel == ActiveLabel; } 114 115 /// Helper to invoke a method. 116 bool ExecuteCall(Function *F, Pointer &&This, const SourceInfo &Info); 117 /// Helper to emit a diagnostic on a missing method. 118 bool ExecuteNoCall(const FunctionDecl *F, const SourceInfo &Info); 119 120 protected: 121 #define GET_EVAL_PROTO 122 #include "Opcodes.inc" 123 #undef GET_EVAL_PROTO 124 }; 125 126 } // namespace interp 127 } // namespace clang 128 129 #endif 130