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 #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"
26 ///////////////////////////////////////////////////////////////////////////////
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##_);
61 constexpr bool useMemory() { return false; }
63 constexpr bool useMemory
<Vptr
>() { return true; }
65 constexpr bool useMemory
<Vptr8
>() { return true; }
67 constexpr bool useMemory
<Vptr16
>() { return true; }
69 constexpr bool useMemory
<Vptr32
>() { return true; }
71 constexpr bool useMemory
<Vptr64
>() { return true; }
73 constexpr bool useMemory
<Vptr128
>() { return true; }
75 ///////////////////////////////////////////////////////////////////////////////
79 ConditionCode
& getConditionCode(Vinstr
& inst
) {
80 auto usage
= ccUsage(inst
);
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) ||
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; }
126 #define UW(s) (assertx(useMemory<decltype(T::s)>()),true) ||
127 #define UM(s) (assertx(useMemory<decltype(T::s)>()),true) ||
145 bool touchesMemory(const Vinstr
& inst
) {
146 return touchesMemory(inst
.op
);
149 bool writesMemory(const Vinstr
& inst
) {
150 return writesMemory(inst
.op
);
154 ///////////////////////////////////////////////////////////////////////////////
158 bool effectsImpl(const Vinstr
& inst
, bool pure
) {
174 case Vinstr::andqi64
:
192 case Vinstr::copyargs
:
198 case Vinstr::cvtsi2sd
:
199 case Vinstr::cvttsd2siq
:
213 case Vinstr::ldundefq
:
246 case Vinstr::roundsd
:
260 case Vinstr::spillbi
:
261 case Vinstr::spillli
:
262 case Vinstr::spillqi
:
263 case Vinstr::spillundefq
:
266 case Vinstr::ssaalias
:
281 case Vinstr::ucomisd
:
282 case Vinstr::unpcklpd
:
290 assertx(!touchesMemory(inst
));
293 // Non-effectful but non-pure:
303 case Vinstr::cvtsi2sdm
:
304 case Vinstr::defvmretdata
:
305 case Vinstr::defvmrettype
:
306 case Vinstr::defvmsp
:
307 case Vinstr::defvmfp
:
315 case Vinstr::loadsbl
:
316 case Vinstr::loadsbq
:
318 case Vinstr::loadtqb
:
319 case Vinstr::loadtql
:
320 case Vinstr::loadups
:
322 case Vinstr::loadzbl
:
323 case Vinstr::loadzbq
:
324 case Vinstr::loadzwq
:
325 case Vinstr::loadzlq
:
327 case Vinstr::testbim
:
329 case Vinstr::testlim
:
331 case Vinstr::testqim
:
333 case Vinstr::testwim
:
335 assertx(!writesMemory(inst
));
336 assertx(!isCall(inst
));
347 case Vinstr::bindaddr
:
348 case Vinstr::ldbindaddr
:
349 case Vinstr::ldbindretaddr
:
350 case Vinstr::bindjcc
:
351 case Vinstr::bindjmp
:
353 case Vinstr::callfaststub
:
355 case Vinstr::callphp
:
356 case Vinstr::callphpfe
:
357 case Vinstr::callphpr
:
358 case Vinstr::callphps
:
361 case Vinstr::callstub
:
362 case Vinstr::conjure
:
363 case Vinstr::conjureuse
:
364 case Vinstr::contenter
:
366 case Vinstr::debugtrap
:
369 case Vinstr::decqmlock
:
370 case Vinstr::decqmlocknosf
:
371 case Vinstr::fallback
:
372 case Vinstr::fallbackcc
:
373 case Vinstr::fallthru
:
379 case Vinstr::inlineend
:
380 case Vinstr::inlinestart
:
388 case Vinstr::killeffects
:
389 case Vinstr::landingpad
:
390 case Vinstr::leavetc
:
391 case Vinstr::loadstubret
:
395 case Vinstr::nothrow
:
402 case Vinstr::phplogue
:
409 case Vinstr::prefetch
:
412 case Vinstr::pushframe
:
416 case Vinstr::pushvmfp
:
417 case Vinstr::recordbasenativesp
:
418 case Vinstr::unrecordbasenativesp
:
419 case Vinstr::recordstack
:
420 case Vinstr::restorerip
:
421 case Vinstr::resumetc
:
425 case Vinstr::storebi
:
427 case Vinstr::storeli
:
428 case Vinstr::storeqi
:
429 case Vinstr::storesd
:
430 case Vinstr::storeups
:
432 case Vinstr::storewi
:
433 case Vinstr::stublogue
:
434 case Vinstr::stubret
:
435 case Vinstr::stubtophp
:
436 case Vinstr::stubunwind
:
438 case Vinstr::syncpoint
:
439 case Vinstr::syncvmret
:
440 case Vinstr::syncvmrettype
:
441 case Vinstr::syncvmsp
:
442 case Vinstr::tailcallstub
:
443 case Vinstr::tailcallstubr
:
445 case Vinstr::unstublogue
:
448 case Vinstr::vinvoke
:
449 case Vinstr::vregrestrict
:
450 case Vinstr::vregunrestrict
:
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);