Coverage Report

Created: 2025-08-28 06:48

/src/hermes/lib/IRGen/IRInstrument.h
Line
Count
Source
1
/*
2
 * Copyright (c) Meta Platforms, Inc. and affiliates.
3
 *
4
 * This source code is licensed under the MIT license found in the
5
 * LICENSE file in the root directory of this source tree.
6
 */
7
8
#ifndef HERMES_IRGEN_IR_INSTRUMENT_H
9
#define HERMES_IRGEN_IR_INSTRUMENT_H
10
11
#include "hermes/IR/IRBuilder.h"
12
13
namespace hermes {
14
15
/// A class to optionally instrument the generated IR. For each supported IR
16
/// expression, it supports a pre and post "hook". The pre-hook receives the
17
/// calculated operands and the AST node and returns an optional "cookie" value.
18
/// The post-hook receives the AST node, the result of the operation and the
19
/// cookie value. The post-hook returns the result value for convenience.
20
class IRInstrument {
21
 public:
22
#ifdef HERMES_ENABLE_IR_INSTRUMENTATION
23
  IRInstrument(Module *M, IRBuilder &builder);
24
  ~IRInstrument();
25
26
  /// Generate a unique source location identifier for a node.
27
  Value *getIID(ESTree::Node *node);
28
29
  /// Conveniently invoke a JS instrumentation hook by name.
30
  Value *invokeHook(llvh::StringRef name, llvh::ArrayRef<Value *> args);
31
32
  Value *undefinedIfNull(Value *v) {
33
    return v ? v : builder_.getLiteralUndefined();
34
  }
35
36
  /// Called before a binary expression is computed.
37
  /// \return an arbitrary value passed to the post-hook
38
  Value *preBinaryExpression(
39
      ESTree::BinaryExpressionNode *,
40
      Value *left,
41
      Value *right);
42
43
  /// Called after a binary expression has been computed.
44
  /// \return a Value* that overrides the result of the expression
45
  Value *postBinaryExpression(
46
      ESTree::BinaryExpressionNode *,
47
      Value *cookie,
48
      Value *result,
49
      Value *left,
50
      Value *right);
51
52
  /// Called before a unary expression is computed.
53
  /// \return an arbitrary value passed to the post-hook
54
  Value *preUnaryExpression(ESTree::UnaryExpressionNode *, Value *operand);
55
56
  /// Called after a unary expression has been computed.
57
  /// \return a Value* that overrides the result of the expression
58
  Value *postUnaryExpression(
59
      ESTree::UnaryExpressionNode *,
60
      Value *cookie,
61
      Value *result,
62
      Value *operand);
63
64
  /// Called before an assignment expression is computed.
65
  /// \param left the LHS operand for += etc, or nullptr for =
66
  /// \param right the RHS of the += or = assignment
67
  /// \return an arbitrary value passed to the post-hook
68
  Value *
69
  preAssignment(ESTree::AssignmentExpressionNode *, Value *left, Value *right);
70
71
  /// Called after an assignment expression has been computed.
72
  /// \return the Value* to assign
73
  Value *postAssignment(
74
      ESTree::AssignmentExpressionNode *,
75
      Value *cookie,
76
      Value *result,
77
      Value *left,
78
      Value *right);
79
80
 private:
81
  IRBuilder &builder_;
82
  /// Name of the global to find hooks on ("__instrument").
83
  LiteralString *globalName_;
84
  /// The module we're instrumenting.
85
  Module *M_;
86
  // Whether we should instrument.
87
  bool enabled_;
88
89
#else
90
  // IR Instrumentation is compiled out, so all these members are just no-ops.
91
70
  IRInstrument(Module *M, IRBuilder &builder) {}
92
  ~IRInstrument() = default;
93
94
  inline Value *preBinaryExpression(
95
      ESTree::BinaryExpressionNode *,
96
      Value *left,
97
253k
      Value *right) {
98
253k
    return nullptr;
99
253k
  }
100
  inline Value *postBinaryExpression(
101
      ESTree::BinaryExpressionNode *,
102
      Value *cookie,
103
      Value *result,
104
      Value *left,
105
253k
      Value *right) {
106
253k
    return result;
107
253k
  }
108
109
  inline Value *preUnaryExpression(
110
      ESTree::UnaryExpressionNode *,
111
13.8k
      Value *operand) {
112
13.8k
    return nullptr;
113
13.8k
  }
114
  inline Value *postUnaryExpression(
115
      ESTree::UnaryExpressionNode *,
116
      Value *cookie,
117
      Value *result,
118
13.8k
      Value *operand) {
119
13.8k
    return result;
120
13.8k
  }
121
122
  inline Value *preAssignment(
123
      ESTree::AssignmentExpressionNode *node,
124
      Value *left,
125
2.32k
      Value *right) {
126
2.32k
    return nullptr;
127
2.32k
  }
128
  inline Value *postAssignment(
129
      ESTree::AssignmentExpressionNode *node,
130
      Value *cookie,
131
      Value *result,
132
      Value *left,
133
2.32k
      Value *right) {
134
2.32k
    return result;
135
2.32k
  }
136
#endif
137
};
138
139
} // namespace hermes
140
141
#endif // HERMES_IRGEN_IR_INSTRUMENT_H