1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-21 18:22:33 +01:00

Implement fmt::ensure (assert-like with formatted message) + fmt::tie

Arguments should be provided via fmt::tie() due to some limitations.
Allow to specify simple message (non-formatting) for plain ::ensure().
Remove redundant function for narrow error.
This commit is contained in:
Nekotekina 2021-06-09 19:05:25 +03:00
parent 766cc2d42f
commit 696be6aacd
4 changed files with 76 additions and 17 deletions

View File

@ -313,17 +313,10 @@ void fmt_class_string<src_loc>::format(std::string& out, u64 arg)
namespace fmt
{
[[noreturn]] void raw_verify_error(const src_loc& loc)
[[noreturn]] void raw_verify_error(const src_loc& loc, const char8_t* msg)
{
std::string out{"Verification failed"};
fmt::append(out, "%s", loc);
thread_ctrl::emergency_exit(out);
}
[[noreturn]] void raw_narrow_error(const src_loc& loc)
{
std::string out{"Narrowing error"};
fmt::append(out, "%s", loc);
std::string out;
fmt::append(out, "%s%s", msg ? msg : u8"Verification failed", loc);
thread_ctrl::emergency_exit(out);
}

View File

@ -293,4 +293,66 @@ namespace fmt
template <typename CharT, usz N, typename... Args>
throw_exception(const CharT(&)[N], const Args&...) -> throw_exception<CharT, N, Args...>;
// Helper template: pack format variables
template <typename Arg = void, typename... Args>
struct tie
{
// Universal reference
std::add_rvalue_reference_t<Arg> arg;
tie<Args...> next;
// Store only references, unveil op is postponed
tie(Arg&& arg, Args&&... args) noexcept
: arg(std::forward<Arg>(arg))
, next(std::forward<Args>(args)...)
{
}
using type = std::remove_cvref_t<Arg>;
// Storage for fmt_unveil (deferred initialization)
decltype(fmt_unveil<type>::get(std::declval<Arg>())) value;
void init(u64 to[])
{
value = fmt_unveil<type>::get(arg);
to[0] = value;
next.init(to + 1);
}
};
template <>
struct tie<void>
{
void init(u64 to[]) const
{
// Isn't really null terminated, this value has no meaning
to[0] = 0;
}
};
template <typename... Args>
tie(Args&&... args) -> tie<Args...>;
// Ensure with formatting
template <typename T, typename CharT, usz N, typename... Args>
decltype(auto) ensure(T&& arg, const CharT(&fmt)[N], tie<Args...> args,
u32 line = __builtin_LINE(),
u32 col = __builtin_COLUMN(),
const char* file = __builtin_FILE(),
const char* func = __builtin_FUNCTION()) noexcept
{
if (std::forward<T>(arg)) [[likely]]
{
return std::forward<T>(arg);
}
// Prepare u64 array
u64 data[sizeof...(Args) + 1];
args.init(data);
raw_throw_exception({line, col, file, func}, reinterpret_cast<const char*>(fmt), type_info_v<std::remove_cvref_t<Args>...>, +data);
}
}

View File

@ -419,7 +419,7 @@ int main(int argc, char** argv)
}
#endif
ensure(thread_ctrl::is_main());
ensure(thread_ctrl::is_main(), "Not main thread");
// Initialize TSC freq (in case it isn't)
static_cast<void>(utils::get_tsc_freq());

View File

@ -802,6 +802,12 @@ struct const_str_t<umax>
const char* chars2;
};
const_str_t()
: size(0)
, chars(nullptr)
{
}
template <usz N>
constexpr const_str_t(const char8_t(&a)[N])
: size(N - 1)
@ -845,12 +851,11 @@ struct src_loc
namespace fmt
{
[[noreturn]] void raw_verify_error(const src_loc& loc);
[[noreturn]] void raw_narrow_error(const src_loc& loc);
[[noreturn]] void raw_verify_error(const src_loc& loc, const char8_t* msg);
}
template <typename T>
constexpr decltype(auto) ensure(T&& arg,
constexpr decltype(auto) ensure(T&& arg, const_str msg = const_str(),
u32 line = __builtin_LINE(),
u32 col = __builtin_COLUMN(),
const char* file = __builtin_FILE(),
@ -861,7 +866,7 @@ constexpr decltype(auto) ensure(T&& arg,
return std::forward<T>(arg);
}
fmt::raw_verify_error({line, col, file, func});
fmt::raw_verify_error({line, col, file, func}, msg);
}
// narrow() function details
@ -946,8 +951,7 @@ template <typename To = void, typename From, typename = decltype(static_cast<To>
// Narrow check
if (narrow_impl<From, To>::test(value)) [[unlikely]]
{
// Pack value as formatting argument
fmt::raw_narrow_error({line, col, file, func});
fmt::raw_verify_error({line, col, file, func}, u8"Narrowing error");
}
return static_cast<To>(value);