mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2025-06-04 08:29:44 -04:00
Switch atmosphere's build target to C++20. (#952)
* ams: update to build with gcc10/c++20 * remove mno-outline-atomics * ams: take care of most TODO C++20s * fusee/sept: update for gcc10 * whoosh, your code now uses pre-compiled headers * make: dependency fixes
This commit is contained in:
parent
17b6bcfd37
commit
3a1ccdd919
258 changed files with 723 additions and 804 deletions
|
@ -50,7 +50,7 @@ namespace ams::util {
|
|||
static constexpr size_t Next = Index + Count;
|
||||
|
||||
using BitPackType = BitPack<IntegralStorageType>;
|
||||
static_assert(std::is_pod<BitPackType>::value);
|
||||
static_assert(util::is_pod<BitPackType>::value);
|
||||
|
||||
static_assert(Mask<Index, Count> != 0);
|
||||
static_assert(std::is_integral<T>::value || std::is_enum<T>::value);
|
||||
|
@ -84,10 +84,10 @@ namespace ams::util {
|
|||
using BitPack32 = impl::BitPack<u32>;
|
||||
using BitPack64 = impl::BitPack<u64>;
|
||||
|
||||
static_assert(std::is_pod<BitPack8>::value);
|
||||
static_assert(std::is_pod<BitPack16>::value);
|
||||
static_assert(std::is_pod<BitPack32>::value);
|
||||
static_assert(std::is_pod<BitPack64>::value);
|
||||
static_assert(util::is_pod<BitPack8>::value);
|
||||
static_assert(util::is_pod<BitPack16>::value);
|
||||
static_assert(util::is_pod<BitPack32>::value);
|
||||
static_assert(util::is_pod<BitPack64>::value);
|
||||
static_assert(std::is_trivially_destructible<BitPack8 >::value);
|
||||
static_assert(std::is_trivially_destructible<BitPack16>::value);
|
||||
static_assert(std::is_trivially_destructible<BitPack32>::value);
|
||||
|
|
|
@ -30,11 +30,9 @@ namespace ams::util {
|
|||
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
template <typename T> requires std::integral<T>
|
||||
class BitsOf {
|
||||
private:
|
||||
static_assert(std::is_integral<T>::value);
|
||||
|
||||
static constexpr ALWAYS_INLINE int GetLsbPos(T v) {
|
||||
return __builtin_ctzll(static_cast<u64>(v));
|
||||
}
|
||||
|
@ -78,69 +76,68 @@ namespace ams::util {
|
|||
}
|
||||
};
|
||||
|
||||
template<typename T = u64, typename ...Args>
|
||||
template<typename T = u64, typename ...Args> requires std::integral<T>
|
||||
constexpr ALWAYS_INLINE T CombineBits(Args... args) {
|
||||
return (... | (T(1u) << args));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename T> requires std::integral<T>
|
||||
constexpr ALWAYS_INLINE T ResetLeastSignificantOneBit(T x) {
|
||||
return x & (x - 1);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename T> requires std::integral<T>
|
||||
constexpr ALWAYS_INLINE T SetLeastSignificantZeroBit(T x) {
|
||||
return x | (x + 1);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename T> requires std::integral<T>
|
||||
constexpr ALWAYS_INLINE T LeastSignificantOneBit(T x) {
|
||||
return x & ~(x - 1);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename T> requires std::integral<T>
|
||||
constexpr ALWAYS_INLINE T LeastSignificantZeroBit(T x) {
|
||||
return ~x & (x + 1);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename T> requires std::integral<T>
|
||||
constexpr ALWAYS_INLINE T ResetTrailingOnes(T x) {
|
||||
return x & (x + 1);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename T> requires std::integral<T>
|
||||
constexpr ALWAYS_INLINE T SetTrailingZeros(T x) {
|
||||
return x | (x - 1);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename T> requires std::integral<T>
|
||||
constexpr ALWAYS_INLINE T MaskTrailingZeros(T x) {
|
||||
return (~x) & (x - 1);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename T> requires std::integral<T>
|
||||
constexpr ALWAYS_INLINE T MaskTrailingOnes(T x) {
|
||||
return ~((~x) | (x + 1));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename T> requires std::integral<T>
|
||||
constexpr ALWAYS_INLINE T MaskTrailingZerosAndLeastSignificantOneBit(T x) {
|
||||
return x ^ (x - 1);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename T> requires std::integral<T>
|
||||
constexpr ALWAYS_INLINE T MaskTrailingOnesAndLeastSignificantZeroBit(T x) {
|
||||
return x ^ (x + 1);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename T> requires std::integral<T>
|
||||
constexpr ALWAYS_INLINE int PopCount(T x) {
|
||||
/* TODO: C++20 std::bit_cast */
|
||||
using U = typename std::make_unsigned<T>::type;
|
||||
U u = static_cast<U>(x);
|
||||
|
||||
/* TODO: C++20 std::is_constant_evaluated */
|
||||
if (false) {
|
||||
if (std::is_constant_evaluated()) {
|
||||
/* https://en.wikipedia.org/wiki/Hamming_weight */
|
||||
constexpr U m1 = U(-1) / 0x03;
|
||||
constexpr U m2 = U(-1) / 0x05;
|
||||
|
@ -168,10 +165,9 @@ namespace ams::util {
|
|||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename T> requires std::integral<T>
|
||||
constexpr ALWAYS_INLINE int CountLeadingZeros(T x) {
|
||||
/* TODO: C++20 std::is_constant_evaluated */
|
||||
if (false) {
|
||||
if (std::is_constant_evaluated()) {
|
||||
for (size_t i = 0; i < impl::Log2<BITSIZEOF(T)>; ++i) {
|
||||
const size_t shift = (0x1 << i);
|
||||
x |= x >> shift;
|
||||
|
@ -195,18 +191,18 @@ namespace ams::util {
|
|||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename T> requires std::integral<T>
|
||||
constexpr ALWAYS_INLINE bool IsPowerOfTwo(T x) {
|
||||
return x > 0 && ResetLeastSignificantOneBit(x) == 0;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename T> requires std::integral<T>
|
||||
constexpr ALWAYS_INLINE T CeilingPowerOfTwo(T x) {
|
||||
AMS_ASSERT(x > 0);
|
||||
return T(1) << (BITSIZEOF(T) - CountLeadingZeros(T(x - 1)));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
template<typename T> requires std::integral<T>
|
||||
constexpr ALWAYS_INLINE T FloorPowerOfTwo(T x) {
|
||||
AMS_ASSERT(x > 0);
|
||||
return T(1) << (BITSIZEOF(T) - CountLeadingZeros(x) - 1);
|
||||
|
|
|
@ -20,27 +20,17 @@
|
|||
|
||||
namespace ams::util {
|
||||
|
||||
/* TODO: C++20 std::endian */
|
||||
|
||||
constexpr bool IsLittleEndian() {
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
return std::endian::native == std::endian::little;
|
||||
}
|
||||
|
||||
constexpr bool IsBigEndian() {
|
||||
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
return std::endian::native == std::endian::big;
|
||||
}
|
||||
|
||||
static_assert(IsLittleEndian() ^ IsBigEndian());
|
||||
|
||||
template<typename U> /* requires unsigned_integral<U> */
|
||||
template<typename U> requires std::unsigned_integral<U>
|
||||
constexpr ALWAYS_INLINE U SwapBytes(const U u) {
|
||||
static_assert(BITSIZEOF(u8) == 8);
|
||||
constexpr U ByteMask = 0xFFu;
|
||||
|
@ -85,14 +75,14 @@ namespace ams::util {
|
|||
((u & (ByteMask << 0)) << 40);
|
||||
}
|
||||
|
||||
template<typename T> /* requires integral<T> */
|
||||
template<typename T> requires std::integral<T>
|
||||
constexpr ALWAYS_INLINE void SwapBytes(T *ptr) {
|
||||
using U = typename std::make_unsigned<T>::type;
|
||||
|
||||
*ptr = static_cast<T>(SwapBytes(static_cast<U>(*ptr)));
|
||||
}
|
||||
|
||||
template<typename T> /* requires integral<T> */
|
||||
template<typename T> requires std::integral<T>
|
||||
constexpr ALWAYS_INLINE T ConvertToBigEndian(const T val) {
|
||||
using U = typename std::make_unsigned<T>::type;
|
||||
|
||||
|
@ -104,7 +94,7 @@ namespace ams::util {
|
|||
}
|
||||
}
|
||||
|
||||
template<typename T> /* requires integral<T> */
|
||||
template<typename T> requires std::integral<T>
|
||||
constexpr ALWAYS_INLINE T ConvertToLittleEndian(const T val) {
|
||||
using U = typename std::make_unsigned<T>::type;
|
||||
|
||||
|
@ -116,7 +106,7 @@ namespace ams::util {
|
|||
}
|
||||
}
|
||||
|
||||
template<typename T> /* requires integral<T> */
|
||||
template<typename T> requires std::integral<T>
|
||||
constexpr ALWAYS_INLINE T ConvertToBigEndian48(const T val) {
|
||||
using U = typename std::make_unsigned<T>::type;
|
||||
static_assert(sizeof(T) == sizeof(u64));
|
||||
|
@ -130,7 +120,7 @@ namespace ams::util {
|
|||
}
|
||||
}
|
||||
|
||||
template<typename T> /* requires integral<T> */
|
||||
template<typename T> requires std::integral<T>
|
||||
constexpr ALWAYS_INLINE T ConvertToLittleEndian48(const T val) {
|
||||
using U = typename std::make_unsigned<T>::type;
|
||||
static_assert(sizeof(T) == sizeof(u64));
|
||||
|
@ -144,12 +134,12 @@ namespace ams::util {
|
|||
}
|
||||
}
|
||||
|
||||
template<typename T> /* requires integral<T> */
|
||||
template<typename T> requires std::integral<T>
|
||||
constexpr ALWAYS_INLINE T LoadBigEndian(T *ptr) {
|
||||
return ConvertToBigEndian(*ptr);
|
||||
}
|
||||
|
||||
template<typename T> /* requires integral<T> */
|
||||
template<typename T> requires std::integral<T>
|
||||
constexpr ALWAYS_INLINE T LoadLittleEndian(T *ptr) {
|
||||
return ConvertToLittleEndian(*ptr);
|
||||
}
|
||||
|
|
|
@ -17,16 +17,14 @@
|
|||
#pragma once
|
||||
#include <vapours/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
#include <vapours/util/util_endian.hpp>
|
||||
|
||||
namespace ams::util {
|
||||
|
||||
template<char A, char B, char C, char D>
|
||||
struct FourCC {
|
||||
/* TODO: C++20 std::endian */
|
||||
static constexpr u32 Code = (static_cast<u32>(A) << 0x00) |
|
||||
(static_cast<u32>(B) << 0x08) |
|
||||
(static_cast<u32>(C) << 0x10) |
|
||||
(static_cast<u32>(D) << 0x18);
|
||||
static constexpr u32 Code = IsLittleEndian() ? ((static_cast<u32>(A) << 0x00) | (static_cast<u32>(B) << 0x08) | (static_cast<u32>(C) << 0x10) | (static_cast<u32>(D) << 0x18))
|
||||
: ((static_cast<u32>(A) << 0x18) | (static_cast<u32>(B) << 0x10) | (static_cast<u32>(C) << 0x08) | (static_cast<u32>(D) << 0x00));
|
||||
|
||||
static constexpr const char String[] = {A, B, C, D};
|
||||
|
||||
|
@ -36,11 +34,8 @@ namespace ams::util {
|
|||
|
||||
template<char A, char B, char C, char D>
|
||||
struct ReverseFourCC {
|
||||
/* TODO: C++20 std::endian */
|
||||
static constexpr u32 Code = (static_cast<u32>(A) << 0x18) |
|
||||
(static_cast<u32>(B) << 0x10) |
|
||||
(static_cast<u32>(C) << 0x08) |
|
||||
(static_cast<u32>(D) << 0x00);
|
||||
static constexpr u32 Code = IsLittleEndian() ? ((static_cast<u32>(A) << 0x18) | (static_cast<u32>(B) << 0x10) | (static_cast<u32>(C) << 0x08) | (static_cast<u32>(D) << 0x00))
|
||||
: ((static_cast<u32>(A) << 0x00) | (static_cast<u32>(B) << 0x08) | (static_cast<u32>(C) << 0x10) | (static_cast<u32>(D) << 0x18));
|
||||
|
||||
static constexpr const char String[] = {D, C, B, A};
|
||||
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <vapours/common.hpp>
|
||||
#include <vapours/assert.hpp>
|
||||
|
||||
namespace ams::util {
|
||||
|
||||
template<typename T>
|
||||
using is_pod = std::bool_constant<std::is_standard_layout<T>::value && std::is_trivial<T>::value>;
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue