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
22namespace clang {
23namespace interp {
24class Context;
25class Function;
26class InterpStack;
27class Program;
28enum Opcode : uint32_t;
29
30/// An emitter which evaluates opcodes as they are emitted.
31class EvalEmitter : public SourceMapper {
32public:
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
42protected:
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
80private:
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
116protected:
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