mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-03-29 22:20:48 +00:00
util/types.hpp: Rewrite narrow<>
This commit is contained in:
parent
fce07bbeab
commit
191e132c6c
@ -493,7 +493,7 @@ namespace rsx
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
fmt::throw_exception("RSXVertexData::GetTypeSize: Bad vertex data type (%d)!", static_cast<u8>(type));
|
fmt::throw_exception("Bad vertex data type (%d)!", static_cast<u8>(type));
|
||||||
}
|
}
|
||||||
|
|
||||||
void tiled_region::write(const void *src, u32 width, u32 height, u32 pitch)
|
void tiled_region::write(const void *src, u32 width, u32 height, u32 pitch)
|
||||||
@ -552,7 +552,7 @@ namespace rsx
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
::narrow(tile->comp);
|
fmt::throw_exception("Bad tile compression type (%d)!", tile->comp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -603,7 +603,7 @@ namespace rsx
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
::narrow(tile->comp);
|
fmt::throw_exception("Bad tile compression type (%d)!", tile->comp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -976,85 +976,33 @@ constexpr decltype(auto) ensure(T&& arg, F&& pred, const_str msg = const_str(),
|
|||||||
fmt::raw_verify_error(src_loc, msg, 0);
|
fmt::raw_verify_error(src_loc, msg, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// narrow() function details
|
template <typename To, typename From> requires (std::is_integral_v<decltype(std::declval<To>() + std::declval<From>())>)
|
||||||
template <typename From, typename To = void, typename = void>
|
|
||||||
struct narrow_impl
|
|
||||||
{
|
|
||||||
// Temporarily (diagnostic)
|
|
||||||
static_assert(std::is_void_v<To>, "narrow_impl<> specialization not found");
|
|
||||||
|
|
||||||
// Returns true if value cannot be represented in type To
|
|
||||||
static constexpr bool test(const From&)
|
|
||||||
{
|
|
||||||
// Unspecialized cases (including cast to void) always considered narrowing
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Unsigned to unsigned narrowing
|
|
||||||
template <typename From, typename To>
|
|
||||||
struct narrow_impl<From, To, std::enable_if_t<std::is_unsigned_v<From> && std::is_unsigned_v<To>>>
|
|
||||||
{
|
|
||||||
static constexpr bool test(const From& value)
|
|
||||||
{
|
|
||||||
return sizeof(To) < sizeof(From) && static_cast<To>(value) != value;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Signed to signed narrowing
|
|
||||||
template <typename From, typename To>
|
|
||||||
struct narrow_impl<From, To, std::enable_if_t<std::is_signed_v<From> && std::is_signed_v<To>>>
|
|
||||||
{
|
|
||||||
static constexpr bool test(const From& value)
|
|
||||||
{
|
|
||||||
return sizeof(To) < sizeof(From) && static_cast<To>(value) != value;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Unsigned to signed narrowing
|
|
||||||
template <typename From, typename To>
|
|
||||||
struct narrow_impl<From, To, std::enable_if_t<std::is_unsigned_v<From> && std::is_signed_v<To>>>
|
|
||||||
{
|
|
||||||
static constexpr bool test(const From& value)
|
|
||||||
{
|
|
||||||
return sizeof(To) <= sizeof(From) && value > (static_cast<std::make_unsigned_t<To>>(-1) >> 1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Signed to unsigned narrowing (I)
|
|
||||||
template <typename From, typename To>
|
|
||||||
struct narrow_impl<From, To, std::enable_if_t<std::is_signed_v<From> && std::is_unsigned_v<To> && sizeof(To) >= sizeof(From)>>
|
|
||||||
{
|
|
||||||
static constexpr bool test(const From& value)
|
|
||||||
{
|
|
||||||
return value < static_cast<From>(0);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Signed to unsigned narrowing (II)
|
|
||||||
template <typename From, typename To>
|
|
||||||
struct narrow_impl<From, To, std::enable_if_t<std::is_signed_v<From> && std::is_unsigned_v<To> && sizeof(To) < sizeof(From)>>
|
|
||||||
{
|
|
||||||
static constexpr bool test(const From& value)
|
|
||||||
{
|
|
||||||
return static_cast<std::make_unsigned_t<From>>(value) > static_cast<To>(-1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Simple type enabled (TODO: allow for To as well)
|
|
||||||
template <typename From, typename To>
|
|
||||||
struct narrow_impl<From, To, std::enable_if_t<!std::is_same_v<std::common_type_t<From>, From>>>
|
|
||||||
: narrow_impl<std::common_type_t<From>, To>
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename To = void, typename From, typename = decltype(static_cast<To>(std::declval<From>()))>
|
|
||||||
[[nodiscard]] constexpr To narrow(const From& value, std::source_location src_loc = std::source_location::current())
|
[[nodiscard]] constexpr To narrow(const From& value, std::source_location src_loc = std::source_location::current())
|
||||||
{
|
{
|
||||||
// Narrow check
|
// Narrow check
|
||||||
if (narrow_impl<From, To>::test(value)) [[unlikely]]
|
using CommonFrom = std::common_type_t<From>;
|
||||||
|
using CommonTo = std::common_type_t<To>;
|
||||||
|
|
||||||
|
using UnFrom = std::make_unsigned_t<CommonFrom>;
|
||||||
|
using UnTo = std::make_unsigned_t<CommonTo>;
|
||||||
|
|
||||||
|
constexpr bool is_from_signed = std::is_signed_v<CommonFrom>;
|
||||||
|
constexpr bool is_to_signed = std::is_signed_v<CommonTo>;
|
||||||
|
|
||||||
|
constexpr auto from_mask = is_from_signed > is_to_signed ? UnFrom{umax} >> 1 : UnFrom{umax};
|
||||||
|
constexpr auto to_mask = is_to_signed > is_from_signed ? UnTo{umax} >> 1 : UnTo{umax};
|
||||||
|
|
||||||
|
constexpr auto mask = ~(from_mask & to_mask);
|
||||||
|
|
||||||
|
// Signed to unsigned always require test
|
||||||
|
// Otherwise, this is bit-wise narrowing or conversion between types of different signedness of the same size
|
||||||
|
if constexpr (is_from_signed > is_to_signed || to_mask < from_mask)
|
||||||
{
|
{
|
||||||
fmt::raw_verify_error(src_loc, u8"Narrowing error", +value);
|
// Try to optimize test if both are of the same signedness
|
||||||
|
if (is_from_signed != is_to_signed ? !!(value & mask) : static_cast<CommonTo>(value) != value) [[unlikely]]
|
||||||
|
{
|
||||||
|
fmt::raw_verify_error(src_loc, u8"Narrowing error", +value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return static_cast<To>(value);
|
return static_cast<To>(value);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user