From 00c0d78199fcfbbb20828be5e06fd2d271fa4c1e Mon Sep 17 00:00:00 2001 From: Steven Le Rouzic Date: Sun, 24 Mar 2024 23:49:26 +0100 Subject: Initial commit --- deimos/core/BUILD | 14 ++++++ deimos/core/allocator.cpp | 55 ++++++++++++++++++++++ deimos/core/allocator.h | 74 +++++++++++++++++++++++++++++ deimos/core/api_registry.cpp | 47 ++++++++++++++++++ deimos/core/api_registry.h | 30 ++++++++++++ deimos/core/base.h | 87 ++++++++++++++++++++++++++++++++++ deimos/core/hash.h | 110 +++++++++++++++++++++++++++++++++++++++++++ deimos/core/id_name.h | 21 +++++++++ 8 files changed, 438 insertions(+) create mode 100644 deimos/core/BUILD create mode 100644 deimos/core/allocator.cpp create mode 100644 deimos/core/allocator.h create mode 100644 deimos/core/api_registry.cpp create mode 100644 deimos/core/api_registry.h create mode 100644 deimos/core/base.h create mode 100644 deimos/core/hash.h create mode 100644 deimos/core/id_name.h (limited to 'deimos/core') diff --git a/deimos/core/BUILD b/deimos/core/BUILD new file mode 100644 index 0000000..2093642 --- /dev/null +++ b/deimos/core/BUILD @@ -0,0 +1,14 @@ +cc_library( + name = "core", + hdrs = [ + "base.h", + "allocator.h", + "api_registry.h", + ], + srcs = [ + "allocator.cpp", + "api_registry.cpp", + ], + visibility = ["//:__subpackages__"], +) + diff --git a/deimos/core/allocator.cpp b/deimos/core/allocator.cpp new file mode 100644 index 0000000..a525bfd --- /dev/null +++ b/deimos/core/allocator.cpp @@ -0,0 +1,55 @@ +#include "deimos/core/allocator.h" + +#include + +namespace deimos +{ + +class SystemAllocatorImpl : public IAllocator +{ +public: + SystemAllocatorImpl() : IAllocator(MemoryScope{0}) {} + + void* Reallocate( + void* old_ptr, int64 /* old_size */, int64 new_size, + const char* /* file */, int32 /* line */) override + { + if (old_ptr == nullptr) + { + return new_size > 0 ? ::malloc((uint64)new_size) : nullptr; + } + + if (new_size == 0) + { + if (old_ptr != nullptr) + { + ::free(old_ptr); + } + } + else + { + return ::realloc(old_ptr, (uint64)new_size); + } + return nullptr; + } +}; + +class AllocatorApiImpl : public AllocatorApi +{ + SystemAllocatorImpl m_system_impl; + +public: + AllocatorApiImpl() + { + system = &m_system_impl; + } +}; + +AllocatorApi* BootstrapAllocatorApi() +{ + static AllocatorApiImpl g_instance{}; + return &g_instance; +} + +} // namespace deimos + diff --git a/deimos/core/allocator.h b/deimos/core/allocator.h new file mode 100644 index 0000000..4acdb6d --- /dev/null +++ b/deimos/core/allocator.h @@ -0,0 +1,74 @@ +#pragma once + +#include "deimos/core/base.h" +#include "deimos/core/id_name.h" + +namespace deimos +{ + +struct MemoryScope { uint32 id; }; + +class IAllocator +{ +protected: + const MemoryScope m_scope; + +public: + constexpr explicit IAllocator(MemoryScope scope) : m_scope{scope} {} + + deimos_NO_COPY_MOVE(IAllocator); + + virtual ~IAllocator() = default; + + [[nodiscard]] + virtual void* Reallocate( + void* old_ptr, int64 old_size, int64 new_size, + const char* file = __builtin_FILE(), int32 line = __builtin_LINE()) = 0; + + [[nodiscard]] + constexpr void* Allocate( + int64 new_size, + const char* file = __builtin_FILE(), int32 line = __builtin_LINE()) + { + return Reallocate(nullptr, 0, new_size, file, line); + } + + constexpr void Free( + void* old_ptr, int64 old_size, + const char* file = __builtin_FILE(), int32 line = __builtin_LINE()) + { + (void)Reallocate(old_ptr, old_size, 0, file, line); + } + + template + T* New( + Args&&... args, + const char* file = __builtin_FILE(), int32 line = __builtin_LINE()) + { + void* ptr = Allocate(sizeof(T), file, line); + return new(ptr) T(std::forward(args)...); + } + + template + void Delete( + T* t, + const char* file = __builtin_FILE(), int32 line = __builtin_LINE()) + { + if constexpr (!kIsTriviallyDestructible) + { + t->~T(); + } + Free(t, sizeof(T), file, line); + } +}; + +class AllocatorApi +{ +public: + static constexpr IdName kApiName{"deimos::AllocatorApi"}; + + IAllocator* system{}; +}; + +} // namespace deimos + diff --git a/deimos/core/api_registry.cpp b/deimos/core/api_registry.cpp new file mode 100644 index 0000000..aa993e0 --- /dev/null +++ b/deimos/core/api_registry.cpp @@ -0,0 +1,47 @@ +#include "deimos/core/api_registry.h" +#include "deimos/core/allocator.h" +#include "deimos/core/hash.h" + +namespace deimos +{ + +AllocatorApi* BootstrapAllocatorApi(); + +struct ApiEntry +{ + const ApiEntry* next{}; + IdName name; + void* impl; + + ApiEntry(const IdName& name, void* impl) : + name{name}, impl{impl} + {} +}; + +class ApiRegistryImpl: public ApiRegistry +{ + IAllocator* m_allocator; + +public: + explicit ApiRegistryImpl(IAllocator* allocator) : + m_allocator{allocator} + {} + + void Set(const IdName& name, void* impl) final + { + } +}; + +ApiRegistry* InitializeGlobalApiRegistry() +{ + AllocatorApi* allocator_api = BootstrapAllocatorApi(); + IAllocator* allocator = allocator_api->system; + ApiRegistry* api_registry = allocator->New(); + + api_registry->Set(allocator_api); + + return api_registry; +} + +} // namespace deimos + diff --git a/deimos/core/api_registry.h b/deimos/core/api_registry.h new file mode 100644 index 0000000..2624935 --- /dev/null +++ b/deimos/core/api_registry.h @@ -0,0 +1,30 @@ +#pragma once + +#include "deimos/core/base.h" +#include "deimos/core/id_name.h" + +namespace deimos +{ + +class ApiRegistry +{ +public: + ApiRegistry() = default; + + deimos_NO_COPY_MOVE(ApiRegistry); + + virtual ~ApiRegistry() = default; + + virtual void Set(const IdName&, void* impl) = 0; + + template + void Set(Api* impl) + { + Set(Api::kApiName, impl); + } +}; + +ApiRegistry* InitializeGlobalApiRegistry(); + +} // namespace deimos + diff --git a/deimos/core/base.h b/deimos/core/base.h new file mode 100644 index 0000000..0530db7 --- /dev/null +++ b/deimos/core/base.h @@ -0,0 +1,87 @@ +#pragma once + +#define deimos_StaticAssert(...) static_assert(__VA_ARGS__, #__VA_ARGS__) + +#define deimos_NO_COPY(TYPE) \ + TYPE(const TYPE&) = delete; \ + TYPE& operator=(const TYPE&) = delete; + +#define deimos_NO_MOVE(TYPE) \ + TYPE(TYPE&&) = delete; \ + TYPE& operator=(TYPE&&) = delete; + +#define deimos_NO_COPY_MOVE(TYPE) \ + deimos_NO_COPY(TYPE); \ + deimos_NO_MOVE(TYPE); + +#define deimos_DEFAULT_COPY(TYPE) \ + TYPE(const TYPE&) = default; \ + TYPE& operator=(const TYPE&) = default; + +#define deimos_DEFAULT_MOVE(TYPE) \ + TYPE(TYPE&&) = default; \ + TYPE& operator=(TYPE&&) = default; + +#define deimos_DEFAULT_COPY_MOVE(TYPE) \ + deimos_DEFAULT_COPY(TYPE); \ + deimos_DEFAULT_MOVE(TYPE); + +namespace deimos +{ + +using uint8 = unsigned char; +using uint16 = unsigned short; +using uint32 = unsigned int; +using uint64 = unsigned long long; + +using int8 = char; +using int16 = short; +using int32 = int; +using int64 = long long; + +using float32 = float; +using float64 = double; + +struct uint128 +{ + uint64 high; + uint64 low; +}; + +template struct RemoveReferenceT { using Type = T; }; +template struct RemoveReferenceT { using Type = T; }; +template struct RemoveReferenceT { using Type = T; }; +template using RemoveReference = RemoveReferenceT::Type; + +template constexpr bool kIsTriviallyDestructible = __is_trivially_destructible(T); + +} // namespace deimos + +constexpr void* operator new(deimos::uint64, void* ptr) +{ + return ptr; +} + +namespace std +{ + +template +constexpr deimos::RemoveReference&& move(T&& t) noexcept +{ + return static_cast&&>(t); +} + +template +constexpr T&& forward(deimos::RemoveReference& t) noexcept +{ + return static_cast(t); +} + +template +constexpr T&& forward(deimos::RemoveReference&& t) noexcept // NOLINT +{ + return static_cast(t); +} + +} // namespace std + diff --git a/deimos/core/hash.h b/deimos/core/hash.h new file mode 100644 index 0000000..3f8935c --- /dev/null +++ b/deimos/core/hash.h @@ -0,0 +1,110 @@ +#pragma once + +#include "deimos/core/base.h" + +namespace deimos +{ + +constexpr uint64 MurmurHash3_GetBlock64(const char* key, uint64 block) +{ + // NOLINTBEGIN + key += block * 8; + return + (uint64)((uint8)key[0]) + | ((uint64)((uint8)key[1]) << 8) + | ((uint64)((uint8)key[2]) << 16) + | ((uint64)((uint8)key[3]) << 24) + | ((uint64)((uint8)key[4]) << 32) + | ((uint64)((uint8)key[5]) << 40) + | ((uint64)((uint8)key[6]) << 48) + | ((uint64)((uint8)key[7]) << 56); + // NOLINTEND +} + +constexpr uint64 MurmurHash3_Fmix64(uint64 k) +{ + k ^= k >> 33U; + k *= 0xff51afd7ed558ccdULL; + k ^= k >> 33U; + k *= 0xc4ceb9fe1a85ec53ULL; + k ^= k >> 33U; + return k; +} + +constexpr uint128 MurmurHash3_x64_128(const char* key) +{ + // NOLINTBEGIN + const uint64 len = __builtin_strlen(key); + const uint64 nblocks = len / 16; + + const int64 seed = 0; + uint64 h1 = seed; + uint64 h2 = seed; + + const uint64 c1 = 0x87c37b91114253d5ULL; + const uint64 c2 = 0x4cf5ad432745937fULL; + + //---------- + // body + + for(uint64 i = 0; i < nblocks; i++) + { + uint64 k1 = MurmurHash3_GetBlock64(key, i * 2 + 0); + uint64 k2 = MurmurHash3_GetBlock64(key, i * 2 + 1); + + k1 *= c1; k1 = _rotl64(k1, 31); k1 *= c2; h1 ^= k1; + h1 = _rotl64(h1, 27); h1 += h2; h1 = h1*5+0x52dce729; + k2 *= c2; k2 = _rotl64(k2, 33); k2 *= c1; h2 ^= k2; + h2 = _rotl64(h2, 31); h2 += h1; h2 = h2*5+0x38495ab5; + } + + //---------- + // tail + + const char* tail = key + nblocks * 16; + + uint64 k1 = 0; + uint64 k2 = 0; + + switch (len & 15ULL) + { + case 15: k2 ^= ((uint64)(uint8)tail[14]) << 48U; + case 14: k2 ^= ((uint64)(uint8)tail[13]) << 40U; + case 13: k2 ^= ((uint64)(uint8)tail[12]) << 32U; + case 12: k2 ^= ((uint64)(uint8)tail[11]) << 24U; + case 11: k2 ^= ((uint64)(uint8)tail[10]) << 16U; + case 10: k2 ^= ((uint64)(uint8)tail[ 9]) << 8U; + case 9: k2 ^= ((uint64)(uint8)tail[ 8]) << 0U; + k2 *= c2; k2 = _rotl64(k2,33); k2 *= c1; h2 ^= k2; + + case 8: k1 ^= ((uint64)(uint8)tail[ 7]) << 56U; + case 7: k1 ^= ((uint64)(uint8)tail[ 6]) << 48U; + case 6: k1 ^= ((uint64)(uint8)tail[ 5]) << 40U; + case 5: k1 ^= ((uint64)(uint8)tail[ 4]) << 32U; + case 4: k1 ^= ((uint64)(uint8)tail[ 3]) << 24U; + case 3: k1 ^= ((uint64)(uint8)tail[ 2]) << 16U; + case 2: k1 ^= ((uint64)(uint8)tail[ 1]) << 8U; + case 1: k1 ^= ((uint64)(uint8)tail[ 0]) << 0U; + k1 *= c1; k1 = _rotl64(k1,31); k1 *= c2; h1 ^= k1; + }; + + //---------- + // finalization + + h1 ^= len; h2 ^= len; + + h1 += h2; + h2 += h1; + + h1 = MurmurHash3_Fmix64(h1); + h2 = MurmurHash3_Fmix64(h2); + + h1 += h2; + h2 += h1; + // NOLINTEND + + return uint128{h1, h2}; +} + +} // namespace deimos + diff --git a/deimos/core/id_name.h b/deimos/core/id_name.h new file mode 100644 index 0000000..eb961ca --- /dev/null +++ b/deimos/core/id_name.h @@ -0,0 +1,21 @@ +#pragma once + +#include "deimos/core/base.h" +#include "deimos/core/hash.h" + +namespace deimos +{ + +struct IdName +{ + uint128 hash; + const char* name; + + explicit constexpr IdName(const char* name) : + hash{MurmurHash3_x64_128(name)}, + name{name} + {} +}; + +} // namespace deimos + -- cgit