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->getSource(PC) : CurrentSource; 75 } 76 77 /// Parameter indices. 78 llvm::DenseMap<const ParmVarDecl *, unsigned> Params; 79 /// Local descriptors. 80 llvm::SmallVector<SmallVector<Local, 8>, 2> Descriptors; 81 82 private: 83 /// Current compilation context. 84 Context &Ctx; 85 /// Current program. 86 Program &P; 87 /// Callee evaluation state. 88 InterpState S; 89 /// Location to write the result to. 90 APValue &Result; 91 92 /// Temporaries which require storage. 93 llvm::DenseMap<unsigned, std::unique_ptr<char[]>> Locals; 94 95 // The emitter always tracks the current instruction and sets OpPC to a token 96 // value which is mapped to the location of the opcode being evaluated. 97 CodePtr OpPC; 98 /// Location of a failure. 99 std::optional<SourceLocation> BailLocation; 100 /// Location of the current instruction. 101 SourceInfo CurrentSource; 102 103 /// Next label ID to generate - first label is 1. 104 LabelTy NextLabel = 1; 105 /// Label being executed - 0 is the entry label. 106 LabelTy CurrentLabel = 0; 107 /// Active block which should be executed. 108 LabelTy ActiveLabel = 0; 109 110 /// Since expressions can only jump forward, predicated execution is 111 /// used to deal with if-else statements. 112 bool isActive() const { return CurrentLabel == ActiveLabel; } 113 114 protected: 115 #define GET_EVAL_PROTO 116 #include "Opcodes.inc" 117 #undef GET_EVAL_PROTO 118 }; 119 120 } // namespace interp 121 } // namespace clang 122 123 #endif 124