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:
parent
a8fb72804c
commit
c20c852554
|
@ -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)
|
||||
|
|
|
@ -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]); \
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
|
@ -7,6 +7,7 @@ project(riscv_emu
|
|||
|
||||
add_library(riscv
|
||||
src/Bus.cpp
|
||||
src/MemoryDevice.cpp
|
||||
)
|
||||
|
||||
target_compile_features(riscv PUBLIC cxx_std_20)
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue