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