diff options
author | fanquake <fanquake@gmail.com> | 2024-03-01 11:18:11 -0500 |
---|---|---|
committer | fanquake <fanquake@gmail.com> | 2024-03-01 11:19:58 -0500 |
commit | 8da62a1041bfaf8ce4e40a4b31c7281cbe8bb916 (patch) | |
tree | 0a4f62b24ce0bc9241b1d6e275aabd20fabe1ee2 /src/serialize.h | |
parent | ae4165f7bc395ffdfc0ff46371d539d29c54dfce (diff) | |
parent | 86b7f28d6c507155a9d3a15487ee883989b88943 (diff) |
Merge bitcoin/bitcoin#29263: serialization: c++20 endian/byteswap/clz modernization
86b7f28d6c507155a9d3a15487ee883989b88943 serialization: use internal endian conversion functions (Cory Fields)
432b18ca8d0654318a8d882b28b20af2cb2d2e5d serialization: detect byteswap builtins without autoconf tests (Cory Fields)
297367b3bb062c57142747719ac9bf2e12717ce9 crypto: replace CountBits with std::bit_width (Cory Fields)
52f9bba889fd9b50a0543fd9fedc389592cdc7e5 crypto: replace non-standard CLZ builtins with c++20's bit_width (Cory Fields)
Pull request description:
This replaces #28674, #29036, and #29057. Now ready for testing and review.
Replaces platform-specific endian and byteswap functions. This is especially useful for kernel, as it means that our deep serialization code no longer requires bitcoin-config.h.
I apologize for the size of the last commit, but it's hard to avoid making those changes at once.
All platforms now use our internal functions rather than libc or platform-specific ones, with the exception of MSVC.
Sadly, benchmarking showed that not all compilers are capable of detecting and optimizing byteswap functions, so compiler builtins are instead used where possible. However, they're now detected via macros rather than autoconf checks.
This[ matches how libc++ implements std::byteswap for c++23](https://github.com/llvm/llvm-project/blob/main/libcxx/include/__bit/byteswap.h#L26).
I suggest we move/rename `compat/endian.h`, but I left that out of this PR to avoid bikeshedding.
#29057 pointed out some irregularities in benchmarks. After messing with various compilers and configs for a few weeks with these changes, I'm of the opinion that we can't win on every platform every time, so we should take the code that makes sense going forward. That said, if any real-world slowdowns are caused here, we should obviously investigate.
ACKs for top commit:
maflcko:
ACK 86b7f28d6c507155a9d3a15487ee883989b88943 📘
fanquake:
ACK 86b7f28d6c507155a9d3a15487ee883989b88943 - we can finish pruning out the __builtin_clz* checks/usage once the minisketch code has been updated. This is more good cleanup pre-CMake & for the kernal.
Tree-SHA512: 715a32ec190c70505ffbce70bfe81fc7b6aa33e376b60292e801f60cf17025aabfcab4e8c53ebb2e28ffc5cf4c20b74fe3dd8548371ad772085c13aec8b7970e
Diffstat (limited to 'src/serialize.h')
-rw-r--r-- | src/serialize.h | 28 |
1 files changed, 14 insertions, 14 deletions
diff --git a/src/serialize.h b/src/serialize.h index ab57376a57..2f13fba582 100644 --- a/src/serialize.h +++ b/src/serialize.h @@ -57,27 +57,27 @@ template<typename Stream> inline void ser_writedata8(Stream &s, uint8_t obj) } template<typename Stream> inline void ser_writedata16(Stream &s, uint16_t obj) { - obj = htole16(obj); + obj = htole16_internal(obj); s.write(AsBytes(Span{&obj, 1})); } template<typename Stream> inline void ser_writedata16be(Stream &s, uint16_t obj) { - obj = htobe16(obj); + obj = htobe16_internal(obj); s.write(AsBytes(Span{&obj, 1})); } template<typename Stream> inline void ser_writedata32(Stream &s, uint32_t obj) { - obj = htole32(obj); + obj = htole32_internal(obj); s.write(AsBytes(Span{&obj, 1})); } template<typename Stream> inline void ser_writedata32be(Stream &s, uint32_t obj) { - obj = htobe32(obj); + obj = htobe32_internal(obj); s.write(AsBytes(Span{&obj, 1})); } template<typename Stream> inline void ser_writedata64(Stream &s, uint64_t obj) { - obj = htole64(obj); + obj = htole64_internal(obj); s.write(AsBytes(Span{&obj, 1})); } template<typename Stream> inline uint8_t ser_readdata8(Stream &s) @@ -90,31 +90,31 @@ template<typename Stream> inline uint16_t ser_readdata16(Stream &s) { uint16_t obj; s.read(AsWritableBytes(Span{&obj, 1})); - return le16toh(obj); + return le16toh_internal(obj); } template<typename Stream> inline uint16_t ser_readdata16be(Stream &s) { uint16_t obj; s.read(AsWritableBytes(Span{&obj, 1})); - return be16toh(obj); + return be16toh_internal(obj); } template<typename Stream> inline uint32_t ser_readdata32(Stream &s) { uint32_t obj; s.read(AsWritableBytes(Span{&obj, 1})); - return le32toh(obj); + return le32toh_internal(obj); } template<typename Stream> inline uint32_t ser_readdata32be(Stream &s) { uint32_t obj; s.read(AsWritableBytes(Span{&obj, 1})); - return be32toh(obj); + return be32toh_internal(obj); } template<typename Stream> inline uint64_t ser_readdata64(Stream &s) { uint64_t obj; s.read(AsWritableBytes(Span{&obj, 1})); - return le64toh(obj); + return le64toh_internal(obj); } @@ -548,10 +548,10 @@ struct CustomUintFormatter { if (v < 0 || v > MAX) throw std::ios_base::failure("CustomUintFormatter value out of range"); if (BigEndian) { - uint64_t raw = htobe64(v); + uint64_t raw = htobe64_internal(v); s.write(AsBytes(Span{&raw, 1}).last(Bytes)); } else { - uint64_t raw = htole64(v); + uint64_t raw = htole64_internal(v); s.write(AsBytes(Span{&raw, 1}).first(Bytes)); } } @@ -563,10 +563,10 @@ struct CustomUintFormatter uint64_t raw = 0; if (BigEndian) { s.read(AsWritableBytes(Span{&raw, 1}).last(Bytes)); - v = static_cast<I>(be64toh(raw)); + v = static_cast<I>(be64toh_internal(raw)); } else { s.read(AsWritableBytes(Span{&raw, 1}).first(Bytes)); - v = static_cast<I>(le64toh(raw)); + v = static_cast<I>(le64toh_internal(raw)); } } }; |