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