Skip to content

Commit 6007999

Browse files
committed
Revert "[C++] Refactor uint128 (#8416)"
This reverts commit b604419.
1 parent 97cb3a8 commit 6007999

File tree

4 files changed

+212
-132
lines changed

4 files changed

+212
-132
lines changed

src/google/protobuf/stubs/int128.cc

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -33,15 +33,18 @@
3333
#include <iomanip>
3434
#include <ostream> // NOLINT(readability/streams)
3535
#include <sstream>
36-
#include <string>
3736

3837
#include <google/protobuf/stubs/logging.h>
3938

4039
#include <google/protobuf/port_def.inc>
4140

4241
namespace google {
4342
namespace protobuf {
44-
namespace int128_internal {
43+
44+
const uint128_pod kuint128max = {
45+
static_cast<uint64>(PROTOBUF_LONGLONG(0xFFFFFFFFFFFFFFFF)),
46+
static_cast<uint64>(PROTOBUF_LONGLONG(0xFFFFFFFFFFFFFFFF))
47+
};
4548

4649
// Returns the 0-based position of the last set bit (i.e., most significant bit)
4750
// in the given uint64. The argument may not be 0.
@@ -185,14 +188,6 @@ std::ostream& operator<<(std::ostream& o, const uint128& b) {
185188
return o << rep;
186189
}
187190

188-
void VerifyValidShift(std::string op, int amount) {
189-
// Shifting more than 127 is UB in Abseil, just crash for now to verify
190-
// callers don't depend on it returning 0.
191-
GOOGLE_CHECK_LT(amount, 128) << "Error executing operator " << op
192-
<< ": shifts of more than 127 are undefined";
193-
}
194-
195-
} // namespace int128_internal
196191
} // namespace protobuf
197192
} // namespace google
198193

src/google/protobuf/stubs/int128.h

Lines changed: 69 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -33,33 +33,38 @@
3333
#include <google/protobuf/stubs/common.h>
3434

3535
#include <iosfwd>
36-
#include <limits>
37-
#include <string>
3836

3937
#include <google/protobuf/port_def.inc>
4038

4139
namespace google {
4240
namespace protobuf {
43-
namespace int128_internal {
4441

45-
// An unsigned 128-bit integer type. Thread-compatible.
46-
class PROTOBUF_EXPORT uint128 {
47-
public:
48-
uint128() = default;
42+
struct uint128_pod;
4943

50-
private:
51-
// Use `MakeUint128` instead.
52-
constexpr uint128(uint64 top, uint64 bottom);
44+
// TODO(xiaofeng): Define GOOGLE_PROTOBUF_HAS_CONSTEXPR when constexpr is
45+
// available.
46+
#ifdef GOOGLE_PROTOBUF_HAS_CONSTEXPR
47+
# define UINT128_CONSTEXPR constexpr
48+
#else
49+
# define UINT128_CONSTEXPR
50+
#endif
5351

52+
// An unsigned 128-bit integer type. Thread-compatible.
53+
class PROTOBUF_EXPORT uint128 {
5454
public:
55+
UINT128_CONSTEXPR uint128(); // Sets to 0, but don't trust on this behavior.
56+
UINT128_CONSTEXPR uint128(uint64 top, uint64 bottom);
5557
#ifndef SWIG
56-
constexpr uint128(int bottom);
57-
constexpr uint128(uint32 bottom); // Top 96 bits = 0
58+
UINT128_CONSTEXPR uint128(int bottom);
59+
UINT128_CONSTEXPR uint128(uint32 bottom); // Top 96 bits = 0
5860
#endif
59-
constexpr uint128(uint64 bottom); // hi_ = 0
61+
UINT128_CONSTEXPR uint128(uint64 bottom); // hi_ = 0
62+
UINT128_CONSTEXPR uint128(const uint128_pod &val);
6063

6164
// Trivial copy constructor, assignment operator and destructor.
6265

66+
void Initialize(uint64 top, uint64 bottom);
67+
6368
// Arithmetic operators.
6469
uint128& operator+=(const uint128& b);
6570
uint128& operator-=(const uint128& b);
@@ -77,10 +82,8 @@ class PROTOBUF_EXPORT uint128 {
7782
uint128& operator++();
7883
uint128& operator--();
7984

80-
friend constexpr uint64 Uint128Low64(const uint128& v);
81-
friend constexpr uint64 Uint128High64(const uint128& v);
82-
83-
friend constexpr uint128 MakeUint128(uint64_t high, uint64_t low);
85+
friend uint64 Uint128Low64(const uint128& v);
86+
friend uint64 Uint128High64(const uint128& v);
8487

8588
// We add "std::" to avoid including all of port.h.
8689
PROTOBUF_EXPORT friend std::ostream& operator<<(std::ostream& o,
@@ -97,25 +100,35 @@ class PROTOBUF_EXPORT uint128 {
97100
uint64 hi_;
98101

99102
// Not implemented, just declared for catching automatic type conversions.
100-
uint128(uint8) = delete;
101-
uint128(uint16) = delete;
102-
uint128(float v) = delete;
103-
uint128(double v) = delete;
103+
uint128(uint8);
104+
uint128(uint16);
105+
uint128(float v);
106+
uint128(double v);
107+
};
108+
109+
// This is a POD form of uint128 which can be used for static variables which
110+
// need to be operated on as uint128.
111+
struct uint128_pod {
112+
// Note: The ordering of fields is different than 'class uint128' but the
113+
// same as its 2-arg constructor. This enables more obvious initialization
114+
// of static instances, which is the primary reason for this struct in the
115+
// first place. This does not seem to defeat any optimizations wrt
116+
// operations involving this struct.
117+
uint64 hi;
118+
uint64 lo;
104119
};
105120

121+
PROTOBUF_EXPORT extern const uint128_pod kuint128max;
122+
106123
// allow uint128 to be logged
107124
PROTOBUF_EXPORT extern std::ostream& operator<<(std::ostream& o,
108125
const uint128& b);
109126

110127
// Methods to access low and high pieces of 128-bit value.
111128
// Defined externally from uint128 to facilitate conversion
112129
// to native 128-bit types when compilers support them.
113-
inline constexpr uint64 Uint128Low64(const uint128& v) { return v.lo_; }
114-
inline constexpr uint64 Uint128High64(const uint128& v) { return v.hi_; }
115-
116-
constexpr uint128 MakeUint128(uint64_t high, uint64_t low) {
117-
return uint128(high, low);
118-
}
130+
inline uint64 Uint128Low64(const uint128& v) { return v.lo_; }
131+
inline uint64 Uint128High64(const uint128& v) { return v.hi_; }
119132

120133
// TODO: perhaps it would be nice to have int128, a signed 128-bit type?
121134

@@ -130,17 +143,27 @@ inline bool operator!=(const uint128& lhs, const uint128& rhs) {
130143
return !(lhs == rhs);
131144
}
132145

133-
inline constexpr uint128::uint128(uint64 top, uint64 bottom)
146+
inline UINT128_CONSTEXPR uint128::uint128() : lo_(0), hi_(0) {}
147+
inline UINT128_CONSTEXPR uint128::uint128(uint64 top, uint64 bottom)
134148
: lo_(bottom), hi_(top) {}
135-
inline constexpr uint128::uint128(uint64 bottom)
149+
inline UINT128_CONSTEXPR uint128::uint128(const uint128_pod& v)
150+
: lo_(v.lo), hi_(v.hi) {}
151+
inline UINT128_CONSTEXPR uint128::uint128(uint64 bottom)
136152
: lo_(bottom), hi_(0) {}
137153
#ifndef SWIG
138-
inline constexpr uint128::uint128(uint32 bottom)
154+
inline UINT128_CONSTEXPR uint128::uint128(uint32 bottom)
139155
: lo_(bottom), hi_(0) {}
140-
inline constexpr uint128::uint128(int bottom)
156+
inline UINT128_CONSTEXPR uint128::uint128(int bottom)
141157
: lo_(bottom), hi_(static_cast<int64>((bottom < 0) ? -1 : 0)) {}
142158
#endif
143159

160+
#undef UINT128_CONSTEXPR
161+
162+
inline void uint128::Initialize(uint64 top, uint64 bottom) {
163+
hi_ = top;
164+
lo_ = bottom;
165+
}
166+
144167
// Comparison operators.
145168

146169
#define CMP128(op) \
@@ -164,9 +187,9 @@ inline uint128 operator-(const uint128& val) {
164187
const uint64 lo_flip = ~Uint128Low64(val);
165188
const uint64 lo_add = lo_flip + 1;
166189
if (lo_add < lo_flip) {
167-
return MakeUint128(hi_flip + 1, lo_add);
190+
return uint128(hi_flip + 1, lo_add);
168191
}
169-
return MakeUint128(hi_flip, lo_add);
192+
return uint128(hi_flip, lo_add);
170193
}
171194

172195
inline bool operator!(const uint128& val) {
@@ -176,13 +199,13 @@ inline bool operator!(const uint128& val) {
176199
// Logical operators.
177200

178201
inline uint128 operator~(const uint128& val) {
179-
return MakeUint128(~Uint128High64(val), ~Uint128Low64(val));
202+
return uint128(~Uint128High64(val), ~Uint128Low64(val));
180203
}
181204

182205
#define LOGIC128(op) \
183206
inline uint128 operator op(const uint128& lhs, const uint128& rhs) { \
184-
return MakeUint128(Uint128High64(lhs) op Uint128High64(rhs), \
185-
Uint128Low64(lhs) op Uint128Low64(rhs)); \
207+
return uint128(Uint128High64(lhs) op Uint128High64(rhs), \
208+
Uint128Low64(lhs) op Uint128Low64(rhs)); \
186209
}
187210

188211
LOGIC128(|)
@@ -206,11 +229,7 @@ LOGICASSIGN128(^=)
206229

207230
// Shift operators.
208231

209-
void VerifyValidShift(std::string op, int amount);
210-
211232
inline uint128 operator<<(const uint128& val, int amount) {
212-
VerifyValidShift("<<", amount);
213-
214233
// uint64 shifts of >= 64 are undefined, so we will need some special-casing.
215234
if (amount < 64) {
216235
if (amount == 0) {
@@ -219,14 +238,15 @@ inline uint128 operator<<(const uint128& val, int amount) {
219238
uint64 new_hi = (Uint128High64(val) << amount) |
220239
(Uint128Low64(val) >> (64 - amount));
221240
uint64 new_lo = Uint128Low64(val) << amount;
222-
return MakeUint128(new_hi, new_lo);
241+
return uint128(new_hi, new_lo);
242+
} else if (amount < 128) {
243+
return uint128(Uint128Low64(val) << (amount - 64), 0);
244+
} else {
245+
return uint128(0, 0);
223246
}
224-
return MakeUint128(Uint128Low64(val) << (amount - 64), 0);
225247
}
226248

227249
inline uint128 operator>>(const uint128& val, int amount) {
228-
VerifyValidShift(">>", amount);
229-
230250
// uint64 shifts of >= 64 are undefined, so we will need some special-casing.
231251
if (amount < 64) {
232252
if (amount == 0) {
@@ -235,10 +255,12 @@ inline uint128 operator>>(const uint128& val, int amount) {
235255
uint64 new_hi = Uint128High64(val) >> amount;
236256
uint64 new_lo = (Uint128Low64(val) >> amount) |
237257
(Uint128High64(val) << (64 - amount));
238-
return MakeUint128(new_hi, new_lo);
258+
return uint128(new_hi, new_lo);
259+
} else if (amount < 128) {
260+
return uint128(0, Uint128High64(val) >> (amount - 64));
261+
} else {
262+
return uint128(0, 0);
239263
}
240-
241-
return MakeUint128(0, Uint128High64(val) >> (amount - 64));
242264
}
243265

244266
inline uint128& uint128::operator<<=(int amount) {
@@ -357,17 +379,6 @@ inline uint128& uint128::operator--() {
357379
return *this;
358380
}
359381

360-
constexpr uint128 Uint128Max() {
361-
return MakeUint128((std::numeric_limits<uint64>::max)(),
362-
(std::numeric_limits<uint64>::max)());
363-
}
364-
365-
} // namespace int128_internal
366-
367-
using google::protobuf::int128_internal::uint128;
368-
using google::protobuf::int128_internal::Uint128Max;
369-
using google::protobuf::int128_internal::MakeUint128;
370-
371382
} // namespace protobuf
372383
} // namespace google
373384

0 commit comments

Comments
 (0)