1*700637cbSDimitry Andric //===--- ByteCodeEmitter.h - Instruction emitter for the VM -----*- C++ -*-===// 2*700637cbSDimitry Andric // 3*700637cbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*700637cbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*700637cbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*700637cbSDimitry Andric // 7*700637cbSDimitry Andric //===----------------------------------------------------------------------===// 8*700637cbSDimitry Andric // 9*700637cbSDimitry Andric // Defines the instruction emitters. 10*700637cbSDimitry Andric // 11*700637cbSDimitry Andric //===----------------------------------------------------------------------===// 12*700637cbSDimitry Andric 13*700637cbSDimitry Andric #ifndef LLVM_CLANG_AST_INTERP_LINKEMITTER_H 14*700637cbSDimitry Andric #define LLVM_CLANG_AST_INTERP_LINKEMITTER_H 15*700637cbSDimitry Andric 16*700637cbSDimitry Andric #include "Context.h" 17*700637cbSDimitry Andric #include "PrimType.h" 18*700637cbSDimitry Andric #include "Program.h" 19*700637cbSDimitry Andric #include "Source.h" 20*700637cbSDimitry Andric 21*700637cbSDimitry Andric namespace clang { 22*700637cbSDimitry Andric namespace interp { 23*700637cbSDimitry Andric enum Opcode : uint32_t; 24*700637cbSDimitry Andric 25*700637cbSDimitry Andric /// An emitter which links the program to bytecode for later use. 26*700637cbSDimitry Andric class ByteCodeEmitter { 27*700637cbSDimitry Andric protected: 28*700637cbSDimitry Andric using LabelTy = uint32_t; 29*700637cbSDimitry Andric using AddrTy = uintptr_t; 30*700637cbSDimitry Andric using Local = Scope::Local; 31*700637cbSDimitry Andric 32*700637cbSDimitry Andric public: 33*700637cbSDimitry Andric /// Compiles the function into the module. 34*700637cbSDimitry Andric void compileFunc(const FunctionDecl *FuncDecl, Function *Func = nullptr); 35*700637cbSDimitry Andric 36*700637cbSDimitry Andric protected: ByteCodeEmitter(Context & Ctx,Program & P)37*700637cbSDimitry Andric ByteCodeEmitter(Context &Ctx, Program &P) : Ctx(Ctx), P(P) {} 38*700637cbSDimitry Andric ~ByteCodeEmitter()39*700637cbSDimitry Andric virtual ~ByteCodeEmitter() {} 40*700637cbSDimitry Andric 41*700637cbSDimitry Andric /// Define a label. 42*700637cbSDimitry Andric void emitLabel(LabelTy Label); 43*700637cbSDimitry Andric /// Create a label. getLabel()44*700637cbSDimitry Andric LabelTy getLabel() { return ++NextLabel; } 45*700637cbSDimitry Andric 46*700637cbSDimitry Andric /// Methods implemented by the compiler. 47*700637cbSDimitry Andric virtual bool visitFunc(const FunctionDecl *E) = 0; 48*700637cbSDimitry Andric virtual bool visitExpr(const Expr *E, bool DestroyToplevelScope) = 0; 49*700637cbSDimitry Andric virtual bool visitDeclAndReturn(const VarDecl *E, bool ConstantContext) = 0; 50*700637cbSDimitry Andric virtual bool visit(const Expr *E) = 0; 51*700637cbSDimitry Andric virtual bool emitBool(bool V, const Expr *E) = 0; 52*700637cbSDimitry Andric 53*700637cbSDimitry Andric /// Emits jumps. 54*700637cbSDimitry Andric bool jumpTrue(const LabelTy &Label); 55*700637cbSDimitry Andric bool jumpFalse(const LabelTy &Label); 56*700637cbSDimitry Andric bool jump(const LabelTy &Label); 57*700637cbSDimitry Andric bool fallthrough(const LabelTy &Label); 58*700637cbSDimitry Andric /// Speculative execution. 59*700637cbSDimitry Andric bool speculate(const CallExpr *E, const LabelTy &EndLabel); 60*700637cbSDimitry Andric 61*700637cbSDimitry Andric /// We're always emitting bytecode. isActive()62*700637cbSDimitry Andric bool isActive() const { return true; } checkingForUndefinedBehavior()63*700637cbSDimitry Andric bool checkingForUndefinedBehavior() const { return false; } 64*700637cbSDimitry Andric 65*700637cbSDimitry Andric /// Callback for local registration. 66*700637cbSDimitry Andric Local createLocal(Descriptor *D); 67*700637cbSDimitry Andric 68*700637cbSDimitry Andric /// Parameter indices. 69*700637cbSDimitry Andric llvm::DenseMap<const ParmVarDecl *, ParamOffset> Params; 70*700637cbSDimitry Andric /// Lambda captures. 71*700637cbSDimitry Andric llvm::DenseMap<const ValueDecl *, ParamOffset> LambdaCaptures; 72*700637cbSDimitry Andric /// Offset of the This parameter in a lambda record. 73*700637cbSDimitry Andric ParamOffset LambdaThisCapture{0, false}; 74*700637cbSDimitry Andric /// Local descriptors. 75*700637cbSDimitry Andric llvm::SmallVector<SmallVector<Local, 8>, 2> Descriptors; 76*700637cbSDimitry Andric 77*700637cbSDimitry Andric private: 78*700637cbSDimitry Andric /// Current compilation context. 79*700637cbSDimitry Andric Context &Ctx; 80*700637cbSDimitry Andric /// Program to link to. 81*700637cbSDimitry Andric Program &P; 82*700637cbSDimitry Andric /// Index of the next available label. 83*700637cbSDimitry Andric LabelTy NextLabel = 0; 84*700637cbSDimitry Andric /// Offset of the next local variable. 85*700637cbSDimitry Andric unsigned NextLocalOffset = 0; 86*700637cbSDimitry Andric /// Label information for linker. 87*700637cbSDimitry Andric llvm::DenseMap<LabelTy, unsigned> LabelOffsets; 88*700637cbSDimitry Andric /// Location of label relocations. 89*700637cbSDimitry Andric llvm::DenseMap<LabelTy, llvm::SmallVector<unsigned, 5>> LabelRelocs; 90*700637cbSDimitry Andric /// Program code. 91*700637cbSDimitry Andric std::vector<std::byte> Code; 92*700637cbSDimitry Andric /// Opcode to expression mapping. 93*700637cbSDimitry Andric SourceMap SrcMap; 94*700637cbSDimitry Andric 95*700637cbSDimitry Andric /// Returns the offset for a jump or records a relocation. 96*700637cbSDimitry Andric int32_t getOffset(LabelTy Label); 97*700637cbSDimitry Andric 98*700637cbSDimitry Andric /// Emits an opcode. 99*700637cbSDimitry Andric template <typename... Tys> 100*700637cbSDimitry Andric bool emitOp(Opcode Op, const Tys &...Args, const SourceInfo &L); 101*700637cbSDimitry Andric 102*700637cbSDimitry Andric protected: 103*700637cbSDimitry Andric #define GET_LINK_PROTO 104*700637cbSDimitry Andric #include "Opcodes.inc" 105*700637cbSDimitry Andric #undef GET_LINK_PROTO 106*700637cbSDimitry Andric }; 107*700637cbSDimitry Andric 108*700637cbSDimitry Andric } // namespace interp 109*700637cbSDimitry Andric } // namespace clang 110*700637cbSDimitry Andric 111*700637cbSDimitry Andric #endif 112