Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

P1272R4 Byteswapping for fun&&nuf #2235

Merged
merged 12 commits into from
Oct 20, 2021
45 changes: 45 additions & 0 deletions stl/inc/bit
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,34 @@ _NODISCARD int _Checked_arm_arm64_countl_zero(const _Ty _Val) noexcept {
}
#endif // defined(_M_ARM) || defined(_M_ARM64)

#if _HAS_CXX23
_NODISCARD constexpr unsigned short _Byteswap_ushort(const unsigned short _Val) noexcept {
if (_STD is_constant_evaluated()) {
return static_cast<unsigned short>((_Val << 8) | (_Val >> 8));
} else {
return _byteswap_ushort(_Val);
StephanTLavavej marked this conversation as resolved.
Show resolved Hide resolved
}
}

_NODISCARD constexpr unsigned long _Byteswap_ulong(const unsigned long _Val) noexcept {
if (_STD is_constant_evaluated()) {
return (_Val << 24) | ((_Val << 8) & 0x00FF'0000) | ((_Val >> 8) & 0x0000'FF00) | (_Val >> 24);
} else {
return _byteswap_ulong(_Val);
}
}

_NODISCARD constexpr unsigned long long _Byteswap_uint64(const unsigned long long _Val) noexcept {
if (_STD is_constant_evaluated()) {
return (_Val << 56) | ((_Val << 40) & 0x00FF'0000'0000'0000) | ((_Val << 24) & 0x0000'FF00'0000'0000)
| ((_Val << 8) & 0x0000'00FF'0000'0000) | ((_Val >> 8) & 0x0000'0000'FF00'0000)
| ((_Val >> 24) & 0x0000'0000'00FF'0000) | ((_Val >> 40) & 0x0000'0000'0000'FF00) | (_Val >> 56);
} else {
return _byteswap_uint64(_Val);
}
}
#endif // _HAS_CXX23

template <class _Ty, enable_if_t<_Is_standard_unsigned_integer<_Ty>, int> _Enabled>
_NODISCARD constexpr int countl_zero(const _Ty _Val) noexcept {
#if defined(_M_IX86) || (defined(_M_X64) && !defined(_M_ARM64EC))
Expand Down Expand Up @@ -268,6 +296,23 @@ _NODISCARD constexpr int popcount(const _Ty _Val) noexcept {
return _Popcount(_Val);
}

#if _HAS_CXX23
template <class _Ty, enable_if_t<is_integral_v<_Ty>, int> = 0>
_NODISCARD constexpr _Ty byteswap(const _Ty _Val) noexcept {
if constexpr (sizeof(_Ty) == 1) {
return _Val;
} else if constexpr (sizeof(_Ty) == 2) {
return static_cast<_Ty>(_Byteswap_ushort(static_cast<unsigned short>(_Val)));
} else if constexpr (sizeof(_Ty) == 4) {
return static_cast<_Ty>(_Byteswap_ulong(static_cast<unsigned long>(_Val)));
} else if constexpr (sizeof(_Ty) == 8) {
return static_cast<_Ty>(_Byteswap_uint64(static_cast<unsigned long long>(_Val)));
} else {
static_assert(_Always_false<_Ty>, "Unexpected integer size");
}
}
#endif
StephanTLavavej marked this conversation as resolved.
Show resolved Hide resolved

enum class endian { little = 0, big = 1, native = little };

_STD_END
Expand Down
2 changes: 2 additions & 0 deletions stl/inc/yvals_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,7 @@
// P0943R6 Supporting C Atomics In C++
// P1048R1 is_scoped_enum
// P1132R7 out_ptr(), inout_ptr()
// P1272R4 byteswap()
// P1425R4 Iterator Pair Constructors For stack And queue
// P1679R3 contains() For basic_string/basic_string_view
// P1682R3 to_underlying() For Enumerations
Expand Down Expand Up @@ -1376,6 +1377,7 @@
#define __cpp_lib_allocate_at_least 202106L
#endif // __cpp_lib_concepts

#define __cpp_lib_byteswap 202110L
#define __cpp_lib_invoke_r 202106L
#define __cpp_lib_is_scoped_enum 202011L

Expand Down
1 change: 1 addition & 0 deletions tests/std/test.lst
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,7 @@ tests\P1135R6_latch
tests\P1135R6_semaphore
tests\P1165R1_consistently_propagating_stateful_allocators
tests\P1208R6_source_location
tests\P1272R4_byteswap
tests\P1423R3_char8_t_remediation
tests\P1425R4_queue_stack_constructors
tests\P1502R1_standard_library_header_units
Expand Down
4 changes: 4 additions & 0 deletions tests/std/tests/P1272R4_byteswap/env.lst
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

RUNALL_INCLUDE ..\usual_latest_matrix.lst
47 changes: 47 additions & 0 deletions tests/std/tests/P1272R4_byteswap/test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#include <bit>
#include <cassert>

using namespace std;

template <typename T>
constexpr bool test_byteswap(const auto src, const auto result) {
static_assert(noexcept(byteswap(T{})));
return byteswap(static_cast<T>(src)) == static_cast<T>(result);
}

constexpr bool test_byteswap_all_types() {
assert(test_byteswap<bool>(true, true));

assert(test_byteswap<char>(0x13, 0x13));
assert(test_byteswap<signed char>(0x13, 0x13));
assert(test_byteswap<unsigned char>(0x13, 0x13));
#ifdef __cpp_char8_t
assert(test_byteswap<char8_t>(0x13, 0x13));
#endif

assert(test_byteswap<short>(0xAC34, 0x34AC));
assert(test_byteswap<unsigned short>(0xAC34, 0x34AC));
assert(test_byteswap<char16_t>(0xAC34, 0x34AC));
assert(test_byteswap<wchar_t>(0xAC34, 0x34AC));
assert(test_byteswap<__wchar_t>(0xAC34, 0x34AC));
StephanTLavavej marked this conversation as resolved.
Show resolved Hide resolved

assert(test_byteswap<int>(0x1234ABCD, 0xCDAB3412));
assert(test_byteswap<unsigned int>(0x1234ABCD, 0xCDAB3412));
assert(test_byteswap<long>(0x1234ABCD, 0xCDAB3412));
assert(test_byteswap<unsigned long>(0x1234ABCD, 0xCDAB3412));
assert(test_byteswap<char32_t>(0x1234ABCD, 0xCDAB3412));

assert(test_byteswap<long long>(0x1234567890ABCDEF, 0xEFCDAB9078563412));
assert(test_byteswap<unsigned long long>(0x1234567890ABCDEF, 0xEFCDAB9078563412));

return true;
}

static_assert(test_byteswap_all_types());

AlexGuteniev marked this conversation as resolved.
Show resolved Hide resolved
int main() {
test_byteswap_all_types();
}
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,20 @@ STATIC_ASSERT(__cpp_lib_byte == 201603L);
#endif
#endif

#if _HAS_CXX23
#ifndef __cpp_lib_byteswap
#error __cpp_lib_byteswap is not defined
#elif __cpp_lib_byteswap != 202110L
#error __cpp_lib_byteswap is not 202110L
#else
STATIC_ASSERT(__cpp_lib_byteswap == 202110L);
#endif
#else
#ifdef __cpp_lib_byteswap
#error __cpp_lib_byteswap is defined
#endif
#endif

#if _HAS_CXX20 && defined(__cpp_char8_t)
#ifndef __cpp_lib_char8_t
#error __cpp_lib_char8_t is not defined
Expand Down