From f65c8f8c6f6ce92ce9bec9d084a30e221dcc9798 Mon Sep 17 00:00:00 2001 From: "Markus F.X.J. Oberhumer" Date: Sun, 26 May 2024 18:22:29 +0200 Subject: [PATCH] src: more work on constexpr --- src/bele.h | 195 +++++++++++++++++------------------- src/check/dt_check.cpp | 82 +++++++++------- src/check/dt_cxxlib.cpp | 144 +++++++++++++++------------ src/conf.h | 36 +++---- src/util/cxxlib.h | 212 +++++++++++++++++++++++++++++++++++++--- 5 files changed, 431 insertions(+), 238 deletions(-) diff --git a/src/bele.h b/src/bele.h index e84e8825..4b7a8656 100644 --- a/src/bele.h +++ b/src/bele.h @@ -32,7 +32,8 @@ // NE - Native Endianness (aka Host Endianness aka CPU Endianness) // TE - Target Endianness (not used here, see various packers) -static_assert(std::is_same_v); +static_assert(std::is_same_v); +static_assert(std::is_same_v); #if defined(upx_is_constant_evaluated) #define bele_constexpr constexpr @@ -109,14 +110,9 @@ using enable_if_xe64 = std::enable_if_t, T>; forceinline bele_constexpr unsigned get_ne16(const byte *p) noexcept { #if defined(upx_is_constant_evaluated) - if (upx_is_constant_evaluated()) { - typedef unsigned U; -#if (ACC_ABI_BIG_ENDIAN) - return (U(p[0]) << 8) | (U(p[1]) << 0); -#else - return (U(p[0]) << 0) | (U(p[1]) << 8); -#endif - } else + if (upx_is_constant_evaluated()) + return upx::compile_time::get_ne16(p); + else #endif { upx_uint16_t v = 0; @@ -127,14 +123,9 @@ forceinline bele_constexpr unsigned get_ne16(const byte *p) noexcept { forceinline bele_constexpr unsigned get_ne32(const byte *p) noexcept { #if defined(upx_is_constant_evaluated) - if (upx_is_constant_evaluated()) { - typedef unsigned U; -#if (ACC_ABI_BIG_ENDIAN) - return (U(p[0]) << 24) | (U(p[1]) << 16) | (U(p[2]) << 8) | (U(p[3]) << 0); -#else - return (U(p[0]) << 0) | (U(p[1]) << 8) | (U(p[2]) << 16) | (U(p[3]) << 24); -#endif - } else + if (upx_is_constant_evaluated()) + return upx::compile_time::get_ne32(p); + else #endif { upx_uint32_t v = 0; @@ -145,16 +136,9 @@ forceinline bele_constexpr unsigned get_ne32(const byte *p) noexcept { forceinline bele_constexpr upx_uint64_t get_ne64(const byte *p) noexcept { #if defined(upx_is_constant_evaluated) - if (upx_is_constant_evaluated()) { - typedef upx_uint64_t U; -#if (ACC_ABI_BIG_ENDIAN) - return (U(p[0]) << 56) | (U(p[1]) << 48) | (U(p[2]) << 40) | (U(p[3]) << 32) | - (U(p[4]) << 24) | (U(p[5]) << 16) | (U(p[6]) << 8) | (U(p[7]) << 0); -#else - return (U(p[0]) << 0) | (U(p[1]) << 8) | (U(p[2]) << 16) | (U(p[3]) << 24) | - (U(p[4]) << 32) | (U(p[5]) << 40) | (U(p[6]) << 48) | (U(p[7]) << 56); -#endif - } else + if (upx_is_constant_evaluated()) + return upx::compile_time::get_ne64(p); + else #endif { upx_uint64_t v = 0; @@ -165,37 +149,21 @@ forceinline bele_constexpr upx_uint64_t get_ne64(const byte *p) noexcept { forceinline bele_constexpr void set_ne16(byte *p, unsigned v) noexcept { #if defined(upx_is_constant_evaluated) - if (upx_is_constant_evaluated()) { -#if (ACC_ABI_BIG_ENDIAN) - p[0] = byte((v >> 8) & 0xff); - p[1] = byte((v >> 0) & 0xff); -#else - p[0] = byte((v >> 0) & 0xff); - p[1] = byte((v >> 8) & 0xff); -#endif - } else + if (upx_is_constant_evaluated()) + upx::compile_time::set_ne16(p, upx_uint16_t(v & 0xffff)); + else #endif { - upx_uint16_t vv = (upx_uint16_t) (v & 0xffff); + upx_uint16_t vv = upx_uint16_t(v & 0xffff); upx_memcpy_inline(p, &vv, sizeof(vv)); } } forceinline bele_constexpr void set_ne32(byte *p, unsigned v) noexcept { #if defined(upx_is_constant_evaluated) - if (upx_is_constant_evaluated()) { -#if (ACC_ABI_BIG_ENDIAN) - p[0] = byte((v >> 24) & 0xff); - p[1] = byte((v >> 16) & 0xff); - p[2] = byte((v >> 8) & 0xff); - p[3] = byte((v >> 0) & 0xff); -#else - p[0] = byte((v >> 0) & 0xff); - p[1] = byte((v >> 8) & 0xff); - p[2] = byte((v >> 16) & 0xff); - p[3] = byte((v >> 24) & 0xff); -#endif - } else + if (upx_is_constant_evaluated()) + upx::compile_time::set_ne32(p, v); + else #endif { upx_uint32_t vv = v; @@ -205,27 +173,9 @@ forceinline bele_constexpr void set_ne32(byte *p, unsigned v) noexcept { forceinline bele_constexpr void set_ne64(byte *p, upx_uint64_t v) noexcept { #if defined(upx_is_constant_evaluated) - if (upx_is_constant_evaluated()) { -#if (ACC_ABI_BIG_ENDIAN) - p[0] = byte((v >> 56) & 0xff); - p[1] = byte((v >> 48) & 0xff); - p[2] = byte((v >> 40) & 0xff); - p[3] = byte((v >> 32) & 0xff); - p[4] = byte((v >> 24) & 0xff); - p[5] = byte((v >> 16) & 0xff); - p[6] = byte((v >> 8) & 0xff); - p[7] = byte((v >> 0) & 0xff); -#else - p[0] = byte((v >> 0) & 0xff); - p[1] = byte((v >> 8) & 0xff); - p[2] = byte((v >> 16) & 0xff); - p[3] = byte((v >> 24) & 0xff); - p[4] = byte((v >> 32) & 0xff); - p[5] = byte((v >> 40) & 0xff); - p[6] = byte((v >> 48) & 0xff); - p[7] = byte((v >> 56) & 0xff); -#endif - } else + if (upx_is_constant_evaluated()) + upx::compile_time::set_ne64(p, v); + else #endif { upx_uint64_t vv = v; @@ -274,7 +224,7 @@ forceinline bele_constexpr void set_ne64(XE64 *p, upx_uint64_t v) noexcept { #if __cpp_lib_byteswap >= 202110L forceinline constexpr unsigned bswap16(unsigned v) noexcept { - return std::byteswap((upx_uint16_t) (v & 0xffff)); + return std::byteswap(upx_uint16_t(v & 0xffff)); } forceinline constexpr unsigned bswap32(unsigned v) noexcept { return std::byteswap(v); } forceinline constexpr upx_uint64_t bswap64(upx_uint64_t v) noexcept { return std::byteswap(v); } @@ -283,30 +233,45 @@ forceinline constexpr upx_uint64_t bswap64(upx_uint64_t v) noexcept { return std ACC_COMPILE_TIME_ASSERT_HEADER(sizeof(long) == 4) -// unfortunately *not* constexpr with current MSVC -forceinline /*constexpr*/ unsigned bswap16(unsigned v) noexcept { - return (unsigned) _byteswap_ulong(v << 16); +// _byteswap_XXX is unfortunately *not* constexpr with current MSVC +forceinline bele_constexpr unsigned bswap16(unsigned v) noexcept { +#if defined(upx_is_constant_evaluated) + if (upx_is_constant_evaluated()) + return upx::compile_time::bswap16(upx_uint16_t(v & 0xffff)); + else +#endif + return (unsigned) _byteswap_ulong(v << 16); } -forceinline /*constexpr*/ unsigned bswap32(unsigned v) noexcept { - return (unsigned) _byteswap_ulong(v); +forceinline bele_constexpr unsigned bswap32(unsigned v) noexcept { +#if defined(upx_is_constant_evaluated) + if (upx_is_constant_evaluated()) + return upx::compile_time::bswap32(v); + else +#endif + return (unsigned) _byteswap_ulong(v); } -forceinline /*constexpr*/ upx_uint64_t bswap64(upx_uint64_t v) noexcept { - return _byteswap_uint64(v); +forceinline bele_constexpr upx_uint64_t bswap64(upx_uint64_t v) noexcept { +#if defined(upx_is_constant_evaluated) + if (upx_is_constant_evaluated()) + return upx::compile_time::bswap64(v); + else +#endif + return _byteswap_uint64(v); } #else forceinline constexpr unsigned bswap16(unsigned v) noexcept { #if defined(__riscv) && __riscv_xlen == 64 - return (unsigned) __builtin_bswap64((upx_uint64_t) v << 48); + return (unsigned) __builtin_bswap64(upx_uint64_t(v) << 48); #else - // return __builtin_bswap16((upx_uint16_t) (v & 0xffff)); + // return __builtin_bswap16(upx_uint16_t(v & 0xffff)); return __builtin_bswap32(v << 16); #endif } forceinline constexpr unsigned bswap32(unsigned v) noexcept { #if defined(__riscv) && __riscv_xlen == 64 - return (unsigned) __builtin_bswap64((upx_uint64_t) v << 32); + return (unsigned) __builtin_bswap64(upx_uint64_t(v) << 32); #else return __builtin_bswap32(v); #endif @@ -389,42 +354,26 @@ inline bele_constexpr void set_le64(XE64 *p, upx_uint64_t v) noexcept { **************************************************************************/ inline constexpr unsigned get_be24(const byte *p) noexcept { - typedef unsigned U; - return (U(p[0]) << 16) | (U(p[1]) << 8) | (U(p[2]) << 0); + return upx::compile_time::get_be24(p); } - inline constexpr unsigned get_le24(const byte *p) noexcept { - typedef unsigned U; - return (U(p[0]) << 0) | (U(p[1]) << 8) | (U(p[2]) << 16); -} - -inline constexpr void set_be24(byte *p, unsigned v) noexcept { - p[0] = byte((v >> 16) & 0xff); - p[1] = byte((v >> 8) & 0xff); - p[2] = byte((v >> 0) & 0xff); -} - -inline constexpr void set_le24(byte *p, unsigned v) noexcept { - p[0] = byte((v >> 0) & 0xff); - p[1] = byte((v >> 8) & 0xff); - p[2] = byte((v >> 16) & 0xff); + return upx::compile_time::get_le24(p); } +inline constexpr void set_be24(byte *p, unsigned v) noexcept { upx::compile_time::set_be24(p, v); } +inline constexpr void set_le24(byte *p, unsigned v) noexcept { upx::compile_time::set_le24(p, v); } REQUIRE_XE24 forceinline bele_constexpr unsigned get_be24(const XE24 *p) noexcept { return get_be24(upx::ptr_static_cast(p)); } - REQUIRE_XE24 forceinline bele_constexpr unsigned get_le24(const XE24 *p) noexcept { return get_le24(upx::ptr_static_cast(p)); } - REQUIRE_XE24 forceinline bele_constexpr void set_be24(XE24 *p, unsigned v) noexcept { set_be24(upx::ptr_static_cast(p), v); } - REQUIRE_XE24 forceinline bele_constexpr void set_le24(XE24 *p, unsigned v) noexcept { set_le24(upx::ptr_static_cast(p), v); @@ -594,7 +543,12 @@ struct alignas(1) BE16 final { } bele_constexpr bool operator==(const BE16 &x) const noexcept { - return upx_memcmp_inline(d, x.d, sizeof(d)) == 0; +#if defined(upx_is_constant_evaluated) + if (upx_is_constant_evaluated()) + return upx::compile_time::mem_eq(d, x.d, sizeof(d)); + else +#endif + return upx_memcmp_inline(d, x.d, sizeof(d)) == 0; } bele_constexpr bool operator<(const BE16 &x) const noexcept { return unsigned(*this) < unsigned(x); @@ -656,7 +610,12 @@ struct alignas(1) BE32 final { } bele_constexpr bool operator==(const BE32 &x) const noexcept { - return upx_memcmp_inline(d, x.d, sizeof(d)) == 0; +#if defined(upx_is_constant_evaluated) + if (upx_is_constant_evaluated()) + return upx::compile_time::mem_eq(d, x.d, sizeof(d)); + else +#endif + return upx_memcmp_inline(d, x.d, sizeof(d)) == 0; } bele_constexpr bool operator<(const BE32 &x) const noexcept { return unsigned(*this) < unsigned(x); @@ -718,7 +677,12 @@ struct alignas(1) BE64 final { } bele_constexpr bool operator==(const BE64 &x) const noexcept { - return upx_memcmp_inline(d, x.d, sizeof(d)) == 0; +#if defined(upx_is_constant_evaluated) + if (upx_is_constant_evaluated()) + return upx::compile_time::mem_eq(d, x.d, sizeof(d)); + else +#endif + return upx_memcmp_inline(d, x.d, sizeof(d)) == 0; } bele_constexpr bool operator<(const BE64 &x) const noexcept { return upx_uint64_t(*this) < upx_uint64_t(x); @@ -780,7 +744,12 @@ struct alignas(1) LE16 final { } bele_constexpr bool operator==(const LE16 &x) const noexcept { - return upx_memcmp_inline(d, x.d, sizeof(d)) == 0; +#if defined(upx_is_constant_evaluated) + if (upx_is_constant_evaluated()) + return upx::compile_time::mem_eq(d, x.d, sizeof(d)); + else +#endif + return upx_memcmp_inline(d, x.d, sizeof(d)) == 0; } bele_constexpr bool operator<(const LE16 &x) const noexcept { return unsigned(*this) < unsigned(x); @@ -842,7 +811,12 @@ struct alignas(1) LE32 final { } bele_constexpr bool operator==(const LE32 &x) const noexcept { - return upx_memcmp_inline(d, x.d, sizeof(d)) == 0; +#if defined(upx_is_constant_evaluated) + if (upx_is_constant_evaluated()) + return upx::compile_time::mem_eq(d, x.d, sizeof(d)); + else +#endif + return upx_memcmp_inline(d, x.d, sizeof(d)) == 0; } bele_constexpr bool operator<(const LE32 &x) const noexcept { return unsigned(*this) < unsigned(x); @@ -904,7 +878,12 @@ struct alignas(1) LE64 final { } bele_constexpr bool operator==(const LE64 &x) const noexcept { - return upx_memcmp_inline(d, x.d, sizeof(d)) == 0; +#if defined(upx_is_constant_evaluated) + if (upx_is_constant_evaluated()) + return upx::compile_time::mem_eq(d, x.d, sizeof(d)); + else +#endif + return upx_memcmp_inline(d, x.d, sizeof(d)) == 0; } bele_constexpr bool operator<(const LE64 &x) const noexcept { return upx_uint64_t(*this) < upx_uint64_t(x); diff --git a/src/check/dt_check.cpp b/src/check/dt_check.cpp index 4247fbda..f6efb1fb 100644 --- a/src/check/dt_check.cpp +++ b/src/check/dt_check.cpp @@ -96,51 +96,49 @@ int upx_doctest_check() { return upx_doctest_check(0, nullptr); } // compile-time checks **************************************************************************/ -// need extra parenthesis because the C preprocessor does not understand C++ templates -ACC_COMPILE_TIME_ASSERT_HEADER((std::is_same::value)) -ACC_COMPILE_TIME_ASSERT_HEADER((std::is_same::value)) -ACC_COMPILE_TIME_ASSERT_HEADER((std::is_same::value)) -ACC_COMPILE_TIME_ASSERT_HEADER((std::is_same::value)) -ACC_COMPILE_TIME_ASSERT_HEADER((std::is_same::value)) -ACC_COMPILE_TIME_ASSERT_HEADER((std::is_same::value)) +static_assert(std::is_same::value); +static_assert(std::is_same::value); +static_assert(std::is_same::value); +static_assert(std::is_same::value); +static_assert(std::is_same::value); +static_assert(std::is_same::value); -ACC_COMPILE_TIME_ASSERT_HEADER(no_bswap16(0x04030201) == 0x0201) -ACC_COMPILE_TIME_ASSERT_HEADER(no_bswap32(0x04030201) == 0x04030201) -ACC_COMPILE_TIME_ASSERT_HEADER(no_bswap64(0x0807060504030201ull) == 0x0807060504030201ull) +static_assert(no_bswap16(0x04030201) == 0x0201); +static_assert(no_bswap32(0x04030201) == 0x04030201); +static_assert(no_bswap64(0x0807060504030201ull) == 0x0807060504030201ull); #if !(ACC_CC_MSC) // unfortunately *not* constexpr with current MSVC -ACC_COMPILE_TIME_ASSERT_HEADER(bswap16(0x04030201) == 0x0102) -ACC_COMPILE_TIME_ASSERT_HEADER(bswap32(0x04030201) == 0x01020304) -ACC_COMPILE_TIME_ASSERT_HEADER(bswap64(0x0807060504030201ull) == 0x0102030405060708ull) -ACC_COMPILE_TIME_ASSERT_HEADER(bswap16(bswap16(0xf4f3f2f1)) == no_bswap16(0xf4f3f2f1)) -ACC_COMPILE_TIME_ASSERT_HEADER(bswap32(bswap32(0xf4f3f2f1)) == no_bswap32(0xf4f3f2f1)) -ACC_COMPILE_TIME_ASSERT_HEADER(bswap64(bswap64(0xf8f7f6f5f4f3f2f1ull)) == - no_bswap64(0xf8f7f6f5f4f3f2f1ull)) +static_assert(bswap16(0x04030201) == 0x0102); +static_assert(bswap32(0x04030201) == 0x01020304); +static_assert(bswap64(0x0807060504030201ull) == 0x0102030405060708ull); +static_assert(bswap16(bswap16(0xf4f3f2f1)) == no_bswap16(0xf4f3f2f1)); +static_assert(bswap32(bswap32(0xf4f3f2f1)) == no_bswap32(0xf4f3f2f1)); +static_assert(bswap64(bswap64(0xf8f7f6f5f4f3f2f1ull)) == no_bswap64(0xf8f7f6f5f4f3f2f1ull)); #endif -ACC_COMPILE_TIME_ASSERT_HEADER(sign_extend(0u + 0, 8) == 0) -ACC_COMPILE_TIME_ASSERT_HEADER(sign_extend(0u + 1, 8) == 1) -ACC_COMPILE_TIME_ASSERT_HEADER(sign_extend(0u + 127, 8) == 127) -ACC_COMPILE_TIME_ASSERT_HEADER(sign_extend(0u + 128, 8) == -128) -ACC_COMPILE_TIME_ASSERT_HEADER(sign_extend(0u - 1, 8) == -1) -ACC_COMPILE_TIME_ASSERT_HEADER(sign_extend(0u + 256, 8) == 0) -ACC_COMPILE_TIME_ASSERT_HEADER(sign_extend(0u + 257, 8) == 1) -ACC_COMPILE_TIME_ASSERT_HEADER(sign_extend(0u + 383, 8) == 127) -ACC_COMPILE_TIME_ASSERT_HEADER(sign_extend(0u + 384, 8) == -128) -ACC_COMPILE_TIME_ASSERT_HEADER(sign_extend(0u + 511, 8) == -1) -ACC_COMPILE_TIME_ASSERT_HEADER(sign_extend(0ull + 0, 1) == 0) -ACC_COMPILE_TIME_ASSERT_HEADER(sign_extend(0ull + 1, 1) == -1) +static_assert(sign_extend(0u + 0, 8) == 0); +static_assert(sign_extend(0u + 1, 8) == 1); +static_assert(sign_extend(0u + 127, 8) == 127); +static_assert(sign_extend(0u + 128, 8) == -128); +static_assert(sign_extend(0u - 1, 8) == -1); +static_assert(sign_extend(0u + 256, 8) == 0); +static_assert(sign_extend(0u + 257, 8) == 1); +static_assert(sign_extend(0u + 383, 8) == 127); +static_assert(sign_extend(0u + 384, 8) == -128); +static_assert(sign_extend(0u + 511, 8) == -1); +static_assert(sign_extend(0ull + 0, 1) == 0); +static_assert(sign_extend(0ull + 1, 1) == -1); -ACC_COMPILE_TIME_ASSERT_HEADER(CHAR_BIT == 8) +static_assert(CHAR_BIT == 8); #if 0 // does not work with MSVC #if '\0' - 1 < 0 -ACC_COMPILE_TIME_ASSERT_HEADER(CHAR_MAX == 127) +static_assert(CHAR_MAX == 127); #else -ACC_COMPILE_TIME_ASSERT_HEADER(CHAR_MAX == 255) +static_assert(CHAR_MAX == 255); #endif #if L'\0' - 1 < 0 -ACC_COMPILE_TIME_ASSERT_HEADER((wchar_t) -1 < 0) +static_assert((wchar_t) -1 < 0); #else -ACC_COMPILE_TIME_ASSERT_HEADER((wchar_t) -1 > 0) +static_assert((wchar_t) -1 > 0); #endif #endif @@ -734,6 +732,14 @@ void upx_compiler_sanity_check(void) noexcept { 0, 0, 0, 0, 0, 0, 0, 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0, 0, 0, 0, 0x7f, 0x7e, 0x7d, 0x7c, 0x7b, 0x7a, 0x79, 0x78, 0, 0, 0, 0, 0}; constexpr const byte *d = dd + 7; + static_assert(upx::compile_time::get_be16(d) == 0xfffe); + static_assert(upx::compile_time::get_be24(d) == 0xfffefd); + static_assert(upx::compile_time::get_be32(d) == 0xfffefdfc); + static_assert(upx::compile_time::get_be64(d) == 0xfffefdfcfbfaf9f8ULL); + static_assert(upx::compile_time::get_le16(d) == 0xfeff); + static_assert(upx::compile_time::get_le24(d) == 0xfdfeff); + static_assert(upx::compile_time::get_le32(d) == 0xfcfdfeff); + static_assert(upx::compile_time::get_le64(d) == 0xf8f9fafbfcfdfeffULL); const N_BELE_RTP::AbstractPolicy *bele; assert_noexcept(upx_adler32(d, 4) == 0x09f003f7); assert_noexcept(upx_adler32(d, 4, 0) == 0x09ec03f6); @@ -762,19 +768,19 @@ void upx_compiler_sanity_check(void) noexcept { assert_noexcept(get_le32_signed(d) == -50462977); assert_noexcept(get_le64(d) == 0xf8f9fafbfcfdfeffULL); assert_noexcept(get_le64_signed(d) == -506097522914230529LL); + static_assert(get_be24(d) == 0xfffefd); + static_assert(get_le24(d) == 0xfdfeff); #if defined(upx_is_constant_evaluated) + static_assert(get_be24_signed(d) == -259); + static_assert(get_le24_signed(d) == -131329); static_assert(get_be16(d) == 0xfffe); static_assert(get_be16_signed(d) == -2); - static_assert(get_be24(d) == 0xfffefd); - static_assert(get_be24_signed(d) == -259); static_assert(get_be32(d) == 0xfffefdfc); static_assert(get_be32_signed(d) == -66052); static_assert(get_be64(d) == 0xfffefdfcfbfaf9f8ULL); static_assert(get_be64_signed(d) == -283686952306184LL); static_assert(get_le16(d) == 0xfeff); static_assert(get_le16_signed(d) == -257); - static_assert(get_le24(d) == 0xfdfeff); - static_assert(get_le24_signed(d) == -131329); static_assert(get_le32(d) == 0xfcfdfeff); static_assert(get_le32_signed(d) == -50462977); static_assert(get_le64(d) == 0xf8f9fafbfcfdfeffULL); diff --git a/src/check/dt_cxxlib.cpp b/src/check/dt_cxxlib.cpp index 1192403e..9b831d00 100644 --- a/src/check/dt_cxxlib.cpp +++ b/src/check/dt_cxxlib.cpp @@ -35,82 +35,100 @@ // compile-time checks **************************************************************************/ -// need extra parenthesis because the C preprocessor does not understand C++ templates -ACC_COMPILE_TIME_ASSERT_HEADER((upx::is_same_all_v) ) -ACC_COMPILE_TIME_ASSERT_HEADER((upx::is_same_all_v) ) -ACC_COMPILE_TIME_ASSERT_HEADER((upx::is_same_all_v) ) -ACC_COMPILE_TIME_ASSERT_HEADER((!upx::is_same_all_v) ) -ACC_COMPILE_TIME_ASSERT_HEADER((!upx::is_same_all_v) ) -ACC_COMPILE_TIME_ASSERT_HEADER((!upx::is_same_all_v) ) +static_assert(upx::is_same_all_v); +static_assert(upx::is_same_all_v); +static_assert(upx::is_same_all_v); +static_assert(!upx::is_same_all_v); +static_assert(!upx::is_same_all_v); +static_assert(!upx::is_same_all_v); -ACC_COMPILE_TIME_ASSERT_HEADER((!upx::is_same_any_v) ) -ACC_COMPILE_TIME_ASSERT_HEADER((upx::is_same_any_v) ) -ACC_COMPILE_TIME_ASSERT_HEADER((upx::is_same_any_v) ) -ACC_COMPILE_TIME_ASSERT_HEADER((upx::is_same_any_v) ) -ACC_COMPILE_TIME_ASSERT_HEADER((!upx::is_same_any_v) ) -ACC_COMPILE_TIME_ASSERT_HEADER((!upx::is_same_any_v) ) -ACC_COMPILE_TIME_ASSERT_HEADER((!upx::is_same_any_v) ) +static_assert(!upx::is_same_any_v); +static_assert(upx::is_same_any_v); +static_assert(upx::is_same_any_v); +static_assert(upx::is_same_any_v); +static_assert(!upx::is_same_any_v); +static_assert(!upx::is_same_any_v); +static_assert(!upx::is_same_any_v); -ACC_COMPILE_TIME_ASSERT_HEADER((upx::is_same_any_v) ) -ACC_COMPILE_TIME_ASSERT_HEADER( - (upx::is_same_any_v) ) +static_assert(upx::is_same_any_v); +static_assert(upx::is_same_any_v); // TODO later: CHERI -ACC_COMPILE_TIME_ASSERT_HEADER( - (upx::is_same_any_v) ) +static_assert(upx::is_same_any_v); -ACC_COMPILE_TIME_ASSERT_HEADER(usizeof(int) == sizeof(int)) -ACC_COMPILE_TIME_ASSERT_HEADER(usizeof('a') == sizeof(char)) -ACC_COMPILE_TIME_ASSERT_HEADER(usizeof("") == 1) -ACC_COMPILE_TIME_ASSERT_HEADER(usizeof("a") == 2) -ACC_COMPILE_TIME_ASSERT_HEADER(usizeof("ab") == 3) -ACC_COMPILE_TIME_ASSERT_HEADER(usizeof(L'a') == sizeof(wchar_t)) -ACC_COMPILE_TIME_ASSERT_HEADER(usizeof(L"") == 1 * sizeof(wchar_t)) -ACC_COMPILE_TIME_ASSERT_HEADER(usizeof(L"a") == 2 * sizeof(wchar_t)) -ACC_COMPILE_TIME_ASSERT_HEADER(usizeof(L"ab") == 3 * sizeof(wchar_t)) -ACC_COMPILE_TIME_ASSERT_HEADER(usizeof(0) == sizeof(int)) -ACC_COMPILE_TIME_ASSERT_HEADER(usizeof(0L) == sizeof(long)) -ACC_COMPILE_TIME_ASSERT_HEADER(usizeof(0LL) == sizeof(long long)) -ACC_COMPILE_TIME_ASSERT_HEADER(usizeof(nullptr) == sizeof(void *)) -ACC_COMPILE_TIME_ASSERT_HEADER(usizeof(sizeof(0)) == sizeof(size_t)) -ACC_COMPILE_TIME_ASSERT_HEADER(usizeof(usizeof(0)) == sizeof(unsigned)) +static_assert(usizeof(int) == sizeof(int)); +static_assert(usizeof('a') == sizeof(char)); +static_assert(usizeof("") == 1); +static_assert(usizeof("a") == 2); +static_assert(usizeof("ab") == 3); +static_assert(usizeof(L'a') == sizeof(wchar_t)); +static_assert(usizeof(L"") == 1 * sizeof(wchar_t)); +static_assert(usizeof(L"a") == 2 * sizeof(wchar_t)); +static_assert(usizeof(L"ab") == 3 * sizeof(wchar_t)); +static_assert(usizeof(0) == sizeof(int)); +static_assert(usizeof(0L) == sizeof(long)); +static_assert(usizeof(0LL) == sizeof(long long)); +static_assert(usizeof(nullptr) == sizeof(void *)); +static_assert(usizeof(sizeof(0)) == sizeof(size_t)); +static_assert(usizeof(usizeof(0)) == sizeof(unsigned)); #if 0 // works, but may trigger clang/gcc warnings "-Wunused-value" -ACC_COMPILE_TIME_ASSERT_HEADER(usizeof((1LL, 1)) == sizeof(int)) -ACC_COMPILE_TIME_ASSERT_HEADER(usizeof((1, 1LL)) == sizeof(long long)) +static_assert(usizeof((1LL, 1)) == sizeof(int)); +static_assert(usizeof((1, 1LL)) == sizeof(long long)); #endif +static_assert(upx::min(1, 2) == 1); +static_assert(upx::min(1, 2) == 1); +static_assert(upx::min(1, 2) == 1); +static_assert(upx::min(1ll, 2ll) == 1); +static_assert(upx::max(1, 2) == 2); +static_assert(upx::max(1, 2) == 2); +static_assert(upx::max(1, 2) == 2); +static_assert(upx::max(1ll, 2ll) == 2); +static_assert(upx::wrapping_add(127, 2) == -127); +static_assert(upx::wrapping_add(32767, 2) == -32767); +static_assert(upx::wrapping_add(2147483647, 2) == -2147483647); +static_assert(upx::wrapping_add(9223372036854775807ll, 2ll) == -9223372036854775807ll); +static_assert(upx::wrapping_sub(-127, 2) == 127); +static_assert(upx::wrapping_sub(-32767, 2) == 32767); +static_assert(upx::wrapping_sub(-2147483647, 2) == 2147483647); +static_assert(upx::wrapping_sub(-9223372036854775807ll, 2ll) == 9223372036854775807ll); + namespace compile_time = upx::compile_time; -ACC_COMPILE_TIME_ASSERT_HEADER(compile_time::string_len("") == 0) -ACC_COMPILE_TIME_ASSERT_HEADER(compile_time::string_len("a") == 1) -ACC_COMPILE_TIME_ASSERT_HEADER(compile_time::string_len("ab") == 2) -ACC_COMPILE_TIME_ASSERT_HEADER(compile_time::string_len("abc") == 3) +static_assert(compile_time::string_len("") == 0); +static_assert(compile_time::string_len("a") == 1); +static_assert(compile_time::string_len("ab") == 2); +static_assert(compile_time::string_len("abc") == 3); -ACC_COMPILE_TIME_ASSERT_HEADER(compile_time::string_eq("", "")) -ACC_COMPILE_TIME_ASSERT_HEADER(!compile_time::string_eq("a", "")) -ACC_COMPILE_TIME_ASSERT_HEADER(!compile_time::string_eq("", "a")) -ACC_COMPILE_TIME_ASSERT_HEADER(compile_time::string_eq("abc", "abc")) -ACC_COMPILE_TIME_ASSERT_HEADER(!compile_time::string_eq("ab", "abc")) -ACC_COMPILE_TIME_ASSERT_HEADER(!compile_time::string_eq("abc", "ab")) +static_assert(compile_time::string_eq("", "")); +static_assert(!compile_time::string_eq("a", "")); +static_assert(!compile_time::string_eq("", "a")); +static_assert(compile_time::string_eq("abc", "abc")); +static_assert(!compile_time::string_eq("ab", "abc")); +static_assert(!compile_time::string_eq("abc", "ab")); -ACC_COMPILE_TIME_ASSERT_HEADER(!compile_time::string_lt("", "")) -ACC_COMPILE_TIME_ASSERT_HEADER(!compile_time::string_lt("a", "")) -ACC_COMPILE_TIME_ASSERT_HEADER(compile_time::string_lt("", "a")) -ACC_COMPILE_TIME_ASSERT_HEADER(!compile_time::string_lt("abc", "abc")) -ACC_COMPILE_TIME_ASSERT_HEADER(compile_time::string_lt("ab", "abc")) -ACC_COMPILE_TIME_ASSERT_HEADER(!compile_time::string_lt("abc", "ab")) -ACC_COMPILE_TIME_ASSERT_HEADER(!compile_time::string_lt("abc", "aba")) -ACC_COMPILE_TIME_ASSERT_HEADER(compile_time::string_lt("abc", "abz")) +static_assert(!compile_time::string_lt("", "")); +static_assert(!compile_time::string_lt("a", "")); +static_assert(compile_time::string_lt("", "a")); +static_assert(!compile_time::string_lt("abc", "abc")); +static_assert(compile_time::string_lt("ab", "abc")); +static_assert(!compile_time::string_lt("abc", "ab")); +static_assert(!compile_time::string_lt("abc", "aba")); +static_assert(compile_time::string_lt("abc", "abz")); -ACC_COMPILE_TIME_ASSERT_HEADER(compile_time::string_ne("abc", "abz")) -ACC_COMPILE_TIME_ASSERT_HEADER(!compile_time::string_gt("abc", "abz")) -ACC_COMPILE_TIME_ASSERT_HEADER(!compile_time::string_ge("abc", "abz")) -ACC_COMPILE_TIME_ASSERT_HEADER(compile_time::string_le("abc", "abz")) +static_assert(compile_time::string_ne("abc", "abz")); +static_assert(!compile_time::string_gt("abc", "abz")); +static_assert(!compile_time::string_ge("abc", "abz")); +static_assert(compile_time::string_le("abc", "abz")); -ACC_COMPILE_TIME_ASSERT_HEADER(compile_time::mem_eq((const char *) nullptr, nullptr, 0)) -ACC_COMPILE_TIME_ASSERT_HEADER(compile_time::mem_eq((const byte *) nullptr, nullptr, 0)) -ACC_COMPILE_TIME_ASSERT_HEADER(compile_time::mem_eq("", "", 0)) -ACC_COMPILE_TIME_ASSERT_HEADER(compile_time::mem_eq("abc", "abc", 3)) -ACC_COMPILE_TIME_ASSERT_HEADER(!compile_time::mem_eq("abc", "abz", 3)) +static_assert(compile_time::mem_eq((const char *) nullptr, nullptr, 0)); +static_assert(compile_time::mem_eq((const byte *) nullptr, nullptr, 0)); +static_assert(compile_time::mem_eq("", "", 0)); +static_assert(compile_time::mem_eq("abc", "abc", 3)); +static_assert(!compile_time::mem_eq("abc", "abz", 3)); + +static_assert(compile_time::bswap16(0x0102) == 0x0201); +static_assert(compile_time::bswap32(0x01020304) == 0x04030201); +static_assert(compile_time::bswap64(0x0102030405060708ull) == 0x0807060504030201ull); /************************************************************************* // diff --git a/src/conf.h b/src/conf.h index 094b5497..6d9c6979 100644 --- a/src/conf.h +++ b/src/conf.h @@ -47,18 +47,18 @@ // reserve name "upx" for namespace namespace upx {} -ACC_COMPILE_TIME_ASSERT_HEADER(CHAR_BIT == 8) -ACC_COMPILE_TIME_ASSERT_HEADER(sizeof(short) == 2) -ACC_COMPILE_TIME_ASSERT_HEADER(sizeof(int) == 4) -ACC_COMPILE_TIME_ASSERT_HEADER(sizeof(long long) == 8) +static_assert(CHAR_BIT == 8); +static_assert(sizeof(short) == 2); +static_assert(sizeof(int) == 4); +static_assert(sizeof(long long) == 8); // check sane compiler mandatory flags -ACC_COMPILE_TIME_ASSERT_HEADER(-1 == ~0) // two's complement - see http://wg21.link/P0907R4 -ACC_COMPILE_TIME_ASSERT_HEADER(0u - 1 == ~0u) // two's complement - see http://wg21.link/P0907R4 -ACC_COMPILE_TIME_ASSERT_HEADER((1u << 31) << 1 == 0) -ACC_COMPILE_TIME_ASSERT_HEADER(((int) (1u << 31)) >> 31 == -1) // arithmetic right shift -ACC_COMPILE_TIME_ASSERT_HEADER((-1) >> 31 == -1) // arithmetic right shift -ACC_COMPILE_TIME_ASSERT_HEADER(CHAR_MAX == 255) // -funsigned-char -ACC_COMPILE_TIME_ASSERT_HEADER((char) (-1) == 255) +static_assert(-1 == ~0); // two's complement - see http://wg21.link/P0907R4 +static_assert(0u - 1 == ~0u); // two's complement - see http://wg21.link/P0907R4 +static_assert((1u << 31) << 1 == 0); +static_assert(((int) (1u << 31)) >> 31 == -1); // arithmetic right shift +static_assert((-1) >> 31 == -1); // arithmetic right shift +static_assert(CHAR_MAX == 255); // -funsigned-char +static_assert((char) (-1) == 255); // enable some more strict warnings for Git developer builds #if defined(UPX_CONFIG_DISABLE_WSTRICT) && (UPX_CONFIG_DISABLE_WSTRICT + 0 == 0) @@ -82,6 +82,12 @@ ACC_COMPILE_TIME_ASSERT_HEADER((char) (-1) == 255) #endif // UPX_CONFIG_DISABLE_WERROR #endif // UPX_CONFIG_DISABLE_WSTRICT +#if __cplusplus >= 202002L // C++20 +#define upx_is_constant_evaluated std::is_constant_evaluated +#elif __has_builtin(__builtin_is_constant_evaluated) // clang-9, gcc-9 +#define upx_is_constant_evaluated __builtin_is_constant_evaluated +#endif + // multithreading (UPX currently does not use multithreading) #if (WITH_THREADS) #define upx_thread_local thread_local @@ -121,12 +127,6 @@ inline constexpr bool upx_is_integral_v = upx_is_integral::value; #define upx_alignas_max alignas(std::max_align_t) #endif -#if __cplusplus >= 202002L -#define upx_is_constant_evaluated std::is_constant_evaluated -#elif __has_builtin(__builtin_is_constant_evaluated) -#define upx_is_constant_evaluated __builtin_is_constant_evaluated -#endif - /************************************************************************* // core **************************************************************************/ @@ -165,7 +165,7 @@ typedef unsigned char uchar; // upx_charptr_unit_type is some opaque type with sizeof(type) == 1 //// typedef char upx_charptr_unit_type; // also works struct alignas(1) upx_charptr_unit_type final { char hidden__; }; -ACC_COMPILE_TIME_ASSERT_HEADER(sizeof(upx_charptr_unit_type) == 1) +static_assert(sizeof(upx_charptr_unit_type) == 1); // using the system off_t was a bad idea even back in 199x... typedef upx_int64_t upx_off_t; diff --git a/src/util/cxxlib.h b/src/util/cxxlib.h index b735aad1..6026c686 100644 --- a/src/util/cxxlib.h +++ b/src/util/cxxlib.h @@ -220,6 +220,20 @@ forceinline constexpr T umax(const T &a, const T &b) noexcept { return a < b ? b : a; } +template +forceinline constexpr T wrapping_add(const T &a, const T &b) noexcept { + static_assert(std::is_integral_v); + typedef std::make_unsigned_t U; + return T(U(a) + U(b)); +} + +template +forceinline constexpr T wrapping_sub(const T &a, const T &b) noexcept { + static_assert(std::is_integral_v); + typedef std::make_unsigned_t U; + return T(U(a) - U(b)); +} + /************************************************************************* // util **************************************************************************/ @@ -235,15 +249,19 @@ template forceinline constexpr Result ptr_static_cast(From *ptr) noexcept { static_assert(std::is_pointer_v); static_assert(!std::is_const_v >); // enforce same constness + // don't cast through "void *" if types already match + typedef std::conditional_t, Result, void *> VoidPtr; // NOLINTNEXTLINE(bugprone-multi-level-implicit-pointer-conversion) - return static_cast(static_cast(ptr)); + return static_cast(static_cast(ptr)); } template forceinline constexpr Result ptr_static_cast(const From *ptr) noexcept { static_assert(std::is_pointer_v); static_assert(std::is_const_v >); // required + // don't cast through "void *" if types already match + typedef std::conditional_t, Result, const void *> VoidPtr; // NOLINTNEXTLINE(bugprone-multi-level-implicit-pointer-conversion) - return static_cast(static_cast(ptr)); + return static_cast(static_cast(ptr)); } #if WITH_THREADS @@ -335,25 +353,197 @@ protected: UPX_CXX_DISABLE_COPY_MOVE(noncopyable) }; +/************************************************************************* +// compile_time +**************************************************************************/ + namespace compile_time { -constexpr std::size_t string_len(const char *a) { return *a == '\0' ? 0 : 1 + string_len(a + 1); } -constexpr bool string_eq(const char *a, const char *b) { + +constexpr std::size_t string_len(const char *a) noexcept { + return *a == '\0' ? 0 : 1 + string_len(a + 1); +} +constexpr bool string_eq(const char *a, const char *b) noexcept { return *a == *b && (*a == '\0' || string_eq(a + 1, b + 1)); } -constexpr bool string_lt(const char *a, const char *b) { +constexpr bool string_lt(const char *a, const char *b) noexcept { return (uchar) *a < (uchar) *b || (*a != '\0' && *a == *b && string_lt(a + 1, b + 1)); } -constexpr bool string_ne(const char *a, const char *b) { return !string_eq(a, b); } -constexpr bool string_gt(const char *a, const char *b) { return string_lt(b, a); } -constexpr bool string_le(const char *a, const char *b) { return !string_lt(b, a); } -constexpr bool string_ge(const char *a, const char *b) { return !string_lt(a, b); } +forceinline constexpr bool string_ne(const char *a, const char *b) noexcept { + return !string_eq(a, b); +} +forceinline constexpr bool string_gt(const char *a, const char *b) noexcept { + return string_lt(b, a); +} +forceinline constexpr bool string_le(const char *a, const char *b) noexcept { + return !string_lt(b, a); +} +forceinline constexpr bool string_ge(const char *a, const char *b) noexcept { + return !string_lt(a, b); +} -constexpr bool mem_eq(const char *a, const char *b, std::size_t n) { +constexpr bool mem_eq(const char *a, const char *b, std::size_t n) noexcept { return n == 0 || (*a == *b && mem_eq(a + 1, b + 1, n - 1)); } -constexpr bool mem_eq(const unsigned char *a, const unsigned char *b, std::size_t n) { +constexpr bool mem_eq(const unsigned char *a, const unsigned char *b, std::size_t n) noexcept { return n == 0 || (*a == *b && mem_eq(a + 1, b + 1, n - 1)); } + +forceinline constexpr upx_uint16_t bswap16(upx_uint16_t v) noexcept { + return ((v >> 8) & 0xff) | ((v & 0xff) << 8); +} +forceinline constexpr upx_uint32_t bswap32(upx_uint32_t v) noexcept { + return ((v >> 24) & 0xff) | ((v >> 8) & 0xff00) | ((v & 0xff00) << 8) | ((v & 0xff) << 24); +} +forceinline constexpr upx_uint64_t bswap64(upx_uint64_t v) noexcept { + return (upx_uint64_t(bswap32(upx_uint32_t(v))) << 32) | bswap32(upx_uint32_t(v >> 32)); +} + +forceinline constexpr upx_uint16_t get_be16(const byte *p) noexcept { + typedef upx_uint16_t U; + return (U(p[0]) << 8) | (U(p[1]) << 0); +} +forceinline constexpr upx_uint32_t get_be24(const byte *p) noexcept { + typedef upx_uint32_t U; + return (U(p[0]) << 16) | (U(p[1]) << 8) | (U(p[2]) << 0); +} +forceinline constexpr upx_uint32_t get_be32(const byte *p) noexcept { + typedef upx_uint32_t U; + return (U(p[0]) << 24) | (U(p[1]) << 16) | (U(p[2]) << 8) | (U(p[3]) << 0); +} +forceinline constexpr upx_uint64_t get_be64(const byte *p) noexcept { + typedef upx_uint64_t U; + return (U(p[0]) << 56) | (U(p[1]) << 48) | (U(p[2]) << 40) | (U(p[3]) << 32) | (U(p[4]) << 24) | + (U(p[5]) << 16) | (U(p[6]) << 8) | (U(p[7]) << 0); +} + +forceinline constexpr void set_be16(byte *p, upx_uint16_t v) noexcept { + p[0] = byte((v >> 8) & 0xff); + p[1] = byte((v >> 0) & 0xff); +} +forceinline constexpr void set_be24(byte *p, upx_uint32_t v) noexcept { + p[0] = byte((v >> 16) & 0xff); + p[1] = byte((v >> 8) & 0xff); + p[2] = byte((v >> 0) & 0xff); +} +forceinline constexpr void set_be32(byte *p, upx_uint32_t v) noexcept { + p[0] = byte((v >> 24) & 0xff); + p[1] = byte((v >> 16) & 0xff); + p[2] = byte((v >> 8) & 0xff); + p[3] = byte((v >> 0) & 0xff); +} +forceinline constexpr void set_be64(byte *p, upx_uint64_t v) noexcept { + p[0] = byte((v >> 56) & 0xff); + p[1] = byte((v >> 48) & 0xff); + p[2] = byte((v >> 40) & 0xff); + p[3] = byte((v >> 32) & 0xff); + p[4] = byte((v >> 24) & 0xff); + p[5] = byte((v >> 16) & 0xff); + p[6] = byte((v >> 8) & 0xff); + p[7] = byte((v >> 0) & 0xff); +} + +forceinline constexpr upx_uint16_t get_le16(const byte *p) noexcept { + typedef upx_uint16_t U; + return (U(p[0]) << 0) | (U(p[1]) << 8); +} +forceinline constexpr upx_uint32_t get_le24(const byte *p) noexcept { + typedef upx_uint32_t U; + return (U(p[0]) << 0) | (U(p[1]) << 8) | (U(p[2]) << 16); +} +forceinline constexpr upx_uint32_t get_le32(const byte *p) noexcept { + typedef upx_uint32_t U; + return (U(p[0]) << 0) | (U(p[1]) << 8) | (U(p[2]) << 16) | (U(p[3]) << 24); +} +forceinline constexpr upx_uint64_t get_le64(const byte *p) noexcept { + typedef upx_uint64_t U; + return (U(p[0]) << 0) | (U(p[1]) << 8) | (U(p[2]) << 16) | (U(p[3]) << 24) | (U(p[4]) << 32) | + (U(p[5]) << 40) | (U(p[6]) << 48) | (U(p[7]) << 56); +} + +forceinline constexpr void set_le16(byte *p, upx_uint16_t v) noexcept { + p[0] = byte((v >> 0) & 0xff); + p[1] = byte((v >> 8) & 0xff); +} +forceinline constexpr void set_le32(byte *p, upx_uint32_t v) noexcept { + p[0] = byte((v >> 0) & 0xff); + p[1] = byte((v >> 8) & 0xff); + p[2] = byte((v >> 16) & 0xff); + p[3] = byte((v >> 24) & 0xff); +} +forceinline constexpr void set_le24(byte *p, upx_uint32_t v) noexcept { + p[0] = byte((v >> 0) & 0xff); + p[1] = byte((v >> 8) & 0xff); + p[2] = byte((v >> 16) & 0xff); +} +forceinline constexpr void set_le64(byte *p, upx_uint64_t v) noexcept { + p[0] = byte((v >> 0) & 0xff); + p[1] = byte((v >> 8) & 0xff); + p[2] = byte((v >> 16) & 0xff); + p[3] = byte((v >> 24) & 0xff); + p[4] = byte((v >> 32) & 0xff); + p[5] = byte((v >> 40) & 0xff); + p[6] = byte((v >> 48) & 0xff); + p[7] = byte((v >> 56) & 0xff); +} + +forceinline constexpr upx_uint16_t get_ne16(const byte *p) noexcept { +#if (ACC_ABI_BIG_ENDIAN) + return get_be16(p); +#else + return get_le16(p); +#endif +} +forceinline constexpr upx_uint32_t get_ne24(const byte *p) noexcept { +#if (ACC_ABI_BIG_ENDIAN) + return get_be24(p); +#else + return get_le24(p); +#endif +} +forceinline constexpr upx_uint32_t get_ne32(const byte *p) noexcept { +#if (ACC_ABI_BIG_ENDIAN) + return get_be32(p); +#else + return get_le32(p); +#endif +} +forceinline constexpr upx_uint64_t get_ne64(const byte *p) noexcept { +#if (ACC_ABI_BIG_ENDIAN) + return get_be64(p); +#else + return get_le64(p); +#endif +} + +forceinline constexpr void set_ne16(byte *p, upx_uint16_t v) noexcept { +#if (ACC_ABI_BIG_ENDIAN) + set_be16(p, v); +#else + set_le16(p, v); +#endif +} +forceinline constexpr void set_ne24(byte *p, upx_uint32_t v) noexcept { +#if (ACC_ABI_BIG_ENDIAN) + set_be24(p, v); +#else + set_le24(p, v); +#endif +} +forceinline constexpr void set_ne32(byte *p, upx_uint32_t v) noexcept { +#if (ACC_ABI_BIG_ENDIAN) + set_be32(p, v); +#else + set_le32(p, v); +#endif +} +forceinline constexpr void set_ne64(byte *p, upx_uint64_t v) noexcept { +#if (ACC_ABI_BIG_ENDIAN) + set_be64(p, v); +#else + set_le64(p, v); +#endif +} + } // namespace compile_time /*************************************************************************