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