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
)
add_library(lucore INTERFACE)
add_library(lucore
src/Assert.cpp
)
target_compile_features(lucore INTERFACE cxx_std_20)
target_include_directories(lucore INTERFACE ${PROJECT_SOURCE_DIR}/include)
target_compile_features(lucore PUBLIC cxx_std_20)
target_include_directories(lucore PUBLIC ${PROJECT_SOURCE_DIR}/include)
add_library(lucore::lucore ALIAS lucore)

View File

@ -1,16 +1,35 @@
//! Lucore Assert Wrappers
// this just plumbs everything to libc by default
// 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>
#pragma once
#ifdef NDEBUG
#define LUCORE_ASSERT(...) assert(__VA_ARGS__)
#include <cstdio>
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
#define LUCORE_ASSERT(...)
#define LUCORE_ASSERT(expr, format, ...)
#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 {};
/// Sentinel value to explicitly not populate an OptionalRef.
inline static Nullref_t NullRef {};
template <class T>
struct OptionalRef; // sfinae on non-reference types
@ -35,7 +38,9 @@ namespace lucore::detail {
}
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;
}
@ -60,8 +65,6 @@ namespace lucore::detail {
T* ptr {};
};
/// Sentinel value to explicitly not populate an OptionalRef.
inline static Nullref_t NullRef {};
} // namespace lucore::detail
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
src/Bus.cpp
src/MemoryDevice.cpp
)
target_compile_features(riscv PUBLIC cxx_std_20)

View File

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