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