Coverage Report

Created: 2024-01-17 10:31

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