Pull in changes from internal project

This commit is contained in:
doylet 2024-08-01 13:34:36 +10:00
parent 765b8255f7
commit 6b403eae71
32 changed files with 2317 additions and 1135 deletions

View File

@ -1,3 +1,4 @@
/*
////////////////////////////////////////////////////////////////////////////////
//
// $$$$$$\ $$$$$$$\ $$$$$$$\ $$$$$$$$\ $$$$$$\ $$\ $$$$$$$$\
@ -12,6 +13,7 @@
// dqn_cpp_file.h -- Functions to emit C++ formatted code
//
////////////////////////////////////////////////////////////////////////////////
*/
#if !defined(DQN_CPP_FILE_H)
#define DQN_CPP_FILE_H

View File

@ -13,7 +13,7 @@ pushd Build
REM O2 Optimisation Level 2
REM Oi Use CPU Intrinsics
REM Z7 Combine multi-debug files to one debug file
set common_flags=-D DQN_WITH_UNIT_TESTS -D DQN_UNIT_TESTS_WITH_MAIN -D DQN_UNIT_TESTS_WITH_KECCAK -D DQN_USE_STD_PRINTF %script_dir%\dqn.cpp
set common_flags=-D DQN_UNIT_TESTS_WITH_MAIN -D DQN_UNIT_TESTS_WITH_KECCAK -D DQN_USE_STD_PRINTF /Tp %script_dir%\dqn.cpp
set msvc_driver_flags=%common_flags% -MT -EHa -GR- -Od -Oi -Z7 -wd4201 -W4 -nologo

14
dqn.cpp
View File

@ -21,7 +21,17 @@
#if !defined(DQN_NO_METADESK)
DQN_MSVC_WARNING_PUSH
DQN_MSVC_WARNING_DISABLE(4505) // warning C4505: '<function>': unreferenced function with internal linkage has been removed
DQN_GCC_WARNING_PUSH
DQN_GCC_WARNING_DISABLE(-Wwrite-strings)
DQN_GCC_WARNING_DISABLE(-Wunused-but-set-variable)
DQN_GCC_WARNING_DISABLE(-Wsign-compare)
DQN_GCC_WARNING_DISABLE(-Wunused-function)
DQN_GCC_WARNING_DISABLE(-Wunused-result)
#include "External/metadesk/md.c"
DQN_GCC_WARNING_POP
DQN_MSVC_WARNING_POP
#endif
#define DQN_CPP_FILE_IMPLEMENTATION
@ -34,13 +44,13 @@
#endif
#include "dqn_base.cpp"
#include "dqn_thread_context.cpp"
#include "dqn_external.cpp"
#include "dqn_allocator.cpp"
#include "dqn_debug.cpp"
#include "dqn_string.cpp"
#include "dqn_containers.cpp"
#include "dqn_type_info.cpp"
#include "dqn_os.cpp"
#if defined(DQN_PLATFORM_EMSCRIPTEN) || defined(DQN_PLATFORM_POSIX) || defined(DQN_PLATFORM_ARM64)
#include "dqn_os_posix.cpp"
@ -50,7 +60,7 @@
#error Please define a platform e.g. 'DQN_PLATFORM_WIN32' to enable the correct implementation for platform APIs
#endif
#include "dqn_os.cpp"
#include "dqn_tls.cpp"
#include "dqn_math.cpp"
#include "dqn_hash.cpp"
#include "dqn_helpers.cpp"

11
dqn.h
View File

@ -126,7 +126,7 @@
//
// Allocations are stored in a global hash-table and their respective stack
// traces for the allocation location. Memory leaks can be dumped at the end
// of the program or some epoch by calling Dqn_Library_DumpLeaks()
// of the program or some epoch by calling Dqn_Debug_DumpLeaks()
//
// #define DQN_LEAK_TRACKING
//
@ -300,17 +300,14 @@
#define _CRT_SECURE_NO_WARNINGS
#define DQN_UNDO_CRT_SECURE_NO_WARNINGS
#endif
#define MD_DEFAULT_SPRINTF 0
#define MD_IMPL_Vsnprintf DQN_VSNPRINTF
#include "External/metadesk/md.h"
#if defined(DQN_UNDO_CRT_SECURE_NO_WARNINGS)
#undef _CRT_SECURE_NO_WARNINGS
#endif
#endif
// Metadesk includes 'stb_sprintf.h' already
#if !defined(DQN_STB_SPRINTF_HEADER_ONLY)
#define DQN_STB_SPRINTF_HEADER_ONLY
#endif
// Metadesk includes Windows.h
#define DQN_NO_WIN32_MIN_HEADER
#endif
@ -321,7 +318,7 @@
#include "dqn_win32.h"
#endif
#include "dqn_allocator.h"
#include "dqn_thread_context.h"
#include "dqn_tls.h"
#include "dqn_debug.h"
#include "dqn_string.h"
#include "dqn_containers.h"

View File

@ -56,11 +56,28 @@ DQN_API Dqn_ArenaBlock *Dqn_Arena_BlockInitFlags(uint64_t reserve, uint64_t comm
return result;
}
static void Dqn_Arena_UpdateStatsOnNewBlock_(Dqn_Arena *arena, Dqn_ArenaBlock const *block)
{
DQN_ASSERT(arena);
if (block) {
arena->stats.info.used += block->used;
arena->stats.info.commit += block->commit;
arena->stats.info.reserve += block->reserve;
arena->stats.info.blocks += 1;
arena->stats.hwm.used = DQN_MAX(arena->stats.hwm.used, arena->stats.info.used);
arena->stats.hwm.commit = DQN_MAX(arena->stats.hwm.commit, arena->stats.info.commit);
arena->stats.hwm.reserve = DQN_MAX(arena->stats.hwm.reserve, arena->stats.info.reserve);
arena->stats.hwm.blocks = DQN_MAX(arena->stats.hwm.blocks, arena->stats.info.blocks);
}
}
DQN_API Dqn_Arena Dqn_Arena_InitSize(uint64_t reserve, uint64_t commit, uint8_t flags)
{
Dqn_Arena result = {};
result.flags = flags;
result.curr = Dqn_Arena_BlockInitFlags(reserve, commit, flags);
Dqn_Arena_UpdateStatsOnNewBlock_(&result, result.curr);
return result;
}
@ -123,8 +140,10 @@ DQN_API void *Dqn_Arena_Alloc(Dqn_Arena *arena, uint64_t size, uint8_t align, Dq
if (!arena)
return nullptr;
if (!arena->curr)
if (!arena->curr) {
arena->curr = Dqn_Arena_BlockInitFlags(DQN_ARENA_RESERVE_SIZE, DQN_ARENA_COMMIT_SIZE, arena->flags);
Dqn_Arena_UpdateStatsOnNewBlock_(arena, arena->curr);
}
if (!arena->curr)
return nullptr;
@ -147,6 +166,7 @@ DQN_API void *Dqn_Arena_Alloc(Dqn_Arena *arena, uint64_t size, uint8_t align, Dq
new_block->prev = arena->curr;
arena->curr = new_block;
new_block->reserve_sum = new_block->prev->reserve_sum + new_block->prev->reserve;
Dqn_Arena_UpdateStatsOnNewBlock_(arena, arena->curr);
goto try_alloc_again;
}
@ -159,11 +179,16 @@ DQN_API void *Dqn_Arena_Alloc(Dqn_Arena *arena, uint64_t size, uint8_t align, Dq
return nullptr;
if (poison)
Dqn_ASAN_PoisonMemoryRegion(commit_ptr, commit_size);
curr->commit = end_commit;
curr->commit = end_commit;
arena->stats.info.commit += commit_size;
arena->stats.hwm.commit = DQN_MAX(arena->stats.hwm.commit, arena->stats.info.commit);
}
void *result = DQN_CAST(char *) curr + offset_pos;
curr->used = end_pos;
void *result = DQN_CAST(char *) curr + offset_pos;
Dqn_usize alloc_size = end_pos - curr->used;
curr->used += alloc_size;
arena->stats.info.used += alloc_size;
arena->stats.hwm.used = DQN_MAX(arena->stats.hwm.used, arena->stats.info.used);
Dqn_ASAN_UnpoisonMemoryRegion(result, size);
if (zero_mem == Dqn_ZeroMem_Yes) {
@ -171,6 +196,10 @@ DQN_API void *Dqn_Arena_Alloc(Dqn_Arena *arena, uint64_t size, uint8_t align, Dq
DQN_MEMSET(result, 0, reused_bytes);
}
DQN_ASSERT(arena->stats.hwm.used >= arena->stats.info.used);
DQN_ASSERT(arena->stats.hwm.commit >= arena->stats.info.commit);
DQN_ASSERT(arena->stats.hwm.reserve >= arena->stats.info.reserve);
DQN_ASSERT(arena->stats.hwm.blocks >= arena->stats.info.blocks);
return result;
}
@ -195,21 +224,27 @@ DQN_API void *Dqn_Arena_Copy(Dqn_Arena *arena, void const *data, uint64_t size,
DQN_API void Dqn_Arena_PopTo(Dqn_Arena *arena, uint64_t init_used)
{
if (!arena)
if (!arena || !arena->curr)
return;
uint64_t used = DQN_MAX(DQN_ARENA_HEADER_SIZE, init_used);
Dqn_ArenaBlock *curr = arena->curr;
while (curr->reserve_sum >= used) {
Dqn_ArenaBlock *block_to_free = curr;
arena->stats.info.used -= block_to_free->used;
arena->stats.info.commit -= block_to_free->commit;
arena->stats.info.reserve -= block_to_free->reserve;
arena->stats.info.blocks -= 1;
curr = curr->prev;
Dqn_Arena_BlockDeinit_(arena, block_to_free);
}
arena->curr = curr;
curr->used = used - curr->reserve_sum;
char *poison_ptr = (char *)curr + Dqn_AlignUpPowerOfTwo(curr->used, DQN_ASAN_POISON_ALIGNMENT);
Dqn_usize poison_size = ((char *)curr + curr->commit) - poison_ptr;
arena->stats.info.used -= curr->used;
arena->curr = curr;
curr->used = used - curr->reserve_sum;
char *poison_ptr = (char *)curr + Dqn_AlignUpPowerOfTwo(curr->used, DQN_ASAN_POISON_ALIGNMENT);
Dqn_usize poison_size = ((char *)curr + curr->commit) - poison_ptr;
Dqn_ASAN_PoisonMemoryRegion(poison_ptr, poison_size);
arena->stats.info.used += curr->used;
}
DQN_API void Dqn_Arena_Pop(Dqn_Arena *arena, uint64_t amount)
@ -237,7 +272,7 @@ DQN_API bool Dqn_Arena_OwnsPtr(Dqn_Arena const *arena, void *ptr)
{
bool result = false;
uintptr_t uint_ptr = DQN_CAST(uintptr_t)ptr;
for (Dqn_ArenaBlock const *block = arena ? arena->curr : nullptr; !result && block; ) {
for (Dqn_ArenaBlock const *block = arena ? arena->curr : nullptr; !result && block; block = block->prev) {
uintptr_t begin = DQN_CAST(uintptr_t) block + DQN_ARENA_HEADER_SIZE;
uintptr_t end = begin + block->reserve;
result = uint_ptr >= begin && uint_ptr <= end;
@ -245,6 +280,42 @@ DQN_API bool Dqn_Arena_OwnsPtr(Dqn_Arena const *arena, void *ptr)
return result;
}
DQN_API Dqn_ArenaStats Dqn_Arena_SumStatsArray(Dqn_ArenaStats const *array, Dqn_usize size)
{
Dqn_ArenaStats result = {};
DQN_FOR_UINDEX(index, size) {
Dqn_ArenaStats stats = array[index];
result.info.used += stats.info.used;
result.info.commit += stats.info.commit;
result.info.reserve += stats.info.reserve;
result.info.blocks += stats.info.blocks;
result.hwm.used = DQN_MAX(result.hwm.used, result.info.used);
result.hwm.commit = DQN_MAX(result.hwm.commit, result.info.commit);
result.hwm.reserve = DQN_MAX(result.hwm.reserve, result.info.reserve);
result.hwm.blocks = DQN_MAX(result.hwm.blocks, result.info.blocks);
}
return result;
}
DQN_API Dqn_ArenaStats Dqn_Arena_SumStats(Dqn_ArenaStats lhs, Dqn_ArenaStats rhs)
{
Dqn_ArenaStats array[] = {lhs, rhs};
Dqn_ArenaStats result = Dqn_Arena_SumStatsArray(array, DQN_ARRAY_UCOUNT(array));
return result;
}
DQN_API Dqn_ArenaStats Dqn_Arena_SumArenaArrayToStats(Dqn_Arena const *array, Dqn_usize size)
{
Dqn_ArenaStats result = {};
for (Dqn_usize index = 0; index < size; index++) {
Dqn_Arena const *arena = array + index;
result = Dqn_Arena_SumStats(result, arena->stats);
}
return result;
}
DQN_API Dqn_ArenaTempMem Dqn_Arena_TempMemBegin(Dqn_Arena *arena)
{
Dqn_ArenaTempMem result = {};
@ -299,13 +370,8 @@ DQN_API void *Dqn_ChunkPool_Alloc(Dqn_ChunkPool *pool, Dqn_usize size)
Dqn_usize const size_to_slot_offset = 5; // __lzcnt64(32) e.g. Dqn_ChunkPoolSlotSize_32B
Dqn_usize slot_index = 0;
if (required_size > 32) {
#if defined(DQN_OS_WIN32)
Dqn_usize dist_to_next_msb = __lzcnt64(required_size) + 1;
#else
Dqn_usize dist_to_next_msb = __builtin_clzll(required_size) + 1;
#endif
// NOTE: Round up if not PoT as the low bits are set.
Dqn_usize dist_to_next_msb = Dqn_CountLeadingZerosU64(required_size) + 1;
dist_to_next_msb -= DQN_CAST(Dqn_usize)(!Dqn_IsPowerOfTwo(required_size));
Dqn_usize const register_size = sizeof(Dqn_usize) * 8;
@ -401,14 +467,17 @@ DQN_API Dqn_Str8 Dqn_ChunkPool_AllocStr8Copy(Dqn_ChunkPool *pool, Dqn_Str8 strin
DQN_API void Dqn_ChunkPool_Dealloc(Dqn_ChunkPool *pool, void *ptr)
{
if (!Dqn_ChunkPool_IsValid(pool))
if (!Dqn_ChunkPool_IsValid(pool) || !ptr)
return;
Dqn_usize offset_to_original_ptr = 0;
DQN_MEMCPY(&offset_to_original_ptr, &(DQN_CAST(char *)ptr)[-1], 1);
DQN_ASSERT(Dqn_Arena_OwnsPtr(pool->arena, ptr));
char const *one_byte_behind_ptr = DQN_CAST(char *) ptr - 1;
Dqn_usize offset_to_original_ptr = 0;
DQN_MEMCPY(&offset_to_original_ptr, one_byte_behind_ptr, 1);
DQN_ASSERT(offset_to_original_ptr <= sizeof(Dqn_ChunkPoolSlot) + pool->align);
char *original_ptr = DQN_CAST(char *)ptr - offset_to_original_ptr;
char *original_ptr = DQN_CAST(char *)ptr - offset_to_original_ptr;
Dqn_ChunkPoolSlot *slot = DQN_CAST(Dqn_ChunkPoolSlot *)original_ptr;
Dqn_ChunkPoolSlotSize slot_index = DQN_CAST(Dqn_ChunkPoolSlotSize)(DQN_CAST(uintptr_t)slot->next);
DQN_ASSERT(slot_index < Dqn_ChunkPoolSlotSize_Count);
@ -417,6 +486,20 @@ DQN_API void Dqn_ChunkPool_Dealloc(Dqn_ChunkPool *pool, void *ptr)
pool->slots[slot_index] = slot;
}
DQN_API void *Dqn_ChunkPool_Copy(Dqn_ChunkPool *pool, void const *data, uint64_t size, uint8_t align)
{
if (!pool || !data || size == 0)
return nullptr;
// TODO: Hmm should align be part of the alloc interface in general? I'm not going to worry
// about this until we crash because of misalignment.
DQN_ASSERT(pool->align >= align);
void *result = Dqn_ChunkPool_Alloc(pool, size);
if (result)
DQN_MEMCPY(result, data, size);
return result;
}
// NOTE: [$ACAT] Dqn_ArenaCatalog //////////////////////////////////////////////////////////////////
DQN_API void Dqn_ArenaCatalog_Init(Dqn_ArenaCatalog *catalog, Dqn_ChunkPool *pool)
@ -440,7 +523,7 @@ DQN_API Dqn_ArenaCatalogItem *Dqn_ArenaCatalog_Find(Dqn_ArenaCatalog *catalog, D
return result;
}
DQN_API void Dqn_ArenaCatalog_AddLabelRef(Dqn_ArenaCatalog *catalog, Dqn_Arena *arena, Dqn_Str8 label)
static void Dqn_ArenaCatalog_AddInternal_(Dqn_ArenaCatalog *catalog, Dqn_Arena *arena, Dqn_Str8 label, bool arena_pool_allocated)
{
// NOTE: We could use an atomic for appending to the sentinel but it is such
// a rare operation to append to the catalog that we don't bother.
@ -451,6 +534,7 @@ DQN_API void Dqn_ArenaCatalog_AddLabelRef(Dqn_ArenaCatalog *catalog, Dqn_Arena *
if (result) {
result->arena = arena;
result->label = label;
result->arena_pool_allocated = arena_pool_allocated;
// NOTE: Add to the catalog (linked list)
Dqn_ArenaCatalogItem *sentinel = &catalog->sentinel;
@ -463,14 +547,6 @@ DQN_API void Dqn_ArenaCatalog_AddLabelRef(Dqn_ArenaCatalog *catalog, Dqn_Arena *
Dqn_TicketMutex_End(&catalog->ticket_mutex);
}
DQN_API void Dqn_ArenaCatalog_AddLabelCopy(Dqn_ArenaCatalog *catalog, Dqn_Arena *arena, Dqn_Str8 label)
{
Dqn_TicketMutex_Begin(&catalog->ticket_mutex);
Dqn_Str8 label_copy = Dqn_ChunkPool_AllocStr8Copy(catalog->pool, label);
Dqn_TicketMutex_End(&catalog->ticket_mutex);
Dqn_ArenaCatalog_AddLabelRef(catalog, arena, label_copy);
}
DQN_API void Dqn_ArenaCatalog_AddF(Dqn_ArenaCatalog *catalog, Dqn_Arena *arena, DQN_FMT_ATTRIB char const *fmt, ...)
{
va_list args;
@ -479,7 +555,7 @@ DQN_API void Dqn_ArenaCatalog_AddF(Dqn_ArenaCatalog *catalog, Dqn_Arena *arena,
Dqn_Str8 label = Dqn_ChunkPool_AllocStr8FV(catalog->pool, fmt, args);
Dqn_TicketMutex_End(&catalog->ticket_mutex);
va_end(args);
Dqn_ArenaCatalog_AddLabelRef(catalog, arena, label);
Dqn_ArenaCatalog_AddInternal_(catalog, arena, label, false /*arena_pool_allocated*/);
}
DQN_API void Dqn_ArenaCatalog_AddFV(Dqn_ArenaCatalog *catalog, Dqn_Arena *arena, DQN_FMT_ATTRIB char const *fmt, va_list args)
@ -487,35 +563,18 @@ DQN_API void Dqn_ArenaCatalog_AddFV(Dqn_ArenaCatalog *catalog, Dqn_Arena *arena,
Dqn_TicketMutex_Begin(&catalog->ticket_mutex);
Dqn_Str8 label = Dqn_ChunkPool_AllocStr8FV(catalog->pool, fmt, args);
Dqn_TicketMutex_End(&catalog->ticket_mutex);
Dqn_ArenaCatalog_AddLabelRef(catalog, arena, label);
}
DQN_API Dqn_Arena *Dqn_ArenaCatalog_AllocLabelRef(Dqn_ArenaCatalog *catalog, Dqn_usize reserve, Dqn_usize commit, uint8_t arena_flags, Dqn_Str8 label)
{
Dqn_TicketMutex_Begin(&catalog->ticket_mutex);
Dqn_Arena *result = Dqn_ChunkPool_New(catalog->pool, Dqn_Arena);
Dqn_TicketMutex_End(&catalog->ticket_mutex);
*result = Dqn_Arena_InitSize(reserve, commit, arena_flags);
Dqn_ArenaCatalog_AddLabelRef(catalog, result, label);
return result;
}
DQN_API Dqn_Arena *Dqn_ArenaCatalog_AllocLabelCopy(Dqn_ArenaCatalog *catalog, Dqn_usize reserve, Dqn_usize commit, uint8_t arena_flags, Dqn_Str8 label)
{
Dqn_TicketMutex_Begin(&catalog->ticket_mutex);
Dqn_Str8 label_copy = Dqn_ChunkPool_AllocStr8Copy(catalog->pool, label);
Dqn_TicketMutex_End(&catalog->ticket_mutex);
Dqn_Arena *result = Dqn_ArenaCatalog_AllocLabelRef(catalog, reserve, commit, arena_flags, label_copy);
return result;
Dqn_ArenaCatalog_AddInternal_(catalog, arena, label, false /*arena_pool_allocated*/);
}
DQN_API Dqn_Arena *Dqn_ArenaCatalog_AllocFV(Dqn_ArenaCatalog *catalog, Dqn_usize reserve, Dqn_usize commit, uint8_t arena_flags, DQN_FMT_ATTRIB char const *fmt, va_list args)
{
Dqn_TicketMutex_Begin(&catalog->ticket_mutex);
Dqn_Str8 label = Dqn_ChunkPool_AllocStr8FV(catalog->pool, fmt, args);
Dqn_Arena *result = Dqn_ChunkPool_New(catalog->pool, Dqn_Arena);
Dqn_TicketMutex_End(&catalog->ticket_mutex);
Dqn_Arena *result = Dqn_ArenaCatalog_AllocLabelRef(catalog, reserve, commit, arena_flags, label);
*result = Dqn_Arena_InitSize(reserve, commit, arena_flags);
Dqn_ArenaCatalog_AddInternal_(catalog, result, label, true /*arena_pool_allocated*/);
return result;
}
@ -525,8 +584,34 @@ DQN_API Dqn_Arena *Dqn_ArenaCatalog_AllocF(Dqn_ArenaCatalog *catalog, Dqn_usize
va_start(args, fmt);
Dqn_TicketMutex_Begin(&catalog->ticket_mutex);
Dqn_Str8 label = Dqn_ChunkPool_AllocStr8FV(catalog->pool, fmt, args);
Dqn_Arena *result = Dqn_ChunkPool_New(catalog->pool, Dqn_Arena);
Dqn_TicketMutex_End(&catalog->ticket_mutex);
Dqn_Arena *result = Dqn_ArenaCatalog_AllocLabelRef(catalog, reserve, commit, arena_flags, label);
va_end(args);
*result = Dqn_Arena_InitSize(reserve, commit, arena_flags);
Dqn_ArenaCatalog_AddInternal_(catalog, result, label, true /*arena_pool_allocated*/);
return result;
}
DQN_API bool Dqn_ArenaCatalog_Erase(Dqn_ArenaCatalog *catalog, Dqn_Arena *arena, Dqn_ArenaCatalogFreeArena free_arena)
{
bool result = false;
Dqn_TicketMutex_Begin(&catalog->ticket_mutex);
for (Dqn_ArenaCatalogItem *item = catalog->sentinel.next; item != &catalog->sentinel; item = item->next) {
if (item->arena == arena) {
item->next->prev = item->prev;
item->prev->next = item->next;
if (item->arena_pool_allocated) {
if (free_arena == Dqn_ArenaCatalogFreeArena_Yes)
Dqn_Arena_Deinit(item->arena);
Dqn_ChunkPool_Dealloc(catalog->pool, item->arena);
}
Dqn_ChunkPool_Dealloc(catalog->pool, item->label.data);
Dqn_ChunkPool_Dealloc(catalog->pool, item);
result = true;
break;
}
}
Dqn_TicketMutex_End(&catalog->ticket_mutex);
return result;
}

View File

@ -50,11 +50,26 @@ enum Dqn_ArenaFlag
Dqn_ArenaFlag_AllocCanLeak = 1 << 3,
};
struct Dqn_ArenaInfo
{
uint64_t used;
uint64_t commit;
uint64_t reserve;
uint64_t blocks;
};
struct Dqn_ArenaStats
{
Dqn_ArenaInfo info;
Dqn_ArenaInfo hwm;
};
struct Dqn_Arena
{
Dqn_ArenaBlock *curr;
uint8_t flags;
Dqn_ArenaStats stats;
Dqn_TicketMutex mutex; // For user code to lock the arena, the arena itself does not use.
uint8_t flags;
};
struct Dqn_ArenaTempMem
@ -131,6 +146,7 @@ struct Dqn_ArenaCatalogItem
{
Dqn_Arena *arena;
Dqn_Str8 label;
bool arena_pool_allocated;
Dqn_ArenaCatalogItem *next;
Dqn_ArenaCatalogItem *prev;
};
@ -143,6 +159,12 @@ struct Dqn_ArenaCatalog
uint16_t arena_count;
};
enum Dqn_ArenaCatalogFreeArena
{
Dqn_ArenaCatalogFreeArena_No,
Dqn_ArenaCatalogFreeArena_Yes,
};
// NOTE: [$AREN] Dqn_Arena /////////////////////////////////////////////////////////////////////////
DQN_API Dqn_Arena Dqn_Arena_InitSize (uint64_t reserve, uint64_t commit, uint8_t flags);
DQN_API void Dqn_Arena_Deinit (Dqn_Arena *arena);
@ -156,6 +178,9 @@ DQN_API void Dqn_Arena_Pop (Dqn_Arena *arena,
DQN_API uint64_t Dqn_Arena_Pos (Dqn_Arena const *arena);
DQN_API void Dqn_Arena_Clear (Dqn_Arena *arena);
DQN_API bool Dqn_Arena_OwnsPtr (Dqn_Arena const *arena, void *ptr);
DQN_API Dqn_ArenaStats Dqn_Arena_SumStatsArray (Dqn_ArenaStats const *array, Dqn_usize size);
DQN_API Dqn_ArenaStats Dqn_Arena_SumStats (Dqn_ArenaStats lhs, Dqn_ArenaStats rhs);
DQN_API Dqn_ArenaStats Dqn_Arena_SumArenaArrayToStats (Dqn_Arena const *array, Dqn_usize size);
DQN_API Dqn_ArenaTempMem Dqn_Arena_TempMemBegin (Dqn_Arena *arena);
DQN_API void Dqn_Arena_TempMemEnd (Dqn_ArenaTempMem mem);
#define Dqn_Arena_New(arena, T, zero_mem) (T *)Dqn_Arena_Alloc(arena, sizeof(T), alignof(T), zero_mem)
@ -164,7 +189,6 @@ DQN_API void Dqn_Arena_TempMemEnd (Dqn_ArenaTempMem m
#define Dqn_Arena_NewArrayCopy(arena, T, src, count) (T *)Dqn_Arena_Copy (arena, (src), sizeof(T) * (count), alignof(T))
// NOTE: [$CHUN] Dqn_ChunkPool /////////////////////////////////////////////////////////////////////
#define Dqn_ChunkPool_New(pool, T) (T *)Dqn_ChunkPool_Alloc(pool, sizeof(T))
DQN_API Dqn_ChunkPool Dqn_ChunkPool_Init (Dqn_Arena *arena, uint8_t align);
DQN_API bool Dqn_ChunkPool_IsValid (Dqn_ChunkPool const *pool);
DQN_API void * Dqn_ChunkPool_Alloc (Dqn_ChunkPool *pool, Dqn_usize size);
@ -172,15 +196,18 @@ DQN_API Dqn_Str8 Dqn_ChunkPool_AllocStr8FV (Dqn_ChunkPool *poo
DQN_API Dqn_Str8 Dqn_ChunkPool_AllocStr8F (Dqn_ChunkPool *pool, DQN_FMT_ATTRIB char const *fmt, ...);
DQN_API Dqn_Str8 Dqn_ChunkPool_AllocStr8Copy (Dqn_ChunkPool *pool, Dqn_Str8 string);
DQN_API void Dqn_ChunkPool_Dealloc (Dqn_ChunkPool *pool, void *ptr);
DQN_API void * Dqn_ChunkPool_Copy (Dqn_ChunkPool *pool, void const *data, uint64_t size, uint8_t align);
#define Dqn_ChunkPool_New(pool, T) (T *)Dqn_ChunkPool_Alloc(pool, sizeof(T))
#define Dqn_ChunkPool_NewArray(pool, T, count) (T *)Dqn_ChunkPool_Alloc(pool, count * sizeof(T))
#define Dqn_ChunkPool_NewCopy(arena, T, src) (T *)Dqn_ChunkPool_Copy (arena, (src), sizeof(T), alignof(T))
#define Dqn_ChunkPool_NewArrayCopy(arena, T, src, count) (T *)Dqn_ChunkPool_Copy (arena, (src), sizeof(T) * (count), alignof(T))
// NOTE: [$ACAT] Dqn_ArenaCatalog //////////////////////////////////////////////////////////////////
DQN_API void Dqn_ArenaCatalog_Init (Dqn_ArenaCatalog *catalog, Dqn_ChunkPool *pool);
DQN_API Dqn_ArenaCatalogItem *Dqn_ArenaCatalog_Find (Dqn_ArenaCatalog *catalog, Dqn_Str8 label);
DQN_API void Dqn_ArenaCatalog_AddLabelRef (Dqn_ArenaCatalog *catalog, Dqn_Arena *arena, Dqn_Str8 label);
DQN_API void Dqn_ArenaCatalog_AddLabelCopy (Dqn_ArenaCatalog *catalog, Dqn_Arena *arena, Dqn_Str8 label);
DQN_API void Dqn_ArenaCatalog_AddF (Dqn_ArenaCatalog *catalog, Dqn_Arena *arena, DQN_FMT_ATTRIB char const *fmt, ...);
DQN_API void Dqn_ArenaCatalog_AddFV (Dqn_ArenaCatalog *catalog, Dqn_Arena *arena, DQN_FMT_ATTRIB char const *fmt, va_list args);
DQN_API Dqn_Arena * Dqn_ArenaCatalog_AllocLabelRef (Dqn_ArenaCatalog *catalog, Dqn_usize reserve, Dqn_usize commit, uint8_t arena_flags, Dqn_Str8 label);
DQN_API Dqn_Arena * Dqn_ArenaCatalog_AllocLabelCopy(Dqn_ArenaCatalog *catalog, Dqn_usize reserve, Dqn_usize commit, uint8_t arena_flags, Dqn_Str8 label);
DQN_API Dqn_Arena * Dqn_ArenaCatalog_AllocFV (Dqn_ArenaCatalog *catalog, Dqn_usize reserve, Dqn_usize commit, uint8_t arena_flags, DQN_FMT_ATTRIB char const *fmt, va_list args);
DQN_API Dqn_Arena * Dqn_ArenaCatalog_AllocF (Dqn_ArenaCatalog *catalog, Dqn_usize reserve, Dqn_usize commit, uint8_t arena_flags, DQN_FMT_ATTRIB char const *fmt, ...);
DQN_API void Dqn_ArenaCatalog_Init (Dqn_ArenaCatalog *catalog, Dqn_ChunkPool *pool);
DQN_API Dqn_ArenaCatalogItem *Dqn_ArenaCatalog_Find (Dqn_ArenaCatalog *catalog, Dqn_Str8 label);
DQN_API void Dqn_ArenaCatalog_AddF (Dqn_ArenaCatalog *catalog, Dqn_Arena *arena, DQN_FMT_ATTRIB char const *fmt, ...);
DQN_API void Dqn_ArenaCatalog_AddFV (Dqn_ArenaCatalog *catalog, Dqn_Arena *arena, DQN_FMT_ATTRIB char const *fmt, va_list args);
DQN_API Dqn_Arena * Dqn_ArenaCatalog_AllocFV (Dqn_ArenaCatalog *catalog, Dqn_usize reserve, Dqn_usize commit, uint8_t arena_flags, DQN_FMT_ATTRIB char const *fmt, va_list args);
DQN_API Dqn_Arena * Dqn_ArenaCatalog_AllocF (Dqn_ArenaCatalog *catalog, Dqn_usize reserve, Dqn_usize commit, uint8_t arena_flags, DQN_FMT_ATTRIB char const *fmt, ...);
DQN_API bool Dqn_ArenaCatalog_Erase (Dqn_ArenaCatalog *catalog, Dqn_Arena *arena, Dqn_ArenaCatalogFreeArena free_arena);

View File

@ -77,8 +77,8 @@ DQN_API void Dqn_CPU_SetFeature(Dqn_CPUReport *report, Dqn_CPUFeature feature)
DQN_API Dqn_CPUReport Dqn_CPU_Report()
{
Dqn_CPUReport result = {};
Dqn_CPUIDResult fn_0000_[16] = {};
Dqn_CPUIDResult fn_8000_[64] = {};
Dqn_CPUIDResult fn_0000_[512] = {};
Dqn_CPUIDResult fn_8000_[512] = {};
int const EXTENDED_FUNC_BASE_EAX = 0x8000'0000;
int const REGISTER_SIZE = sizeof(fn_0000_[0].reg.eax);
@ -102,8 +102,10 @@ DQN_API Dqn_CPUReport Dqn_CPU_Report()
// NOTE: Enumerate all CPUID results for the known function counts /////////////////////////////
{
DQN_ASSERT((STANDARD_FUNC_MAX_EAX + 1) <= DQN_ARRAY_ICOUNT(fn_0000_));
DQN_ASSERT((DQN_CAST(Dqn_isize)EXTENDED_FUNC_MAX_EAX - EXTENDED_FUNC_BASE_EAX + 1) <= DQN_ARRAY_ICOUNT(fn_8000_));
DQN_ASSERTF((STANDARD_FUNC_MAX_EAX + 1) <= DQN_ARRAY_ICOUNT(fn_0000_),
"Max standard count is %zu", STANDARD_FUNC_MAX_EAX + 1);
DQN_ASSERTF((DQN_CAST(Dqn_isize)EXTENDED_FUNC_MAX_EAX - EXTENDED_FUNC_BASE_EAX + 1) <= DQN_ARRAY_ICOUNT(fn_8000_),
"Max extended count is %zu", DQN_CAST(Dqn_isize)EXTENDED_FUNC_MAX_EAX - EXTENDED_FUNC_BASE_EAX + 1);
for (int eax = 1; eax <= STANDARD_FUNC_MAX_EAX; eax++) {
Dqn_CPUIDArgs args = {};
@ -535,15 +537,15 @@ DQN_FILE_SCOPE void Dqn_Log_FVDefault_(Dqn_Str8 type, int log_type, void *user_d
// NOTE: Open log file for appending if requested //////////////////////////
Dqn_TicketMutex_Begin(&lib->log_file_mutex);
if (lib->log_to_file && !lib->log_file.handle && !lib->log_file.error) {
Dqn_Scratch scratch = Dqn_Scratch_Get(nullptr);
Dqn_Str8 log_path = Dqn_OS_PathConvertF(scratch.arena, "%.*s/dqn.log", DQN_STR_FMT(lib->exe_dir));
lib->log_file = Dqn_OS_FileOpen(log_path, Dqn_OSFileOpen_CreateAlways, Dqn_OSFileAccess_AppendOnly, nullptr);
Dqn_TLSTMem t_mem = Dqn_TLS_TMem(nullptr);
Dqn_Str8 log_path = Dqn_OS_PathF(t_mem.arena, "%.*s/dqn.log", DQN_STR_FMT(lib->exe_dir));
lib->log_file = Dqn_OS_FileOpen(log_path, Dqn_OSFileOpen_CreateAlways, Dqn_OSFileAccess_AppendOnly, nullptr);
}
Dqn_TicketMutex_End(&lib->log_file_mutex);
// NOTE: Generate the log header ///////////////////////////////////////////
Dqn_Scratch scratch = Dqn_Scratch_Get(nullptr);
Dqn_Str8 log_line = Dqn_Log_MakeStr8(scratch.arena, !lib->log_no_colour, type, log_type, call_site, fmt, args);
Dqn_TLSTMem t_mem = Dqn_TLS_TMem(nullptr);
Dqn_Str8 log_line = Dqn_Log_MakeStr8(t_mem.arena, !lib->log_no_colour, type, log_type, call_site, fmt, args);
// NOTE: Print log /////////////////////////////////////////////////////////
Dqn_Print_StdLn(Dqn_PrintStd_Out, log_line);
@ -597,13 +599,14 @@ DQN_API void Dqn_Log_TypeFCallSite(Dqn_LogType type, Dqn_CallSite call_site, DQN
// NOTE: [$ERRS] Dqn_ErrorSink /////////////////////////////////////////////////////////////////////
DQN_API Dqn_ErrorSink *Dqn_ErrorSink_Begin(Dqn_ErrorSinkMode mode)
{
Dqn_ThreadContext *thread_context = Dqn_ThreadContext_Get();
Dqn_ErrorSink *result = &thread_context->error_sink;
Dqn_ErrorSinkNode *node = Dqn_Arena_New(result->arena, Dqn_ErrorSinkNode, Dqn_ZeroMem_Yes);
node->next = result->stack;
node->arena_pos = Dqn_Arena_Pos(result->arena);
node->mode = mode;
result->stack = node;
Dqn_TLS *tls = Dqn_TLS_Get();
Dqn_ErrorSink *result = &tls->error_sink;
Dqn_usize arena_pos = Dqn_Arena_Pos(result->arena);
Dqn_ErrorSinkNode *node = Dqn_Arena_New(result->arena, Dqn_ErrorSinkNode, Dqn_ZeroMem_Yes);
node->next = result->stack;
node->arena_pos = arena_pos;
node->mode = mode;
result->stack = node;
return result;
}
@ -640,8 +643,8 @@ DQN_API void Dqn_ErrorSink_EndAndIgnore(Dqn_ErrorSink *error)
DQN_API bool Dqn_ErrorSink_EndAndLogError(Dqn_ErrorSink *error, Dqn_Str8 error_msg)
{
Dqn_Scratch scratch = Dqn_Scratch_Get(nullptr);
Dqn_ErrorSinkNode node = Dqn_ErrorSink_End(scratch.arena, error);
Dqn_TLSTMem t_mem = Dqn_TLS_TMem(nullptr);
Dqn_ErrorSinkNode node = Dqn_ErrorSink_End(t_mem.arena, error);
if (node.error) {
if (Dqn_Str8_HasData(error_msg)) {
Dqn_Log_TypeFCallSite(Dqn_LogType_Error, node.call_site, "%.*s: %.*s", DQN_STR_FMT(error_msg), DQN_STR_FMT(node.msg));
@ -655,8 +658,8 @@ DQN_API bool Dqn_ErrorSink_EndAndLogError(Dqn_ErrorSink *error, Dqn_Str8 error_m
DQN_API bool Dqn_ErrorSink_EndAndLogErrorFV(Dqn_ErrorSink *error, DQN_FMT_ATTRIB char const *fmt, va_list args)
{
Dqn_Scratch scratch = Dqn_Scratch_Get(nullptr);
Dqn_Str8 log = Dqn_Str8_InitFV(scratch.arena, fmt, args);
Dqn_TLSTMem t_mem = Dqn_TLS_TMem(nullptr);
Dqn_Str8 log = Dqn_Str8_InitFV(t_mem.arena, fmt, args);
bool result = Dqn_ErrorSink_EndAndLogError(error, log);
return result;
}
@ -665,8 +668,8 @@ DQN_API bool Dqn_ErrorSink_EndAndLogErrorF(Dqn_ErrorSink *error, DQN_FMT_ATTRIB
{
va_list args;
va_start(args, fmt);
Dqn_Scratch scratch = Dqn_Scratch_Get(nullptr);
Dqn_Str8 log = Dqn_Str8_InitFV(scratch.arena, fmt, args);
Dqn_TLSTMem t_mem = Dqn_TLS_TMem(nullptr);
Dqn_Str8 log = Dqn_Str8_InitFV(t_mem.arena, fmt, args);
bool result = Dqn_ErrorSink_EndAndLogError(error, log);
va_end(args);
return result;
@ -699,7 +702,7 @@ DQN_API void Dqn_ErrorSink_MakeFV_(Dqn_ErrorSink *error, uint32_t error_code, DQ
node->msg = Dqn_Str8_InitFV(error->arena, fmt, args);
node->error_code = error_code;
node->error = true;
node->call_site = Dqn_ThreadContext_Get()->call_site;
node->call_site = Dqn_TLS_Get()->call_site;
if (node->mode == Dqn_ErrorSinkMode_ExitOnError)
Dqn_ErrorSink_EndAndExitIfErrorF(error, error_code, "Fatal error %u", error_code);
}

View File

@ -145,16 +145,16 @@
#if !defined(DQN_MEMCPY) || !defined(DQN_MEMSET) || !defined(DQN_MEMCMP) || !defined(DQN_MEMMOVE)
#include <string.h>
#if !defined(DQN_MEMCPY)
#define DQN_MEMCPY(dest, src, count) memcpy(dest, src, count)
#define DQN_MEMCPY(dest, src, count) memcpy((dest), (src), (count))
#endif
#if !defined(DQN_MEMSET)
#define DQN_MEMSET(dest, value, count) memset(dest, value, count)
#define DQN_MEMSET(dest, value, count) memset((dest), (value), (count))
#endif
#if !defined(DQN_MEMCMP)
#define DQN_MEMCMP(lhs, rhs, count) memcmp(lhs, rhs, count)
#define DQN_MEMCMP(lhs, rhs, count) memcmp((lhs), (rhs), (count))
#endif
#if !defined(DQN_MEMMOVE)
#define DQN_MEMMOVE(dest, src, count) memmove(dest, src, count)
#define DQN_MEMMOVE(dest, src, count) memmove((dest), (src), (count))
#endif
#endif
@ -424,6 +424,9 @@ struct Dqn_ErrorSink
#define Dqn_Atomic_AddU64(target, value) _InterlockedExchangeAdd64((__int64 volatile *)target, value)
#define Dqn_Atomic_SubU32(target, value) Dqn_Atomic_AddU32(DQN_CAST(long volatile *)target, (long)-value)
#define Dqn_Atomic_SubU64(target, value) Dqn_Atomic_AddU64(target, (uint64_t)-value)
#define Dqn_CountLeadingZerosU64(value) __lzcnt64(value)
#define Dqn_CPU_TSC() __rdtsc()
#define Dqn_CompilerReadBarrierAndCPUReadFence _ReadBarrier(); _mm_lfence()
#define Dqn_CompilerWriteBarrierAndCPUWriteFence _WriteBarrier(); _mm_sfence()
@ -439,6 +442,8 @@ struct Dqn_ErrorSink
#define Dqn_Atomic_AddU64(target, value) __atomic_fetch_add(target, value, __ATOMIC_ACQ_REL)
#define Dqn_Atomic_SubU32(target, value) __atomic_fetch_sub(target, value, __ATOMIC_ACQ_REL)
#define Dqn_Atomic_SubU64(target, value) __atomic_fetch_sub(target, value, __ATOMIC_ACQ_REL)
#define Dqn_CountLeadingZerosU64(value) __builtin_clzll(value)
#if defined(DQN_COMPILER_GCC)
#define Dqn_CPU_TSC() __rdtsc()
#else
@ -752,8 +757,8 @@ DQN_API bool Dqn_ErrorSink_EndAndLogErrorF
DQN_API void Dqn_ErrorSink_EndAndExitIfErrorF (Dqn_ErrorSink *error, uint32_t exit_code, DQN_FMT_ATTRIB char const *fmt, ...);
DQN_API void Dqn_ErrorSink_EndAndExitIfErrorFV (Dqn_ErrorSink *error, uint32_t exit_code, DQN_FMT_ATTRIB char const *fmt, va_list args);
#define Dqn_ErrorSink_MakeFV(error, error_code, fmt, args) do { Dqn_ThreadContext_SaveCallSite; Dqn_ErrorSink_MakeFV_(error, error_code, fmt, args); } while (0)
#define Dqn_ErrorSink_MakeF(error, error_code, fmt, ...) do { Dqn_ThreadContext_SaveCallSite; Dqn_ErrorSink_MakeF_(error, error_code, fmt, ## __VA_ARGS__); } while (0)
#define Dqn_ErrorSink_MakeFV(error, error_code, fmt, args) do { Dqn_TLS_SaveCallSite; Dqn_ErrorSink_MakeFV_(error, error_code, fmt, args); } while (0)
#define Dqn_ErrorSink_MakeF(error, error_code, fmt, ...) do { Dqn_TLS_SaveCallSite; Dqn_ErrorSink_MakeF_(error, error_code, fmt, ## __VA_ARGS__); } while (0)
DQN_API void Dqn_ErrorSink_MakeFV_ (Dqn_ErrorSink *error, uint32_t error_code, DQN_FMT_ATTRIB char const *fmt, va_list args);
DQN_API void Dqn_ErrorSink_MakeF_ (Dqn_ErrorSink *error, uint32_t error_code, DQN_FMT_ATTRIB char const *fmt, ...);

View File

@ -1,3 +1,4 @@
/*
////////////////////////////////////////////////////////////////////////////////////////////////////
//
// $$$$$$\ $$$$$$\ $$$$$$$$\ $$\ $$\
@ -12,6 +13,7 @@
// dqn_cgen.cpp
//
////////////////////////////////////////////////////////////////////////////////////////////////////
*/
Dqn_CGenMapNodeToEnum const DQN_CGEN_TABLE_KEY_LIST[] =
{
@ -48,6 +50,7 @@ Dqn_CGenTableHeaderType const DQN_CGEN_TABLE_CODE_GEN_STRUCT_HEADER_LIST[] =
Dqn_CGenTableHeaderType_CppOpEquals,
Dqn_CGenTableHeaderType_CppArraySize,
Dqn_CGenTableHeaderType_CppArraySizeField,
Dqn_CGenTableHeaderType_CppLabel,
Dqn_CGenTableHeaderType_GenTypeInfo,
};
@ -57,6 +60,7 @@ Dqn_CGenTableHeaderType const DQN_CGEN_TABLE_CODE_GEN_ENUM_HEADER_LIST[] =
Dqn_CGenTableHeaderType_Table,
Dqn_CGenTableHeaderType_CppName,
Dqn_CGenTableHeaderType_CppValue,
Dqn_CGenTableHeaderType_CppLabel,
Dqn_CGenTableHeaderType_GenTypeInfo,
Dqn_CGenTableHeaderType_GenEnumCount,
};
@ -159,6 +163,7 @@ static bool Dqn_CGen_GatherTables_(Dqn_CGen *cgen, Dqn_ErrorSink *error)
// NOTE: Validate table headers ////////////////////////////////////////////////////////////
switch (table->type) {
case Dqn_CGenTableType_Nil: DQN_INVALID_CODE_PATH;
case Dqn_CGenTableType_Count: DQN_INVALID_CODE_PATH;
case Dqn_CGenTableType_Data: {
} break;
@ -299,7 +304,6 @@ DQN_API Dqn_CGen Dqn_CGen_InitFilesArgV(int argc, char const **argv, Dqn_ErrorSi
MD_String8 file_name = MD_S8CString(DQN_CAST(char *)argv[arg_index]);
MD_ParseResult parse_result = MD_ParseWholeFile(result.arena, file_name);
for (MD_Message *message = parse_result.errors.first; message != 0; message = message->next) {
MD_CodeLoc code_loc = MD_CodeLocFromNode(message->node);
has_error = true;
Dqn_CGen_LogF(message->kind, message->node, error, "%.*s", MD_S8VArg(message->string));
}
@ -324,6 +328,7 @@ DQN_API Dqn_Str8 Dqn_CGen_TableHeaderTypeToDeclStr8(Dqn_CGenTableHeaderType type
case Dqn_CGenTableHeaderType_CppOpEquals: result = DQN_STR8("cpp_op_equals"); break;
case Dqn_CGenTableHeaderType_CppArraySize: result = DQN_STR8("cpp_array_size"); break;
case Dqn_CGenTableHeaderType_CppArraySizeField: result = DQN_STR8("cpp_array_size_field"); break;
case Dqn_CGenTableHeaderType_CppLabel: result = DQN_STR8("cpp_label"); break;
case Dqn_CGenTableHeaderType_GenTypeInfo: result = DQN_STR8("gen_type_info"); break;
case Dqn_CGenTableHeaderType_GenEnumCount: result = DQN_STR8("gen_enum_count"); break;
case Dqn_CGenTableHeaderType_Count: result = DQN_STR8("XX BAD ENUM VALUE XX"); break;
@ -345,56 +350,63 @@ DQN_API Dqn_CGenMapNodeToEnum Dqn_CGen_MapNodeToEnumOrExit(MD_Node const *node,
if (result.enum_val == 0) {
MD_CodeLoc loc = MD_CodeLocFromNode(DQN_CAST(MD_Node *)node);
Dqn_Scratch scratch = Dqn_Scratch_Get(nullptr);
Dqn_TLSTMem tmem = Dqn_TLS_TMem(nullptr);
va_list args;
va_start(args, fmt);
Dqn_Str8 user_msg = Dqn_Str8_InitFV(scratch.arena, fmt, args);
Dqn_Str8 user_msg = Dqn_Str8_InitFV(tmem.arena, fmt, args);
va_end(args);
Dqn_Str8Builder builder = {};
builder.arena = scratch.arena;
builder.arena = tmem.arena;
Dqn_Str8Builder_AppendF(&builder, "%.*s: '%.*s' is not recognised, the supported values are ", DQN_STR_FMT(user_msg), MD_S8VArg(node->string));
Dqn_Str8Builder_AddF(&builder, "%.*s: '%.*s' is not recognised, the supported values are ", DQN_STR_FMT(user_msg), MD_S8VArg(node->string));
for (Dqn_usize index = 0; index < valid_keys_size; index++) {
Dqn_CGenMapNodeToEnum const *validator = valid_keys + index;
Dqn_Str8Builder_AppendF(&builder, DQN_CAST(char *)"%s'%.*s'", index ? ", " : "", DQN_STR_FMT(validator->node_string));
Dqn_Str8Builder_AddF(&builder, DQN_CAST(char *)"%s'%.*s'", index ? ", " : "", DQN_STR_FMT(validator->node_string));
}
Dqn_Str8 error_msg = Dqn_Str8Builder_Build(&builder, scratch.arena);
Dqn_Str8 error_msg = Dqn_Str8Builder_Build(&builder, tmem.arena);
MD_PrintMessageFmt(stderr, loc, MD_MessageKind_Error, DQN_CAST(char *) "%.*s", DQN_STR_FMT(error_msg));
Dqn_OS_Exit(DQN_CAST(uint32_t)-1);
}
return result;
}
DQN_API Dqn_usize Dqn_CGen_NodeChildrenCount(MD_Node const *node)
{
Dqn_usize result = 0;
for (MD_EachNode(item, node->first_child))
result++;
return result;
}
DQN_API void Dqn_CGen_LogF(MD_MessageKind kind, MD_Node *node, Dqn_ErrorSink *error, char const *fmt, ...)
{
if (!error)
return;
Dqn_Scratch scratch = Dqn_Scratch_Get(nullptr);
Dqn_Str8Builder builder = {};
builder.arena = scratch.arena;
Dqn_TLSTMem tmem = Dqn_TLS_PushTMem(nullptr);
Dqn_Str8Builder builder = Dqn_Str8Builder_Init_TLS();
MD_String8 kind_string = MD_StringFromMessageKind(kind);
MD_CodeLoc loc = MD_CodeLocFromNode(node);
Dqn_Str8Builder_AppendF(&builder, "" MD_FmtCodeLoc " %.*s: ", MD_CodeLocVArg(loc), MD_S8VArg(kind_string));
Dqn_Str8Builder_AddF(&builder, "" MD_FmtCodeLoc " %.*s: ", MD_CodeLocVArg(loc), MD_S8VArg(kind_string));
va_list args;
va_start(args, fmt);
Dqn_Str8Builder_AppendFV(&builder, fmt, args);
Dqn_Str8Builder_AddFV(&builder, fmt, args);
va_end(args);
Dqn_Str8 msg = Dqn_Str8Builder_Build(&builder, scratch.arena);
Dqn_Str8 msg = Dqn_Str8Builder_Build(&builder, tmem.arena);
Dqn_ErrorSink_MakeF(error, DQN_CAST(uint32_t)-1, "%.*s", DQN_STR_FMT(msg));
}
DQN_API bool Dqn_CGen_TableHasHeaders(Dqn_CGenTable const *table, Dqn_Str8 const *headers, Dqn_usize header_count, Dqn_ErrorSink *error)
{
bool result = true;
Dqn_Scratch scratch = Dqn_Scratch_Get(nullptr);
Dqn_TLSTMem tmem = Dqn_TLS_TMem(nullptr);
Dqn_Str8Builder builder = {};
builder.arena = scratch.arena;
builder.arena = tmem.arena;
for (Dqn_usize index = 0; index < header_count; index++) {
Dqn_Str8 header = headers[index];
@ -402,12 +414,12 @@ DQN_API bool Dqn_CGen_TableHasHeaders(Dqn_CGenTable const *table, Dqn_Str8 const
MD_MapSlot *slot = MD_MapLookup(DQN_CAST(MD_Map *)&table->headers_map, MD_MapKeyStr(header_md));
if (!slot) {
result = false;
Dqn_Str8Builder_AppendF(&builder, "%s%.*s", builder.count ? ", " : "", DQN_STR_FMT(header));
Dqn_Str8Builder_AddF(&builder, "%s%.*s", builder.count ? ", " : "", DQN_STR_FMT(header));
}
}
if (!result) {
Dqn_Str8 missing_headers = Dqn_Str8Builder_Build(&builder, scratch.arena);
Dqn_Str8 missing_headers = Dqn_Str8Builder_Build(&builder, tmem.arena);
Dqn_CGen_LogF(MD_MessageKind_Error,
table->headers_node,
error,
@ -482,6 +494,26 @@ DQN_API bool Dqn_CGen_LookupNextTableInCodeGenTable(Dqn_CGen *cgen, Dqn_CGenTabl
return true;
}
DQN_API bool Dqn_CGen_WillCodeGenTypeName(Dqn_CGen const *cgen, Dqn_Str8 name)
{
if (!Dqn_Str8_HasData(name))
return false;
for (Dqn_CGenTable *table = cgen->first_table; table != 0; table = table->next) {
if (table->type != Dqn_CGenTableType_CodeGenStruct && table->type != Dqn_CGenTableType_CodeGenEnum)
continue;
for (Dqn_usize row_index = 0; row_index < table->row_count; row_index++) {
Dqn_CGenTableRow const *row = table->rows + row_index;
Dqn_CGenTableColumn const *column = row->columns + table->column_indexes[Dqn_CGenTableHeaderType_Name];
if (column->string == name)
return true;
}
}
return false;
}
static void Dqn_CGen_EmitRowWhitespace_(Dqn_CGenTableRow const *row, Dqn_CppFile *cpp)
{
for (Dqn_CGenTableRowTag *tag = row->first_tag; tag; tag = tag->next) {
@ -492,8 +524,8 @@ static void Dqn_CGen_EmitRowWhitespace_(Dqn_CGenTableRow const *row, Dqn_CppFile
if (tag->comment.size <= 0)
break;
Dqn_Scratch scratch = Dqn_Scratch_Get(nullptr);
Dqn_Str8 prefix = Dqn_Str8_InitF(scratch.arena, "// NOTE: %.*s ", MD_S8VArg(tag->comment));
Dqn_TLSTMem tmem = Dqn_TLS_TMem(nullptr);
Dqn_Str8 prefix = Dqn_Str8_InitF(tmem.arena, "// NOTE: %.*s ", MD_S8VArg(tag->comment));
int line_padding = DQN_MAX(100 - (DQN_CAST(int) prefix.size + (Dqn_CppSpacePerIndent(cpp) * cpp->indent)), 0);
Dqn_CppPrint(cpp, "%.*s", DQN_STR_FMT(prefix));
for (int index = 0; index < line_padding; index++)
@ -508,62 +540,105 @@ static void Dqn_CGen_EmitRowWhitespace_(Dqn_CGenTableRow const *row, Dqn_CppFile
}
}
Dqn_Str8 Dqn_CGen_StripQualifiersOnCppType_(Dqn_Arena *arena, Dqn_Str8 type)
{
Dqn_TLSTMem tmem = Dqn_TLS_TMem(arena);
Dqn_Str8 result = Dqn_Str8_TrimWhitespaceAround(type);
result = Dqn_Str8_Replace(result, /*find*/ DQN_STR8("*"), /*replace*/ DQN_STR8(""), /*start_index*/ 0, tmem.arena, Dqn_Str8EqCase_Sensitive);
result = Dqn_Str8_Replace(result, /*find*/ DQN_STR8("constexpr"), /*replace*/ DQN_STR8(""), /*start_index*/ 0, tmem.arena, Dqn_Str8EqCase_Sensitive);
result = Dqn_Str8_Replace(result, /*find*/ DQN_STR8("const"), /*replace*/ DQN_STR8(""), /*start_index*/ 0, tmem.arena, Dqn_Str8EqCase_Sensitive);
result = Dqn_Str8_Replace(result, /*find*/ DQN_STR8("static"), /*replace*/ DQN_STR8(""), /*start_index*/ 0, tmem.arena, Dqn_Str8EqCase_Sensitive);
result = Dqn_Str8_Replace(result, /*find*/ DQN_STR8(" "), /*replace*/ DQN_STR8(""), /*start_index*/ 0, arena, Dqn_Str8EqCase_Sensitive);
result = Dqn_Str8_TrimWhitespaceAround(result);
return result;
}
DQN_API void Dqn_CGen_EmitCodeForTables(Dqn_CGen *cgen, Dqn_CGenEmit emit, Dqn_CppFile *cpp, Dqn_Str8 emit_prefix)
{
DQN_ASSERT(Dqn_Str8_HasData(emit_prefix));
if (emit & Dqn_CGenEmit_Prototypes) {
// NOTE: Generate type info enums //////////////////////////////////////////////////////////
Dqn_CppEnumBlock(cpp, "%.*s_Type", DQN_STR_FMT(emit_prefix)) {
Dqn_CppLine(cpp, "%.*s_Type_Nil,", DQN_STR_FMT(emit_prefix));
Dqn_CppEnumBlock(cpp, "%.*sType", DQN_STR_FMT(emit_prefix)) {
Dqn_CppLine(cpp, "%.*sType_Nil,", DQN_STR_FMT(emit_prefix));
for (Dqn_CGenTable *table = cgen->first_table; table != 0; table = table->next) {
for (Dqn_CGenLookupTableIterator it = {}; Dqn_CGen_LookupNextTableInCodeGenTable(cgen, table, &it);)
Dqn_CppLine(cpp, "%.*s_Type_%.*s,", DQN_STR_FMT(emit_prefix), DQN_STR_FMT(it.cgen_table_column[Dqn_CGenTableHeaderType_Name].string));
Dqn_CppLine(cpp, "%.*sType_%.*s,", DQN_STR_FMT(emit_prefix), DQN_STR_FMT(it.cgen_table_column[Dqn_CGenTableHeaderType_Name].string));
}
Dqn_CppLine(cpp, "%.*s_Type_Count,", DQN_STR_FMT(emit_prefix));
Dqn_CppLine(cpp, "%.*sType_Count,", DQN_STR_FMT(emit_prefix));
}
Dqn_CppNewLine(cpp);
// NOTE: Generate structs + enums //////////////////////////////////////////////////////////////
for (Dqn_CGenTable *table = cgen->first_table; table != 0; table = table->next) {
switch (table->type) {
case Dqn_CGenTableType_Nil: DQN_INVALID_CODE_PATH;
case Dqn_CGenTableType_Data: continue;
case Dqn_CGenTableType_Nil: DQN_INVALID_CODE_PATH;
case Dqn_CGenTableType_Count: DQN_INVALID_CODE_PATH;
case Dqn_CGenTableType_CodeGenBuiltinTypes: continue;
case Dqn_CGenTableType_Data: continue;
case Dqn_CGenTableType_CodeGenStruct: {
for (Dqn_CGenLookupTableIterator it = {}; Dqn_CGen_LookupNextTableInCodeGenTable(cgen, table, &it); ) {
// TODO(doyle): Verify the codegen table has the headers from the table it references
Dqn_CppStructBlock(cpp, "%.*s", DQN_STR_FMT(it.cgen_table_column[Dqn_CGenTableHeaderType_Name].string)) {
int longest_type_name = 0;
for (Dqn_usize row_index = 0; row_index < it.table->row_count; row_index++) {
Dqn_TLSTMem tmem = Dqn_TLS_TMem(nullptr);
Dqn_CGenTableRow const *row = it.table->rows + row_index;
Dqn_CGenLookupColumnAtHeader cpp_type = Dqn_CGen_LookupColumnAtHeader(it.table, it.cgen_table_column[Dqn_CGenTableHeaderType_CppType].string, row);
Dqn_usize length = cpp_type.column.string.size;
Dqn_Str8 find_name = Dqn_CGen_StripQualifiersOnCppType_(tmem.arena, cpp_type.column.string);
if (Dqn_CGen_WillCodeGenTypeName(cgen, find_name))
length += emit_prefix.size;
longest_type_name = DQN_MAX(longest_type_name, DQN_CAST(int)length);
}
Dqn_CppStructBlock(cpp, "%.*s%.*s", DQN_STR_FMT(emit_prefix), DQN_STR_FMT(it.cgen_table_column[Dqn_CGenTableHeaderType_Name].string)) {
for (Dqn_usize row_index = 0; row_index < it.table->row_count; row_index++) {
Dqn_CGenTableRow const *row = it.table->rows + row_index;
Dqn_CGenLookupColumnAtHeader cpp_name = Dqn_CGen_LookupColumnAtHeader(it.table, it.cgen_table_column[Dqn_CGenTableHeaderType_CppName].string, row);
Dqn_CGenLookupColumnAtHeader cpp_type = Dqn_CGen_LookupColumnAtHeader(it.table, it.cgen_table_column[Dqn_CGenTableHeaderType_CppType].string, row);
Dqn_CGenLookupColumnAtHeader cpp_array_size = Dqn_CGen_LookupColumnAtHeader(it.table, it.cgen_table_column[Dqn_CGenTableHeaderType_CppArraySize].string, row);
int name_to_type_padding = 1 + it.table->headers[cpp_type.index].longest_string - DQN_CAST(int) cpp_type.column.string.size;
if (cpp_name.column.string.size <= 0 || cpp_type.column.string.size <= 0)
continue;
Dqn_CGen_EmitRowWhitespace_(row, cpp);
Dqn_Scratch scratch = Dqn_Scratch_Get(nullptr);
// NOTE: Generate cpp array size ///////////////////////////////////
Dqn_TLSTMem tmem = Dqn_TLS_TMem(nullptr);
Dqn_Str8 array_size = {};
if (cpp_array_size.column.string.size)
array_size = Dqn_Str8_InitF(scratch.arena, "[%.*s]", DQN_STR_FMT(cpp_array_size.column.string));
array_size = Dqn_Str8_InitF(tmem.arena, "[%.*s]", DQN_STR_FMT(cpp_array_size.column.string));
// NOTE: Check if we're referencing a code generated type. If we
// are, append the `emit_prefix`
Dqn_Str8 emit_cpp_type = cpp_type.column.string;
{
Dqn_Str8 find_name = Dqn_CGen_StripQualifiersOnCppType_(tmem.arena, emit_cpp_type);
if (Dqn_CGen_WillCodeGenTypeName(cgen, find_name))
emit_cpp_type = Dqn_Str8_InitF(tmem.arena, "%.*s%.*s", DQN_STR_FMT(emit_prefix), DQN_STR_FMT(cpp_type.column.string));
}
int name_to_type_padding = 1 + longest_type_name - DQN_CAST(int) emit_cpp_type.size;
// NOTE: Emit decl /////////////////////////////////////////////////
Dqn_CGen_EmitRowWhitespace_(row, cpp);
Dqn_CppLine(cpp,
"%.*s%*s%.*s%.*s;",
DQN_STR_FMT(cpp_type.column.string),
DQN_STR_FMT(emit_cpp_type),
name_to_type_padding,
"",
DQN_STR_FMT(cpp_name.column.string),
DQN_STR_FMT(array_size));
}
}
Dqn_CppNewLine(cpp);
Dqn_CppNewLine(cpp);
}
} break;
case Dqn_CGenTableType_CodeGenEnum: {
for (Dqn_CGenLookupTableIterator it = {}; Dqn_CGen_LookupNextTableInCodeGenTable(cgen, table, &it); ) {
Dqn_CppEnumBlock(cpp, "%.*s", DQN_STR_FMT(it.cgen_table_column[Dqn_CGenTableHeaderType_Name].string)) {
Dqn_CppEnumBlock(cpp, "%.*s%.*s", DQN_STR_FMT(emit_prefix), DQN_STR_FMT(it.cgen_table_column[Dqn_CGenTableHeaderType_Name].string)) {
Dqn_usize enum_count = 0;
for (Dqn_usize row_index = 0; row_index < it.table->row_count; row_index++) {
Dqn_CGenTableRow const *row = it.table->rows + row_index;
@ -576,13 +651,15 @@ DQN_API void Dqn_CGen_EmitCodeForTables(Dqn_CGen *cgen, Dqn_CGenEmit emit, Dqn_C
Dqn_CGen_EmitRowWhitespace_(row, cpp);
if (cpp_value.column.string.size) {
Dqn_CppLine(cpp,
"%.*s_%.*s = %.*s,",
"%.*s%.*s_%.*s = %.*s,",
DQN_STR_FMT(emit_prefix),
DQN_STR_FMT(it.cgen_table_column[Dqn_CGenTableHeaderType_Name].string),
DQN_STR_FMT(cpp_name.column.string),
DQN_STR_FMT(cpp_value.column.string));
} else {
Dqn_CppLine(cpp,
"%.*s_%.*s = %zu,",
"%.*s%.*s_%.*s = %zu,",
DQN_STR_FMT(emit_prefix),
DQN_STR_FMT(it.cgen_table_column[Dqn_CGenTableHeaderType_Name].string),
DQN_STR_FMT(cpp_name.column.string),
row_index);
@ -593,11 +670,13 @@ DQN_API void Dqn_CGen_EmitCodeForTables(Dqn_CGen *cgen, Dqn_CGenEmit emit, Dqn_C
Dqn_CGenTableColumn gen_enum_count_column = it.cgen_table_column[Dqn_CGenTableHeaderType_GenEnumCount];
if (gen_enum_count_column.string.size)
Dqn_CppLine(cpp,
"%.*s_%.*s = %zu,",
"%.*s%.*s_%.*s = %zu,",
DQN_STR_FMT(emit_prefix),
DQN_STR_FMT(it.cgen_table_column[Dqn_CGenTableHeaderType_Name].string),
DQN_STR_FMT(gen_enum_count_column.string),
enum_count);
}
Dqn_CppNewLine(cpp);
}
} break;
}
@ -606,24 +685,27 @@ DQN_API void Dqn_CGen_EmitCodeForTables(Dqn_CGen *cgen, Dqn_CGenEmit emit, Dqn_C
// NOTE: Generate enums for struct fields //////////////////////////////////////////////////
for (Dqn_CGenTable *table = cgen->first_table; table != 0; table = table->next) {
switch (table->type) {
case Dqn_CGenTableType_Nil: DQN_INVALID_CODE_PATH;
case Dqn_CGenTableType_Data: continue;
case Dqn_CGenTableType_CodeGenEnum: continue;
case Dqn_CGenTableType_Nil: DQN_INVALID_CODE_PATH;
case Dqn_CGenTableType_Count: DQN_INVALID_CODE_PATH;
case Dqn_CGenTableType_Data: continue;
case Dqn_CGenTableType_CodeGenBuiltinTypes: continue;
case Dqn_CGenTableType_CodeGenEnum: continue;
case Dqn_CGenTableType_CodeGenStruct: {
for (Dqn_CGenLookupTableIterator it = {}; Dqn_CGen_LookupNextTableInCodeGenTable(cgen, table, &it); ) {
Dqn_Str8 struct_name = it.cgen_table_column[Dqn_CGenTableHeaderType_Name].string;
Dqn_CppEnumBlock(cpp, "%.*sTypeField", DQN_STR_FMT(struct_name)) {
Dqn_CppEnumBlock(cpp, "%.*s%.*sTypeField", DQN_STR_FMT(emit_prefix), DQN_STR_FMT(struct_name)) {
for (Dqn_usize row_index = 0; row_index < it.table->row_count; row_index++) {
Dqn_CGenTableRow const *row = it.table->rows + row_index;
Dqn_CGenLookupColumnAtHeader cpp_name = Dqn_CGen_LookupColumnAtHeader(it.table, it.cgen_table_column[Dqn_CGenTableHeaderType_CppName].string, row);
if (cpp_name.column.string.size <= 0)
continue;
Dqn_CGen_EmitRowWhitespace_(row, cpp);
Dqn_CppLine(cpp, "%.*sTypeField_%.*s,", DQN_STR_FMT(struct_name), DQN_STR_FMT(cpp_name.column.string));
Dqn_CppLine(cpp, "%.*s%.*sTypeField_%.*s,", DQN_STR_FMT(emit_prefix), DQN_STR_FMT(struct_name), DQN_STR_FMT(cpp_name.column.string));
}
Dqn_CppLine(cpp, "%.*sTypeField_Count,", DQN_STR_FMT(struct_name));
Dqn_CppLine(cpp, "%.*s%.*sTypeField_Count,", DQN_STR_FMT(emit_prefix), DQN_STR_FMT(struct_name));
}
Dqn_CppNewLine(cpp);
}
} break;
}
@ -636,10 +718,11 @@ DQN_API void Dqn_CGen_EmitCodeForTables(Dqn_CGen *cgen, Dqn_CGenEmit emit, Dqn_C
for (Dqn_CGenLookupTableIterator it = {}; Dqn_CGen_LookupNextTableInCodeGenTable(cgen, table, &it);) {
Dqn_Str8 type_name = it.cgen_table_column[Dqn_CGenTableHeaderType_Name].string;
Dqn_CppStructBlock(cpp, "%.*sStr8ToEnumResult", DQN_STR_FMT(type_name)) {
Dqn_CppStructBlock(cpp, "%.*s%.*sStr8ToEnumResult", DQN_STR_FMT(emit_prefix), DQN_STR_FMT(type_name)) {
Dqn_CppLine(cpp, "bool success;");
Dqn_CppLine(cpp, "%.*s value;", DQN_STR_FMT(type_name));
Dqn_CppLine(cpp, "%.*s%.*s value;", DQN_STR_FMT(emit_prefix), DQN_STR_FMT(type_name));
}
Dqn_CppNewLine(cpp);
}
}
@ -649,7 +732,12 @@ DQN_API void Dqn_CGen_EmitCodeForTables(Dqn_CGen *cgen, Dqn_CGenEmit emit, Dqn_C
for (Dqn_CGenLookupTableIterator it = {}; Dqn_CGen_LookupNextTableInCodeGenTable(cgen, table, &it);) {
Dqn_Str8 type_name = it.cgen_table_column[Dqn_CGenTableHeaderType_Name].string;
Dqn_CppLine(cpp, "%.*sStr8ToEnumResult %.*s_Str8ToEnum(Dqn_Str8 string);", DQN_STR_FMT(type_name), DQN_STR_FMT(type_name));
Dqn_CppLine(cpp,
"%.*s%.*sStr8ToEnumResult %.*s%.*s_Str8ToEnum(Dqn_Str8 string);",
DQN_STR_FMT(emit_prefix),
DQN_STR_FMT(type_name),
DQN_STR_FMT(emit_prefix),
DQN_STR_FMT(type_name));
}
}
@ -664,8 +752,18 @@ DQN_API void Dqn_CGen_EmitCodeForTables(Dqn_CGen *cgen, Dqn_CGenEmit emit, Dqn_C
continue;
Dqn_Str8 type_name = it.cgen_table_column[Dqn_CGenTableHeaderType_Name].string;
Dqn_CppLine(cpp, "bool operator==(%.*s const &lhs, %.*s const &rhs);", DQN_STR_FMT(type_name), DQN_STR_FMT(type_name));
Dqn_CppLine(cpp, "bool operator!=(%.*s const &lhs, %.*s const &rhs);", DQN_STR_FMT(type_name), DQN_STR_FMT(type_name));
Dqn_CppLine(cpp,
"bool operator==(%.*s%.*s const &lhs, %.*s%.*s const &rhs);",
DQN_STR_FMT(emit_prefix),
DQN_STR_FMT(type_name),
DQN_STR_FMT(emit_prefix),
DQN_STR_FMT(type_name));
Dqn_CppLine(cpp,
"bool operator!=(%.*s%.*s const &lhs, %.*s%.*s const &rhs);",
DQN_STR_FMT(emit_prefix),
DQN_STR_FMT(type_name),
DQN_STR_FMT(emit_prefix),
DQN_STR_FMT(type_name));
}
}
}
@ -679,8 +777,29 @@ DQN_API void Dqn_CGen_EmitCodeForTables(Dqn_CGen *cgen, Dqn_CGenEmit emit, Dqn_C
continue;
Dqn_Str8 struct_or_enum_name = it.cgen_table_column[Dqn_CGenTableHeaderType_Name].string;
Dqn_CppBlock(cpp, ";\n\n", "Dqn_TypeField const g_%.*s_type_fields[] =", DQN_STR_FMT(struct_or_enum_name)) {
Dqn_CppBlock(cpp, ";\n\n", "Dqn_TypeField const g_%.*s%.*s_type_fields[] =", DQN_STR_FMT(emit_prefix), DQN_STR_FMT(struct_or_enum_name)) {
if (table->type == Dqn_CGenTableType_CodeGenStruct) {
// NOTE: Construct the cpp type string first. We will prepend `emit_prefix`
// for types that are declared in the same mdesk file. We will also
// calculate the longest type name that we will generate for whitespace
// padding purposes.
Dqn_TLSTMem tmem = Dqn_TLS_PushTMem(nullptr);
Dqn_usize longest_cpp_type_name = 0;
auto cpp_type_list = Dqn_SArray_Init<Dqn_Str8>(tmem.arena, it.table->row_count, Dqn_ZeroMem_Yes);
for (Dqn_usize row_index = 0; row_index < it.table->row_count; row_index++) {
Dqn_CGenTableRow const *row = it.table->rows + row_index;
Dqn_CGenLookupColumnAtHeader cpp_type = Dqn_CGen_LookupColumnAtHeader(it.table, it.cgen_table_column[Dqn_CGenTableHeaderType_CppType].string, row);
Dqn_Str8 cpp_type_name = Dqn_CGen_StripQualifiersOnCppType_(tmem.arena, cpp_type.column.string);
if (Dqn_CGen_WillCodeGenTypeName(cgen, cpp_type_name))
cpp_type_name = Dqn_Str8_InitF_TLS("%.*s%.*s", DQN_STR_FMT(emit_prefix), DQN_STR_FMT(cpp_type_name));
longest_cpp_type_name = DQN_MAX(longest_cpp_type_name, cpp_type_name.size);
Dqn_SArray_Add(&cpp_type_list, cpp_type_name);
}
// NOTE: Iterate each row and emit the C++ declarations ////////////////////
for (Dqn_usize row_index = 0; row_index < it.table->row_count; row_index++) {
Dqn_CGenTableRow const *row = it.table->rows + row_index;
Dqn_CGenLookupColumnAtHeader cpp_name = Dqn_CGen_LookupColumnAtHeader(it.table, it.cgen_table_column[Dqn_CGenTableHeaderType_CppName].string, row);
@ -688,12 +807,12 @@ DQN_API void Dqn_CGen_EmitCodeForTables(Dqn_CGen *cgen, Dqn_CGenEmit emit, Dqn_C
Dqn_CGenLookupColumnAtHeader cpp_is_ptr = Dqn_CGen_LookupColumnAtHeader(it.table, it.cgen_table_column[Dqn_CGenTableHeaderType_CppIsPtr].string, row);
Dqn_CGenLookupColumnAtHeader cpp_array_size = Dqn_CGen_LookupColumnAtHeader(it.table, it.cgen_table_column[Dqn_CGenTableHeaderType_CppArraySize].string, row);
Dqn_CGenLookupColumnAtHeader cpp_array_size_field = Dqn_CGen_LookupColumnAtHeader(it.table, it.cgen_table_column[Dqn_CGenTableHeaderType_CppArraySizeField].string, row);
Dqn_CGenLookupColumnAtHeader cpp_label = Dqn_CGen_LookupColumnAtHeader(it.table, it.cgen_table_column[Dqn_CGenTableHeaderType_CppLabel].string, row);
bool cpp_is_ptr_b32 = cpp_is_ptr.column.string == DQN_STR8("true");
Dqn_Str8 cpp_array_size_str8 = Dqn_Str8_HasData(cpp_array_size.column.string) ? cpp_array_size.column.string : DQN_STR8("0");
Dqn_CGenTableColumn struct_name = it.cgen_table_row->columns[table->column_indexes[Dqn_CGenTableHeaderType_Name]];
Dqn_Scratch scratch = Dqn_Scratch_Get(nullptr);
Dqn_Str8 cpp_array_size_field_str8 = DQN_STR8("NULL");
if (cpp_array_size_field.column.string.size) {
@ -707,57 +826,100 @@ DQN_API void Dqn_CGen_EmitCodeForTables(Dqn_CGen *cgen, Dqn_CGenEmit emit, Dqn_C
if (sub_cpp_name.string == cpp_array_size_field.column.string)
index_the_field_references = sub_row_index;
}
cpp_array_size_field_str8 = Dqn_Str8_InitF(scratch.arena,
"&g_%.*s_type_fields[%zu]",
DQN_STR_FMT(struct_name.string),
index_the_field_references);
cpp_array_size_field_str8 =
Dqn_Str8_InitF_TLS("&g_%.*s%.*s_type_fields[%zu]",
DQN_STR_FMT(emit_prefix),
DQN_STR_FMT(struct_name.string),
index_the_field_references);
}
Dqn_Str8 orig_cpp_type_info = Dqn_Str8_InitF(scratch.arena, "%.*s", DQN_STR_FMT(cpp_type.column.string));
Dqn_Str8 cpp_type_info = orig_cpp_type_info;
cpp_type_info = Dqn_Str8_Replace(cpp_type_info, /*find*/ DQN_STR8("*"), /*replace*/ DQN_STR8(""), /*start_index*/ 0, scratch.arena, Dqn_Str8EqCase_Sensitive);
cpp_type_info = Dqn_Str8_Replace(cpp_type_info, /*find*/ DQN_STR8("constexpr"), /*replace*/ DQN_STR8(""), /*start_index*/ 0, scratch.arena, Dqn_Str8EqCase_Sensitive);
cpp_type_info = Dqn_Str8_Replace(cpp_type_info, /*find*/ DQN_STR8("const"), /*replace*/ DQN_STR8(""), /*start_index*/ 0, scratch.arena, Dqn_Str8EqCase_Sensitive);
cpp_type_info = Dqn_Str8_Replace(cpp_type_info, /*find*/ DQN_STR8("static"), /*replace*/ DQN_STR8(""), /*start_index*/ 0, scratch.arena, Dqn_Str8EqCase_Sensitive);
cpp_type_info =</