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:
SciresM 2020-05-11 15:02:10 -07:00 committed by GitHub
parent 17b6bcfd37
commit 3a1ccdd919
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
258 changed files with 723 additions and 804 deletions

View file

@ -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);

View file

@ -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);

View file

@ -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);
}

View file

@ -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};

View file

@ -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>;
}