2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-present Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
17 #ifndef incl_HPHP_JIT_VASM_VISIT_H_
18 #define incl_HPHP_JIT_VASM_VISIT_H_
20 #include "hphp/runtime/vm/jit/containers.h"
21 #include "hphp/runtime/vm/jit/phys-reg.h"
22 #include "hphp/runtime/vm/jit/vasm.h"
23 #include "hphp/runtime/vm/jit/vasm-instr.h"
24 #include "hphp/runtime/vm/jit/vasm-reg.h"
25 #include "hphp/runtime/vm/jit/vasm-unit.h"
27 #include "hphp/util/type-traits.h"
29 #include <boost/dynamic_bitset.hpp>
33 namespace HPHP
{ namespace jit
{
35 ///////////////////////////////////////////////////////////////////////////////
39 template<class F
, class A1
, class A2
>
40 auto invoke(F
&& f
, A1
&& a1
, A2
&& a2
)
41 -> decltype(std::forward
<F
>(f
)(std::forward
<A1
>(a1
))) {
42 return std::forward
<F
>(f
)(std::forward
<A1
>(a1
));
45 template<class F
, class A1
, class A2
>
46 auto invoke(F
&& f
, A1
&& a1
, A2
&& a2
)
47 -> decltype(std::forward
<F
>(f
)(std::forward
<A1
>(a1
), std::forward
<A2
>(a2
))) {
48 return std::forward
<F
>(f
)(std::forward
<A1
>(a1
), std::forward
<A2
>(a2
));
53 ///////////////////////////////////////////////////////////////////////////////
55 template<class R
, class F
>
56 typename
std::enable_if
<
59 Vreg
, VregSF
, Vreg8
, Vreg16
, Vreg32
, Vreg64
, Vreg128
, VregDbl
, PhysReg
62 visit(const Vunit
&, R v
, F f
) {
63 detail::invoke(f
, v
, width(v
));
67 void visit(const Vunit
&, Vptr p
, F f
) {
68 if (p
.base
.isValid()) detail::invoke(f
, p
.base
, width(p
.base
));
69 if (p
.index
.isValid()) detail::invoke(f
, p
.index
, width(p
.index
));
73 void visit(const Vunit
& unit
, Vtuple t
, F f
) {
74 for (auto r
: unit
.tuples
[t
]) detail::invoke(f
, r
, width(r
));
78 void visit(const Vunit
& unit
, VcallArgsId a
, F f
) {
79 auto& args
= unit
.vcallArgs
[a
];
80 for (auto r
: args
.args
) detail::invoke(f
, r
, width(r
));
81 for (auto r
: args
.simdArgs
) detail::invoke(f
, r
, width(r
));
82 for (auto r
: args
.stkArgs
) detail::invoke(f
, r
, width(r
));
86 void visit(const Vunit
& unit
, RegSet regs
, F f
) {
87 regs
.forEach([&](Vreg r
) { detail::invoke(f
, r
, width(r
)); });
90 ///////////////////////////////////////////////////////////////////////////////
93 void visitUses(const Vunit
& unit
, const Vinstr
& inst
, Use use
) {
95 #define O(name, imms, uses, defs) \
96 case Vinstr::name: { \
97 auto& i = inst.name##_; (void)i; \
101 #define U(s) visit(unit, i.s, use);
102 #define UA(s) visit(unit, i.s, use);
103 #define UH(s,h) visit(unit, i.s, use);
115 void visitDefs(const Vunit
& unit
, const Vinstr
& inst
, Def def
) {
117 #define O(name, imms, uses, defs) \
118 case Vinstr::name: { \
119 auto& i = inst.name##_; (void)i; \
123 #define D(d) visit(unit, i.d, def);
124 #define DH(d,h) visit(unit, i.d, def);
135 * visitOperands visits all operands of the given instruction, calling
136 * visitor.imm(), visitor.use(), visitor.across(), and visitor.def() as defined
137 * in the VASM_OPCODES macro.
139 * The template spew is necessary to support callers that only have a const
140 * Vinstr& as well as callers with a Vinstr& that wish to mutate the
141 * instruction in the visitor.
143 template<class Tinstr
, class Visitor
>
144 typename maybe_const
<Tinstr
, Vinstr
>::type
145 visitOperands(Tinstr
& inst
, Visitor
& visitor
) {
147 #define O(name, imms, uses, defs) \
148 case Vinstr::name: { \
149 auto& i = inst.name##_; (void)i; \
155 #define I(f) visitor.imm(i.f);
156 #define U(s) visitor.use(i.s);
157 #define UA(s) visitor.across(i.s);
158 #define UH(s,h) visitor.useHint(i.s, i.h);
159 #define D(d) visitor.def(i.d);
160 #define DH(d,h) visitor.defHint(i.d, i.h);
178 ///////////////////////////////////////////////////////////////////////////////
181 * Visit reachable blocks, calling `pre' and `post' on each one.
184 explicit DfsWalker(const Vunit
& u
)
186 , visited(u
.blocks
.size())
189 template<class Pre
, class Post
>
190 void dfs(Vlabel b
, Pre pre
, Post post
) {
191 if (visited
.test(b
)) return;
195 for (auto s
: succs(unit
.blocks
[b
])) {
201 template<class Pre
, class Post
>
202 void dfs(Pre pre
, Post post
) {
203 dfs(unit
.entry
, pre
, post
);
208 boost::dynamic_bitset
<> visited
;
212 * Visit reachable blocks in postorder, calling `fn' on each one.
214 * Guaranteed not to use standard iterators on u.blocks, because several passes
215 * (e.g., vlower) forbid it.
217 struct PostorderWalker
{
218 explicit PostorderWalker(const Vunit
& u
) : m_dfs
{u
} {}
221 void dfs(Post post
) {
222 m_dfs
.dfs([](Vlabel
){}, post
);
229 using PredVector
= jit::vector
<jit::vector
<Vlabel
>>;
230 PredVector
computePreds(const Vunit
& unit
);
232 ///////////////////////////////////////////////////////////////////////////////