lucore now has its own assertion system

ripped off of how ive done it in like 10 different projects by now™️
This commit is contained in:
Lily Tsuru 2023-07-16 05:40:38 -04:00
parent a8fb72804c
commit c20c852554
6 changed files with 71 additions and 38 deletions

View File

@ -5,9 +5,11 @@ project(lucore
LANGUAGES CXX LANGUAGES CXX
) )
add_library(lucore INTERFACE) add_library(lucore
src/Assert.cpp
)
target_compile_features(lucore INTERFACE cxx_std_20) target_compile_features(lucore PUBLIC cxx_std_20)
target_include_directories(lucore INTERFACE ${PROJECT_SOURCE_DIR}/include) target_include_directories(lucore PUBLIC ${PROJECT_SOURCE_DIR}/include)
add_library(lucore::lucore ALIAS lucore) add_library(lucore::lucore ALIAS lucore)

View File

@ -1,16 +1,35 @@
//! Lucore Assert Wrappers //! Lucore Assert Wrappers
// this just plumbs everything to libc by default #pragma once
// your project can choose to configure its own assertion handler by
// defining LUCORE_ASSERT()
// TODO: LUCORE_VERIFY/plumbing this into our own assertion code?
#ifndef LUCORE_ASSERT
#include <cassert>
#ifdef NDEBUG #include <cstdio>
#define LUCORE_ASSERT(...) assert(__VA_ARGS__)
namespace lucore {
// TODO: wrapper which uses source_location (we don't need no macros anymore!)
[[noreturn]] void ExitMsg(const char* fileName, int fileLine, const char* message);
}
#ifndef NDEBUG
#define LUCORE_ASSERT(expr, format, ...) \
if(!(expr)) [[unlikely]] { \
char buffer[256]; \
std::snprintf(&buffer[0], sizeof(buffer), \
"[Lucore] Assertion \"%s\" failed with message: " format "\n", #expr, \
##__VA_ARGS__); \
::lucore::ExitMsg(__FILE__, __LINE__, &buffer[0]); \
}
#else #else
#define LUCORE_ASSERT(...) #define LUCORE_ASSERT(expr, format, ...)
#endif #endif
#endif // CHECK() is always active, even in release builds
#define LUCORE_CHECK(expr, format, ...) \
if(!(expr)) [[unlikely]] { \
char buffer[256]; \
std::snprintf(&buffer[0], sizeof(buffer), \
"[Lucore] Check \"%s\" failed with message: " format "\n", #expr, \
##__VA_ARGS__); \
::lucore::ExitMsg(__FILE__, __LINE__, &buffer[0]); \
}

View File

@ -6,6 +6,9 @@ namespace lucore::detail {
struct Nullref_t {}; struct Nullref_t {};
/// Sentinel value to explicitly not populate an OptionalRef.
inline static Nullref_t NullRef {};
template <class T> template <class T>
struct OptionalRef; // sfinae on non-reference types struct OptionalRef; // sfinae on non-reference types
@ -35,7 +38,9 @@ namespace lucore::detail {
} }
constexpr T& Value() const { constexpr T& Value() const {
LUCORE_ASSERT(HasValue() && "Attempt to access OptionalRef without stored value!"); // this is a CHECK() since allowing unchecked access in release builds is probably a
// very very bad idea
LUCORE_CHECK(HasValue(), "Attempt to access OptionalRef without stored value!");
return *ptr; return *ptr;
} }
@ -60,8 +65,6 @@ namespace lucore::detail {
T* ptr {}; T* ptr {};
}; };
/// Sentinel value to explicitly not populate an OptionalRef.
inline static Nullref_t NullRef {};
} // namespace lucore::detail } // namespace lucore::detail
namespace lucore { namespace lucore {

View File

@ -0,0 +1,15 @@
//! Implementation of lucore assertion facilities
#include <cstdio>
#include <cstdlib>
namespace lucore {
[[noreturn]] void ExitMsg(const char* fileName, int fileLine, const char* message) {
// TODO: move this to logger functionality of lucore (gmsv_lcpu will end up containing a
// Sink impl..)
std::puts(message);
std::quick_exit(0xAF);
}
} // namespace lucore

View File

@ -7,6 +7,7 @@ project(riscv_emu
add_library(riscv add_library(riscv
src/Bus.cpp src/Bus.cpp
src/MemoryDevice.cpp
) )
target_compile_features(riscv PUBLIC cxx_std_20) target_compile_features(riscv PUBLIC cxx_std_20)

View File

@ -1,21 +1,17 @@
#include <riscv/Bus.hpp> #include <riscv/Bus.hpp>
#include "riscv/Types.hpp"
#include <span> #include <span>
#include "riscv/Types.hpp"
namespace riscv { namespace riscv {
namespace { namespace {
template <bool Rom> template <bool Rom>
struct BasicMemoryDevice : public Bus::Device { struct BasicMemoryDevice : public Bus::Device {
BasicMemoryDevice(usize size) BasicMemoryDevice(usize size) : memorySize(size) {
: memorySize(size) {
memory = new u8[size]; memory = new u8[size];
// TODO(feat): we should have a global panic system which is hooked in LUCORE_CHECK(memory, "Could not allocate buffer for memory device.");
// so that we don't just blindly crash everything
assert(memory && "Out of host memory");
} }
virtual ~BasicMemoryDevice() { virtual ~BasicMemoryDevice() {
@ -71,8 +67,6 @@ namespace riscv {
} }
private: private:
/// helper used for implementing stuff /// helper used for implementing stuff
template <class T> template <class T>
constexpr usize OffsetToIndex(AddressT offset) { constexpr usize OffsetToIndex(AddressT offset) {
@ -90,9 +84,8 @@ namespace riscv {
using RamDevice = BasicMemoryDevice<false>; using RamDevice = BasicMemoryDevice<false>;
using RomDevice = BasicMemoryDevice<true>; using RomDevice = BasicMemoryDevice<true>;
} } // namespace
// Bus::Device* NewRam() // Bus::Device* NewRam()
} } // namespace riscv