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