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
25namespace clang {
26namespace interp {
27class Context;
28class Function;
29class InterpState;
30class Program;
31class SourceInfo;
32enum Opcode : uint32_t;
33
34/// An emitter which evaluates opcodes as they are emitted.
35class EvalEmitter : public SourceMapper {
36public:
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
44protected:
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
82private:
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
114protected:
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