1353942Sdim//===--- EvalEmitter.h - Instruction emitter for the VM ---------*- C++ -*-===// 2353942Sdim// 3353942Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353942Sdim// See https://llvm.org/LICENSE.txt for license information. 5353942Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6353942Sdim// 7353942Sdim//===----------------------------------------------------------------------===// 8353942Sdim// 9353942Sdim// Defines the instruction emitters. 10353942Sdim// 11353942Sdim//===----------------------------------------------------------------------===// 12353942Sdim 13353942Sdim#ifndef LLVM_CLANG_AST_INTERP_EVALEMITTER_H 14353942Sdim#define LLVM_CLANG_AST_INTERP_EVALEMITTER_H 15353942Sdim 16353942Sdim#include "ByteCodeGenError.h" 17353942Sdim#include "Context.h" 18353942Sdim#include "InterpStack.h" 19353942Sdim#include "InterpState.h" 20353942Sdim#include "PrimType.h" 21353942Sdim#include "Program.h" 22353942Sdim#include "Source.h" 23353942Sdim#include "llvm/Support/Error.h" 24353942Sdim 25353942Sdimnamespace clang { 26353942Sdimclass FunctionDecl; 27353942Sdimnamespace interp { 28353942Sdimclass Context; 29353942Sdimclass Function; 30353942Sdimclass InterpState; 31353942Sdimclass Program; 32353942Sdimclass SourceInfo; 33353942Sdimenum Opcode : uint32_t; 34353942Sdim 35353942Sdim/// An emitter which evaluates opcodes as they are emitted. 36353942Sdimclass EvalEmitter : public SourceMapper { 37353942Sdimpublic: 38353942Sdim using LabelTy = uint32_t; 39353942Sdim using AddrTy = uintptr_t; 40353942Sdim using Local = Scope::Local; 41353942Sdim 42353942Sdim llvm::Expected<bool> interpretExpr(const Expr *E); 43353942Sdim llvm::Expected<bool> interpretDecl(const VarDecl *VD); 44353942Sdim 45353942Sdimprotected: 46353942Sdim EvalEmitter(Context &Ctx, Program &P, State &Parent, InterpStack &Stk, 47353942Sdim APValue &Result); 48353942Sdim 49353942Sdim virtual ~EvalEmitter() {} 50353942Sdim 51353942Sdim /// Define a label. 52353942Sdim void emitLabel(LabelTy Label); 53353942Sdim /// Create a label. 54353942Sdim LabelTy getLabel(); 55353942Sdim 56353942Sdim /// Methods implemented by the compiler. 57353942Sdim virtual bool visitExpr(const Expr *E) = 0; 58353942Sdim virtual bool visitDecl(const VarDecl *VD) = 0; 59353942Sdim 60353942Sdim bool bail(const Stmt *S) { return bail(S->getBeginLoc()); } 61353942Sdim bool bail(const Decl *D) { return bail(D->getBeginLoc()); } 62353942Sdim bool bail(const SourceLocation &Loc); 63353942Sdim 64353942Sdim /// Emits jumps. 65353942Sdim bool jumpTrue(const LabelTy &Label); 66353942Sdim bool jumpFalse(const LabelTy &Label); 67353942Sdim bool jump(const LabelTy &Label); 68353942Sdim bool fallthrough(const LabelTy &Label); 69353942Sdim 70353942Sdim /// Callback for registering a local. 71353942Sdim Local createLocal(Descriptor *D); 72353942Sdim 73353942Sdim /// Returns the source location of the current opcode. 74353942Sdim SourceInfo getSource(Function *F, CodePtr PC) const override { 75353942Sdim return F ? F->getSource(PC) : CurrentSource; 76353942Sdim } 77353942Sdim 78353942Sdim /// Parameter indices. 79353942Sdim llvm::DenseMap<const ParmVarDecl *, unsigned> Params; 80353942Sdim /// Local descriptors. 81353942Sdim llvm::SmallVector<SmallVector<Local, 8>, 2> Descriptors; 82353942Sdim 83353942Sdimprivate: 84353942Sdim /// Current compilation context. 85353942Sdim Context &Ctx; 86353942Sdim /// Current program. 87353942Sdim Program &P; 88353942Sdim /// Callee evaluation state. 89353942Sdim InterpState S; 90353942Sdim /// Location to write the result to. 91353942Sdim APValue &Result; 92353942Sdim 93353942Sdim /// Temporaries which require storage. 94353942Sdim llvm::DenseMap<unsigned, std::unique_ptr<char[]>> Locals; 95353942Sdim 96353942Sdim // The emitter always tracks the current instruction and sets OpPC to a token 97353942Sdim // value which is mapped to the location of the opcode being evaluated. 98353942Sdim CodePtr OpPC; 99353942Sdim /// Location of a failure. 100353942Sdim llvm::Optional<SourceLocation> BailLocation; 101353942Sdim /// Location of the current instruction. 102353942Sdim SourceInfo CurrentSource; 103353942Sdim 104353942Sdim /// Next label ID to generate - first label is 1. 105353942Sdim LabelTy NextLabel = 1; 106353942Sdim /// Label being executed - 0 is the entry label. 107353942Sdim LabelTy CurrentLabel = 0; 108353942Sdim /// Active block which should be executed. 109353942Sdim LabelTy ActiveLabel = 0; 110353942Sdim 111353942Sdim /// Since expressions can only jump forward, predicated execution is 112353942Sdim /// used to deal with if-else statements. 113353942Sdim bool isActive() { return CurrentLabel == ActiveLabel; } 114353942Sdim 115353942Sdim /// Helper to invoke a method. 116353942Sdim bool ExecuteCall(Function *F, Pointer &&This, const SourceInfo &Info); 117353942Sdim /// Helper to emit a diagnostic on a missing method. 118353942Sdim bool ExecuteNoCall(const FunctionDecl *F, const SourceInfo &Info); 119353942Sdim 120353942Sdimprotected: 121353942Sdim#define GET_EVAL_PROTO 122353942Sdim#include "Opcodes.inc" 123353942Sdim#undef GET_EVAL_PROTO 124353942Sdim}; 125353942Sdim 126353942Sdim} // namespace interp 127353942Sdim} // namespace clang 128353942Sdim 129353942Sdim#endif 130