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 { 26namespace interp { 27class Context; 28class Function; 29class InterpState; 30class Program; 31class SourceInfo; 32enum Opcode : uint32_t; 33 34/// An emitter which evaluates opcodes as they are emitted. 35class EvalEmitter : public SourceMapper { 36public: 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 44protected: 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 82private: 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 114protected: 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