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