/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 |