1353942Sdim//===--- EvalEmitter.h - Instruction emitter for the VM ---------*- C++ -*-===//
2353942Sdim//
3353942Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353942Sdim// See https://llvm.org/LICENSE.txt for license information.
5353942Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6353942Sdim//
7353942Sdim//===----------------------------------------------------------------------===//
8353942Sdim//
9353942Sdim// Defines the instruction emitters.
10353942Sdim//
11353942Sdim//===----------------------------------------------------------------------===//
12353942Sdim
13353942Sdim#ifndef LLVM_CLANG_AST_INTERP_EVALEMITTER_H
14353942Sdim#define LLVM_CLANG_AST_INTERP_EVALEMITTER_H
15353942Sdim
16353942Sdim#include "ByteCodeGenError.h"
17353942Sdim#include "Context.h"
18353942Sdim#include "InterpStack.h"
19353942Sdim#include "InterpState.h"
20353942Sdim#include "PrimType.h"
21353942Sdim#include "Program.h"
22353942Sdim#include "Source.h"
23353942Sdim#include "llvm/Support/Error.h"
24353942Sdim
25353942Sdimnamespace clang {
26353942Sdimclass FunctionDecl;
27353942Sdimnamespace interp {
28353942Sdimclass Context;
29353942Sdimclass Function;
30353942Sdimclass InterpState;
31353942Sdimclass Program;
32353942Sdimclass SourceInfo;
33353942Sdimenum Opcode : uint32_t;
34353942Sdim
35353942Sdim/// An emitter which evaluates opcodes as they are emitted.
36353942Sdimclass EvalEmitter : public SourceMapper {
37353942Sdimpublic:
38353942Sdim  using LabelTy = uint32_t;
39353942Sdim  using AddrTy = uintptr_t;
40353942Sdim  using Local = Scope::Local;
41353942Sdim
42353942Sdim  llvm::Expected<bool> interpretExpr(const Expr *E);
43353942Sdim  llvm::Expected<bool> interpretDecl(const VarDecl *VD);
44353942Sdim
45353942Sdimprotected:
46353942Sdim  EvalEmitter(Context &Ctx, Program &P, State &Parent, InterpStack &Stk,
47353942Sdim              APValue &Result);
48353942Sdim
49353942Sdim  virtual ~EvalEmitter() {}
50353942Sdim
51353942Sdim  /// Define a label.
52353942Sdim  void emitLabel(LabelTy Label);
53353942Sdim  /// Create a label.
54353942Sdim  LabelTy getLabel();
55353942Sdim
56353942Sdim  /// Methods implemented by the compiler.
57353942Sdim  virtual bool visitExpr(const Expr *E) = 0;
58353942Sdim  virtual bool visitDecl(const VarDecl *VD) = 0;
59353942Sdim
60353942Sdim  bool bail(const Stmt *S) { return bail(S->getBeginLoc()); }
61353942Sdim  bool bail(const Decl *D) { return bail(D->getBeginLoc()); }
62353942Sdim  bool bail(const SourceLocation &Loc);
63353942Sdim
64353942Sdim  /// Emits jumps.
65353942Sdim  bool jumpTrue(const LabelTy &Label);
66353942Sdim  bool jumpFalse(const LabelTy &Label);
67353942Sdim  bool jump(const LabelTy &Label);
68353942Sdim  bool fallthrough(const LabelTy &Label);
69353942Sdim
70353942Sdim  /// Callback for registering a local.
71353942Sdim  Local createLocal(Descriptor *D);
72353942Sdim
73353942Sdim  /// Returns the source location of the current opcode.
74353942Sdim  SourceInfo getSource(Function *F, CodePtr PC) const override {
75353942Sdim    return F ? F->getSource(PC) : CurrentSource;
76353942Sdim  }
77353942Sdim
78353942Sdim  /// Parameter indices.
79353942Sdim  llvm::DenseMap<const ParmVarDecl *, unsigned> Params;
80353942Sdim  /// Local descriptors.
81353942Sdim  llvm::SmallVector<SmallVector<Local, 8>, 2> Descriptors;
82353942Sdim
83353942Sdimprivate:
84353942Sdim  /// Current compilation context.
85353942Sdim  Context &Ctx;
86353942Sdim  /// Current program.
87353942Sdim  Program &P;
88353942Sdim  /// Callee evaluation state.
89353942Sdim  InterpState S;
90353942Sdim  /// Location to write the result to.
91353942Sdim  APValue &Result;
92353942Sdim
93353942Sdim  /// Temporaries which require storage.
94353942Sdim  llvm::DenseMap<unsigned, std::unique_ptr<char[]>> Locals;
95353942Sdim
96353942Sdim  // The emitter always tracks the current instruction and sets OpPC to a token
97353942Sdim  // value which is mapped to the location of the opcode being evaluated.
98353942Sdim  CodePtr OpPC;
99353942Sdim  /// Location of a failure.
100353942Sdim  llvm::Optional<SourceLocation> BailLocation;
101353942Sdim  /// Location of the current instruction.
102353942Sdim  SourceInfo CurrentSource;
103353942Sdim
104353942Sdim  /// Next label ID to generate - first label is 1.
105353942Sdim  LabelTy NextLabel = 1;
106353942Sdim  /// Label being executed - 0 is the entry label.
107353942Sdim  LabelTy CurrentLabel = 0;
108353942Sdim  /// Active block which should be executed.
109353942Sdim  LabelTy ActiveLabel = 0;
110353942Sdim
111353942Sdim  /// Since expressions can only jump forward, predicated execution is
112353942Sdim  /// used to deal with if-else statements.
113353942Sdim  bool isActive() { return CurrentLabel == ActiveLabel; }
114353942Sdim
115353942Sdim  /// Helper to invoke a method.
116353942Sdim  bool ExecuteCall(Function *F, Pointer &&This, const SourceInfo &Info);
117353942Sdim  /// Helper to emit a diagnostic on a missing method.
118353942Sdim  bool ExecuteNoCall(const FunctionDecl *F, const SourceInfo &Info);
119353942Sdim
120353942Sdimprotected:
121353942Sdim#define GET_EVAL_PROTO
122353942Sdim#include "Opcodes.inc"
123353942Sdim#undef GET_EVAL_PROTO
124353942Sdim};
125353942Sdim
126353942Sdim} // namespace interp
127353942Sdim} // namespace clang
128353942Sdim
129353942Sdim#endif
130