-
-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #26 from bitsh1ft3r/logging_improvement
Emulator: Logging improvement.
- Loading branch information
Showing
66 changed files
with
4,114 additions
and
1,143 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
// Copyright 2025 Xenon Emulator Project | ||
|
||
#pragma once | ||
|
||
#include <cstddef> | ||
#include <type_traits> | ||
|
||
namespace Base { | ||
|
||
template <typename T> | ||
[[nodiscard]] constexpr T AlignUp(T value, std::size_t size) { | ||
static_assert(std::is_unsigned_v<T>, "T must be an unsigned value."); | ||
auto mod{static_cast<T>(value % size)}; | ||
value -= mod; | ||
return static_cast<T>(mod == T{0} ? value : value + size); | ||
} | ||
|
||
template <typename T> | ||
[[nodiscard]] constexpr T AlignDown(T value, std::size_t size) { | ||
static_assert(std::is_unsigned_v<T>, "T must be an unsigned value."); | ||
return static_cast<T>(value - value % size); | ||
} | ||
|
||
template <typename T> | ||
requires std::is_integral_v<T> | ||
[[nodiscard]] constexpr bool IsAligned(T value, std::size_t alignment) { | ||
return (value & (alignment - 1)) == 0; | ||
} | ||
|
||
template <typename T> | ||
requires std::is_integral_v<T> | ||
[[nodiscard]] constexpr bool Is16KBAligned(T value) { | ||
return (value & 0x3FFF) == 0; | ||
} | ||
|
||
template <typename T> | ||
requires std::is_integral_v<T> | ||
[[nodiscard]] constexpr bool Is64KBAligned(T value) { | ||
return (value & 0xFFFF) == 0; | ||
} | ||
|
||
template <typename T> | ||
requires std::is_integral_v<T> | ||
[[nodiscard]] constexpr bool Is2MBAligned(T value) { | ||
return (value & 0x1FFFFF) == 0; | ||
} | ||
|
||
} // namespace Base |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
// Copyright 2025 Xenon Emulator Project | ||
|
||
#pragma once | ||
|
||
#if defined(__x86_64__) || defined(_M_X64) | ||
#define ARCH_X86_64 1 | ||
#elif defined(__aarch64__) || defined(_M_ARM64) | ||
#define ARCH_ARM64 1 | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
// Copyright 2025 Xenon Emulator Project | ||
|
||
#include "Arch.h" | ||
#include "Assert.h" | ||
#include "Logging/Backend.h" | ||
|
||
#ifdef _MSC_VER | ||
#define Crash() __debugbreak() | ||
#else | ||
#if defined(ARCH_X86_64) | ||
#define Crash() __asm__ __volatile__("int $3") | ||
#elif defined(ARCH_ARM64) | ||
#define Crash() __asm__ __volatile__("brk 0") | ||
#else | ||
#error "Missing Crash() implementation for target CPU architecture." | ||
#endif | ||
#endif // _MSVC_VER | ||
|
||
void assert_fail_impl() { | ||
Base::Log::Stop(); | ||
std::fflush(stdout); | ||
Crash(); | ||
} | ||
|
||
[[noreturn]] void unreachable_impl() { | ||
Base::Log::Stop(); | ||
std::fflush(stdout); | ||
Crash(); | ||
throw std::runtime_error("Unreachable code"); | ||
} | ||
|
||
void assert_fail_debug_msg(const char* msg) { | ||
LOG_CRITICAL(Debug, "Assertion Failed!\n{}", msg); | ||
assert_fail_impl(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
// Copyright 2025 Xenon Emulator Project | ||
|
||
#pragma once | ||
|
||
#include "Logging/Log.h" | ||
|
||
// Sometimes we want to try to continue even after hitting an assert. | ||
// However touching this file yields a global recompilation as this header is included almost | ||
// everywhere. So let's just move the handling of the failed assert to a single cpp file. | ||
|
||
void assert_fail_impl(); | ||
[[noreturn]] void unreachable_impl(); | ||
|
||
#ifdef _MSC_VER | ||
#define XENON_NO_INLINE __declspec(noinline) | ||
#else | ||
#define XENON_NO_INLINE __attribute__((noinline)) | ||
#endif | ||
|
||
#define ASSERT(_a_) \ | ||
([&]() XENON_NO_INLINE { \ | ||
if (!(_a_)) [[unlikely]] { \ | ||
LOG_CRITICAL(Debug, "Assertion Failed!"); \ | ||
assert_fail_impl(); \ | ||
} \ | ||
}()) | ||
|
||
#define ASSERT_MSG(_a_, ...) \ | ||
([&]() XENON_NO_INLINE { \ | ||
if (!(_a_)) [[unlikely]] { \ | ||
LOG_CRITICAL(Debug, "Assertion Failed!\n" __VA_ARGS__); \ | ||
assert_fail_impl(); \ | ||
} \ | ||
}()) | ||
|
||
#define UNREACHABLE() \ | ||
do { \ | ||
LOG_CRITICAL(Debug, "Unreachable code!"); \ | ||
unreachable_impl(); \ | ||
} while (0) | ||
|
||
#define UNREACHABLE_MSG(...) \ | ||
do { \ | ||
LOG_CRITICAL(Debug, "Unreachable code!\n" __VA_ARGS__); \ | ||
unreachable_impl(); \ | ||
} while (0) | ||
|
||
#ifdef _DEBUG | ||
#define DEBUG_ASSERT(_a_) ASSERT(_a_) | ||
#define DEBUG_ASSERT_MSG(_a_, ...) ASSERT_MSG(_a_, __VA_ARGS__) | ||
#else // not debug | ||
#define DEBUG_ASSERT(_a_) \ | ||
do { \ | ||
} while (0) | ||
#define DEBUG_ASSERT_MSG(_a_, _desc_, ...) \ | ||
do { \ | ||
} while (0) | ||
#endif | ||
|
||
#define UNIMPLEMENTED() ASSERT_MSG(false, "Unimplemented code!") | ||
#define UNIMPLEMENTED_MSG(...) ASSERT_MSG(false, __VA_ARGS__) | ||
|
||
#define UNIMPLEMENTED_IF(cond) ASSERT_MSG(!(cond), "Unimplemented code!") | ||
#define UNIMPLEMENTED_IF_MSG(cond, ...) ASSERT_MSG(!(cond), __VA_ARGS__) | ||
|
||
// If the assert is ignored, execute _b_ | ||
#define ASSERT_OR_EXECUTE(_a_, _b_) \ | ||
do { \ | ||
ASSERT(_a_); \ | ||
if (!(_a_)) [[unlikely]] { \ | ||
_b_ \ | ||
} \ | ||
} while (0) | ||
|
||
// If the assert is ignored, execute _b_ | ||
#define ASSERT_OR_EXECUTE_MSG(_a_, _b_, ...) \ | ||
do { \ | ||
ASSERT_MSG(_a_, __VA_ARGS__); \ | ||
if (!(_a_)) [[unlikely]] { \ | ||
_b_ \ | ||
} \ | ||
} while (0) |
Oops, something went wrong.