codemod 2010-2016 to 2010-present
[hiphop-php.git] / hphp / runtime / vm / jit / vasm-visit.h
blob427c366d29c799b6bad6299eeebf9788df1ca5c6
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
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>
31 #include <utility>
33 namespace HPHP { namespace jit {
35 ///////////////////////////////////////////////////////////////////////////////
37 namespace detail {
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<
57 is_any<
59 Vreg, VregSF, Vreg8, Vreg16, Vreg32, Vreg64, Vreg128, VregDbl, PhysReg
60 >::value
61 >::type
62 visit(const Vunit&, R v, F f) {
63 detail::invoke(f, v, width(v));
66 template<class F>
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));
72 template<class F>
73 void visit(const Vunit& unit, Vtuple t, F f) {
74 for (auto r : unit.tuples[t]) detail::invoke(f, r, width(r));
77 template<class F>
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));
85 template<class F>
86 void visit(const Vunit& unit, RegSet regs, F f) {
87 regs.forEach([&](Vreg r) { detail::invoke(f, r, width(r)); });
90 ///////////////////////////////////////////////////////////////////////////////
92 template<class Use>
93 void visitUses(const Vunit& unit, const Vinstr& inst, Use use) {
94 switch (inst.op) {
95 #define O(name, imms, uses, defs) \
96 case Vinstr::name: { \
97 auto& i = inst.name##_; (void)i; \
98 uses \
99 break; \
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);
104 #define Un
105 VASM_OPCODES
106 #undef Un
107 #undef UH
108 #undef UA
109 #undef U
110 #undef O
114 template<class Def>
115 void visitDefs(const Vunit& unit, const Vinstr& inst, Def def) {
116 switch (inst.op) {
117 #define O(name, imms, uses, defs) \
118 case Vinstr::name: { \
119 auto& i = inst.name##_; (void)i; \
120 defs \
121 break; \
123 #define D(d) visit(unit, i.d, def);
124 #define DH(d,h) visit(unit, i.d, def);
125 #define Dn
126 VASM_OPCODES
127 #undef Dn
128 #undef DH
129 #undef D
130 #undef O
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) {
146 switch (inst.op) {
147 #define O(name, imms, uses, defs) \
148 case Vinstr::name: { \
149 auto& i = inst.name##_; (void)i; \
150 imms \
151 uses \
152 defs \
153 break; \
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);
161 #define Inone
162 #define Un
163 #define Dn
164 VASM_OPCODES
165 #undef Dn
166 #undef Un
167 #undef Inone
168 #undef DH
169 #undef D
170 #undef UH
171 #undef UA
172 #undef U
173 #undef I
174 #undef O
178 ///////////////////////////////////////////////////////////////////////////////
181 * Visit reachable blocks, calling `pre' and `post' on each one.
183 struct DfsWalker {
184 explicit DfsWalker(const Vunit& u)
185 : unit(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;
192 visited.set(b);
194 pre(b);
195 for (auto s : succs(unit.blocks[b])) {
196 dfs(s, pre, post);
198 post(b);
201 template<class Pre, class Post>
202 void dfs(Pre pre, Post post) {
203 dfs(unit.entry, pre, post);
206 private:
207 const Vunit& unit;
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} {}
220 template<class Post>
221 void dfs(Post post) {
222 m_dfs.dfs([](Vlabel){}, post);
225 private:
226 DfsWalker m_dfs;
229 using PredVector = jit::vector<jit::vector<Vlabel>>;
230 PredVector computePreds(const Vunit& unit);
232 ///////////////////////////////////////////////////////////////////////////////
236 #endif