diff --git a/cmake/ProjectFuncs.cmake b/cmake/ProjectFuncs.cmake index 85092f5..1653a9f 100644 --- a/cmake/ProjectFuncs.cmake +++ b/cmake/ProjectFuncs.cmake @@ -2,7 +2,7 @@ function(tv2hv_target target) target_compile_definitions(${target} PRIVATE "$<$:TV2HV_DEBUG>") #target_include_directories(${target} PRIVATE ${PROJECT_SOURCE_DIR}) target_compile_features(${target} PRIVATE cxx_std_23) - target_include_directories(${target} PRIVATE ${PROJECT_SOURCE_DIR}/src/lib ${CMAKE_CURRENT_BINARY_DIR}) + target_include_directories(${target} PRIVATE ${PROJECT_SOURCE_DIR}/src ${CMAKE_CURRENT_BINARY_DIR}) endfunction() function(_tv2hv_set_alternate_linker) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5f2aef0..605f0ed 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,5 +1,9 @@ add_executable(tv2hv + + # utility code + utils/error.cpp + main.cpp ) diff --git a/src/kvm/vm.hpp b/src/kvm/vm.hpp new file mode 100644 index 0000000..37c42f4 --- /dev/null +++ b/src/kvm/vm.hpp @@ -0,0 +1,19 @@ +#include +#include + +namespace kvm { + + class CPU; + + class VM { + /// The primary vCPU. + util::Ref vcpu; + public: + + /// Creates a new VM instance. + static util::ErrorOr> create(); + + // TODO: more stuff + }; + +} diff --git a/src/utils/error.cpp b/src/utils/error.cpp new file mode 100644 index 0000000..8d8120f --- /dev/null +++ b/src/utils/error.cpp @@ -0,0 +1,16 @@ +#include +#include + +namespace util { + + Error Error::vFormat(const std::string_view formatString, std::format_args args) { + return Error(std::vformat(formatString, args)); + } + + Error Error::systemError() { + char errBuffer[128]{}; + auto* pStr = strerror_r(errno, &errBuffer[0], sizeof(errBuffer)); + return Error::format("System error: {}", std::string_view(pStr)); + } + +} diff --git a/src/utils/error.hpp b/src/utils/error.hpp new file mode 100644 index 0000000..765d0b7 --- /dev/null +++ b/src/utils/error.hpp @@ -0,0 +1,82 @@ +#pragma once +#include +#include +#include +#include + +namespace util { + + /// An error. + class Error { + std::string msg; + + static Error vFormat(const std::string_view formatString, std::format_args args); + + public: + explicit Error(const std::string& message) + : msg(message) {} + + template + static constexpr auto format(const std::string_view formatString, Args... args) { + return vFormat(formatString, std::make_format_args(args...)); + } + + /// Formats a system error. + static Error systemError(); + + const char* message() const { return msg.c_str(); } + }; + + /// A type which can store either an error or a value. + template + class ErrorOr { + std::variant< + Error, + T + > variant; + public: + constexpr ErrorOr(const Error& error) + : variant(error) {} + + constexpr ErrorOr(const T& value) + : variant(value) {} + + bool isValue() const { + return std::holds_alternative(variant); + } + + bool isError() const { + return std::holds_alternative(variant); + } + + const Error& err() const { + return std::get(variant); + } + + T& value() { + return std::get(variant); + } + + T& value() const { + return std::get(variant); + } + }; + + template<> + class ErrorOr { + std::optional error; + public: + ErrorOr() = default; + ErrorOr(const Error& error) + : error(error) {} + + bool isError() const { + return error.has_value(); + } + + const Error& err() const { + return error.value(); + } + }; + +} diff --git a/src/utils/types.hpp b/src/utils/types.hpp new file mode 100644 index 0000000..597a48b --- /dev/null +++ b/src/utils/types.hpp @@ -0,0 +1,59 @@ +//! Core types and includes +#pragma once + +#include +#include +#include + +#include + +// these are in the global namespace since most libraries +// won't try defining anything like this in the global namespace +// (and I'd like these types to be used globally a lot more anyways) +using u8 = std::uint8_t; +using i8 = std::int8_t; +using u16 = std::uint16_t; +using i16 = std::int16_t; +using u32 = std::uint32_t; +using i32 = std::int32_t; +using u64 = std::uint64_t; +using i64 = std::int64_t; +using usize = std::size_t; +using isize = std::intptr_t; + +namespace util { + + template + constexpr void Unused(T t) { + static_cast(t); + } + + template + using Ref = std::shared_ptr; + + template > + using Unique = std::unique_ptr; + + template + struct OverloadVisitor : Ts... { + using Ts::operator()...; + }; + + template + OverloadVisitor(Ts...) -> OverloadVisitor; + + template + struct UniqueCDeleter { + constexpr void operator()(T* ptr) { + if(ptr) + Free(reinterpret_cast(ptr)); + } + }; + + /// Use this for wrapping a C-allocated memory block. The defaults here assume + /// you're wrapping data allocated by malloc(), however, any deallocator pattern + /// is supported by the UniqueCDeleter. + template + using CUnique = Unique>; + +} // namespace base