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