xref: /freebsd/contrib/llvm-project/clang/lib/AST/Interp/EvalEmitter.h (revision 734e82fe33aa764367791a7d603b383996c6b40b)
1 //===--- EvalEmitter.h - Instruction emitter for the VM ---------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Defines the instruction emitters.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef LLVM_CLANG_AST_INTERP_EVALEMITTER_H
14 #define LLVM_CLANG_AST_INTERP_EVALEMITTER_H
15 
16 #include "ByteCodeGenError.h"
17 #include "Context.h"
18 #include "InterpStack.h"
19 #include "InterpState.h"
20 #include "PrimType.h"
21 #include "Program.h"
22 #include "Source.h"
23 #include "llvm/Support/Error.h"
24 
25 namespace clang {
26 namespace interp {
27 class Context;
28 class Function;
29 class InterpState;
30 class Program;
31 class SourceInfo;
32 enum Opcode : uint32_t;
33 
34 /// An emitter which evaluates opcodes as they are emitted.
35 class EvalEmitter : public SourceMapper {
36 public:
37   using LabelTy = uint32_t;
38   using AddrTy = uintptr_t;
39   using Local = Scope::Local;
40 
41   llvm::Expected<bool> interpretExpr(const Expr *E);
42   llvm::Expected<bool> interpretDecl(const VarDecl *VD);
43 
44 protected:
45   EvalEmitter(Context &Ctx, Program &P, State &Parent, InterpStack &Stk,
46               APValue &Result);
47 
48   virtual ~EvalEmitter() {}
49 
50   /// Define a label.
51   void emitLabel(LabelTy Label);
52   /// Create a label.
53   LabelTy getLabel();
54 
55   /// Methods implemented by the compiler.
56   virtual bool visitExpr(const Expr *E) = 0;
57   virtual bool visitDecl(const VarDecl *VD) = 0;
58 
59   bool bail(const Stmt *S) { return bail(S->getBeginLoc()); }
60   bool bail(const Decl *D) { return bail(D->getBeginLoc()); }
61   bool bail(const SourceLocation &Loc);
62 
63   /// Emits jumps.
64   bool jumpTrue(const LabelTy &Label);
65   bool jumpFalse(const LabelTy &Label);
66   bool jump(const LabelTy &Label);
67   bool fallthrough(const LabelTy &Label);
68 
69   /// Callback for registering a local.
70   Local createLocal(Descriptor *D);
71 
72   /// Returns the source location of the current opcode.
73   SourceInfo getSource(const Function *F, CodePtr PC) const override {
74     return F ? F->getSource(PC) : CurrentSource;
75   }
76 
77   /// Parameter indices.
78   llvm::DenseMap<const ParmVarDecl *, unsigned> Params;
79   /// Local descriptors.
80   llvm::SmallVector<SmallVector<Local, 8>, 2> Descriptors;
81 
82 private:
83   /// Current compilation context.
84   Context &Ctx;
85   /// Current program.
86   Program &P;
87   /// Callee evaluation state.
88   InterpState S;
89   /// Location to write the result to.
90   APValue &Result;
91 
92   /// Temporaries which require storage.
93   llvm::DenseMap<unsigned, std::unique_ptr<char[]>> Locals;
94 
95   // The emitter always tracks the current instruction and sets OpPC to a token
96   // value which is mapped to the location of the opcode being evaluated.
97   CodePtr OpPC;
98   /// Location of a failure.
99   std::optional<SourceLocation> BailLocation;
100   /// Location of the current instruction.
101   SourceInfo CurrentSource;
102 
103   /// Next label ID to generate - first label is 1.
104   LabelTy NextLabel = 1;
105   /// Label being executed - 0 is the entry label.
106   LabelTy CurrentLabel = 0;
107   /// Active block which should be executed.
108   LabelTy ActiveLabel = 0;
109 
110   /// Since expressions can only jump forward, predicated execution is
111   /// used to deal with if-else statements.
112   bool isActive() const { return CurrentLabel == ActiveLabel; }
113 
114 protected:
115 #define GET_EVAL_PROTO
116 #include "Opcodes.inc"
117 #undef GET_EVAL_PROTO
118 };
119 
120 } // namespace interp
121 } // namespace clang
122 
123 #endif
124