1 //===--- ByteCodeEmitter.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_LINKEMITTER_H 14 #define LLVM_CLANG_AST_INTERP_LINKEMITTER_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 25 namespace clang { 26 namespace interp { 27 class Context; 28 class SourceInfo; 29 enum Opcode : uint32_t; 30 31 /// An emitter which links the program to bytecode for later use. 32 class ByteCodeEmitter { 33 protected: 34 using LabelTy = uint32_t; 35 using AddrTy = uintptr_t; 36 using Local = Scope::Local; 37 38 public: 39 /// Compiles the function into the module. 40 llvm::Expected<Function *> compileFunc(const FunctionDecl *FuncDecl); 41 42 protected: 43 ByteCodeEmitter(Context &Ctx, Program &P) : Ctx(Ctx), P(P) {} 44 45 virtual ~ByteCodeEmitter() {} 46 47 /// Define a label. 48 void emitLabel(LabelTy Label); 49 /// Create a label. 50 LabelTy getLabel() { return ++NextLabel; } 51 52 /// Methods implemented by the compiler. 53 virtual bool visitFunc(const FunctionDecl *E) = 0; 54 virtual bool visitExpr(const Expr *E) = 0; 55 virtual bool visitDecl(const VarDecl *E) = 0; 56 57 /// Bails out if a given node cannot be compiled. 58 bool bail(const Stmt *S) { return bail(S->getBeginLoc()); } 59 bool bail(const Decl *D) { return bail(D->getBeginLoc()); } 60 bool bail(const SourceLocation &Loc); 61 62 /// Emits jumps. 63 bool jumpTrue(const LabelTy &Label); 64 bool jumpFalse(const LabelTy &Label); 65 bool jump(const LabelTy &Label); 66 bool fallthrough(const LabelTy &Label); 67 68 /// Callback for local registration. 69 Local createLocal(Descriptor *D); 70 71 /// Parameter indices. 72 llvm::DenseMap<const ParmVarDecl *, unsigned> Params; 73 /// Lambda captures. 74 /// Map from Decl* to [Offset, IsReference] pair. 75 llvm::DenseMap<const ValueDecl *, std::pair<unsigned, bool>> LambdaCaptures; 76 unsigned LambdaThisCapture; 77 /// Local descriptors. 78 llvm::SmallVector<SmallVector<Local, 8>, 2> Descriptors; 79 80 private: 81 /// Current compilation context. 82 Context &Ctx; 83 /// Program to link to. 84 Program &P; 85 /// Index of the next available label. 86 LabelTy NextLabel = 0; 87 /// Offset of the next local variable. 88 unsigned NextLocalOffset = 0; 89 /// Location of a failure. 90 std::optional<SourceLocation> BailLocation; 91 /// Label information for linker. 92 llvm::DenseMap<LabelTy, unsigned> LabelOffsets; 93 /// Location of label relocations. 94 llvm::DenseMap<LabelTy, llvm::SmallVector<unsigned, 5>> LabelRelocs; 95 /// Program code. 96 std::vector<std::byte> Code; 97 /// Opcode to expression mapping. 98 SourceMap SrcMap; 99 100 /// Returns the offset for a jump or records a relocation. 101 int32_t getOffset(LabelTy Label); 102 103 /// Emits an opcode. 104 template <typename... Tys> 105 bool emitOp(Opcode Op, const Tys &... Args, const SourceInfo &L); 106 107 protected: 108 #define GET_LINK_PROTO 109 #include "Opcodes.inc" 110 #undef GET_LINK_PROTO 111 }; 112 113 } // namespace interp 114 } // namespace clang 115 116 #endif 117