From 2af7a047d249bc3dd3f83376d48154b4b2d1c32a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Wed, 29 Jan 2025 10:04:51 +0100 Subject: [PATCH] HLE logging; Use function metadata to decide the type for logging the return type. --- Common/CommonTypes.h | 4 ++++ Core/HLE/HLE.cpp | 43 +++++++++++++++++++++++------------ Core/HLE/HLE.h | 36 +++++++++++++++-------------- Core/HLE/sceGe.cpp | 2 +- GPU/Vulkan/DrawEngineVulkan.h | 9 +------- 5 files changed, 53 insertions(+), 41 deletions(-) diff --git a/Common/CommonTypes.h b/Common/CommonTypes.h index 2fc1451c0b..41045019ae 100644 --- a/Common/CommonTypes.h +++ b/Common/CommonTypes.h @@ -24,6 +24,8 @@ #if defined(_MSC_VER) +#define NO_INLINE __declspec(noinline) + typedef unsigned __int8 u8; typedef unsigned __int16 u16; typedef unsigned __int32 u32; @@ -36,6 +38,8 @@ typedef signed __int64 s64; #else +#define NO_INLINE __attribute__((noinline)) + #ifdef __SWITCH__ // Some HID conflicts #define KEY_UP PKEY_UP diff --git a/Core/HLE/HLE.cpp b/Core/HLE/HLE.cpp index b3aaf69c51..a8775a1534 100644 --- a/Core/HLE/HLE.cpp +++ b/Core/HLE/HLE.cpp @@ -982,7 +982,7 @@ void hleLeave() { } // else warn? } -void hleDoLogInternal(Log t, LogLevel level, u64 res, const char *file, int line, const char *reportTag, char retmask, const char *reason, const char *formatted_reason) { +void hleDoLogInternal(Log t, LogLevel level, u64 res, const char *file, int line, const char *reportTag, const char *reason, const char *formatted_reason) { char formatted_args[2048]; const char *funcName = "?"; u32 funcFlags = 0; @@ -995,6 +995,7 @@ void hleDoLogInternal(Log t, LogLevel level, u64 res, const char *file, int line const HLEFunction *hleFunc = g_stack[g_stackSize - 1]; + char retmask = hleFunc->retmask; if (stackSize) { _dbg_assert_(hleFunc->argmask != nullptr); @@ -1007,35 +1008,47 @@ void hleDoLogInternal(Log t, LogLevel level, u64 res, const char *file, int line truncate_cpy(formatted_args, "...N/A..."); } - // This acts as an override (for error returns which are usually hex.) - if (retmask == '\0') - retmask = hleFunc->retmask; - funcName = hleFunc->name; funcFlags = hleFunc->flags; } else { - strcpy(formatted_args, "?"); + formatted_args[0] = '?'; + formatted_args[1] = '\0'; } const char *fmt; - if (retmask == 'x') { - fmt = "%s%08llx=%s(%s)%s"; + switch (retmask) { + case 'x': // Truncate the high bits of the result (from any sign extension.) res = (u32)res; - } else if (retmask == 'i' || retmask == 'I') { + fmt = "%s%08llx=%s(%s)%s"; + break; + case 'i': + case 'I': fmt = "%s%lld=%s(%s)%s"; - } else if (retmask == 'f') { + break; + case 'f': // TODO: For now, floats are just shown as bits. - fmt = "%s%08x=%s(%s)%s"; - } else { + fmt = "%s%08llx=%s(%s)%s"; + break; + case 'v': + // Void. Return value should not be shown. + fmt = "%s=%s(%s)%s"; + break; + default: _dbg_assert_msg_(false, "Invalid return format: %c", retmask); fmt = "%s%08llx=%s(%s)%s"; + break; } - const char *kernelFlag = (funcFlags & HLE_KERNEL_SYSCALL) != 0 ? "K " : ""; - GenericLog(level, t, file, line, fmt, kernelFlag, res, funcName, formatted_args, formatted_reason); + const char *kernelFlag = (funcFlags & HLE_KERNEL_SYSCALL) ? "K " : ""; + if (retmask != 'v') { + GenericLog(level, t, file, line, fmt, kernelFlag, res, funcName, formatted_args, formatted_reason); + } else { + // Skipping the res argument for this format string. + GenericLog(level, t, file, line, fmt, kernelFlag, funcName, formatted_args, formatted_reason); + } - if (reportTag != nullptr) { + if (reportTag) { // A blank string means always log, not just once. if (reportTag[0] == '\0' || Reporting::ShouldLogNTimes(reportTag, 1)) { // Here we want the original key, so that different args, etc. group together. diff --git a/Core/HLE/HLE.h b/Core/HLE/HLE.h index fdbfd2eb28..323097f453 100644 --- a/Core/HLE/HLE.h +++ b/Core/HLE/HLE.h @@ -172,14 +172,15 @@ const HLEFunction *GetSyscallFuncPointer(MIPSOpcode op); // For jit, takes arg: const HLEFunction * void *GetQuickSyscallFunc(MIPSOpcode op); -void hleDoLogInternal(Log t, LogLevel level, u64 res, const char *file, int line, const char *reportTag, char retmask, const char *reason, const char *formatted_reason); +void hleDoLogInternal(Log t, LogLevel level, u64 res, const char *file, int line, const char *reportTag, const char *reason, const char *formatted_reason); template [[nodiscard]] #ifdef __GNUC__ -__attribute__((format(printf, 8, 9))) +__attribute__((format(printf, 7, 8))) #endif -T hleDoLog(Log t, LogLevel level, T res, const char *file, int line, const char *reportTag, char retmask, const char *reasonFmt, ...) { +NO_INLINE +T hleDoLog(Log t, LogLevel level, T res, const char *file, int line, const char *reportTag, const char *reasonFmt, ...) { if (!GenericLogEnabled(level, t)) { if (leave) { hleLeave(); @@ -205,7 +206,7 @@ T hleDoLog(Log t, LogLevel level, T res, const char *file, int line, const char } else if (std::is_signed::value) { fmtRes = (s64)res; } - hleDoLogInternal(t, level, fmtRes, file, line, reportTag, retmask, reasonFmt, formatted_reason); + hleDoLogInternal(t, level, fmtRes, file, line, reportTag, reasonFmt, formatted_reason); if (leave) { hleLeave(); } @@ -214,7 +215,8 @@ T hleDoLog(Log t, LogLevel level, T res, const char *file, int line, const char template [[nodiscard]] -T hleDoLog(Log t, LogLevel level, T res, const char *file, int line, const char *reportTag, char retmask) { +NO_INLINE +T hleDoLog(Log t, LogLevel level, T res, const char *file, int line, const char *reportTag) { if (((int)level > MAX_LOGLEVEL || !GenericLogEnabled(level, t)) && !reportTag) { if (leave) { hleLeave(); @@ -229,7 +231,7 @@ T hleDoLog(Log t, LogLevel level, T res, const char *file, int line, const char } else if (std::is_signed::value) { fmtRes = (s64)res; } - hleDoLogInternal(t, level, fmtRes, file, line, reportTag, retmask, nullptr, ""); + hleDoLogInternal(t, level, fmtRes, file, line, reportTag, nullptr, ""); if (leave) { hleLeave(); } @@ -281,18 +283,18 @@ inline R hleCallImpl(std::string_view module, std::string_view funcName, F func, // IMPORTANT: These *must* only be used directly in HLE functions. They cannot be used by utility functions // called by them. Use regular ERROR_LOG etc for those. -#define hleLogReturnHelper(t, level, res, retmask, ...) \ - (((int)level <= MAX_LOGLEVEL) ? hleDoLog(t, level, (res), __FILE__, __LINE__, nullptr, retmask, ##__VA_ARGS__) : (res)) +#define hleLogReturnHelper(t, level, res, ...) \ + (((int)level <= MAX_LOGLEVEL) ? hleDoLog(t, level, (res), __FILE__, __LINE__, nullptr, ##__VA_ARGS__) : (res)) -#define hleLogError(t, res, ...) hleLogReturnHelper(t, LogLevel::LERROR, res, 'x', ##__VA_ARGS__) -#define hleLogWarning(t, res, ...) hleLogReturnHelper(t, LogLevel::LWARNING, res, 'x', ##__VA_ARGS__) -#define hleLogDebug(t, res, ...) hleLogReturnHelper(t, HLE_LOG_LDEBUG, res, 'x', ##__VA_ARGS__) -#define hleLogInfo(t, res, ...) hleLogReturnHelper(t, LogLevel::LINFO, res, 'x', ##__VA_ARGS__) -#define hleLogVerbose(t, res, ...) hleLogReturnHelper(t, HLE_LOG_LVERBOSE, res, 'x', ##__VA_ARGS__) +#define hleLogError(t, res, ...) hleLogReturnHelper(t, LogLevel::LERROR, res, ##__VA_ARGS__) +#define hleLogWarning(t, res, ...) hleLogReturnHelper(t, LogLevel::LWARNING, res, ##__VA_ARGS__) +#define hleLogDebug(t, res, ...) hleLogReturnHelper(t, HLE_LOG_LDEBUG, res, ##__VA_ARGS__) +#define hleLogInfo(t, res, ...) hleLogReturnHelper(t, LogLevel::LINFO, res, ##__VA_ARGS__) +#define hleLogVerbose(t, res, ...) hleLogReturnHelper(t, HLE_LOG_LVERBOSE, res, ##__VA_ARGS__) // If res is negative, log warn/error, otherwise log debug. -#define hleLogDebugOrWarn(t, res, ...) hleLogReturnHelper(t, ((int)res < 0 ? LogLevel::LWARNING : HLE_LOG_LDEBUG), res, 'x', ##__VA_ARGS__) -#define hleLogDebugOrError(t, res, ...) hleLogReturnHelper(t, ((int)res < 0 ? LogLevel::LERROR : HLE_LOG_LDEBUG), res, 'x', ##__VA_ARGS__) +#define hleLogDebugOrWarn(t, res, ...) hleLogReturnHelper(t, ((int)res < 0 ? LogLevel::LWARNING : HLE_LOG_LDEBUG), res, ##__VA_ARGS__) +#define hleLogDebugOrError(t, res, ...) hleLogReturnHelper(t, ((int)res < 0 ? LogLevel::LERROR : HLE_LOG_LDEBUG), res, ##__VA_ARGS__) -#define hleReportError(t, res, ...) hleDoLog(t, LogLevel::LERROR, res, __FILE__, __LINE__, "", 'x', ##__VA_ARGS__) -#define hleReportWarning(t, res, ...) hleDoLog(t, LogLevel::LWARNING, res, __FILE__, __LINE__, "", 'x', ##__VA_ARGS__) +#define hleReportError(t, res, ...) hleDoLog(t, LogLevel::LERROR, res, __FILE__, __LINE__, "", ##__VA_ARGS__) +#define hleReportWarning(t, res, ...) hleDoLog(t, LogLevel::LWARNING, res, __FILE__, __LINE__, "", ##__VA_ARGS__) diff --git a/Core/HLE/sceGe.cpp b/Core/HLE/sceGe.cpp index 6f69690f40..910923d600 100644 --- a/Core/HLE/sceGe.cpp +++ b/Core/HLE/sceGe.cpp @@ -634,7 +634,7 @@ const HLEFunction sceGe_user[] = { {0XAB49E76A, &WrapU_UUIU, "sceGeListEnQueue", 'x', "xxip"}, {0X1C0D95A6, &WrapU_UUIU, "sceGeListEnQueueHead", 'x', "xxip"}, {0XE0D68148, &WrapI_UU, "sceGeListUpdateStallAddr", 'i', "xx" }, - {0X03444EB4, &WrapI_UU, "sceGeListSync", 'i', "xx" }, + {0X03444EB4, &WrapI_UU, "sceGeListSync", 'x', "xx" }, {0XB287BD61, &WrapU_U, "sceGeDrawSync", 'x', "x" }, {0XB448EC0D, &WrapI_UU, "sceGeBreak", 'i', "xx" }, {0X4C06E472, &WrapI_V, "sceGeContinue", 'i', "" }, diff --git a/GPU/Vulkan/DrawEngineVulkan.h b/GPU/Vulkan/DrawEngineVulkan.h index 2d7aceaf90..f46ddddb14 100644 --- a/GPU/Vulkan/DrawEngineVulkan.h +++ b/GPU/Vulkan/DrawEngineVulkan.h @@ -31,6 +31,7 @@ // The format of the various uniform buffers may vary though - vertex shaders that don't skin // won't get any bone data, etc. +#include "Common/CommonTypes.h" #include "Common/Data/Collections/Hashmaps.h" #include "GPU/Vulkan/VulkanUtil.h" @@ -44,14 +45,6 @@ #include "GPU/Vulkan/StateMappingVulkan.h" #include "GPU/Vulkan/VulkanRenderManager.h" - -// TODO: Move to some appropriate header. -#ifdef _MSC_VER -#define NO_INLINE __declspec(noinline) -#else -#define NO_INLINE __attribute__((noinline)) -#endif - struct DecVtxFormat; struct UVScale;