v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
define-assembler-macros.inc
Go to the documentation of this file.
1
// Copyright 2023 the V8 project authors. All rights reserved.
2
// Use of this source code is governed by a BSD-style license that can be
3
// found in the LICENSE file.
4
5
// PRESUBMIT_INTENTIONALLY_MISSING_INCLUDE_GUARD
6
7
// This file defines Turboshaft's assembler macros. Include this file before
8
// your reducers and don't forget to include 'undef-assembler-macros.inc'
9
// afterwards.
10
11
#ifdef V8_COMPILER_TURBOSHAFT_ASSEMBLER_MACROS_DEFINED
12
#error \
13
"Assembler macros already defined. Did you forget to #include \"undef-assembler-macros.inc\" in a previous file?"
14
#endif
15
16
#define V8_COMPILER_TURBOSHAFT_ASSEMBLER_MACROS_DEFINED 1
17
18
#define TSA_DCHECK(assembler, condition) \
19
(assembler)->Asm().Dcheck(condition, #condition, __FILE__, __LINE__ )
20
#ifdef ENABLE_SLOW_DCHECKS
21
#define TSA_SLOW_DCHECK(assembler, ...) \
22
do { \
23
if (v8_flags.enable_slow_asserts) { \
24
TSA_DCHECK(assembler, __VA_ARGS__); \
25
} \
26
} while(false)
27
#else
28
#define TSA_SLOW_DCHECK(assembler, ...) ((void)0)
29
#endif
30
31
#define LIKELY(...) ConditionWithHint(__VA_ARGS__, BranchHint::kTrue)
32
#define UNLIKELY(...) ConditionWithHint(__VA_ARGS__, BranchHint::kFalse)
33
34
#define BIND(label, ...) \
35
auto [CONCAT(is_bound_, __LINE__), ##__VA_ARGS__] = \
36
Asm().ControlFlowHelper_Bind(label); \
37
(::v8::internal::compiler::turboshaft::detail::SuppressUnusedWarning( \
38
CONCAT(is_bound_, __LINE__)))
39
#define BIND_LOOP(loop_label, ...) \
40
for(auto [CONCAT(run_loop_, __LINE__), ##__VA_ARGS__] = \
41
Asm().ControlFlowHelper_BindLoop(loop_label); CONCAT(run_loop_, __LINE__); \
42
Asm().ControlFlowHelper_EndLoop(loop_label), \
43
CONCAT(run_loop_, __LINE__) = false)
44
45
#define WHILE(...) \
46
for (auto [CONCAT(run_loop_, __LINE__), loop_header_xx, loop_exit_xx] \
47
= Asm().ControlFlowHelper_While([&]() { \
48
return Asm().resolve(ConstOrV<Word32>(__VA_ARGS__)); \
49
}); \
50
CONCAT(run_loop_, __LINE__); \
51
Asm().ControlFlowHelper_EndWhileLoop(loop_header_xx, loop_exit_xx), \
52
CONCAT(run_loop_, __LINE__) = false)
53
#define FOREACH_IMPL_2(arg, iterable) \
54
for (auto [CONCAT(run_loop_, __LINE__), iterable_xx, loop_header_yy, \
55
loop_exit_xx, current_iterator_xx, arg] = \
56
Asm().ControlFlowHelper_Foreach(iterable); \
57
CONCAT(run_loop_, __LINE__); \
58
Asm().ControlFlowHelper_EndForeachLoop( \
59
std::move(iterable_xx), loop_header_yy, loop_exit_xx, \
60
current_iterator_xx), \
61
CONCAT(run_loop_, __LINE__) = false)
62
#define FOREACH_IMPL_3(arg0, arg1, iterable) \
63
for (auto [CONCAT(run_loop_, __LINE__), iterable_xx, loop_header_yy, \
64
loop_exit_xx, current_iterator_xx, arg0, arg1] = \
65
Asm().ControlFlowHelper_Foreach(iterable); \
66
CONCAT(run_loop_, __LINE__); \
67
Asm().ControlFlowHelper_EndForeachLoop( \
68
std::move(iterable_xx), loop_header_yy, loop_exit_xx, \
69
current_iterator_xx), \
70
CONCAT(run_loop_, __LINE__) = false)
71
// TODO(nicohartmann): Add more `FOREACH_IMPL_N` versions when we see need.
72
#define FOREACH(...) \
73
CONCAT(FOREACH_IMPL_, COUNT_MACRO_ARGS(__VA_ARGS__))(__VA_ARGS__)
74
75
#define BREAK Asm().ControlFlowHelper_Goto(loop_exit_xx, {})
76
// TODO(nicohartmann): CONTINUE currently doesn't work for FOREACH.
77
#define CONTINUE Asm().ControlFlowHelper_Goto(loop_header_xx, {})
78
79
#define GOTO(label, ...) \
80
Asm().ControlFlowHelper_Goto(label, {__VA_ARGS__})
81
#define GOTO_IF(cond, label, ...) \
82
Asm().ControlFlowHelper_GotoIf(cond, label, {__VA_ARGS__})
83
#define GOTO_IF_NOT(cond, label, ...) \
84
Asm().ControlFlowHelper_GotoIfNot(cond, label, {__VA_ARGS__})
85
86
// Clang/GCC helpfully warn us about dangling else in nested if statements. This
87
// dangling is intentional for the way these macros work, so suppress the
88
// warning with Pragmas. Clang and GCC helpfully disagree on where the warning
89
// is (on the if or the else), so they need separate macros.
90
#if defined(__clang__)
91
// TODO(chromium:377144577): re-enable force-unrolling once this has been fixed
92
// in LLVM.
93
#define FORCE_UNROLL_LOOP
94
#define SUPPRESSED_DANGLING_ELSE_WARNING_IF(...) if (__VA_ARGS__)
95
#define SUPPRESSED_DANGLING_ELSE_WARNING_ELSE \
96
_Pragma("GCC diagnostic push") \
97
_Pragma("GCC diagnostic ignored \"-Wdangling-else\"") else _Pragma( \
98
"GCC diagnostic pop")
99
#elif defined(__GNUC__)
100
#define FORCE_UNROLL_LOOP
101
#define SUPPRESSED_DANGLING_ELSE_WARNING_IF(...) \
102
_Pragma("GCC diagnostic push") \
103
_Pragma("GCC diagnostic ignored \"-Wdangling-else\"") if (__VA_ARGS__) \
104
_Pragma("GCC diagnostic pop")
105
#define SUPPRESSED_DANGLING_ELSE_WARNING_ELSE else
106
#else
107
#define FORCE_UNROLL_LOOP
108
#define SUPPRESSED_DANGLING_ELSE_WARNING_IF(...) if (__VA_ARGS__)
109
#define SUPPRESSED_DANGLING_ELSE_WARNING_ELSE else
110
#endif
111
112
#define NO_SHADOW \
113
_Pragma("GCC diagnostic push") \
114
_Pragma("GCC diagnostic ignored \"-Wshadow\"")
115
#define RE_SHADOW _Pragma("GCC diagnostic pop")
116
117
// IF/ELSE macros. These expand to a real C++ if-else, so that we can get
118
// similar block syntax behaviour (with an optional `ELSE`). Since C++ will only
119
// evaluate one side of the if-else, wrap it in a for loop that executes the
120
// if-else three times: once for each side of the branch, and once to close the
121
// if. Each iteration also emits a goto-end if the corresponding branch target
122
// was bound. An if around the for loop encapsulates the state -- this is
123
// outside the for loop to make it easier for the compiler to unroll the three
124
// loop iterations.
125
#define IF(...) \
126
NO_SHADOW \
127
SUPPRESSED_DANGLING_ELSE_WARNING_IF( \
128
typename std::decay_t<decltype(Asm())>::ControlFlowHelper_IfState state; \
129
true) \
130
FORCE_UNROLL_LOOP \
131
for (int iteration = 0, bound = false; iteration < 3; \
132
(bound ? Asm().ControlFlowHelper_FinishIfBlock(&state) : (void)0), \
133
bound = false, iteration++) \
134
RE_SHADOW \
135
SUPPRESSED_DANGLING_ELSE_WARNING_IF(iteration == 2) { \
136
Asm().ControlFlowHelper_EndIf(&state); \
137
} \
138
SUPPRESSED_DANGLING_ELSE_WARNING_ELSE if ( \
139
iteration == 0 && \
140
(bound = Asm().ControlFlowHelper_BindIf(__VA_ARGS__, &state)))
141
142
#define IF_NOT(...) \
143
NO_SHADOW \
144
SUPPRESSED_DANGLING_ELSE_WARNING_IF( \
145
typename std::decay_t<decltype(Asm())>::ControlFlowHelper_IfState state; \
146
true) \
147
FORCE_UNROLL_LOOP \
148
for (int iteration = 0, bound = false; iteration < 3; \
149
(bound ? Asm().ControlFlowHelper_FinishIfBlock(&state) : (void)0), \
150
bound = false, iteration++) \
151
RE_SHADOW \
152
SUPPRESSED_DANGLING_ELSE_WARNING_IF(iteration == 2) { \
153
Asm().ControlFlowHelper_EndIf(&state); \
154
} \
155
SUPPRESSED_DANGLING_ELSE_WARNING_ELSE if ( \
156
iteration == 0 && \
157
(bound = Asm().ControlFlowHelper_BindIfNot(__VA_ARGS__, &state)))
158
159
#define ELSE \
160
SUPPRESSED_DANGLING_ELSE_WARNING_ELSE if ( \
161
iteration == 1 && (bound = Asm().ControlFlowHelper_BindElse(&state)))
162
163
#define Assert(condition) AssertImpl(condition, #condition, __FILE__, __LINE__)
164
165
#ifdef DEBUG
166
// In debug builds, `REDUCE(operation)` makes sure that `operation##Op` exists
167
// by using this name in an expression. This will detect typos in the name which
168
// would otherwise stay unnoticed potentially.
169
#define REDUCE(operation) \
170
CONCAT(CHECK_Reduce, operation) = \
171
(::v8::internal::compiler::turboshaft::detail::SuppressUnusedWarning( \
172
std::is_same_v<operation##Op, operation##Op>), \
173
decltype(CONCAT(CHECK_Reduce, operation)){}); \
174
template <class... Args> \
175
decltype(CONCAT(CHECK_Reduce, operation)) Reduce##operation(Args... args) { \
176
if (v8_flags.turboshaft_trace_intermediate_reductions) { \
177
base::SmallVector<OperationStorageSlot, 32> storage; \
178
operation##Op* op = CreateOperation<operation##Op>(storage, args...); \
179
PrintF("%*s", Asm().intermediate_tracing_depth(), ""); \
180
std::cout << "[" << ReducerName() << "]: reducing " << *op << "\n"; \
181
} \
182
Asm().intermediate_tracing_depth()++; \
183
decltype(CONCAT(CHECK_Reduce, operation)) result = \
184
Reduce##operation##Helper(args...); \
185
Asm().intermediate_tracing_depth()--; \
186
return result; \
187
} \
188
decltype(CONCAT(CHECK_Reduce, operation)) Reduce##operation##Helper
189
190
#define REDUCE_INPUT_GRAPH(operation) \
191
CONCAT(CHECK_ReduceInputGraph, operation) = \
192
(::v8::internal::compiler::turboshaft::detail::SuppressUnusedWarning( \
193
std::is_same_v<operation##Op, operation##Op>), \
194
decltype(CONCAT(CHECK_ReduceInputGraph, operation)){}); \
195
decltype(CONCAT( \
196
CHECK_ReduceInputGraph, \
197
operation)) ReduceInputGraph##operation(OpIndex ig_index, \
198
const operation##Op& op) { \
199
if (v8_flags.turboshaft_trace_intermediate_reductions) { \
200
PrintF("%*s", Asm().intermediate_tracing_depth(), ""); \
201
std::cout << "[" << ReducerName() << "]: @input-reducing " << op << "\n";\
202
} \
203
Asm().intermediate_tracing_depth()++; \
204
decltype(CONCAT(CHECK_ReduceInputGraph, operation)) result = \
205
ReduceInputGraph##operation##Helper(ig_index, op); \
206
Asm().intermediate_tracing_depth()--; \
207
return result; \
208
} \
209
decltype(CONCAT(CHECK_ReduceInputGraph, \
210
operation)) ReduceInputGraph##operation##Helper
211
#else
212
#define REDUCE(operation) Reduce##operation
213
#define REDUCE_INPUT_GRAPH(operation) ReduceInputGraph##operation
214
#endif
// DEBUG
215
216
#define __ Asm().
src
compiler
turboshaft
define-assembler-macros.inc
Generated on Sun Apr 6 2025 21:08:52 for v8 by
1.12.0