From 696be6aacd9bdb044ef4a521795add790aadcd32 Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Wed, 9 Jun 2021 19:05:25 +0300 Subject: [PATCH] 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. --- Utilities/StrFmt.cpp | 13 +++------- Utilities/StrFmt.h | 62 ++++++++++++++++++++++++++++++++++++++++++++ rpcs3/main.cpp | 2 +- rpcs3/util/types.hpp | 16 +++++++----- 4 files changed, 76 insertions(+), 17 deletions(-) diff --git a/Utilities/StrFmt.cpp b/Utilities/StrFmt.cpp index c66d3cad01..082ae05339 100644 --- a/Utilities/StrFmt.cpp +++ b/Utilities/StrFmt.cpp @@ -313,17 +313,10 @@ void fmt_class_string::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); } diff --git a/Utilities/StrFmt.h b/Utilities/StrFmt.h index dae5725119..e3bb916753 100644 --- a/Utilities/StrFmt.h +++ b/Utilities/StrFmt.h @@ -293,4 +293,66 @@ namespace fmt template throw_exception(const CharT(&)[N], const Args&...) -> throw_exception; + + // Helper template: pack format variables + template + struct tie + { + // Universal reference + std::add_rvalue_reference_t arg; + + tie next; + + // Store only references, unveil op is postponed + tie(Arg&& arg, Args&&... args) noexcept + : arg(std::forward(arg)) + , next(std::forward(args)...) + { + } + + using type = std::remove_cvref_t; + + // Storage for fmt_unveil (deferred initialization) + decltype(fmt_unveil::get(std::declval())) value; + + void init(u64 to[]) + { + value = fmt_unveil::get(arg); + to[0] = value; + next.init(to + 1); + } + }; + + template <> + struct tie + { + void init(u64 to[]) const + { + // Isn't really null terminated, this value has no meaning + to[0] = 0; + } + }; + + template + tie(Args&&... args) -> tie; + + // Ensure with formatting + template + decltype(auto) ensure(T&& arg, const CharT(&fmt)[N], tie args, + u32 line = __builtin_LINE(), + u32 col = __builtin_COLUMN(), + const char* file = __builtin_FILE(), + const char* func = __builtin_FUNCTION()) noexcept + { + if (std::forward(arg)) [[likely]] + { + return std::forward(arg); + } + + // Prepare u64 array + u64 data[sizeof...(Args) + 1]; + args.init(data); + + raw_throw_exception({line, col, file, func}, reinterpret_cast(fmt), type_info_v...>, +data); + } } diff --git a/rpcs3/main.cpp b/rpcs3/main.cpp index 3c06b26a1b..859d0fc2a6 100644 --- a/rpcs3/main.cpp +++ b/rpcs3/main.cpp @@ -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(utils::get_tsc_freq()); diff --git a/rpcs3/util/types.hpp b/rpcs3/util/types.hpp index 736236a785..e814bb2bf5 100644 --- a/rpcs3/util/types.hpp +++ b/rpcs3/util/types.hpp @@ -802,6 +802,12 @@ struct const_str_t const char* chars2; }; + const_str_t() + : size(0) + , chars(nullptr) + { + } + template 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 -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(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 // Narrow check if (narrow_impl::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(value);