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