This fixes a bug in PHP/HH's crypt_blowfish implementation that can cause a short...
[hiphop-php.git] / hphp / util / immed.h
blobf5c606781edfe312f487840d441f156c62403962
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 #pragma once
19 #include "hphp/util/safe-cast.h"
21 namespace HPHP::jit {
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 ||
34 s == sz::word ||
35 s == sz::dword);
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 ||
43 s == sz::word ||
44 s == sz::dword);
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.
63 struct Immed {
64 /* implicit */ Immed(int i) : m_int(i) {}
65 #ifdef _MSC_VER
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) {}
71 #else
72 /* implicit */ Immed(unsigned i) = delete;
73 #endif
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; }
93 private:
94 int32_t m_int;
97 struct Immed64 {
98 template<class T>
99 /* implicit */ Immed64(T i,
100 typename std::enable_if<
101 std::is_integral<T>::value ||
102 std::is_enum<T>::value
103 >::type* = 0)
104 : m_long(i)
107 template<class T>
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; }
122 private:
123 int64_t m_long;