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 "EvaluationResult.h"
17 #include "InterpState.h"
18 #include "PrimType.h"
19 #include "Source.h"
20 #include "llvm/Support/Error.h"
21 
22 namespace clang {
23 namespace interp {
24 class Context;
25 class Function;
26 class InterpStack;
27 class Program;
28 enum Opcode : uint32_t;
29 
30 /// An emitter which evaluates opcodes as they are emitted.
31 class EvalEmitter : public SourceMapper {
32 public:
33   using LabelTy = uint32_t;
34   using AddrTy = uintptr_t;
35   using Local = Scope::Local;
36 
37   EvaluationResult interpretExpr(const Expr *E);
38   EvaluationResult interpretDecl(const VarDecl *VD);
39 
40   InterpState &getState() { return S; }
41 
42 protected:
43   EvalEmitter(Context &Ctx, Program &P, State &Parent, InterpStack &Stk,
44               APValue &Result);
45 
46   virtual ~EvalEmitter();
47 
48   /// Define a label.
49   void emitLabel(LabelTy Label);
50   /// Create a label.
51   LabelTy getLabel();
52 
53   /// Methods implemented by the compiler.
54   virtual bool visitExpr(const Expr *E) = 0;
55   virtual bool visitDecl(const VarDecl *VD) = 0;
56 
57   /// Emits jumps.
58   bool jumpTrue(const LabelTy &Label);
59   bool jumpFalse(const LabelTy &Label);
60   bool jump(const LabelTy &Label);
61   bool fallthrough(const LabelTy &Label);
62 
63   /// Callback for registering a local.
64   Local createLocal(Descriptor *D);
65 
66   /// Returns the source location of the current opcode.
67   SourceInfo getSource(const Function *F, CodePtr PC) const override {
68     return (F && F->hasBody()) ? F->getSource(PC) : CurrentSource;
69   }
70 
71   /// Parameter indices.
72   llvm::DenseMap<const ParmVarDecl *, ParamOffset> Params;
73   /// Lambda captures.
74   llvm::DenseMap<const ValueDecl *, ParamOffset> LambdaCaptures;
75   /// Offset of the This parameter in a lambda record.
76   unsigned LambdaThisCapture = 0;
77   /// Local descriptors.
78   llvm::SmallVector<SmallVector<Local, 8>, 2> Descriptors;
79 
80 private:
81   /// Current compilation context.
82   Context &Ctx;
83   /// Current program.
84   Program &P;
85   /// Callee evaluation state.
86   InterpState S;
87   /// Location to write the result to.
88   EvaluationResult EvalResult;
89 
90   /// Temporaries which require storage.
91   llvm::DenseMap<unsigned, std::unique_ptr<char[]>> Locals;
92 
93   Block *getLocal(unsigned Index) const {
94     auto It = Locals.find(Index);
95     assert(It != Locals.end() && "Missing local variable");
96     return reinterpret_cast<Block *>(It->second.get());
97   }
98 
99   // The emitter always tracks the current instruction and sets OpPC to a token
100   // value which is mapped to the location of the opcode being evaluated.
101   CodePtr OpPC;
102   /// Location of the current instruction.
103   SourceInfo CurrentSource;
104 
105   /// Next label ID to generate - first label is 1.
106   LabelTy NextLabel = 1;
107   /// Label being executed - 0 is the entry label.
108   LabelTy CurrentLabel = 0;
109   /// Active block which should be executed.
110   LabelTy ActiveLabel = 0;
111 
112   /// Since expressions can only jump forward, predicated execution is
113   /// used to deal with if-else statements.
114   bool isActive() const { return CurrentLabel == ActiveLabel; }
115 
116 protected:
117 #define GET_EVAL_PROTO
118 #include "Opcodes.inc"
119 #undef GET_EVAL_PROTO
120 };
121 
122 } // namespace interp
123 } // namespace clang
124 
125 #endif
126