Skip to content

Commit

Permalink
Merge pull request #26 from bitsh1ft3r/logging_improvement
Browse files Browse the repository at this point in the history
Emulator: Logging improvement.
  • Loading branch information
bitsh1ft3r authored Jan 29, 2025
2 parents a07f324 + 4154532 commit 1026e23
Show file tree
Hide file tree
Showing 66 changed files with 4,114 additions and 1,143 deletions.
4 changes: 4 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,7 @@
path = third_party/toml11
url = https://github.com/ToruNiina/toml11.git
shallow = true
[submodule "third_party/fmt"]
path = third_party/fmt
url = https://github.com/fmtlib/fmt.git
shallow = true
38 changes: 37 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,51 @@ function(create_target_directory_groups target_name)
endforeach()
endfunction()

find_package(fmt 11.1.3 CONFIG)
find_package(SDL3 3.2.0 CONFIG)
find_package(toml11 4.3.0 CONFIG)

add_subdirectory(third_party)
include_directories(Xenon)

set(Logging
Xenon/Base/Logging/Backend.cpp
Xenon/Base/Logging/Backend.h
Xenon/Base/Logging/Filter.cpp
Xenon/Base/Logging/Filter.h
Xenon/Base/Logging/Formatter.h
Xenon/Base/Logging/Log.h
Xenon/Base/Logging/Log_entry.h
Xenon/Base/Logging/Text_formatter.cpp
Xenon/Base/Logging/Text_formatter.h
Xenon/Base/Logging/Types.h
)

set(Base
${Logging}
Xenon/Base/Alignment.h
Xenon/Base/Arch.h
Xenon/Base/Assert.cpp
Xenon/Base/Assert.h
Xenon/Base/Bounded_threadsafe_queue.h
Xenon/Base/Concepts.h
Xenon/Base/Config.cpp
Xenon/Base/Config.h
Xenon/Base/Error.cpp
Xenon/Base/Error.h
Xenon/Base/Enum.h
Xenon/Base/io_file.cpp
Xenon/Base/io_file.h
Xenon/Base/ntapi.cpp
Xenon/Base/ntapi.h
Xenon/Base/Path_util.cpp
Xenon/Base/Path_util.h
Xenon/Base/Polyfill_thread.h
Xenon/Base/String_util.cpp
Xenon/Base/String_util.h
Xenon/Base/SystemDevice.h
Xenon/Base/Thread.cpp
Xenon/Base/Thread.h
Xenon/Base/Types.h
Xenon/Base/Version.h
)
Expand Down Expand Up @@ -139,7 +172,10 @@ add_executable(Xenon
create_target_directory_groups(Xenon)

target_include_directories(Xenon PRIVATE ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(Xenon PRIVATE SDL3::SDL3 toml11::toml11)
target_link_libraries(Xenon PRIVATE fmt::fmt SDL3::SDL3 toml11::toml11)

add_definitions(-DNTDDI_VERSION=0x0A000006 -D_WIN32_WINNT=0x0A00 -DWINVER=0x0A00)
add_definitions(-DNOMINMAX -DWIN32_LEAN_AND_MEAN)

if (WIN32)
target_sources(Xenon PRIVATE Xenon/Xenon.rc)
Expand Down
48 changes: 48 additions & 0 deletions Xenon/Base/Alignment.h
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
9 changes: 9 additions & 0 deletions Xenon/Base/Arch.h
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
35 changes: 35 additions & 0 deletions Xenon/Base/Assert.cpp
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();
}
82 changes: 82 additions & 0 deletions Xenon/Base/Assert.h
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)
Loading

0 comments on commit 1026e23

Please sign in to comment.