Fix saving/restoring return address on ARM
[hiphop-php.git] / hphp / runtime / vm / jit / vasm-info.cpp
blob5b29bfd4b60171e70c8caa34b0ef971e9ccd32b3
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 #include "hphp/runtime/vm/jit/vasm-info.h"
19 #include "hphp/runtime/vm/jit/vasm-instr.h"
20 #include "hphp/runtime/vm/jit/vasm-reg.h"
22 #include <utility>
24 namespace HPHP::jit {
26 ///////////////////////////////////////////////////////////////////////////////
28 namespace {
30 ///////////////////////////////////////////////////////////////////////////////
33 * Provide a default template that matches every instruction, but which
34 * is only a near match for a non-const Inst&.
36 template <typename Inst>
37 std::pair<ConditionCode*,Vreg> ccUsageHelper(const Inst&) {
38 return { nullptr, Vreg{} };
42 * Provide a template that only matches instructions with cc and sf
43 * members, and is an exact match for a non-const Inst&.
45 template <typename Inst>
46 auto ccUsageHelper(Inst& i) ->
47 decltype(std::make_pair(&i.cc, Vreg(size_t(i.sf)))) {
48 return { &i.cc, Vreg(size_t(i.sf)) };
51 std::pair<ConditionCode*,Vreg> ccUsage(Vinstr& inst) {
52 #define O(name,...) case Vinstr::name: return ccUsageHelper(inst.name##_);
53 switch (inst.op) {
54 VASM_OPCODES
56 #undef O
57 not_reached();
60 template<typename M>
61 constexpr bool useMemory() { return false; }
62 template<>
63 constexpr bool useMemory<Vptr>() { return true; }
64 template<>
65 constexpr bool useMemory<Vptr8>() { return true; }
66 template<>
67 constexpr bool useMemory<Vptr16>() { return true; }
68 template<>
69 constexpr bool useMemory<Vptr32>() { return true; }
70 template<>
71 constexpr bool useMemory<Vptr64>() { return true; }
72 template<>
73 constexpr bool useMemory<Vptr128>() { return true; }
75 ///////////////////////////////////////////////////////////////////////////////
79 ConditionCode& getConditionCode(Vinstr& inst) {
80 auto usage = ccUsage(inst);
81 assertx(usage.first);
82 return *usage.first;
85 Vreg getSFUseReg(const Vinstr& inst) {
86 return ccUsage(const_cast<Vinstr&>(inst)).second;
89 bool touchesMemory(Vinstr::Opcode op) {
90 if (op == Vinstr::killeffects) return true;
91 if (op == Vinstr::lea) return false;
92 if (isCall(op)) return true;
93 #define O(name, imms, uses, defs) \
94 case Vinstr::name: { using T = name; return uses false; }
95 #define U(s) useMemory<decltype(T::s)>() ||
96 #define UA(s) useMemory<decltype(T::s)>() ||
97 #define UH(s,h) (assertx(!useMemory<decltype(T::s)>()),false) ||
98 #define UW(s) (assertx(useMemory<decltype(T::s)>()),true) ||
99 #define UM(s) (assertx(useMemory<decltype(T::s)>()),true) ||
100 #define Un false ||
102 switch (op) {
103 VASM_OPCODES
105 return false;
107 #undef Un
108 #undef UH
109 #undef UA
110 #undef UW
111 #undef UM
112 #undef U
114 #undef O
117 bool writesMemory(Vinstr::Opcode op) {
118 if (op == Vinstr::killeffects) return true;
119 if (isCall(op)) return true;
120 #define O(name, imms, uses, defs) \
121 case Vinstr::name: { using T = name; return uses false; }
123 #define U(s)
124 #define UA(s)
125 #define UH(s,h)
126 #define UW(s) (assertx(useMemory<decltype(T::s)>()),true) ||
127 #define UM(s) (assertx(useMemory<decltype(T::s)>()),true) ||
128 #define Un
130 switch (op) {
131 VASM_OPCODES
133 return false;
135 #undef Un
136 #undef UH
137 #undef UA
138 #undef UW
139 #undef UM
140 #undef U
142 #undef O
145 bool touchesMemory(const Vinstr& inst) {
146 return touchesMemory(inst.op);
149 bool writesMemory(const Vinstr& inst) {
150 return writesMemory(inst.op);
154 ///////////////////////////////////////////////////////////////////////////////
156 namespace {
158 bool effectsImpl(const Vinstr& inst, bool pure) {
159 switch (inst.op) {
160 // Pure:
161 case Vinstr::absdbl:
162 case Vinstr::addl:
163 case Vinstr::addli:
164 case Vinstr::addq:
165 case Vinstr::addqi:
166 case Vinstr::addsd:
167 case Vinstr::andb:
168 case Vinstr::andbi:
169 case Vinstr::andw:
170 case Vinstr::andwi:
171 case Vinstr::andl:
172 case Vinstr::andli:
173 case Vinstr::andq:
174 case Vinstr::andqi64:
175 case Vinstr::andqi:
176 case Vinstr::btrq:
177 case Vinstr::cmovb:
178 case Vinstr::cmovl:
179 case Vinstr::cmovq:
180 case Vinstr::cmovw:
181 case Vinstr::cmpb:
182 case Vinstr::cmpbi:
183 case Vinstr::cmpl:
184 case Vinstr::cmpli:
185 case Vinstr::cmpq:
186 case Vinstr::cmpqi:
187 case Vinstr::cmpsd:
188 case Vinstr::cmpw:
189 case Vinstr::cmpwi:
190 case Vinstr::copy2:
191 case Vinstr::copy:
192 case Vinstr::copyargs:
193 case Vinstr::crc32q:
194 case Vinstr::csincb:
195 case Vinstr::csincl:
196 case Vinstr::csincq:
197 case Vinstr::csincw:
198 case Vinstr::cvtsi2sd:
199 case Vinstr::cvttsd2siq:
200 case Vinstr::decl:
201 case Vinstr::decq:
202 case Vinstr::divint:
203 case Vinstr::divsd:
204 case Vinstr::fcvtzs:
205 case Vinstr::imul:
206 case Vinstr::incl:
207 case Vinstr::incq:
208 case Vinstr::incw:
209 case Vinstr::ldimmb:
210 case Vinstr::ldimml:
211 case Vinstr::ldimmq:
212 case Vinstr::ldimmw:
213 case Vinstr::ldundefq:
214 case Vinstr::lea:
215 case Vinstr::lead:
216 case Vinstr::movb:
217 case Vinstr::movl:
218 case Vinstr::movsbl:
219 case Vinstr::movsbq:
220 case Vinstr::movslq:
221 case Vinstr::movswl:
222 case Vinstr::movswq:
223 case Vinstr::movtdb:
224 case Vinstr::movtdq:
225 case Vinstr::movtqb:
226 case Vinstr::movtql:
227 case Vinstr::movtqw:
228 case Vinstr::movw:
229 case Vinstr::movzbl:
230 case Vinstr::movzbq:
231 case Vinstr::movzbw:
232 case Vinstr::movzlq:
233 case Vinstr::movzwl:
234 case Vinstr::movzwq:
235 case Vinstr::mulsd:
236 case Vinstr::neg:
237 case Vinstr::nop:
238 case Vinstr::not:
239 case Vinstr::notb:
240 case Vinstr::orbi:
241 case Vinstr::orwi:
242 case Vinstr::orli:
243 case Vinstr::orq:
244 case Vinstr::orqi:
245 case Vinstr::reload:
246 case Vinstr::roundsd:
247 case Vinstr::sar:
248 case Vinstr::sarq:
249 case Vinstr::sarqi:
250 case Vinstr::setcc:
251 case Vinstr::shl:
252 case Vinstr::shr:
253 case Vinstr::shlli:
254 case Vinstr::shlq:
255 case Vinstr::shlqi:
256 case Vinstr::shrq:
257 case Vinstr::shrli:
258 case Vinstr::shrqi:
259 case Vinstr::spill:
260 case Vinstr::spillbi:
261 case Vinstr::spillli:
262 case Vinstr::spillqi:
263 case Vinstr::spillundefq:
264 case Vinstr::sqrtsd:
265 case Vinstr::srem:
266 case Vinstr::ssaalias:
267 case Vinstr::subl:
268 case Vinstr::subli:
269 case Vinstr::subq:
270 case Vinstr::subqi:
271 case Vinstr::subsd:
272 case Vinstr::testb:
273 case Vinstr::testbi:
274 case Vinstr::testl:
275 case Vinstr::testli:
276 case Vinstr::testq:
277 case Vinstr::testqi:
278 case Vinstr::testw:
279 case Vinstr::testwi:
280 case Vinstr::ubfmli:
281 case Vinstr::ucomisd:
282 case Vinstr::unpcklpd:
283 case Vinstr::xorb:
284 case Vinstr::xorbi:
285 case Vinstr::xorw:
286 case Vinstr::xorwi:
287 case Vinstr::xorl:
288 case Vinstr::xorq:
289 case Vinstr::xorqi:
290 assertx(!touchesMemory(inst));
291 return pure;
293 // Non-effectful but non-pure:
294 case Vinstr::cloadq:
295 case Vinstr::cmpbim:
296 case Vinstr::cmpbm:
297 case Vinstr::cmplim:
298 case Vinstr::cmplm:
299 case Vinstr::cmpqim:
300 case Vinstr::cmpqm:
301 case Vinstr::cmpwim:
302 case Vinstr::cmpwm:
303 case Vinstr::cvtsi2sdm:
304 case Vinstr::defvmretdata:
305 case Vinstr::defvmrettype:
306 case Vinstr::defvmsp:
307 case Vinstr::defvmfp:
308 case Vinstr::leap:
309 case Vinstr::leav:
310 case Vinstr::load:
311 case Vinstr::loadb:
312 case Vinstr::loadl:
313 case Vinstr::loadqd:
314 case Vinstr::loadqp:
315 case Vinstr::loadsbl:
316 case Vinstr::loadsbq:
317 case Vinstr::loadsd:
318 case Vinstr::loadtqb:
319 case Vinstr::loadtql:
320 case Vinstr::loadups:
321 case Vinstr::loadw:
322 case Vinstr::loadzbl:
323 case Vinstr::loadzbq:
324 case Vinstr::loadzwq:
325 case Vinstr::loadzlq:
326 case Vinstr::mrs:
327 case Vinstr::testbim:
328 case Vinstr::testbm:
329 case Vinstr::testlim:
330 case Vinstr::testlm:
331 case Vinstr::testqim:
332 case Vinstr::testqm:
333 case Vinstr::testwim:
334 case Vinstr::testwm:
335 assertx(!writesMemory(inst));
336 assertx(!isCall(inst));
337 return false;
339 // Effectful:
340 case Vinstr::addlim:
341 case Vinstr::addlm:
342 case Vinstr::addqim:
343 case Vinstr::addqmr:
344 case Vinstr::addqrm:
345 case Vinstr::addwm:
346 case Vinstr::andbim:
347 case Vinstr::bindaddr:
348 case Vinstr::ldbindaddr:
349 case Vinstr::ldbindretaddr:
350 case Vinstr::bindjcc:
351 case Vinstr::bindjmp:
352 case Vinstr::call:
353 case Vinstr::callfaststub:
354 case Vinstr::callm:
355 case Vinstr::callphp:
356 case Vinstr::callphpfe:
357 case Vinstr::callphpr:
358 case Vinstr::callphps:
359 case Vinstr::callr:
360 case Vinstr::calls:
361 case Vinstr::callstub:
362 case Vinstr::conjure:
363 case Vinstr::conjureuse:
364 case Vinstr::contenter:
365 case Vinstr::cqo:
366 case Vinstr::debugtrap:
367 case Vinstr::declm:
368 case Vinstr::decqm:
369 case Vinstr::decqmlock:
370 case Vinstr::decqmlocknosf:
371 case Vinstr::fallback:
372 case Vinstr::fallbackcc:
373 case Vinstr::fallthru:
374 case Vinstr::idiv:
375 case Vinstr::inclm:
376 case Vinstr::incqm:
377 case Vinstr::incwm:
378 case Vinstr::inittc:
379 case Vinstr::inlineend:
380 case Vinstr::inlinestart:
381 case Vinstr::jcc:
382 case Vinstr::jcci:
383 case Vinstr::jmp:
384 case Vinstr::jmps:
385 case Vinstr::jmpi:
386 case Vinstr::jmpm:
387 case Vinstr::jmpr:
388 case Vinstr::killeffects:
389 case Vinstr::landingpad:
390 case Vinstr::leavetc:
391 case Vinstr::loadstubret:
392 case Vinstr::mcprep:
393 case Vinstr::movqs:
394 case Vinstr::msr:
395 case Vinstr::nothrow:
396 case Vinstr::orbim:
397 case Vinstr::orlim:
398 case Vinstr::orqim:
399 case Vinstr::orwim:
400 case Vinstr::phidef:
401 case Vinstr::phijmp:
402 case Vinstr::phplogue:
403 case Vinstr::phpret:
404 case Vinstr::pop:
405 case Vinstr::popf:
406 case Vinstr::popm:
407 case Vinstr::popp:
408 case Vinstr::poppm:
409 case Vinstr::prefetch:
410 case Vinstr::push:
411 case Vinstr::pushf:
412 case Vinstr::pushframe:
413 case Vinstr::pushm:
414 case Vinstr::pushp:
415 case Vinstr::pushpm:
416 case Vinstr::pushvmfp:
417 case Vinstr::recordbasenativesp:
418 case Vinstr::unrecordbasenativesp:
419 case Vinstr::recordstack:
420 case Vinstr::restorerip:
421 case Vinstr::resumetc:
422 case Vinstr::ret:
423 case Vinstr::store:
424 case Vinstr::storeb:
425 case Vinstr::storebi:
426 case Vinstr::storel:
427 case Vinstr::storeli:
428 case Vinstr::storeqi:
429 case Vinstr::storesd:
430 case Vinstr::storeups:
431 case Vinstr::storew:
432 case Vinstr::storewi:
433 case Vinstr::stublogue:
434 case Vinstr::stubret:
435 case Vinstr::stubtophp:
436 case Vinstr::stubunwind:
437 case Vinstr::subqim:
438 case Vinstr::syncpoint:
439 case Vinstr::syncvmret:
440 case Vinstr::syncvmrettype:
441 case Vinstr::syncvmsp:
442 case Vinstr::tailcallstub:
443 case Vinstr::tailcallstubr:
444 case Vinstr::trap:
445 case Vinstr::unstublogue:
446 case Vinstr::unwind:
447 case Vinstr::vcall:
448 case Vinstr::vinvoke:
449 case Vinstr::vregrestrict:
450 case Vinstr::vregunrestrict:
451 return !pure;
453 always_assert(false);
458 bool effectful(const Vinstr& inst) {
459 return effectsImpl(inst, false);
462 bool isPure(const Vinstr& inst) {
463 return effectsImpl(inst, true);