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 +----------------------------------------------------------------------+
19 #include "hphp/util/safe-cast.h"
24 * When selecting encodings, we often need to assess a two's complement
25 * distance to see if it fits in a shorter encoding.
27 inline bool deltaFitsBits(int64_t delta
, int64_t bits
) {
28 return delta
< (1ll << (bits
-1)) && delta
>= -(1ll << (bits
-1));
31 inline bool deltaFits(int64_t delta
, int s
) {
32 // sz::qword is always true
33 assert(s
== sz::byte
||
36 return deltaFitsBits(delta
, s
* 8);
39 // The unsigned equivalent of deltaFits
40 inline bool magFits(uint64_t val
, int s
) {
41 // sz::qword is always true
42 assert(s
== sz::byte
||
45 uint64_t bits
= s
* 8;
46 return (val
& ((1ull << bits
) - 1)) == val
;
50 * Immediate wrappers for the assembler.
52 * Immed only allows 32-bit signed values. Unsigned-32bit values and
53 * larger values will not safely fit, we want the caller to deal with
54 * it or explicitly downcast to int32_t.
56 * The Immed64 wrapper picks up whether the immediate argument was an integer
57 * or a pointer type, so we don't have to cast pointers at callsites.
59 * Immediates are always treated as sign-extended values, but it's
60 * often convenient to use unsigned types, so we allow it with an
61 * implicit implementation-defined conversion.
64 /* implicit */ Immed(int i
) : m_int(i
) {}
66 // MSVC prefers not changing the sign of the value when
67 // resolving the overloads, which means that an unsigned
68 // argument, even of a size smaller than int, will error
69 // so we provide an unsigned overload to fix that.
70 /* implicit */ Immed(unsigned int i
) : m_int((int)i
) {}
72 /* implicit */ Immed(unsigned i
) = delete;
74 /* implicit */ Immed(long i
) = delete;
75 /* implicit */ Immed(unsigned long i
) = delete;
76 /* implicit */ Immed(long long i
) = delete;
77 /* implicit */ Immed(unsigned long long i
) = delete;
79 int64_t q() const { return m_int
; }
80 int32_t l() const { return safe_cast
<int32_t>(m_int
); }
81 int16_t w() const { return safe_cast
<int16_t>(m_int
); }
82 uint16_t uw() const { return static_cast<uint16_t>(m_int
); }
83 int8_t b() const { return safe_cast
<int8_t>(m_int
); }
84 uint8_t ub() const { return static_cast<uint8_t>(m_int
); }
86 bool fits(int sz
) const { return deltaFits(m_int
, sz
); }
88 Immed
operator-() { return -this->m_int
; }
90 bool operator==(Immed o
) const { return m_int
== o
.m_int
; }
91 bool operator!=(Immed o
) const { return m_int
!= o
.m_int
; }
99 /* implicit */ Immed64(T i
,
100 typename
std::enable_if
<
101 std::is_integral
<T
>::value
||
102 std::is_enum
<T
>::value
108 /* implicit */ Immed64(T
* p
)
109 : m_long(reinterpret_cast<uintptr_t>(p
))
112 int64_t q() const { return m_long
; }
113 int32_t l() const { return safe_cast
<int32_t>(m_long
); }
114 int16_t w() const { return safe_cast
<int16_t>(m_long
); }
115 int8_t b() const { return safe_cast
<int8_t>(m_long
); }
117 bool fits(int sz
) const { return deltaFits(m_long
, sz
); }
119 bool operator==(Immed64 o
) const { return m_long
== o
.m_long
; }
120 bool operator!=(Immed64 o
) const { return m_long
!= o
.m_long
; }