| //===--- ByteCodeEmitter.h - Instruction emitter for the VM -----*- C++ -*-===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // Defines the instruction emitters. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef LLVM_CLANG_AST_INTERP_LINKEMITTER_H |
| #define LLVM_CLANG_AST_INTERP_LINKEMITTER_H |
| |
| #include "Context.h" |
| #include "PrimType.h" |
| #include "Program.h" |
| #include "Source.h" |
| |
| namespace clang { |
| namespace interp { |
| enum Opcode : uint32_t; |
| |
| /// An emitter which links the program to bytecode for later use. |
| class ByteCodeEmitter { |
| protected: |
| using LabelTy = uint32_t; |
| using AddrTy = uintptr_t; |
| using Local = Scope::Local; |
| |
| public: |
| /// Compiles the function into the module. |
| void compileFunc(const FunctionDecl *FuncDecl, Function *Func = nullptr); |
| |
| protected: |
| ByteCodeEmitter(Context &Ctx, Program &P) : Ctx(Ctx), P(P) {} |
| |
| virtual ~ByteCodeEmitter() {} |
| |
| /// Define a label. |
| void emitLabel(LabelTy Label); |
| /// Create a label. |
| LabelTy getLabel() { return ++NextLabel; } |
| |
| /// Methods implemented by the compiler. |
| virtual bool visitFunc(const FunctionDecl *E) = 0; |
| virtual bool visitExpr(const Expr *E, bool DestroyToplevelScope) = 0; |
| virtual bool visitDeclAndReturn(const VarDecl *E, bool ConstantContext) = 0; |
| virtual bool visit(const Expr *E) = 0; |
| virtual bool emitBool(bool V, const Expr *E) = 0; |
| |
| /// Emits jumps. |
| bool jumpTrue(const LabelTy &Label); |
| bool jumpFalse(const LabelTy &Label); |
| bool jump(const LabelTy &Label); |
| bool fallthrough(const LabelTy &Label); |
| /// Speculative execution. |
| bool speculate(const CallExpr *E, const LabelTy &EndLabel); |
| |
| /// We're always emitting bytecode. |
| bool isActive() const { return true; } |
| bool checkingForUndefinedBehavior() const { return false; } |
| |
| /// Callback for local registration. |
| Local createLocal(Descriptor *D); |
| |
| /// Parameter indices. |
| llvm::DenseMap<const ParmVarDecl *, ParamOffset> Params; |
| /// Lambda captures. |
| llvm::DenseMap<const ValueDecl *, ParamOffset> LambdaCaptures; |
| /// Offset of the This parameter in a lambda record. |
| ParamOffset LambdaThisCapture{0, false}; |
| /// Local descriptors. |
| llvm::SmallVector<SmallVector<Local, 8>, 2> Descriptors; |
| std::optional<SourceInfo> LocOverride = std::nullopt; |
| |
| private: |
| /// Current compilation context. |
| Context &Ctx; |
| /// Program to link to. |
| Program &P; |
| /// Index of the next available label. |
| LabelTy NextLabel = 0; |
| /// Offset of the next local variable. |
| unsigned NextLocalOffset = 0; |
| /// Label information for linker. |
| llvm::DenseMap<LabelTy, unsigned> LabelOffsets; |
| /// Location of label relocations. |
| llvm::DenseMap<LabelTy, llvm::SmallVector<unsigned, 5>> LabelRelocs; |
| /// Program code. |
| llvm::SmallVector<std::byte> Code; |
| /// Opcode to expression mapping. |
| SourceMap SrcMap; |
| |
| /// Returns the offset for a jump or records a relocation. |
| int32_t getOffset(LabelTy Label); |
| |
| /// Emits an opcode. |
| template <typename... Tys> |
| bool emitOp(Opcode Op, const Tys &...Args, const SourceInfo &L); |
| |
| protected: |
| #define GET_LINK_PROTO |
| #include "Opcodes.inc" |
| #undef GET_LINK_PROTO |
| }; |
| |
| } // namespace interp |
| } // namespace clang |
| |
| #endif |