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 25namespace clang { 26class FunctionDecl; 27namespace interp { 28class Context; 29class Function; 30class InterpState; 31class Program; 32class SourceInfo; 33enum Opcode : uint32_t; 34 35/// An emitter which evaluates opcodes as they are emitted. 36class EvalEmitter : public SourceMapper { 37public: 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 45protected: 46 EvalEmitter(Context &Ctx, Program &P, State &Parent, InterpStack &Stk, 47 APValue &Result); 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 visitDecl(const VarDecl *VD) = 0; 59 60 bool bail(const Stmt *S) { return bail(S->getBeginLoc()); } 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. 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 83private: 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. 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 120protected: 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