mirror of
https://github.com/Ed94/WATL_Exercise.git
synced 2025-11-08 17:49:18 -08:00
Compare commits
15 Commits
3554615244
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| bd9d2b3a7b | |||
| f5330c686b | |||
| a48681fc00 | |||
| acb5e916c1 | |||
| 5a44788b4a | |||
| dbb1367acb | |||
| aab3a3f689 | |||
| d7790795dd | |||
| ac05262c8d | |||
| 3bb46692e1 | |||
| a7d17a8b70 | |||
| 7aaf617b3c | |||
| 5e3e8970d8 | |||
| 8269ea9cc5 | |||
| d9bce18ccb |
File diff suppressed because it is too large
Load Diff
@@ -4,11 +4,14 @@ Version: 0 (From Scratch, 1-Stage Compilation, LLVM & WinAPI Only, Win CRT Mul
|
|||||||
Host: Windows 11 (x86-64)
|
Host: Windows 11 (x86-64)
|
||||||
Toolchain: LLVM (2025-08-30), C-Stanard: 11
|
Toolchain: LLVM (2025-08-30), C-Stanard: 11
|
||||||
|
|
||||||
Based on: Neokineogfx - Fixing C, personalized to include typeinfo more readily.
|
Based on: Neokineogfx - Fixing C, personalized to utilize typeinfo.
|
||||||
https://youtu.be/RrL7121MOeA
|
https://youtu.be/RrL7121MOeA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma clang diagnostic push
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wpre-c11-compat"
|
||||||
|
// #pragma clang diagnostic ignored "-Wc++-keyword"
|
||||||
|
#pragma clang diagnostic ignored "-Wcast-qual"
|
||||||
#pragma clang diagnostic ignored "-Wunused-const-variable"
|
#pragma clang diagnostic ignored "-Wunused-const-variable"
|
||||||
#pragma clang diagnostic ignored "-Wunused-but-set-variable"
|
#pragma clang diagnostic ignored "-Wunused-but-set-variable"
|
||||||
#pragma clang diagnostic ignored "-Wswitch"
|
#pragma clang diagnostic ignored "-Wswitch"
|
||||||
@@ -20,14 +23,12 @@ https://youtu.be/RrL7121MOeA
|
|||||||
#pragma clang diagnostic ignored "-W#pragma-messages"
|
#pragma clang diagnostic ignored "-W#pragma-messages"
|
||||||
#pragma clang diagnostic ignored "-Wstatic-in-inline"
|
#pragma clang diagnostic ignored "-Wstatic-in-inline"
|
||||||
#pragma clang diagnostic ignored "-Wkeyword-macro"
|
#pragma clang diagnostic ignored "-Wkeyword-macro"
|
||||||
#pragma clang diagnostic ignored "-Wc23-compat"
|
|
||||||
#pragma clang diagnostic ignored "-Wreserved-identifier"
|
#pragma clang diagnostic ignored "-Wreserved-identifier"
|
||||||
#pragma clang diagnostic ignored "-Wpre-c11-compat"
|
#pragma clang diagnostic ignored "-Wc23-compat"
|
||||||
#pragma clang diagnostic ignored "-Wc23-extensions"
|
#pragma clang diagnostic ignored "-Wc23-extensions"
|
||||||
#pragma clang diagnostic ignored "-Wunused-macros"
|
#pragma clang diagnostic ignored "-Wunused-macros"
|
||||||
#pragma clang diagnostic ignored "-Wdeclaration-after-statement"
|
#pragma clang diagnostic ignored "-Wdeclaration-after-statement"
|
||||||
#pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
|
#pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
|
||||||
#pragma clang diagnostic ignored "-Wc++-keyword"
|
|
||||||
#pragma clang diagnostic ignored "-Wimplicit-function-declaration"
|
#pragma clang diagnostic ignored "-Wimplicit-function-declaration"
|
||||||
#pragma clang diagnostic ignored "-Wcast-align"
|
#pragma clang diagnostic ignored "-Wcast-align"
|
||||||
#pragma clang diagnostic ignored "-Wunused-parameter"
|
#pragma clang diagnostic ignored "-Wunused-parameter"
|
||||||
@@ -39,24 +40,24 @@ https://youtu.be/RrL7121MOeA
|
|||||||
#pragma region Header
|
#pragma region Header
|
||||||
|
|
||||||
#pragma region DSL
|
#pragma region DSL
|
||||||
#define align_(value) __attribute__((aligned (value))) // for easy alignment
|
#define local_persist static
|
||||||
#define expect_(x, y) __builtin_expect(x, y) // so compiler knows the common path
|
#define global static
|
||||||
#define finline static inline __attribute__((always_inline)) // force inline
|
#define internal static
|
||||||
#define no_inline static __attribute__((noinline)) // force no inline [used in thread api]
|
|
||||||
#define R_ __restrict // pointers are either restricted or volatile and nothing else
|
#define align_(value) __attribute__((aligned (value))) // for easy alignment
|
||||||
#define V_ volatile // pointers are either restricted or volatile and nothing else
|
#define expect_(x, y) __builtin_expect(x, y) // so compiler knows the common path
|
||||||
|
#define finline internal inline __attribute__((always_inline)) // force inline
|
||||||
|
#define no_inline internal __attribute__((noinline)) // force no inline [used in thread api]
|
||||||
|
#define R_ __restrict // pointers are either restricted or volatile and nothing else
|
||||||
|
#define V_ volatile // pointers are either restricted or volatile and nothing else
|
||||||
#define W_ __attribute((__stdcall__)) __attribute__((__force_align_arg_pointer__))
|
#define W_ __attribute((__stdcall__)) __attribute__((__force_align_arg_pointer__))
|
||||||
|
|
||||||
#define glue_impl(A, B) A ## B
|
#define glue_impl(A, B) A ## B
|
||||||
#define glue(A, B) glue_impl(A, B)
|
#define glue(A, B) glue_impl(A, B)
|
||||||
#define stringify_impl(S) #S
|
#define stringify_impl(S) #S
|
||||||
#define stringify(S) stringify_impl(S)
|
#define stringify(S) cast(UTF8*, stringify_impl(S))
|
||||||
#define tmpl(prefix, type) prefix ## _ ## type
|
#define tmpl(prefix, type) prefix ## _ ## type
|
||||||
|
|
||||||
#define local_persist static
|
|
||||||
#define global static
|
|
||||||
#define internal static
|
|
||||||
|
|
||||||
#define static_assert _Static_assert
|
#define static_assert _Static_assert
|
||||||
#define typeof __typeof__
|
#define typeof __typeof__
|
||||||
#define typeof_ptr(ptr) typeof(ptr[0])
|
#define typeof_ptr(ptr) typeof(ptr[0])
|
||||||
@@ -176,15 +177,15 @@ typedef def_struct(Slice_Str8) { Str8* ptr; U8 len; };
|
|||||||
{ \
|
{ \
|
||||||
assert_handler( \
|
assert_handler( \
|
||||||
stringify(cond), \
|
stringify(cond), \
|
||||||
__FILE__, \
|
(UTF8*)__FILE__, \
|
||||||
__func__, \
|
(UTF8*)__func__, \
|
||||||
cast(S4, __LINE__), \
|
cast(S4, __LINE__), \
|
||||||
msg, \
|
msg, \
|
||||||
## __VA_ARGS__); \
|
## __VA_ARGS__); \
|
||||||
debug_trap(); \
|
debug_trap(); \
|
||||||
} \
|
} \
|
||||||
} while(0)
|
} while(0)
|
||||||
void assert_handler(UTF8*R_ condition, UTF8*R_ file, UTF8*R_ function, S4 line, UTF8*R_ msg, ... );
|
internal void assert_handler(UTF8*R_ condition, UTF8*R_ file, UTF8*R_ function, S4 line, UTF8*R_ msg, ... );
|
||||||
#else
|
#else
|
||||||
#define debug_trap()
|
#define debug_trap()
|
||||||
#define assert_trap(cond)
|
#define assert_trap(cond)
|
||||||
@@ -277,7 +278,6 @@ void slice__copy(Slice_B1 dest, U8 dest_typewidth, Slice_B1 src, U8 src_typewidt
|
|||||||
iter.cursor op iter.r.end; \
|
iter.cursor op iter.r.end; \
|
||||||
++ iter.cursor \
|
++ iter.cursor \
|
||||||
)
|
)
|
||||||
|
|
||||||
#define def_span(type) \
|
#define def_span(type) \
|
||||||
def_struct(tmpl( Span,type)) { type begin; type end; }; \
|
def_struct(tmpl( Span,type)) { type begin; type end; }; \
|
||||||
typedef def_struct(tmpl(Iter_Span,type)) { tmpl(Span,type) r; type cursor; }
|
typedef def_struct(tmpl(Iter_Span,type)) { tmpl(Span,type) r; type cursor; }
|
||||||
@@ -403,14 +403,14 @@ typedef def_struct(FArena) {
|
|||||||
U8 capacity;
|
U8 capacity;
|
||||||
U8 used;
|
U8 used;
|
||||||
};
|
};
|
||||||
finline FArena farena_make (Slice_Mem mem);
|
finline FArena farena_make (Slice_Mem mem);
|
||||||
finline void farena_init (FArena_R arena, Slice_Mem byte);
|
finline void farena_init (FArena_R arena, Slice_Mem byte);
|
||||||
Slice_Mem farena__push (FArena_R arena, U8 amount, U8 type_width, Opts_farena*R_ opts);
|
internal Slice_Mem farena__push (FArena_R arena, U8 amount, U8 type_width, Opts_farena*R_ opts);
|
||||||
finline void farena_reset (FArena_R arena);
|
finline void farena_reset (FArena_R arena);
|
||||||
finline void farena_rewind(FArena_R arena, AllocatorSP save_point);
|
finline void farena_rewind(FArena_R arena, AllocatorSP save_point);
|
||||||
finline AllocatorSP farena_save (FArena arena);
|
finline AllocatorSP farena_save (FArena arena);
|
||||||
|
|
||||||
void farena_allocator_proc(AllocatorProc_In in, AllocatorProc_Out_R out);
|
internal void farena_allocator_proc(AllocatorProc_In in, AllocatorProc_Out_R out);
|
||||||
#define ainfo_farena(arena) (AllocatorInfo){ .proc = farena_allocator_proc, .data = u8_(& arena) }
|
#define ainfo_farena(arena) (AllocatorInfo){ .proc = farena_allocator_proc, .data = u8_(& arena) }
|
||||||
|
|
||||||
#define farena_push_mem(arena, amount, ...) farena__push(arena, amount, 1, opt_args(Opts_farena, lit(stringify(B1)), __VA_ARGS__))
|
#define farena_push_mem(arena, amount, ...) farena__push(arena, amount, 1, opt_args(Opts_farena, lit(stringify(B1)), __VA_ARGS__))
|
||||||
@@ -434,8 +434,8 @@ typedef def_struct(Opts_vmem) {
|
|||||||
B4 no_large_pages;
|
B4 no_large_pages;
|
||||||
A4_B1 _PAD_;
|
A4_B1 _PAD_;
|
||||||
};
|
};
|
||||||
void os_init(void);
|
internal void os_init (void);
|
||||||
finline OS_SystemInfo* os_system_info(void);
|
finline OS_SystemInfo* os_system_info(void);
|
||||||
|
|
||||||
finline B4 os__vmem_commit (U8 vm, U8 size, Opts_vmem*R_ opts);
|
finline B4 os__vmem_commit (U8 vm, U8 size, Opts_vmem*R_ opts);
|
||||||
finline U8 os__vmem_reserve( U8 size, Opts_vmem*R_ opts);
|
finline U8 os__vmem_reserve( U8 size, Opts_vmem*R_ opts);
|
||||||
@@ -466,17 +466,17 @@ typedef def_struct(Opts_varena_make) {
|
|||||||
VArenaFlags flags;
|
VArenaFlags flags;
|
||||||
A4_B1 _PAD_;
|
A4_B1 _PAD_;
|
||||||
};
|
};
|
||||||
VArena* varena__make(Opts_varena_make*R_ opts);
|
internal VArena* varena__make(Opts_varena_make*R_ opts);
|
||||||
#define varena_make(...) varena__make(opt_args(Opts_varena_make, __VA_ARGS__))
|
#define varena_make(...) varena__make(opt_args(Opts_varena_make, __VA_ARGS__))
|
||||||
|
|
||||||
Slice_Mem varena__push (VArena_R arena, U8 amount, U8 type_width, Opts_varena*R_ opts);
|
internal Slice_Mem varena__push (VArena_R arena, U8 amount, U8 type_width, Opts_varena*R_ opts);
|
||||||
finline void varena_release(VArena_R arena);
|
finline void varena_release(VArena_R arena);
|
||||||
finline void varena_rewind (VArena_R arena, AllocatorSP save_point);
|
finline void varena_rewind (VArena_R arena, AllocatorSP save_point);
|
||||||
void varena_reset (VArena_R arena);
|
internal void varena_reset (VArena_R arena);
|
||||||
Slice_Mem varena__shrink(VArena_R arena, Slice_Mem old_allocation, U8 requested_size);
|
internal Slice_Mem varena__shrink(VArena_R arena, Slice_Mem old_allocation, U8 requested_size);
|
||||||
finline AllocatorSP varena_save (VArena_R arena);
|
finline AllocatorSP varena_save (VArena_R arena);
|
||||||
|
|
||||||
void varena_allocator_proc(AllocatorProc_In in, AllocatorProc_Out_R out);
|
internal void varena_allocator_proc(AllocatorProc_In in, AllocatorProc_Out_R out);
|
||||||
#define ainfo_varena(varena) (AllocatorInfo) { .proc = & varena_allocator_proc, .data = u8_(varena) }
|
#define ainfo_varena(varena) (AllocatorInfo) { .proc = & varena_allocator_proc, .data = u8_(varena) }
|
||||||
|
|
||||||
#define varena_push_mem(arena, amount, ...) varena__push(arena, amount, 1, opt_args(Opts_varena, lit(stringify(B1)), __VA_ARGS__))
|
#define varena_push_mem(arena, amount, ...) varena__push(arena, amount, 1, opt_args(Opts_varena, lit(stringify(B1)), __VA_ARGS__))
|
||||||
@@ -504,14 +504,14 @@ typedef def_struct(Arena) {
|
|||||||
A4_B1 _PAD_;
|
A4_B1 _PAD_;
|
||||||
};
|
};
|
||||||
typedef Opts_varena_make Opts_arena_make;
|
typedef Opts_varena_make Opts_arena_make;
|
||||||
Arena* arena__make (Opts_arena_make*R_ opts);
|
internal Arena* arena__make (Opts_arena_make*R_ opts);
|
||||||
Slice_Mem arena__push (Arena_R arena, U8 amount, U8 type_width, Opts_arena*R_ opts);
|
internal Slice_Mem arena__push (Arena_R arena, U8 amount, U8 type_width, Opts_arena*R_ opts);
|
||||||
finline void arena_release(Arena_R arena);
|
finline void arena_release(Arena_R arena);
|
||||||
finline void arena_reset (Arena_R arena);
|
finline void arena_reset (Arena_R arena);
|
||||||
void arena_rewind (Arena_R arena, AllocatorSP save_point);
|
internal void arena_rewind (Arena_R arena, AllocatorSP save_point);
|
||||||
finline AllocatorSP arena_save (Arena_R arena);
|
finline AllocatorSP arena_save (Arena_R arena);
|
||||||
|
|
||||||
void arena_allocator_proc(AllocatorProc_In in, AllocatorProc_Out_R out);
|
internal void arena_allocator_proc(AllocatorProc_In in, AllocatorProc_Out_R out);
|
||||||
#define ainfo_arena(arena) (AllocatorInfo){ .proc = & arena_allocator_proc, .data = u8_(arena) }
|
#define ainfo_arena(arena) (AllocatorInfo){ .proc = & arena_allocator_proc, .data = u8_(arena) }
|
||||||
|
|
||||||
#define arena_make(...) arena__make(opt_args(Opts_arena_make, __VA_ARGS__))
|
#define arena_make(...) arena__make(opt_args(Opts_arena_make, __VA_ARGS__))
|
||||||
@@ -567,7 +567,7 @@ typedef def_farray(Str8, 2);
|
|||||||
typedef def_Slice(A2_Str8);
|
typedef def_Slice(A2_Str8);
|
||||||
typedef def_KTL_Slot(Str8);
|
typedef def_KTL_Slot(Str8);
|
||||||
typedef def_KTL(Str8);
|
typedef def_KTL(Str8);
|
||||||
void ktl_populate_slice_a2_str8(KTL_Str8*R_ kt, AllocatorInfo backing, Slice_A2_Str8 values);
|
finline void ktl_populate_slice_a2_str8(KTL_Str8*R_ kt, AllocatorInfo backing, Slice_A2_Str8 values);
|
||||||
#pragma endregion KTL
|
#pragma endregion KTL
|
||||||
|
|
||||||
#pragma region Key Table 1-Layer Chained-Chunked-Cells (KT1CX)
|
#pragma region Key Table 1-Layer Chained-Chunked-Cells (KT1CX)
|
||||||
@@ -622,11 +622,11 @@ typedef def_struct(KT1CX_Info) {
|
|||||||
AllocatorInfo backing_table;
|
AllocatorInfo backing_table;
|
||||||
AllocatorInfo backing_cells;
|
AllocatorInfo backing_cells;
|
||||||
};
|
};
|
||||||
void kt1cx_init (KT1CX_Info info, KT1CX_InfoMeta m, KT1CX_Byte*R_ result);
|
internal void kt1cx_init (KT1CX_Info info, KT1CX_InfoMeta m, KT1CX_Byte*R_ result);
|
||||||
void kt1cx_clear (KT1CX_Byte kt, KT1CX_ByteMeta meta);
|
internal void kt1cx_clear (KT1CX_Byte kt, KT1CX_ByteMeta meta);
|
||||||
finline U8 kt1cx_slot_id(KT1CX_Byte kt, U8 key, KT1CX_ByteMeta meta);
|
finline U8 kt1cx_slot_id(KT1CX_Byte kt, U8 key, KT1CX_ByteMeta meta);
|
||||||
U8 kt1cx_get (KT1CX_Byte kt, U8 key, KT1CX_ByteMeta meta);
|
internal U8 kt1cx_get (KT1CX_Byte kt, U8 key, KT1CX_ByteMeta meta);
|
||||||
U8 kt1cx_set (KT1CX_Byte kt, U8 key, Slice_Mem value, AllocatorInfo backing_cells, KT1CX_ByteMeta meta);
|
internal U8 kt1cx_set (KT1CX_Byte kt, U8 key, Slice_Mem value, AllocatorInfo backing_cells, KT1CX_ByteMeta meta);
|
||||||
|
|
||||||
#define kt1cx_assert(kt) do { \
|
#define kt1cx_assert(kt) do { \
|
||||||
slice_assert(kt.table); \
|
slice_assert(kt.table); \
|
||||||
@@ -641,14 +641,14 @@ finline U1 integer_symbols(U1 value) {
|
|||||||
local_persist U1 lookup_table[16] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F', }; return lookup_table[cast(U1, value)];
|
local_persist U1 lookup_table[16] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F', }; return lookup_table[cast(U1, value)];
|
||||||
}
|
}
|
||||||
|
|
||||||
finline char* str8_to_cstr_capped(Str8 content, Slice_Mem mem);
|
finline char* str8_to_cstr_capped(Str8 content, Slice_Mem mem);
|
||||||
Str8 str8_from_u32(AllocatorInfo ainfo, U4 num, U4 radix, U4 min_digits, U4 digit_group_separator);
|
internal Str8 str8_from_u32(AllocatorInfo ainfo, U4 num, U4 radix, U4 min_digits, U4 digit_group_separator);
|
||||||
|
|
||||||
finline Str8 str8__fmt_backed(AllocatorInfo tbl_backing, AllocatorInfo buf_backing, Str8 fmt_template, Slice_A2_Str8*R_ entries);
|
finline Str8 str8__fmt_backed(AllocatorInfo tbl_backing, AllocatorInfo buf_backing, Str8 fmt_template, Slice_A2_Str8*R_ entries);
|
||||||
#define str8_fmt_backed(tbl_backing, buf_backing, fmt_template, ...) \
|
#define str8_fmt_backed(tbl_backing, buf_backing, fmt_template, ...) \
|
||||||
str8__fmt_backed(tbl_backing, buf_backing, lit(fmt_template), slice_arg_from_array(A2_Str8, __VA_ARGS__))
|
str8__fmt_backed(tbl_backing, buf_backing, lit(fmt_template), slice_arg_from_array(A2_Str8, __VA_ARGS__))
|
||||||
|
|
||||||
Str8 str8__fmt(Str8 fmt_template, Slice_A2_Str8*R_ entries);
|
internal Str8 str8__fmt(Str8 fmt_template, Slice_A2_Str8*R_ entries);
|
||||||
#define str8_fmt(fmt_template, ...) str8__fmt(lit(fmt_template), slice_arg_from_array(A2_Str8, __VA_ARGS__))
|
#define str8_fmt(fmt_template, ...) str8__fmt(lit(fmt_template), slice_arg_from_array(A2_Str8, __VA_ARGS__))
|
||||||
|
|
||||||
#define Str8Cache_CELL_DEPTH 4
|
#define Str8Cache_CELL_DEPTH 4
|
||||||
@@ -671,8 +671,8 @@ typedef def_struct(Opts_str8cache_init) {
|
|||||||
U8 cell_pool_size;
|
U8 cell_pool_size;
|
||||||
U8 table_size;
|
U8 table_size;
|
||||||
};
|
};
|
||||||
void str8cache__init(Str8Cache_R cache, Opts_str8cache_init*R_ opts);
|
internal void str8cache__init(Str8Cache_R cache, Opts_str8cache_init*R_ opts);
|
||||||
finline Str8Cache str8cache__make( Opts_str8cache_init*R_ opts);
|
finline Str8Cache str8cache__make( Opts_str8cache_init*R_ opts);
|
||||||
|
|
||||||
#define str8cache_init(cache, ...) str8cache__init(cache, opt_args(Opts_str8cache_init, __VA_ARGS__))
|
#define str8cache_init(cache, ...) str8cache__init(cache, opt_args(Opts_str8cache_init, __VA_ARGS__))
|
||||||
#define str8cache_make(...) str8cache__make( opt_args(Opts_str8cache_init, __VA_ARGS__))
|
#define str8cache_make(...) str8cache__make( opt_args(Opts_str8cache_init, __VA_ARGS__))
|
||||||
@@ -696,8 +696,8 @@ finline Str8Gen str8gen_make( AllocatorInfo backing);
|
|||||||
|
|
||||||
finline Str8 str8_from_str8gen(Str8Gen gen) { return (Str8){ cast(UTF8_R, gen.ptr), gen.len}; }
|
finline Str8 str8_from_str8gen(Str8Gen gen) { return (Str8){ cast(UTF8_R, gen.ptr), gen.len}; }
|
||||||
|
|
||||||
finline void str8gen_append_str8(Str8Gen_R gen, Str8 str);
|
finline void str8gen_append_str8(Str8Gen_R gen, Str8 str);
|
||||||
void str8gen__append_fmt(Str8Gen_R gen, Str8 fmt_template, Slice_A2_Str8*R_ tokens);
|
internal void str8gen__append_fmt(Str8Gen_R gen, Str8 fmt_template, Slice_A2_Str8*R_ tokens);
|
||||||
|
|
||||||
#define str8gen_append_fmt(gen, fmt_template, ...) str8gen__append_fmt(gen, lit(fmt_template), slice_arg_from_array(A2_Str8, __VA_ARGS__))
|
#define str8gen_append_fmt(gen, fmt_template, ...) str8gen__append_fmt(gen, lit(fmt_template), slice_arg_from_array(A2_Str8, __VA_ARGS__))
|
||||||
#pragma endregion String Operations
|
#pragma endregion String Operations
|
||||||
@@ -711,8 +711,8 @@ typedef def_struct(Opts_read_file_contents) {
|
|||||||
B4 zero_backing;
|
B4 zero_backing;
|
||||||
A4_B1 _PAD_;
|
A4_B1 _PAD_;
|
||||||
};
|
};
|
||||||
void api_file_read_contents(FileOpInfo_R result, Str8 path, Opts_read_file_contents opts);
|
internal void api_file_read_contents(FileOpInfo_R result, Str8 path, Opts_read_file_contents opts);
|
||||||
void file_write_str8 (Str8 path, Str8 content);
|
internal void file_write_str8 (Str8 path, Str8 content);
|
||||||
|
|
||||||
finline FileOpInfo file__read_contents(Str8 path, Opts_read_file_contents*R_ opts);
|
finline FileOpInfo file__read_contents(Str8 path, Opts_read_file_contents*R_ opts);
|
||||||
#define file_read_contents(path, ...) file__read_contents(path, opt_args(Opts_read_file_contents, __VA_ARGS__))
|
#define file_read_contents(path, ...) file__read_contents(path, opt_args(Opts_read_file_contents, __VA_ARGS__))
|
||||||
@@ -755,8 +755,8 @@ typedef def_struct(Opts_watl_lex) {
|
|||||||
B1 failon_slice_constraint_fail;
|
B1 failon_slice_constraint_fail;
|
||||||
A4_B1 _PAD_;
|
A4_B1 _PAD_;
|
||||||
};
|
};
|
||||||
void api_watl_lex(WATL_LexInfo_R info, Str8 source, Opts_watl_lex*R_ opts);
|
internal void api_watl_lex(WATL_LexInfo_R info, Str8 source, Opts_watl_lex*R_ opts);
|
||||||
WATL_LexInfo watl__lex ( Str8 source, Opts_watl_lex*R_ opts);
|
finline WATL_LexInfo watl__lex ( Str8 source, Opts_watl_lex*R_ opts);
|
||||||
#define watl_lex(source, ...) watl__lex(source, opt_args(Opts_watl_lex, __VA_ARGS__))
|
#define watl_lex(source, ...) watl__lex(source, opt_args(Opts_watl_lex, __VA_ARGS__))
|
||||||
|
|
||||||
typedef Str8 WATL_Node; typedef def_ptr_set(WATL_Node);
|
typedef Str8 WATL_Node; typedef def_ptr_set(WATL_Node);
|
||||||
@@ -787,11 +787,11 @@ typedef def_struct(Opts_watl_parse) {
|
|||||||
B4 failon_slice_constraint_fail;
|
B4 failon_slice_constraint_fail;
|
||||||
A4_B1 _PAD_;
|
A4_B1 _PAD_;
|
||||||
};
|
};
|
||||||
void api_watl_parse(WATL_ParseInfo_R info, Slice_WATL_Tok tokens, Opts_watl_parse*R_ opts);
|
internal void api_watl_parse(WATL_ParseInfo_R info, Slice_WATL_Tok tokens, Opts_watl_parse*R_ opts);
|
||||||
WATL_ParseInfo watl__parse ( Slice_WATL_Tok tokens, Opts_watl_parse*R_ opts);
|
finline WATL_ParseInfo watl__parse ( Slice_WATL_Tok tokens, Opts_watl_parse*R_ opts);
|
||||||
#define watl_parse(tokens, ...) watl__parse(tokens, opt_args(Opts_watl_parse, __VA_ARGS__))
|
#define watl_parse(tokens, ...) watl__parse(tokens, opt_args(Opts_watl_parse, __VA_ARGS__))
|
||||||
|
|
||||||
Str8 watl_dump_listing(AllocatorInfo buffer, Slice_WATL_Line lines);
|
internal Str8 watl_dump_listing(AllocatorInfo buffer, Slice_WATL_Line lines);
|
||||||
#pragma endregion WATL
|
#pragma endregion WATL
|
||||||
|
|
||||||
#pragma endregion Header
|
#pragma endregion Header
|
||||||
@@ -823,8 +823,7 @@ void mem_rewind(AllocatorInfo ainfo, AllocatorSP save_point) {
|
|||||||
finline
|
finline
|
||||||
AllocatorSP mem_save_point(AllocatorInfo ainfo) {
|
AllocatorSP mem_save_point(AllocatorInfo ainfo) {
|
||||||
assert(ainfo.proc != nullptr);
|
assert(ainfo.proc != nullptr);
|
||||||
AllocatorProc_Out out;
|
AllocatorProc_Out out; ainfo.proc((AllocatorProc_In){.data = ainfo.data, .op = AllocatorOp_SavePoint}, & out);
|
||||||
ainfo.proc((AllocatorProc_In){.data = ainfo.data, .op = AllocatorOp_SavePoint}, & out);
|
|
||||||
return out.save_point;
|
return out.save_point;
|
||||||
}
|
}
|
||||||
finline
|
finline
|
||||||
@@ -837,8 +836,7 @@ Slice_Mem mem__alloc(AllocatorInfo ainfo, U8 size, Opts_mem_alloc*R_ opts) {
|
|||||||
.requested_size = size,
|
.requested_size = size,
|
||||||
.alignment = opts->alignment,
|
.alignment = opts->alignment,
|
||||||
};
|
};
|
||||||
AllocatorProc_Out out;
|
AllocatorProc_Out out; ainfo.proc(in, & out);
|
||||||
ainfo.proc(in, & out);
|
|
||||||
return out.allocation;
|
return out.allocation;
|
||||||
}
|
}
|
||||||
finline
|
finline
|
||||||
@@ -852,8 +850,7 @@ Slice_Mem mem__grow(AllocatorInfo ainfo, Slice_Mem mem, U8 size, Opts_mem_grow*R
|
|||||||
.alignment = opts->alignment,
|
.alignment = opts->alignment,
|
||||||
.old_allocation = mem
|
.old_allocation = mem
|
||||||
};
|
};
|
||||||
AllocatorProc_Out out;
|
AllocatorProc_Out out; ainfo.proc(in, & out);
|
||||||
ainfo.proc(in, & out);
|
|
||||||
return (Slice_Mem){ out.allocation.ptr, opts->give_actual ? out.allocation.len : in.requested_size };
|
return (Slice_Mem){ out.allocation.ptr, opts->give_actual ? out.allocation.len : in.requested_size };
|
||||||
}
|
}
|
||||||
finline
|
finline
|
||||||
@@ -867,8 +864,7 @@ Slice_Mem mem__resize(AllocatorInfo ainfo, Slice_Mem mem, U8 size, Opts_mem_resi
|
|||||||
.alignment = opts->alignment,
|
.alignment = opts->alignment,
|
||||||
.old_allocation = mem,
|
.old_allocation = mem,
|
||||||
};
|
};
|
||||||
AllocatorProc_Out out;
|
AllocatorProc_Out out; ainfo.proc(in, & out);
|
||||||
ainfo.proc(in, & out);
|
|
||||||
return (Slice_Mem){ out.allocation.ptr, opts->give_actual ? out.allocation.len : in.requested_size };
|
return (Slice_Mem){ out.allocation.ptr, opts->give_actual ? out.allocation.len : in.requested_size };
|
||||||
}
|
}
|
||||||
finline
|
finline
|
||||||
@@ -882,8 +878,7 @@ Slice_Mem mem__shrink(AllocatorInfo ainfo, Slice_Mem mem, U8 size, Opts_mem_shri
|
|||||||
.alignment = opts->alignment,
|
.alignment = opts->alignment,
|
||||||
.old_allocation = mem
|
.old_allocation = mem
|
||||||
};
|
};
|
||||||
AllocatorProc_Out out;
|
AllocatorProc_Out out; ainfo.proc(in, & out);
|
||||||
ainfo.proc(in, & out);
|
|
||||||
return out.allocation;
|
return out.allocation;
|
||||||
}
|
}
|
||||||
#pragma endregion Allocator Interface
|
#pragma endregion Allocator Interface
|
||||||
@@ -897,7 +892,7 @@ void farena_init(FArena_R arena, Slice_Mem mem) {
|
|||||||
arena->used = 0;
|
arena->used = 0;
|
||||||
}
|
}
|
||||||
finline FArena farena_make(Slice_Mem mem) { FArena a; farena_init(& a, mem); return a; }
|
finline FArena farena_make(Slice_Mem mem) { FArena a; farena_init(& a, mem); return a; }
|
||||||
inline
|
internal inline
|
||||||
Slice_Mem farena__push(FArena_R arena, U8 amount, U8 type_width, Opts_farena*R_ opts) {
|
Slice_Mem farena__push(FArena_R arena, U8 amount, U8 type_width, Opts_farena*R_ opts) {
|
||||||
assert(opts != nullptr);
|
assert(opts != nullptr);
|
||||||
if (amount == 0) { return (Slice_Mem){}; }
|
if (amount == 0) { return (Slice_Mem){}; }
|
||||||
@@ -908,7 +903,7 @@ Slice_Mem farena__push(FArena_R arena, U8 amount, U8 type_width, Opts_farena*R_
|
|||||||
arena->used += to_commit;
|
arena->used += to_commit;
|
||||||
return (Slice_Mem){ptr, desired};
|
return (Slice_Mem){ptr, desired};
|
||||||
}
|
}
|
||||||
inline
|
internal inline
|
||||||
Slice_Mem farena__grow(FArena_R arena, Slice_Mem old_allocation, U8 requested_size, U8 alignment, B4 should_zero) {
|
Slice_Mem farena__grow(FArena_R arena, Slice_Mem old_allocation, U8 requested_size, U8 alignment, B4 should_zero) {
|
||||||
// Check if the allocation is at the end of the arena
|
// Check if the allocation is at the end of the arena
|
||||||
U8 alloc_end = old_allocation.ptr + old_allocation.len;
|
U8 alloc_end = old_allocation.ptr + old_allocation.len;
|
||||||
@@ -926,11 +921,10 @@ Slice_Mem farena__grow(FArena_R arena, Slice_Mem old_allocation, U8 requested_si
|
|||||||
return (Slice_Mem){0};
|
return (Slice_Mem){0};
|
||||||
}
|
}
|
||||||
arena->used += aligned_grow;
|
arena->used += aligned_grow;
|
||||||
Slice_Mem result = (Slice_Mem){ old_allocation.ptr, aligned_grow + requested_size };
|
|
||||||
mem_zero(old_allocation.ptr + old_allocation.len, grow_amount * cast(U8, should_zero));
|
mem_zero(old_allocation.ptr + old_allocation.len, grow_amount * cast(U8, should_zero));
|
||||||
return result;
|
return (Slice_Mem){ old_allocation.ptr, aligned_grow + requested_size };
|
||||||
}
|
}
|
||||||
inline
|
internal inline
|
||||||
Slice_Mem farena__shrink(FArena_R arena, Slice_Mem old_allocation, U8 requested_size, U8 alignment)
|
Slice_Mem farena__shrink(FArena_R arena, Slice_Mem old_allocation, U8 requested_size, U8 alignment)
|
||||||
{
|
{
|
||||||
// Check if the allocation is at the end of the arena
|
// Check if the allocation is at the end of the arena
|
||||||
@@ -956,6 +950,7 @@ finline
|
|||||||
AllocatorSP farena_save (FArena arena) {
|
AllocatorSP farena_save (FArena arena) {
|
||||||
return (AllocatorSP){ .type_sig = & farena_allocator_proc, .slot = arena.used };
|
return (AllocatorSP){ .type_sig = & farena_allocator_proc, .slot = arena.used };
|
||||||
}
|
}
|
||||||
|
internal
|
||||||
void farena_allocator_proc(AllocatorProc_In in, AllocatorProc_Out*R_ out)
|
void farena_allocator_proc(AllocatorProc_In in, AllocatorProc_Out*R_ out)
|
||||||
{
|
{
|
||||||
assert(out != nullptr);
|
assert(out != nullptr);
|
||||||
@@ -963,38 +958,38 @@ void farena_allocator_proc(AllocatorProc_In in, AllocatorProc_Out*R_ out)
|
|||||||
FArena_R arena = cast(FArena_R, in.data);
|
FArena_R arena = cast(FArena_R, in.data);
|
||||||
switch (in.op)
|
switch (in.op)
|
||||||
{
|
{
|
||||||
case AllocatorOp_Alloc:
|
case AllocatorOp_Alloc:
|
||||||
case AllocatorOp_Alloc_NoZero:
|
case AllocatorOp_Alloc_NoZero:
|
||||||
out->allocation = farena_push_mem(arena, in.requested_size, .alignment = in.alignment);
|
out->allocation = farena_push_mem(arena, in.requested_size, .alignment = in.alignment);
|
||||||
mem_zero(out->allocation.ptr, out->allocation.len * in.op);
|
mem_zero(out->allocation.ptr, out->allocation.len * in.op);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AllocatorOp_Free: break;
|
case AllocatorOp_Free: break;
|
||||||
case AllocatorOp_Reset: farena_reset(arena); break;
|
case AllocatorOp_Reset: farena_reset(arena); break;
|
||||||
|
|
||||||
case AllocatorOp_Grow:
|
case AllocatorOp_Grow:
|
||||||
case AllocatorOp_Grow_NoZero:
|
case AllocatorOp_Grow_NoZero:
|
||||||
out->allocation = farena__grow(arena, in.old_allocation, in.requested_size, in.alignment, in.op - AllocatorOp_Grow_NoZero);
|
out->allocation = farena__grow(arena, in.old_allocation, in.requested_size, in.alignment, in.op - AllocatorOp_Grow_NoZero);
|
||||||
break;
|
break;
|
||||||
case AllocatorOp_Shrink:
|
case AllocatorOp_Shrink:
|
||||||
out->allocation = farena__shrink(arena, in.old_allocation, in.requested_size, in.alignment);
|
out->allocation = farena__shrink(arena, in.old_allocation, in.requested_size, in.alignment);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AllocatorOp_Rewind: farena_rewind(arena, in.save_point); break;
|
case AllocatorOp_Rewind: farena_rewind(arena, in.save_point); break;
|
||||||
case AllocatorOp_SavePoint: out->save_point = farena_save(arena[0]); break;
|
case AllocatorOp_SavePoint: out->save_point = farena_save(arena[0]); break;
|
||||||
|
|
||||||
case AllocatorOp_Query:
|
case AllocatorOp_Query:
|
||||||
out->features =
|
out->features =
|
||||||
AllocatorQuery_Alloc
|
AllocatorQuery_Alloc
|
||||||
| AllocatorQuery_Reset
|
| AllocatorQuery_Reset
|
||||||
| AllocatorQuery_Resize
|
| AllocatorQuery_Resize
|
||||||
| AllocatorQuery_Rewind
|
| AllocatorQuery_Rewind
|
||||||
;
|
;
|
||||||
out->max_alloc = arena->capacity - arena->used;
|
out->max_alloc = arena->capacity - arena->used;
|
||||||
out->min_alloc = 0;
|
out->min_alloc = 0;
|
||||||
out->left = out->max_alloc;
|
out->left = out->max_alloc;
|
||||||
out->save_point = farena_save(arena[0]);
|
out->save_point = farena_save(arena[0]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1009,6 +1004,7 @@ void farena_allocator_proc(AllocatorProc_In in, AllocatorProc_Out*R_ out)
|
|||||||
#define MS_ANYSIZE_ARRAY 1
|
#define MS_ANYSIZE_ARRAY 1
|
||||||
#define MS_MEM_COMMIT 0x00001000
|
#define MS_MEM_COMMIT 0x00001000
|
||||||
#define MS_MEM_RESERVE 0x00002000
|
#define MS_MEM_RESERVE 0x00002000
|
||||||
|
#define MS_MEM_RELEASE 0x00008000
|
||||||
#define MS_MEM_LARGE_PAGES 0x20000000
|
#define MS_MEM_LARGE_PAGES 0x20000000
|
||||||
#define MS_PAGE_READWRITE 0x04
|
#define MS_PAGE_READWRITE 0x04
|
||||||
#define MS_TOKEN_ADJUST_PRIVILEGES (0x0020)
|
#define MS_TOKEN_ADJUST_PRIVILEGES (0x0020)
|
||||||
@@ -1056,7 +1052,7 @@ typedef def_struct(OS_Windows_State) { OS_SystemInfo system_info; };
|
|||||||
global OS_Windows_State os__windows_info;
|
global OS_Windows_State os__windows_info;
|
||||||
|
|
||||||
finline OS_SystemInfo* os_system_info(void) { return & os__windows_info.system_info; }
|
finline OS_SystemInfo* os_system_info(void) { return & os__windows_info.system_info; }
|
||||||
inline
|
internal inline
|
||||||
void os__enable_large_pages(void) {
|
void os__enable_large_pages(void) {
|
||||||
MS_HANDLE token;
|
MS_HANDLE token;
|
||||||
if (OpenProcessToken(GetCurrentProcess(), MS_TOKEN_ADJUST_PRIVILEGES | MS_TOKEN_QUERY, &token))
|
if (OpenProcessToken(GetCurrentProcess(), MS_TOKEN_ADJUST_PRIVILEGES | MS_TOKEN_QUERY, &token))
|
||||||
@@ -1073,7 +1069,7 @@ void os__enable_large_pages(void) {
|
|||||||
CloseHandle(token);
|
CloseHandle(token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
inline
|
internal inline
|
||||||
void os_init(void) {
|
void os_init(void) {
|
||||||
os__enable_large_pages();
|
os__enable_large_pages();
|
||||||
OS_SystemInfo*R_ info = & os__windows_info.system_info;
|
OS_SystemInfo*R_ info = & os__windows_info.system_info;
|
||||||
@@ -1095,13 +1091,12 @@ finline B4 os__vmem_commit(U8 vm, U8 size, Opts_vmem*R_ opts) {
|
|||||||
B4 result = (VirtualAlloc(cast(MS_LPVOID, vm), size, MS_MEM_COMMIT, MS_PAGE_READWRITE) != 0);
|
B4 result = (VirtualAlloc(cast(MS_LPVOID, vm), size, MS_MEM_COMMIT, MS_PAGE_READWRITE) != 0);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
inline void os_vmem_release(U8 vm, U8 size) { VirtualFree(cast(MS_LPVOID, vm), 0, MS_MEM_RESERVE); }
|
internal inline void os_vmem_release(U8 vm, U8 size) { VirtualFree(cast(MS_LPVOID, vm), 0, MS_MEM_RELEASE); }
|
||||||
#pragma endregion OS
|
#pragma endregion OS
|
||||||
|
|
||||||
#pragma region VArena (Virutal Address Space Arena)
|
#pragma region VArena (Virutal Address Space Arena)
|
||||||
finline U8 varena_header_size(void) { return align_pow2(size_of(VArena), MEMORY_ALIGNMENT_DEFAULT); }
|
finline U8 varena_header_size(void) { return align_pow2(size_of(VArena), MEMORY_ALIGNMENT_DEFAULT); }
|
||||||
|
internal inline
|
||||||
inline
|
|
||||||
VArena* varena__make(Opts_varena_make*R_ opts) {
|
VArena* varena__make(Opts_varena_make*R_ opts) {
|
||||||
assert(opts != nullptr);
|
assert(opts != nullptr);
|
||||||
if (opts->reserve_size == 0) { opts->reserve_size = mega(64); }
|
if (opts->reserve_size == 0) { opts->reserve_size = mega(64); }
|
||||||
@@ -1123,20 +1118,18 @@ VArena* varena__make(Opts_varena_make*R_ opts) {
|
|||||||
};
|
};
|
||||||
return vm;
|
return vm;
|
||||||
}
|
}
|
||||||
inline
|
internal inline
|
||||||
Slice_Mem varena__push(VArena_R vm, U8 amount, U8 type_width, Opts_varena*R_ opts) {
|
Slice_Mem varena__push(VArena_R vm, U8 amount, U8 type_width, Opts_varena*R_ opts) {
|
||||||
assert(vm != nullptr);
|
assert(vm != nullptr);
|
||||||
assert(amount != 0);
|
assert(amount != 0);
|
||||||
U8 alignment = opts->alignment ? opts->alignment : MEMORY_ALIGNMENT_DEFAULT;
|
U8 alignment = opts->alignment ? opts->alignment : MEMORY_ALIGNMENT_DEFAULT;
|
||||||
U8 requested_size = amount * type_width;
|
U8 requested_size = amount * type_width;
|
||||||
U8 aligned_size = align_pow2(requested_size, alignment);
|
U8 aligned_size = align_pow2(requested_size, alignment);
|
||||||
U8 current_offset = vm->reserve_start + vm->commit_used;
|
|
||||||
U8 to_be_used = vm->commit_used + aligned_size;
|
U8 to_be_used = vm->commit_used + aligned_size;
|
||||||
U8 reserve_left = vm->reserve - vm->commit_used;
|
U8 reserve_left = vm->reserve - vm->commit_used;
|
||||||
U8 commit_left = vm->committed - vm->commit_used;
|
U8 commit_left = vm->committed - vm->commit_used;
|
||||||
B4 exhausted = commit_left < to_be_used; assert(to_be_used < reserve_left);
|
assert(to_be_used < reserve_left);
|
||||||
if (exhausted)
|
if (/*exhausted?*/commit_left < to_be_used) {
|
||||||
{
|
|
||||||
U8 next_commit_size = reserve_left > 0 ?
|
U8 next_commit_size = reserve_left > 0 ?
|
||||||
max(vm->commit_size, to_be_used)
|
max(vm->commit_size, to_be_used)
|
||||||
: align_pow2( reserve_left, os_system_info()->target_page_size);
|
: align_pow2( reserve_left, os_system_info()->target_page_size);
|
||||||
@@ -1148,21 +1141,21 @@ Slice_Mem varena__push(VArena_R vm, U8 amount, U8 type_width, Opts_varena*R_ opt
|
|||||||
vm->committed += next_commit_size;
|
vm->committed += next_commit_size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
vm->commit_used = to_be_used;
|
U8 current_offset = vm->reserve_start + vm->commit_used;
|
||||||
|
vm->commit_used = to_be_used;
|
||||||
return (Slice_Mem){.ptr = current_offset, .len = requested_size};
|
return (Slice_Mem){.ptr = current_offset, .len = requested_size};
|
||||||
}
|
}
|
||||||
inline
|
internal inline
|
||||||
Slice_Mem varena__grow(VArena_R vm, Slice_Mem old_allocation, U8 requested_size, U8 alignment, B4 no_zero) {
|
Slice_Mem varena__grow(VArena_R vm, Slice_Mem old_allocation, U8 requested_size, U8 alignment, B4 should_zero) {
|
||||||
U8 grow_amount = requested_size - old_allocation.len;
|
U8 grow_amount = requested_size - old_allocation.len;
|
||||||
if (grow_amount == 0) { return old_allocation; } // Growing when not the last allocation not allowed
|
if (grow_amount == 0) { return old_allocation; } // Growing when not the last allocation not allowed
|
||||||
U8 current_offset = vm->reserve_start + vm->commit_used; assert(old_allocation.ptr == current_offset);
|
U8 current_offset = vm->reserve_start + vm->commit_used; assert(old_allocation.ptr == current_offset);
|
||||||
Slice_Mem allocation = varena_push_mem(vm, grow_amount, alignment); assert(allocation.ptr != 0);
|
Slice_Mem allocation = varena_push_mem(vm, grow_amount, alignment); assert(allocation.ptr != 0);
|
||||||
Slice_Mem result = (Slice_Mem){ old_allocation.ptr, requested_size + allocation.len };
|
mem_zero(allocation.ptr, allocation.len * should_zero);
|
||||||
mem_zero(result.ptr, result.len * no_zero);
|
return (Slice_Mem){ old_allocation.ptr, old_allocation.len + allocation.len };
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
finline void varena_release(VArena_R arena) { os_vmem_release(u8_(arena), arena->reserve); }
|
finline void varena_release(VArena_R arena) { os_vmem_release(u8_(arena), arena->reserve); }
|
||||||
inline
|
internal inline
|
||||||
Slice_Mem varena__shrink(VArena_R vm, Slice_Mem old_allocation, U8 requested_size) {
|
Slice_Mem varena__shrink(VArena_R vm, Slice_Mem old_allocation, U8 requested_size) {
|
||||||
U8 shrink_amount = old_allocation.len - requested_size;
|
U8 shrink_amount = old_allocation.len - requested_size;
|
||||||
if (lt_s(shrink_amount, 0)) { return old_allocation; }
|
if (lt_s(shrink_amount, 0)) { return old_allocation; }
|
||||||
@@ -1177,6 +1170,7 @@ void varena_rewind(VArena_R vm, AllocatorSP sp) {
|
|||||||
vm->commit_used = max(sp.slot, sizeof(VArena));
|
vm->commit_used = max(sp.slot, sizeof(VArena));
|
||||||
}
|
}
|
||||||
finline AllocatorSP varena_save(VArena_R vm) { return (AllocatorSP){varena_allocator_proc, vm->commit_used}; }
|
finline AllocatorSP varena_save(VArena_R vm) { return (AllocatorSP){varena_allocator_proc, vm->commit_used}; }
|
||||||
|
internal
|
||||||
void varena_allocator_proc(AllocatorProc_In in, AllocatorProc_Out* out)
|
void varena_allocator_proc(AllocatorProc_In in, AllocatorProc_Out* out)
|
||||||
{
|
{
|
||||||
VArena_R vm = cast(VArena_R, in.data);
|
VArena_R vm = cast(VArena_R, in.data);
|
||||||
@@ -1219,13 +1213,13 @@ void varena_allocator_proc(AllocatorProc_In in, AllocatorProc_Out* out)
|
|||||||
#pragma endregion VArena
|
#pragma endregion VArena
|
||||||
|
|
||||||
#pragma region Arena (Chained Arena)
|
#pragma region Arena (Chained Arena)
|
||||||
inline
|
finline U8 arena_header_size(void) { return align_pow2(size_of(Arena), MEMORY_ALIGNMENT_DEFAULT); }
|
||||||
|
internal inline
|
||||||
Arena* arena__make(Opts_arena_make*R_ opts) {
|
Arena* arena__make(Opts_arena_make*R_ opts) {
|
||||||
assert(opts != nullptr);
|
assert(opts != nullptr);
|
||||||
U8 header_size = align_pow2(size_of(Arena), MEMORY_ALIGNMENT_DEFAULT);
|
U8 header_size = arena_header_size();
|
||||||
VArena_R current = varena__make(opts);
|
VArena_R current = varena__make(opts); assert(current != nullptr);
|
||||||
assert(current != nullptr);
|
Arena* arena = varena_push(current, Arena); r_(arena)[0] = (Arena){
|
||||||
Arena* arena = varena_push(current, Arena); r_(arena)[0] = (Arena){
|
|
||||||
.backing = current,
|
.backing = current,
|
||||||
.prev = nullptr,
|
.prev = nullptr,
|
||||||
.current = arena,
|
.current = arena,
|
||||||
@@ -1235,6 +1229,7 @@ Arena* arena__make(Opts_arena_make*R_ opts) {
|
|||||||
};
|
};
|
||||||
return arena;
|
return arena;
|
||||||
}
|
}
|
||||||
|
internal inline
|
||||||
Slice_Mem arena__push(Arena_R arena, U8 amount, U8 type_width, Opts_arena* opts) {
|
Slice_Mem arena__push(Arena_R arena, U8 amount, U8 type_width, Opts_arena* opts) {
|
||||||
assert(arena != nullptr);
|
assert(arena != nullptr);
|
||||||
assert(opts != nullptr);
|
assert(opts != nullptr);
|
||||||
@@ -1266,6 +1261,45 @@ Slice_Mem arena__push(Arena_R arena, U8 amount, U8 type_width, Opts_arena* opts)
|
|||||||
active->pos = pos_pst;
|
active->pos = pos_pst;
|
||||||
return vresult;
|
return vresult;
|
||||||
}
|
}
|
||||||
|
internal inline
|
||||||
|
Slice_Mem arena__grow(Arena_R arena, Slice_Mem old_allocation, U8 requested_size, U8 alignment, B4 should_zero) {
|
||||||
|
Arena_R active = arena->current;
|
||||||
|
U8 alloc_end = old_allocation.ptr + old_allocation.len + requested_size;
|
||||||
|
U8 arena_end = u8_(active) + active->pos;
|
||||||
|
if (alloc_end == arena_end)
|
||||||
|
{
|
||||||
|
U8 grow_amount = requested_size - old_allocation.len;
|
||||||
|
U8 aligned_grow = align_pow2(grow_amount, alignment ? alignment : MEMORY_ALIGNMENT_DEFAULT);
|
||||||
|
if (active->pos + aligned_grow <= active->backing->reserve) {
|
||||||
|
Slice_Mem vresult = varena_push_mem(active->backing, aligned_grow, .alignment = alignment);
|
||||||
|
if (vresult.ptr != null) {
|
||||||
|
active->pos += aligned_grow;
|
||||||
|
mem_zero(old_allocation.ptr + old_allocation.len, aligned_grow * (U8)should_zero);
|
||||||
|
return (Slice_Mem){old_allocation.ptr, aligned_grow + old_allocation.len};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#pragma diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wnrvo"
|
||||||
|
Slice_Mem new_alloc = arena__push(arena, requested_size, 1, &(Opts_arena){.alignment = alignment});
|
||||||
|
if (new_alloc.ptr == null) { return (Slice_Mem){0}; }
|
||||||
|
mem_copy(new_alloc.ptr, old_allocation.ptr, old_allocation.len);
|
||||||
|
mem_zero(new_alloc.ptr + old_allocation.len, (new_alloc.len - old_allocation.len) * (U8)should_zero);
|
||||||
|
return new_alloc;
|
||||||
|
#pragma diagnostic pop
|
||||||
|
}
|
||||||
|
internal inline
|
||||||
|
Slice_Mem arena__shrink(Arena_R arena, Slice_Mem old_allocation, U8 requested_size, U8 alignment) {
|
||||||
|
Arena_R active = arena->current;
|
||||||
|
U8 alloc_end = old_allocation.ptr + old_allocation.len;
|
||||||
|
U8 arena_end = u8_(active) + active->pos;
|
||||||
|
if (alloc_end != arena_end) { return (Slice_Mem){old_allocation.ptr, requested_size}; }
|
||||||
|
U8 aligned_original = align_pow2(old_allocation.len, MEMORY_ALIGNMENT_DEFAULT);
|
||||||
|
U8 aligned_new = align_pow2(requested_size, alignment ? alignment : MEMORY_ALIGNMENT_DEFAULT);
|
||||||
|
U8 pos_reduction = aligned_original - aligned_new;
|
||||||
|
active->pos -= pos_reduction;
|
||||||
|
return varena__shrink(active->backing, old_allocation, requested_size);
|
||||||
|
}
|
||||||
finline
|
finline
|
||||||
void arena_release(Arena_R arena) {
|
void arena_release(Arena_R arena) {
|
||||||
assert(arena != nullptr);
|
assert(arena != nullptr);
|
||||||
@@ -1277,6 +1311,7 @@ void arena_release(Arena_R arena) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
finline void arena_reset(Arena_R arena) { arena_rewind(arena, (AllocatorSP){.type_sig = arena_allocator_proc, .slot = 0}); }
|
finline void arena_reset(Arena_R arena) { arena_rewind(arena, (AllocatorSP){.type_sig = arena_allocator_proc, .slot = 0}); }
|
||||||
|
internal inline
|
||||||
void arena_rewind(Arena_R arena, AllocatorSP save_point) {
|
void arena_rewind(Arena_R arena, AllocatorSP save_point) {
|
||||||
assert(arena != nullptr);
|
assert(arena != nullptr);
|
||||||
assert(save_point.type_sig == arena_allocator_proc);
|
assert(save_point.type_sig == arena_allocator_proc);
|
||||||
@@ -1288,12 +1323,12 @@ void arena_rewind(Arena_R arena, AllocatorSP save_point) {
|
|||||||
varena_release(curr->backing);
|
varena_release(curr->backing);
|
||||||
}
|
}
|
||||||
arena->current = curr;
|
arena->current = curr;
|
||||||
U8 new_pos = big_pos - curr->base_pos;
|
U8 new_pos = big_pos - curr->base_pos; assert(new_pos <= curr->pos);
|
||||||
assert(new_pos <= curr->pos);
|
curr->pos = new_pos;
|
||||||
curr->pos = new_pos;
|
|
||||||
varena_rewind(curr->backing, (AllocatorSP){varena_allocator_proc, curr->pos + size_of(VArena)});
|
varena_rewind(curr->backing, (AllocatorSP){varena_allocator_proc, curr->pos + size_of(VArena)});
|
||||||
}
|
}
|
||||||
finline AllocatorSP arena_save(Arena_R arena) { return (AllocatorSP){arena_allocator_proc, arena->base_pos + arena->current->pos}; }
|
finline AllocatorSP arena_save(Arena_R arena) { return (AllocatorSP){arena_allocator_proc, arena->base_pos + arena->current->pos}; }
|
||||||
|
internal
|
||||||
void arena_allocator_proc(AllocatorProc_In in, AllocatorProc_Out*R_ out)
|
void arena_allocator_proc(AllocatorProc_In in, AllocatorProc_Out*R_ out)
|
||||||
{
|
{
|
||||||
assert(out != nullptr);
|
assert(out != nullptr);
|
||||||
@@ -1311,53 +1346,11 @@ void arena_allocator_proc(AllocatorProc_In in, AllocatorProc_Out*R_ out)
|
|||||||
case AllocatorOp_Reset: arena_reset(arena); break;
|
case AllocatorOp_Reset: arena_reset(arena); break;
|
||||||
|
|
||||||
case AllocatorOp_Grow:
|
case AllocatorOp_Grow:
|
||||||
case AllocatorOp_Grow_NoZero: {
|
case AllocatorOp_Grow_NoZero:
|
||||||
Arena_R active = arena->current;
|
out->allocation = arena__grow(arena, in.old_allocation, in.requested_size, in.alignment, in.op - AllocatorOp_Grow_NoZero);
|
||||||
U8 alloc_end = in.old_allocation.ptr + in.old_allocation.len;
|
|
||||||
U8 arena_end = u8_(active) + active->pos;
|
|
||||||
if (alloc_end == arena_end)
|
|
||||||
{
|
|
||||||
U8 grow_amount = in.requested_size - in.old_allocation.len;
|
|
||||||
U8 aligned_grow = align_pow2(grow_amount, in.alignment ? in.alignment : MEMORY_ALIGNMENT_DEFAULT);
|
|
||||||
if (active->pos + aligned_grow <= active->backing->reserve)
|
|
||||||
{
|
|
||||||
Slice_Mem vresult = varena_push_mem(active->backing, aligned_grow, .alignment = in.alignment);
|
|
||||||
if (vresult.ptr != null)
|
|
||||||
{
|
|
||||||
active->pos += aligned_grow;
|
|
||||||
out->allocation = (Slice_Mem){in.old_allocation.ptr, in.requested_size};
|
|
||||||
mem_zero(in.old_allocation.ptr + in.old_allocation.len, grow_amount * in.op - AllocatorOp_Grow_NoZero);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Slice_Mem new_alloc = arena__push(arena, in.requested_size, 1, &(Opts_arena){.alignment = in.alignment});
|
|
||||||
if (new_alloc.ptr == null) {
|
|
||||||
out->allocation = (Slice_Mem){0};
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
mem_copy(new_alloc.ptr, in.old_allocation.ptr, in.old_allocation.len);
|
|
||||||
mem_zero(new_alloc.ptr + in.old_allocation.len, (in.requested_size - in.old_allocation.len) * in.op - AllocatorOp_Grow_NoZero);
|
|
||||||
out->allocation = new_alloc;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
case AllocatorOp_Shrink:
|
||||||
case AllocatorOp_Shrink: {
|
out->allocation = arena__shrink(arena, in.old_allocation, in.requested_size, in.alignment);
|
||||||
Arena_R active = arena->current;
|
|
||||||
U8 alloc_end = in.old_allocation.ptr + in.old_allocation.len;
|
|
||||||
U8 arena_end = u8_(active) + active->pos;
|
|
||||||
if (alloc_end != arena_end) {
|
|
||||||
out->allocation = (Slice_Mem){in.old_allocation.ptr, in.requested_size};
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
//SSIZE shrink_amount = in.old_allocation.len - in.requested_size;
|
|
||||||
U8 aligned_original = align_pow2(in.old_allocation.len, MEMORY_ALIGNMENT_DEFAULT);
|
|
||||||
U8 aligned_new = align_pow2(in.requested_size, in.alignment ? in.alignment : MEMORY_ALIGNMENT_DEFAULT);
|
|
||||||
U8 pos_reduction = aligned_original - aligned_new;
|
|
||||||
active->pos -= pos_reduction;
|
|
||||||
varena__shrink(active->backing, in.old_allocation, in.requested_size);
|
|
||||||
out->allocation = (Slice_Mem){in.old_allocation.ptr, in.requested_size};
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AllocatorOp_Rewind: arena_rewind(arena, in.save_point); break;
|
case AllocatorOp_Rewind: arena_rewind(arena, in.save_point); break;
|
||||||
@@ -1380,7 +1373,7 @@ void arena_allocator_proc(AllocatorProc_In in, AllocatorProc_Out*R_ out)
|
|||||||
#pragma endregion Arena
|
#pragma endregion Arena
|
||||||
|
|
||||||
#pragma region Key Table Linear (KTL)
|
#pragma region Key Table Linear (KTL)
|
||||||
inline
|
finline
|
||||||
void ktl_populate_slice_a2_str8(KTL_Str8*R_ kt, AllocatorInfo backing, Slice_A2_Str8 values) {
|
void ktl_populate_slice_a2_str8(KTL_Str8*R_ kt, AllocatorInfo backing, Slice_A2_Str8 values) {
|
||||||
assert(kt != nullptr);
|
assert(kt != nullptr);
|
||||||
if (values.len == 0) return;
|
if (values.len == 0) return;
|
||||||
@@ -1393,7 +1386,7 @@ void ktl_populate_slice_a2_str8(KTL_Str8*R_ kt, AllocatorInfo backing, Slice_A2_
|
|||||||
#pragma endregion KTL
|
#pragma endregion KTL
|
||||||
|
|
||||||
#pragma region Key Table 1-Layer Chained-Chunked_Cells (KT1CX)
|
#pragma region Key Table 1-Layer Chained-Chunked_Cells (KT1CX)
|
||||||
inline
|
internal inline
|
||||||
void kt1cx_init(KT1CX_Info info, KT1CX_InfoMeta m, KT1CX_Byte*R_ result) {
|
void kt1cx_init(KT1CX_Info info, KT1CX_InfoMeta m, KT1CX_Byte*R_ result) {
|
||||||
assert(result != nullptr);
|
assert(result != nullptr);
|
||||||
assert(info.backing_cells.proc != nullptr);
|
assert(info.backing_cells.proc != nullptr);
|
||||||
@@ -1405,7 +1398,7 @@ void kt1cx_init(KT1CX_Info info, KT1CX_InfoMeta m, KT1CX_Byte*R_ result) {
|
|||||||
result->table = mem_alloc(info.backing_table, m.table_size * m.cell_size); slice_assert(result->table);
|
result->table = mem_alloc(info.backing_table, m.table_size * m.cell_size); slice_assert(result->table);
|
||||||
result->table.len = m.table_size; // Setting to the table number of elements instead of byte length.
|
result->table.len = m.table_size; // Setting to the table number of elements instead of byte length.
|
||||||
}
|
}
|
||||||
inline
|
internal inline
|
||||||
void kt1cx_clear(KT1CX_Byte kt, KT1CX_ByteMeta m) {
|
void kt1cx_clear(KT1CX_Byte kt, KT1CX_ByteMeta m) {
|
||||||
U8 cell_cursor = kt.table.ptr;
|
U8 cell_cursor = kt.table.ptr;
|
||||||
U8 table_len = kt.table.len * m.cell_size;
|
U8 table_len = kt.table.len * m.cell_size;
|
||||||
@@ -1428,9 +1421,9 @@ void kt1cx_clear(KT1CX_Byte kt, KT1CX_ByteMeta m) {
|
|||||||
}
|
}
|
||||||
finline
|
finline
|
||||||
U8 kt1cx_slot_id(KT1CX_Byte kt, U8 key, KT1CX_ByteMeta m) {
|
U8 kt1cx_slot_id(KT1CX_Byte kt, U8 key, KT1CX_ByteMeta m) {
|
||||||
U8 hash_index = key % kt.table.len;
|
return key % kt.table.len;
|
||||||
return hash_index;
|
|
||||||
}
|
}
|
||||||
|
inline
|
||||||
U8 kt1cx_get(KT1CX_Byte kt, U8 key, KT1CX_ByteMeta m) {
|
U8 kt1cx_get(KT1CX_Byte kt, U8 key, KT1CX_ByteMeta m) {
|
||||||
U8 hash_index = kt1cx_slot_id(kt, key, m);
|
U8 hash_index = kt1cx_slot_id(kt, key, m);
|
||||||
U8 cell_offset = hash_index * m.cell_size;
|
U8 cell_offset = hash_index * m.cell_size;
|
||||||
@@ -1457,7 +1450,7 @@ U8 kt1cx_get(KT1CX_Byte kt, U8 key, KT1CX_ByteMeta m) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
inline
|
internal
|
||||||
U8 kt1cx_set(KT1CX_Byte kt, U8 key, Slice_Mem value, AllocatorInfo backing_cells, KT1CX_ByteMeta m) {
|
U8 kt1cx_set(KT1CX_Byte kt, U8 key, Slice_Mem value, AllocatorInfo backing_cells, KT1CX_ByteMeta m) {
|
||||||
U8 hash_index = kt1cx_slot_id(kt, key, m);
|
U8 hash_index = kt1cx_slot_id(kt, key, m);
|
||||||
U8 cell_offset = hash_index * m.cell_size;
|
U8 cell_offset = hash_index * m.cell_size;
|
||||||
@@ -1507,24 +1500,25 @@ char* str8_to_cstr_capped(Str8 content, Slice_Mem mem) {
|
|||||||
u1_r(mem.ptr)[copy_len] = '\0';
|
u1_r(mem.ptr)[copy_len] = '\0';
|
||||||
return cast(char*, mem.ptr);
|
return cast(char*, mem.ptr);
|
||||||
}
|
}
|
||||||
|
internal
|
||||||
Str8 str8_from_u32(AllocatorInfo ainfo, U4 num, U4 radix, U4 min_digits, U4 digit_group_separator)
|
Str8 str8_from_u32(AllocatorInfo ainfo, U4 num, U4 radix, U4 min_digits, U4 digit_group_separator)
|
||||||
{
|
{
|
||||||
Str8 result = {0};
|
Str8 result = {0};
|
||||||
Str8 prefix = {0};
|
Str8 prefix = {0};
|
||||||
switch (radix) {
|
switch (radix) {
|
||||||
case 16: { prefix = lit("0x"); } break;
|
case 16: { prefix = lit("0x"); } break;
|
||||||
case 8: { prefix = lit("0o"); } break;
|
case 8: { prefix = lit("0o"); } break;
|
||||||
case 2: { prefix = lit("0b"); } break;
|
case 2: { prefix = lit("0b"); } break;
|
||||||
}
|
}
|
||||||
U4 digit_group_size = 3;
|
U4 digit_group_size = 3;
|
||||||
switch (radix) {
|
switch (radix) {
|
||||||
default: break;
|
default: break;
|
||||||
case 2:
|
case 2:
|
||||||
case 8:
|
case 8:
|
||||||
case 16: {
|
case 16: {
|
||||||
digit_group_size = 4;
|
digit_group_size = 4;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
U4 needed_leading_zeros = 0;
|
U4 needed_leading_zeros = 0;
|
||||||
{
|
{
|
||||||
@@ -1666,17 +1660,16 @@ finline
|
|||||||
Str8 str8__fmt_backed(AllocatorInfo tbl_backing, AllocatorInfo buf_backing, Str8 fmt_template, Slice_A2_Str8*R_ entries) {
|
Str8 str8__fmt_backed(AllocatorInfo tbl_backing, AllocatorInfo buf_backing, Str8 fmt_template, Slice_A2_Str8*R_ entries) {
|
||||||
KTL_Str8 kt; kt1l_populate_slice_a2_str8(& kt, tbl_backing, entries[0] );
|
KTL_Str8 kt; kt1l_populate_slice_a2_str8(& kt, tbl_backing, entries[0] );
|
||||||
U8 buf_size = kilo(64); Slice_Mem buffer = mem_alloc(buf_backing, buf_size);
|
U8 buf_size = kilo(64); Slice_Mem buffer = mem_alloc(buf_backing, buf_size);
|
||||||
Str8 result = str8__fmt_ktl(buf_backing, & buffer, kt, fmt_template);
|
return str8__fmt_ktl(buf_backing, & buffer, kt, fmt_template);
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
finline
|
||||||
Str8 str8__fmt(Str8 fmt_template, Slice_A2_Str8*R_ entries) {
|
Str8 str8__fmt(Str8 fmt_template, Slice_A2_Str8*R_ entries) {
|
||||||
local_persist B1 tbl_mem[kilo(32)]; FArena tbl_arena = farena_make(slice_fmem(tbl_mem));
|
local_persist B1 tbl_mem[kilo(32)]; FArena tbl_arena = farena_make(slice_fmem(tbl_mem));
|
||||||
local_persist B1 buf_mem[kilo(64)];
|
local_persist B1 buf_mem[kilo(64)];
|
||||||
KTL_Str8 kt = {0}; ktl_populate_slice_a2_str8(& kt, ainfo_farena(tbl_arena), entries[0] );
|
KTL_Str8 kt = {0}; ktl_populate_slice_a2_str8(& kt, ainfo_farena(tbl_arena), entries[0] );
|
||||||
Str8 result = str8__fmt_ktl((AllocatorInfo){0}, & slice_fmem(buf_mem), kt, fmt_template);
|
return str8__fmt_ktl((AllocatorInfo){0}, & slice_fmem(buf_mem), kt, fmt_template);
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
inline
|
internal inline
|
||||||
void str8cache__init(Str8Cache_R cache, Opts_str8cache_init*R_ opts) {
|
void str8cache__init(Str8Cache_R cache, Opts_str8cache_init*R_ opts) {
|
||||||
assert(cache != nullptr);
|
assert(cache != nullptr);
|
||||||
assert(opts != nullptr);
|
assert(opts != nullptr);
|
||||||
@@ -1764,8 +1757,7 @@ finline
|
|||||||
Str8 cache_str8(Str8Cache_R cache, Str8 str) {
|
Str8 cache_str8(Str8Cache_R cache, Str8 str) {
|
||||||
assert(cache != nullptr);
|
assert(cache != nullptr);
|
||||||
U8 key = 0; hash64_fnv1a(& key, slice_mem_s(str));
|
U8 key = 0; hash64_fnv1a(& key, slice_mem_s(str));
|
||||||
Str8_R result = str8cache_set(cache->kt, key, str, cache->str_reserve, cache->cell_reserve);
|
return str8cache_set(cache->kt, key, str, cache->str_reserve, cache->cell_reserve)[0];
|
||||||
return result[0];
|
|
||||||
}
|
}
|
||||||
finline
|
finline
|
||||||
void str8gen_init(Str8Gen_R gen, AllocatorInfo backing) {
|
void str8gen_init(Str8Gen_R gen, AllocatorInfo backing) {
|
||||||
@@ -1787,6 +1779,7 @@ void str8gen_append_str8(Str8Gen_R gen, Str8 str){
|
|||||||
gen->len += str.len;
|
gen->len += str.len;
|
||||||
gen->cap = result.len;
|
gen->cap = result.len;
|
||||||
}
|
}
|
||||||
|
internal inline
|
||||||
void str8gen__append_fmt(Str8Gen_R gen, Str8 fmt_template, Slice_A2_Str8*R_ entries){
|
void str8gen__append_fmt(Str8Gen_R gen, Str8 fmt_template, Slice_A2_Str8*R_ entries){
|
||||||
local_persist B1 tbl_mem[kilo(32)]; FArena tbl_arena = farena_make(slice_fmem(tbl_mem));
|
local_persist B1 tbl_mem[kilo(32)]; FArena tbl_arena = farena_make(slice_fmem(tbl_mem));
|
||||||
KTL_Str8 kt = {0}; ktl_populate_slice_a2_str8(& kt, ainfo_farena(tbl_arena), entries[0] );
|
KTL_Str8 kt = {0}; ktl_populate_slice_a2_str8(& kt, ainfo_farena(tbl_arena), entries[0] );
|
||||||
@@ -1842,6 +1835,7 @@ FileOpInfo file__read_contents(Str8 path, Opts_read_file_contents*R_ opts) {
|
|||||||
FileOpInfo result = {0}; api_file_read_contents(& result, path, opts[0]);
|
FileOpInfo result = {0}; api_file_read_contents(& result, path, opts[0]);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
internal
|
||||||
void api_file_read_contents(FileOpInfo_R result, Str8 path, Opts_read_file_contents opts)
|
void api_file_read_contents(FileOpInfo_R result, Str8 path, Opts_read_file_contents opts)
|
||||||
{
|
{
|
||||||
assert(result != nullptr);
|
assert(result != nullptr);
|
||||||
@@ -1901,6 +1895,7 @@ void api_file_read_contents(FileOpInfo_R result, Str8 path, Opts_read_file_conte
|
|||||||
result->content.len = u8_(file_size.QuadPart);
|
result->content.len = u8_(file_size.QuadPart);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
internal
|
||||||
void file_write_str8(Str8 path, Str8 content)
|
void file_write_str8(Str8 path, Str8 content)
|
||||||
{
|
{
|
||||||
slice_assert(path);
|
slice_assert(path);
|
||||||
@@ -1975,6 +1970,7 @@ int printf_err(char const* fmt, ...) {
|
|||||||
va_end(args);
|
va_end(args);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
internal inline
|
||||||
void assert_handler( UTF8*R_ condition, UTF8*R_ file, UTF8*R_ function, S4 line, UTF8*R_ msg, ... ) {
|
void assert_handler( UTF8*R_ condition, UTF8*R_ file, UTF8*R_ function, S4 line, UTF8*R_ msg, ... ) {
|
||||||
printf_err( "%s - %s:(%d): Assert Failure: ", file, function, line );
|
printf_err( "%s - %s:(%d): Assert Failure: ", file, function, line );
|
||||||
if ( condition )
|
if ( condition )
|
||||||
@@ -1991,6 +1987,7 @@ void assert_handler( UTF8*R_ condition, UTF8*R_ file, UTF8*R_ function, S4 line,
|
|||||||
#pragma endregion Debug
|
#pragma endregion Debug
|
||||||
|
|
||||||
#pragma region WATL
|
#pragma region WATL
|
||||||
|
internal
|
||||||
void api_watl_lex(WATL_LexInfo_R info, Str8 source, Opts_watl_lex*R_ opts)
|
void api_watl_lex(WATL_LexInfo_R info, Str8 source, Opts_watl_lex*R_ opts)
|
||||||
{
|
{
|
||||||
if (source.len == 0) { return; }
|
if (source.len == 0) { return; }
|
||||||
@@ -2012,52 +2009,52 @@ void api_watl_lex(WATL_LexInfo_R info, Str8 source, Opts_watl_lex*R_ opts)
|
|||||||
#define alloc_tok() alloc_type(opts->ainfo_toks, WATL_Tok, .alignment = alignof(WATL_Tok), .no_zero = true)
|
#define alloc_tok() alloc_type(opts->ainfo_toks, WATL_Tok, .alignment = alignof(WATL_Tok), .no_zero = true)
|
||||||
switch (code)
|
switch (code)
|
||||||
{
|
{
|
||||||
case WATL_Tok_Space:
|
case WATL_Tok_Space:
|
||||||
case WATL_Tok_Tab:
|
case WATL_Tok_Tab:
|
||||||
{
|
{
|
||||||
if (prev[0] != cursor[0]) {
|
if (prev[0] != cursor[0]) {
|
||||||
WATL_Tok_R new_tok = alloc_tok(); if (new_tok - 1 != tok && tok != nullptr) { goto slice_constraint_fail; }
|
|
||||||
tok = new_tok;
|
|
||||||
tok[0] = (WATL_Tok){ cursor, 0 };
|
|
||||||
was_formatting = true;
|
|
||||||
++ num;
|
|
||||||
}
|
|
||||||
cursor += 1;
|
|
||||||
tok->len += 1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case WATL_Tok_LineFeed: {
|
|
||||||
WATL_Tok_R new_tok = alloc_tok(); if (new_tok - 1 != tok && tok != nullptr) { goto slice_constraint_fail; }
|
WATL_Tok_R new_tok = alloc_tok(); if (new_tok - 1 != tok && tok != nullptr) { goto slice_constraint_fail; }
|
||||||
tok = new_tok;
|
tok = new_tok;
|
||||||
tok[0] = (WATL_Tok){ cursor, 1 };
|
tok[0] = (WATL_Tok){ cursor, 0 };
|
||||||
cursor += 1;
|
|
||||||
was_formatting = true;
|
was_formatting = true;
|
||||||
++ num;
|
++ num;
|
||||||
}
|
}
|
||||||
break;
|
cursor += 1;
|
||||||
// Assuming what comes after is line feed.
|
tok->len += 1;
|
||||||
case WATL_Tok_CarriageReturn: {
|
}
|
||||||
|
break;
|
||||||
|
case WATL_Tok_LineFeed: {
|
||||||
|
WATL_Tok_R new_tok = alloc_tok(); if (new_tok - 1 != tok && tok != nullptr) { goto slice_constraint_fail; }
|
||||||
|
tok = new_tok;
|
||||||
|
tok[0] = (WATL_Tok){ cursor, 1 };
|
||||||
|
cursor += 1;
|
||||||
|
was_formatting = true;
|
||||||
|
++ num;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
// Assuming what comes after is line feed.
|
||||||
|
case WATL_Tok_CarriageReturn: {
|
||||||
|
WATL_Tok_R new_tok = alloc_tok(); if (new_tok - 1 != tok && tok != nullptr) { goto slice_constraint_fail; }
|
||||||
|
tok = new_tok;
|
||||||
|
tok[0] = (WATL_Tok){ cursor, 2 };
|
||||||
|
cursor += 2;
|
||||||
|
was_formatting = true;
|
||||||
|
++ num;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
if (was_formatting) {
|
||||||
WATL_Tok_R new_tok = alloc_tok(); if (new_tok - 1 != tok && tok != nullptr) { goto slice_constraint_fail; }
|
WATL_Tok_R new_tok = alloc_tok(); if (new_tok - 1 != tok && tok != nullptr) { goto slice_constraint_fail; }
|
||||||
tok = new_tok;
|
tok = new_tok;
|
||||||
tok[0] = (WATL_Tok){ cursor, 2 };
|
tok[0] = (WATL_Tok){ cursor, 0 };
|
||||||
cursor += 2;
|
was_formatting = false;
|
||||||
was_formatting = true;
|
|
||||||
++ num;
|
++ num;
|
||||||
}
|
}
|
||||||
break;
|
cursor += 1;
|
||||||
default:
|
tok->len += 1;
|
||||||
{
|
}
|
||||||
if (was_formatting) {
|
break;
|
||||||
WATL_Tok_R new_tok = alloc_tok(); if (new_tok - 1 != tok && tok != nullptr) { goto slice_constraint_fail; }
|
|
||||||
tok = new_tok;
|
|
||||||
tok[0] = (WATL_Tok){ cursor, 0 };
|
|
||||||
was_formatting = false;
|
|
||||||
++ num;
|
|
||||||
}
|
|
||||||
cursor += 1;
|
|
||||||
tok->len += 1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
prev = cursor - 1;
|
prev = cursor - 1;
|
||||||
code = cursor[0];
|
code = cursor[0];
|
||||||
@@ -2080,7 +2077,7 @@ slice_constraint_fail:
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
inline WATL_LexInfo watl__lex(Str8 source, Opts_watl_lex*R_ opts) { WATL_LexInfo info = {0}; api_watl_lex(& info, source, opts); return info; }
|
inline WATL_LexInfo watl__lex(Str8 source, Opts_watl_lex*R_ opts) { WATL_LexInfo info = {0}; api_watl_lex(& info, source, opts); return info; }
|
||||||
|
internal
|
||||||
void api_watl_parse(WATL_ParseInfo_R info, Slice_WATL_Tok tokens, Opts_watl_parse*R_ opts)
|
void api_watl_parse(WATL_ParseInfo_R info, Slice_WATL_Tok tokens, Opts_watl_parse*R_ opts)
|
||||||
{
|
{
|
||||||
if (tokens.len == 0) { return; }
|
if (tokens.len == 0) { return; }
|
||||||
@@ -2100,49 +2097,49 @@ void api_watl_parse(WATL_ParseInfo_R info, Slice_WATL_Tok tokens, Opts_watl_pars
|
|||||||
{
|
{
|
||||||
switch(token->ptr[0])
|
switch(token->ptr[0])
|
||||||
{
|
{
|
||||||
case WATL_Tok_CarriageReturn:
|
case WATL_Tok_CarriageReturn:
|
||||||
case WATL_Tok_LineFeed:
|
case WATL_Tok_LineFeed:
|
||||||
{
|
{
|
||||||
WATL_Line_R new_line = alloc_type(opts->ainfo_lines, WATL_Line); if (new_line - 1 != line) {
|
WATL_Line_R new_line = alloc_type(opts->ainfo_lines, WATL_Line); if (new_line - 1 != line) {
|
||||||
info->signal |= WATL_ParseStatus_MemFail_SliceConstraintFail;
|
info->signal |= WATL_ParseStatus_MemFail_SliceConstraintFail;
|
||||||
WATL_ParseMsg_R msg = alloc_type(opts->ainfo_msgs, WATL_ParseMsg);
|
WATL_ParseMsg_R msg = alloc_type(opts->ainfo_msgs, WATL_ParseMsg);
|
||||||
msg->content = lit("Line slice allocation was not contiguous");
|
msg->content = lit("Line slice allocation was not contiguous");
|
||||||
msg->pos = (WATL_Pos){cast(S4, info->lines.len), cast(S4, line->len)};
|
msg->pos = (WATL_Pos){cast(S4, info->lines.len), cast(S4, line->len)};
|
||||||
msg->line = line;
|
msg->line = line;
|
||||||
msg->tok = token;
|
msg->tok = token;
|
||||||
sll_queue_push_n(info->msgs, msg_last, msg, next);
|
sll_queue_push_n(info->msgs, msg_last, msg, next);
|
||||||
assert(opts->failon_slice_constraint_fail == false);
|
assert(opts->failon_slice_constraint_fail == false);
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
line = new_line;
|
|
||||||
line->ptr = curr;
|
|
||||||
info->lines.len += 1;
|
|
||||||
}
|
}
|
||||||
continue;
|
line = new_line;
|
||||||
|
line->ptr = curr;
|
||||||
default:
|
info->lines.len += 1;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
curr[0] = cache_str8(opts->str_cache, token[0]);
|
|
||||||
WATL_Node_R new_node = alloc_type(opts->ainfo_nodes, WATL_Node); if (new_node - 1 != curr) {
|
|
||||||
info->signal |= WATL_ParseStatus_MemFail_SliceConstraintFail;
|
|
||||||
WATL_ParseMsg_R msg = alloc_type(opts->ainfo_msgs, WATL_ParseMsg);
|
|
||||||
msg->content = lit("Nodes slice allocation was not contiguous");
|
|
||||||
msg->pos = (WATL_Pos){cast(S4, info->lines.len), cast(S4, line->len)};
|
|
||||||
msg->line = line;
|
|
||||||
msg->tok = token;
|
|
||||||
sll_queue_push_n(info->msgs, msg_last, msg, next);
|
|
||||||
assert(opts->failon_slice_constraint_fail == false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
curr = new_node;
|
|
||||||
line->len += 1;
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
curr[0] = cache_str8(opts->str_cache, token[0]);
|
||||||
|
WATL_Node_R new_node = alloc_type(opts->ainfo_nodes, WATL_Node); if (new_node - 1 != curr) {
|
||||||
|
info->signal |= WATL_ParseStatus_MemFail_SliceConstraintFail;
|
||||||
|
WATL_ParseMsg_R msg = alloc_type(opts->ainfo_msgs, WATL_ParseMsg);
|
||||||
|
msg->content = lit("Nodes slice allocation was not contiguous");
|
||||||
|
msg->pos = (WATL_Pos){cast(S4, info->lines.len), cast(S4, line->len)};
|
||||||
|
msg->line = line;
|
||||||
|
msg->tok = token;
|
||||||
|
sll_queue_push_n(info->msgs, msg_last, msg, next);
|
||||||
|
assert(opts->failon_slice_constraint_fail == false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
curr = new_node;
|
||||||
|
line->len += 1;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
inline WATL_ParseInfo watl__parse(Slice_WATL_Tok tokens, Opts_watl_parse*R_ opts) { WATL_ParseInfo info = {0}; api_watl_parse(& info, tokens, opts); return info; }
|
finline WATL_ParseInfo watl__parse(Slice_WATL_Tok tokens, Opts_watl_parse*R_ opts) { WATL_ParseInfo info = {0}; api_watl_parse(& info, tokens, opts); return info; }
|
||||||
|
internal
|
||||||
Str8 watl_dump_listing(AllocatorInfo buffer, Slice_WATL_Line lines)
|
Str8 watl_dump_listing(AllocatorInfo buffer, Slice_WATL_Line lines)
|
||||||
{
|
{
|
||||||
local_persist B1 scratch[kilo(64)] = {0}; FArena sarena = farena_make(slice_fmem(scratch)); AllocatorInfo sinfo = ainfo_farena(sarena);
|
local_persist B1 scratch[kilo(64)] = {0}; FArena sarena = farena_make(slice_fmem(scratch)); AllocatorInfo sinfo = ainfo_farena(sarena);
|
||||||
@@ -2162,11 +2159,10 @@ Str8 watl_dump_listing(AllocatorInfo buffer, Slice_WATL_Line lines)
|
|||||||
for slice_iter(line[0], chunk)
|
for slice_iter(line[0], chunk)
|
||||||
{
|
{
|
||||||
Str8 id;
|
Str8 id;
|
||||||
switch (chunk->ptr[0])
|
switch (chunk->ptr[0]) {
|
||||||
{
|
case WATL_Tok_Space: id = lit("Space"); break;
|
||||||
case WATL_Tok_Space: id = lit("Space"); break;
|
case WATL_Tok_Tab: id = lit("Tab"); break;
|
||||||
case WATL_Tok_Tab: id = lit("Tab"); break;
|
default: id = lit("Visible"); break;
|
||||||
default: id = lit("Visible"); break;
|
|
||||||
}
|
}
|
||||||
Str8 str_chunk_len = str8_from_u32(sinfo, cast(U4, chunk->len), 10, 0, 0);
|
Str8 str_chunk_len = str8_from_u32(sinfo, cast(U4, chunk->len), 10, 0, 0);
|
||||||
str8gen_append_fmt(& result, "\t<id>(<size>): '<chunk>'\n"
|
str8gen_append_fmt(& result, "\t<id>(<size>): '<chunk>'\n"
|
||||||
|
|||||||
777
C/watl.v0.msvc.c
777
C/watl.v0.msvc.c
File diff suppressed because it is too large
Load Diff
61
Odin/watl.v0.ideomatic.odin
Normal file
61
Odin/watl.v0.ideomatic.odin
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
package watl
|
||||||
|
|
||||||
|
import "core:os/os2"
|
||||||
|
import "core:mem/virtual"
|
||||||
|
import "core:mem"
|
||||||
|
|
||||||
|
|
||||||
|
main :: proc()
|
||||||
|
{
|
||||||
|
os_init()
|
||||||
|
|
||||||
|
// Note(Ed): Possible compiler bug, cannot resolve proc map with named arguments.
|
||||||
|
|
||||||
|
vm_file: virtual.Arena; virtual.arena_init_static(& vm_file, reserved = mem.Gigabytes * 4)
|
||||||
|
data, err := os2.read_entire_file_from_path("watl.v0.ideomatic.odin", virtual.arena_allocator(& vm_file), )
|
||||||
|
assert(err != .None)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
a_msgs := arena_make()
|
||||||
|
a_toks := arena_make()
|
||||||
|
// lex_res := watl_lex(transmute(string) file.content,
|
||||||
|
// ainfo_msgs = ainfo(a_msgs),
|
||||||
|
// ainfo_toks = ainfo(a_toks),
|
||||||
|
// )
|
||||||
|
lex_res := watl_lex(transmute(string) file.content,
|
||||||
|
ainfo(a_msgs),
|
||||||
|
ainfo(a_toks),
|
||||||
|
)
|
||||||
|
assert(lex_res.signal & { .MemFail_SliceConstraintFail } == {})
|
||||||
|
|
||||||
|
str8_cache_kt1_ainfo := arena_make()
|
||||||
|
str_cache := str8cache_make(
|
||||||
|
str_reserve = ainfo(arena_make()),
|
||||||
|
cell_reserve = ainfo(str8_cache_kt1_ainfo),
|
||||||
|
tbl_backing = ainfo(str8_cache_kt1_ainfo),
|
||||||
|
cell_pool_size = Kilo * 4,
|
||||||
|
table_size = Kilo * 32,
|
||||||
|
)
|
||||||
|
|
||||||
|
a_lines := arena_make()
|
||||||
|
// parse_res := watl_parse(lex_res.toks,
|
||||||
|
// ainfo_msgs = ainfo(a_msgs),
|
||||||
|
// ainfo_nodes = ainfo(a_toks),
|
||||||
|
// ainfo_lines = ainfo(a_lines),
|
||||||
|
// str_cache = & str_cache
|
||||||
|
// )
|
||||||
|
parse_res := watl_parse(lex_res.toks,
|
||||||
|
ainfo(a_msgs),
|
||||||
|
ainfo(a_toks),
|
||||||
|
ainfo(a_lines),
|
||||||
|
& str_cache
|
||||||
|
)
|
||||||
|
assert(parse_res.signal & { .MemFail_SliceConstraintFail } == {})
|
||||||
|
|
||||||
|
arena_reset(a_msgs)
|
||||||
|
arena_reset(a_toks)
|
||||||
|
listing := watl_dump_listing(ainfo(a_msgs), parse_res.lines)
|
||||||
|
file_write_str8("watl.v0.win32.odin.listing.txt", listing)
|
||||||
|
return
|
||||||
|
}
|
||||||
@@ -100,23 +100,14 @@ align_pow2 :: #force_inline proc(x: int, b: int) -> int {
|
|||||||
assert((b & (b - 1)) == 0) // Check power of 2
|
assert((b & (b - 1)) == 0) // Check power of 2
|
||||||
return ((x + b - 1) & ~(b - 1))
|
return ((x + b - 1) & ~(b - 1))
|
||||||
}
|
}
|
||||||
memory_zero :: #force_inline proc "contextless" (data: rawptr, len: int) -> rawptr {
|
memory_zero :: #force_inline proc "contextless" (data: rawptr, len: int) -> rawptr { intrinsics.mem_zero(data, len); return data }
|
||||||
intrinsics.mem_zero(data, len)
|
|
||||||
return data
|
|
||||||
}
|
|
||||||
memory_zero_explicit :: #force_inline proc "contextless" (data: rawptr, len: int) -> rawptr {
|
memory_zero_explicit :: #force_inline proc "contextless" (data: rawptr, len: int) -> rawptr {
|
||||||
intrinsics.mem_zero_volatile(data, len) // Use the volatile mem_zero
|
intrinsics.mem_zero_volatile(data, len) // Use the volatile mem_zero
|
||||||
intrinsics.atomic_thread_fence(.Seq_Cst) // Prevent reordering
|
intrinsics.atomic_thread_fence(.Seq_Cst) // Prevent reordering
|
||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
memory_copy_overlapping :: #force_inline proc "contextless" (dst, src: rawptr, len: int) -> rawptr {
|
memory_copy_overlapping :: #force_inline proc "contextless" (dst, src: rawptr, len: int) -> rawptr { intrinsics.mem_copy(dst, src, len); return dst }
|
||||||
intrinsics.mem_copy(dst, src, len)
|
memory_copy :: #force_inline proc "contextless" (dst, src: rawptr, len: int) -> rawptr { intrinsics.mem_copy_non_overlapping(dst, src, len); return dst }
|
||||||
return dst
|
|
||||||
}
|
|
||||||
memory_copy :: #force_inline proc "contextless" (dst, src: rawptr, len: int) -> rawptr {
|
|
||||||
intrinsics.mem_copy_non_overlapping(dst, src, len)
|
|
||||||
return dst
|
|
||||||
}
|
|
||||||
|
|
||||||
sll_stack_push_n :: proc "contextless" (curr, n, n_link: ^^$Type) {
|
sll_stack_push_n :: proc "contextless" (curr, n, n_link: ^^$Type) {
|
||||||
(n_link ^) = (curr ^)
|
(n_link ^) = (curr ^)
|
||||||
@@ -136,21 +127,13 @@ sll_queue_push_nz :: proc "contextless" (first: ^$ParentType, last, n: ^^$Type,
|
|||||||
}
|
}
|
||||||
sll_queue_push_n :: #force_inline proc "contextless" (first: $ParentType, last, n: ^^$Type) { sll_queue_push_nz(first, last, n, nil) }
|
sll_queue_push_n :: #force_inline proc "contextless" (first: $ParentType, last, n: ^^$Type) { sll_queue_push_nz(first, last, n, nil) }
|
||||||
|
|
||||||
SliceByte :: struct {
|
SliceByte :: struct { data: [^]byte, len: int }
|
||||||
data: [^]byte,
|
SliceRaw :: struct($Type: typeid) { data: [^]Type, len: int, }
|
||||||
len: int
|
|
||||||
}
|
|
||||||
SliceRaw :: struct ($Type: typeid) {
|
|
||||||
data: [^]Type,
|
|
||||||
len: int,
|
|
||||||
}
|
|
||||||
slice :: #force_inline proc "contextless" (s: [^] $Type, num: $Some_Integer) -> [ ]Type { return transmute([]Type) SliceRaw(Type) { s, cast(int) num } }
|
slice :: #force_inline proc "contextless" (s: [^] $Type, num: $Some_Integer) -> [ ]Type { return transmute([]Type) SliceRaw(Type) { s, cast(int) num } }
|
||||||
slice_cursor :: #force_inline proc "contextless" (s: []$Type) -> [^]Type { return transmute([^]Type) raw_data(s) }
|
slice_cursor :: #force_inline proc "contextless" (s: []$Type) -> [^]Type { return transmute([^]Type) raw_data(s) }
|
||||||
slice_assert :: #force_inline proc (s: $SliceType / []$Type) {
|
slice_end :: #force_inline proc "contextless" (s : $SliceType / []$Type) -> ^Type { return & cursor(s)[len(s)] }
|
||||||
assert(len(s) > 0)
|
|
||||||
assert(s != nil)
|
slice_assert :: #force_inline proc (s: $SliceType / []$Type) { assert(len(s) > 0); assert(s != nil) }
|
||||||
}
|
|
||||||
slice_end :: #force_inline proc "contextless" (s : $SliceType / []$Type) -> ^Type { return & cursor(s)[len(s)] }
|
|
||||||
|
|
||||||
@(require_results) slice_to_bytes :: proc "contextless" (s: []$Type) -> []byte { return ([^]byte)(raw_data(s))[:len(s) * size_of(Type)] }
|
@(require_results) slice_to_bytes :: proc "contextless" (s: []$Type) -> []byte { return ([^]byte)(raw_data(s))[:len(s) * size_of(Type)] }
|
||||||
@(require_results) slice_raw :: proc "contextless" (s: []$Type) -> SliceRaw(Type) { return transmute(SliceRaw(Type)) s }
|
@(require_results) slice_raw :: proc "contextless" (s: []$Type) -> SliceRaw(Type) { return transmute(SliceRaw(Type)) s }
|
||||||
@@ -270,8 +253,7 @@ mem_alloc :: proc(ainfo: AllocatorInfo, size: int, alignment: int = MEMORY_ALIGN
|
|||||||
requested_size = size,
|
requested_size = size,
|
||||||
alignment = alignment,
|
alignment = alignment,
|
||||||
}
|
}
|
||||||
output: AllocatorProc_Out
|
output: AllocatorProc_Out; ainfo.procedure(input, & output)
|
||||||
ainfo.procedure(input, & output)
|
|
||||||
return output.allocation
|
return output.allocation
|
||||||
}
|
}
|
||||||
mem_grow :: proc(ainfo: AllocatorInfo, mem: []byte, size: int, alignment: int = MEMORY_ALIGNMENT_DEFAULT, no_zero: b32 = false, give_actual: b32 = false) -> []byte {
|
mem_grow :: proc(ainfo: AllocatorInfo, mem: []byte, size: int, alignment: int = MEMORY_ALIGNMENT_DEFAULT, no_zero: b32 = false, give_actual: b32 = false) -> []byte {
|
||||||
@@ -283,8 +265,7 @@ mem_grow :: proc(ainfo: AllocatorInfo, mem: []byte, size: int, alignment: int =
|
|||||||
alignment = alignment,
|
alignment = alignment,
|
||||||
old_allocation = mem,
|
old_allocation = mem,
|
||||||
}
|
}
|
||||||
output: AllocatorProc_Out
|
output: AllocatorProc_Out; ainfo.procedure(input, & output)
|
||||||
ainfo.procedure(input, & output)
|
|
||||||
return slice(cursor(output.allocation), give_actual ? len(output.allocation) : size)
|
return slice(cursor(output.allocation), give_actual ? len(output.allocation) : size)
|
||||||
}
|
}
|
||||||
mem_resize :: proc(ainfo: AllocatorInfo, mem: []byte, size: int, alignment: int = MEMORY_ALIGNMENT_DEFAULT, no_zero: b32 = false, give_actual: b32 = false) -> []byte {
|
mem_resize :: proc(ainfo: AllocatorInfo, mem: []byte, size: int, alignment: int = MEMORY_ALIGNMENT_DEFAULT, no_zero: b32 = false, give_actual: b32 = false) -> []byte {
|
||||||
@@ -296,8 +277,7 @@ mem_resize :: proc(ainfo: AllocatorInfo, mem: []byte, size: int, alignment: int
|
|||||||
alignment = alignment,
|
alignment = alignment,
|
||||||
old_allocation = mem,
|
old_allocation = mem,
|
||||||
}
|
}
|
||||||
output: AllocatorProc_Out
|
output: AllocatorProc_Out; ainfo.procedure(input, & output)
|
||||||
ainfo.procedure(input, & output)
|
|
||||||
return slice(cursor(output.allocation), give_actual ? len(output.allocation) : size)
|
return slice(cursor(output.allocation), give_actual ? len(output.allocation) : size)
|
||||||
}
|
}
|
||||||
mem_shrink :: proc(ainfo: AllocatorInfo, mem: []byte, size: int, alignment: int = MEMORY_ALIGNMENT_DEFAULT, no_zero: b32 = false) -> []byte {
|
mem_shrink :: proc(ainfo: AllocatorInfo, mem: []byte, size: int, alignment: int = MEMORY_ALIGNMENT_DEFAULT, no_zero: b32 = false) -> []byte {
|
||||||
@@ -309,8 +289,7 @@ mem_shrink :: proc(ainfo: AllocatorInfo, mem: []byte, size: int, alignment: int
|
|||||||
alignment = alignment,
|
alignment = alignment,
|
||||||
old_allocation = mem,
|
old_allocation = mem,
|
||||||
}
|
}
|
||||||
output: AllocatorProc_Out
|
output: AllocatorProc_Out; ainfo.procedure(input, & output)
|
||||||
ainfo.procedure(input, & output)
|
|
||||||
return output.allocation
|
return output.allocation
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -322,8 +301,7 @@ alloc_type :: proc(ainfo: AllocatorInfo, $Type: typeid, alignment: int = MEMORY
|
|||||||
requested_size = size_of(Type),
|
requested_size = size_of(Type),
|
||||||
alignment = alignment,
|
alignment = alignment,
|
||||||
}
|
}
|
||||||
output: AllocatorProc_Out
|
output: AllocatorProc_Out; ainfo.procedure(input, & output)
|
||||||
ainfo.procedure(input, & output)
|
|
||||||
return transmute(^Type) raw_data(output.allocation)
|
return transmute(^Type) raw_data(output.allocation)
|
||||||
}
|
}
|
||||||
alloc_slice :: proc(ainfo: AllocatorInfo, $SliceType: typeid / []$Type, num : int, alignment: int = MEMORY_ALIGNMENT_DEFAULT, no_zero: b32 = false) -> []Type {
|
alloc_slice :: proc(ainfo: AllocatorInfo, $SliceType: typeid / []$Type, num : int, alignment: int = MEMORY_ALIGNMENT_DEFAULT, no_zero: b32 = false) -> []Type {
|
||||||
@@ -334,17 +312,13 @@ alloc_slice :: proc(ainfo: AllocatorInfo, $SliceType: typeid / []$Type, num : in
|
|||||||
requested_size = size_of(Type) * num,
|
requested_size = size_of(Type) * num,
|
||||||
alignment = alignment,
|
alignment = alignment,
|
||||||
}
|
}
|
||||||
output: AllocatorProc_Out
|
output: AllocatorProc_Out; ainfo.procedure(input, & output)
|
||||||
ainfo.procedure(input, & output)
|
|
||||||
return transmute([]Type) slice(raw_data(output.allocation), num)
|
return transmute([]Type) slice(raw_data(output.allocation), num)
|
||||||
}
|
}
|
||||||
//endregion Allocator Interface
|
//endregion Allocator Interface
|
||||||
|
|
||||||
//region Strings
|
//region Strings
|
||||||
Raw_String :: struct {
|
Raw_String :: struct { data: [^]byte, len: int, }
|
||||||
data: [^]byte,
|
|
||||||
len: int,
|
|
||||||
}
|
|
||||||
string_cursor :: proc(s: string) -> [^]u8 { return slice_cursor(transmute([]byte) s) }
|
string_cursor :: proc(s: string) -> [^]u8 { return slice_cursor(transmute([]byte) s) }
|
||||||
string_copy :: proc(dst, src: string) { slice_copy (transmute([]byte) dst, transmute([]byte) src) }
|
string_copy :: proc(dst, src: string) { slice_copy (transmute([]byte) dst, transmute([]byte) src) }
|
||||||
string_end :: proc(s: string) -> ^u8 { return slice_end (transmute([]byte) s) }
|
string_end :: proc(s: string) -> ^u8 { return slice_end (transmute([]byte) s) }
|
||||||
@@ -356,10 +330,7 @@ FArena :: struct {
|
|||||||
mem: []byte,
|
mem: []byte,
|
||||||
used: int,
|
used: int,
|
||||||
}
|
}
|
||||||
farena_make :: proc(backing: []byte) -> FArena {
|
farena_make :: proc(backing: []byte) -> FArena { return {mem = backing} }
|
||||||
arena := FArena {mem = backing}
|
|
||||||
return arena
|
|
||||||
}
|
|
||||||
farena_init :: proc(arena: ^FArena, backing: []byte) {
|
farena_init :: proc(arena: ^FArena, backing: []byte) {
|
||||||
assert(arena != nil)
|
assert(arena != nil)
|
||||||
arena.mem = backing
|
arena.mem = backing
|
||||||
@@ -367,20 +338,15 @@ farena_init :: proc(arena: ^FArena, backing: []byte) {
|
|||||||
}
|
}
|
||||||
farena_push :: proc(arena: ^FArena, $Type: typeid, amount: int, alignment: int = MEMORY_ALIGNMENT_DEFAULT) -> []Type {
|
farena_push :: proc(arena: ^FArena, $Type: typeid, amount: int, alignment: int = MEMORY_ALIGNMENT_DEFAULT) -> []Type {
|
||||||
assert(arena != nil)
|
assert(arena != nil)
|
||||||
if amount == 0 {
|
if amount == 0 { return {} }
|
||||||
return {}
|
|
||||||
}
|
|
||||||
desired := size_of(Type) * amount
|
desired := size_of(Type) * amount
|
||||||
to_commit := align_pow2(desired, alignment)
|
to_commit := align_pow2(desired, alignment)
|
||||||
unused := len(arena.mem) - arena.used
|
unused := len(arena.mem) - arena.used; assert(to_commit <= unused)
|
||||||
assert(to_commit <= unused)
|
|
||||||
ptr := cursor(arena.mem[arena.used:])
|
ptr := cursor(arena.mem[arena.used:])
|
||||||
arena.used += to_commit
|
arena.used += to_commit
|
||||||
return slice(ptr, amount)
|
return slice(ptr, amount)
|
||||||
}
|
}
|
||||||
farena_reset :: proc(arena: ^FArena) {
|
farena_reset :: #force_inline proc(arena: ^FArena) { arena.used = 0 }
|
||||||
arena.used = 0
|
|
||||||
}
|
|
||||||
farena_rewind :: proc(arena: ^FArena, save_point: AllocatorSP) {
|
farena_rewind :: proc(arena: ^FArena, save_point: AllocatorSP) {
|
||||||
assert(save_point.type_sig == farena_allocator_proc)
|
assert(save_point.type_sig == farena_allocator_proc)
|
||||||
assert(save_point.slot >= 0 && save_point.slot <= arena.used)
|
assert(save_point.slot >= 0 && save_point.slot <= arena.used)
|
||||||
@@ -391,7 +357,6 @@ farena_allocator_proc :: proc(input: AllocatorProc_In, output: ^AllocatorProc_Ou
|
|||||||
assert(output != nil)
|
assert(output != nil)
|
||||||
assert(input.data != nil)
|
assert(input.data != nil)
|
||||||
arena := transmute(^FArena) input.data
|
arena := transmute(^FArena) input.data
|
||||||
|
|
||||||
switch input.op
|
switch input.op
|
||||||
{
|
{
|
||||||
case .Alloc, .Alloc_NoZero:
|
case .Alloc, .Alloc_NoZero:
|
||||||
@@ -399,12 +364,9 @@ farena_allocator_proc :: proc(input: AllocatorProc_In, output: ^AllocatorProc_Ou
|
|||||||
if input.op == .Alloc {
|
if input.op == .Alloc {
|
||||||
zero(output.allocation)
|
zero(output.allocation)
|
||||||
}
|
}
|
||||||
|
|
||||||
case .Free:
|
case .Free: // No-op for arena
|
||||||
// No-op for arena
|
case .Reset: farena_reset(arena)
|
||||||
|
|
||||||
case .Reset:
|
|
||||||
farena_reset(arena)
|
|
||||||
|
|
||||||
case .Grow, .Grow_NoZero:
|
case .Grow, .Grow_NoZero:
|
||||||
// Check if the allocation is at the end of the arena
|
// Check if the allocation is at the end of the arena
|
||||||
@@ -453,11 +415,8 @@ farena_allocator_proc :: proc(input: AllocatorProc_In, output: ^AllocatorProc_Ou
|
|||||||
arena.used -= (aligned_original - aligned_new)
|
arena.used -= (aligned_original - aligned_new)
|
||||||
output.allocation = input.old_allocation[:input.requested_size]
|
output.allocation = input.old_allocation[:input.requested_size]
|
||||||
|
|
||||||
case .Rewind:
|
case .Rewind: farena_rewind(arena, input.save_point)
|
||||||
farena_rewind(arena, input.save_point)
|
case .SavePoint: output.save_point = farena_save(arena^)
|
||||||
|
|
||||||
case .SavePoint:
|
|
||||||
output.save_point = farena_save(arena^)
|
|
||||||
|
|
||||||
case .Query:
|
case .Query:
|
||||||
output.features = {.Alloc, .Reset, .Grow, .Shrink, .Rewind}
|
output.features = {.Alloc, .Reset, .Grow, .Shrink, .Rewind}
|
||||||
@@ -471,14 +430,9 @@ farena_ainfo :: #force_inline proc "contextless" (arena : ^FArena) -> AllocatorI
|
|||||||
//endregion FArena
|
//endregion FArena
|
||||||
|
|
||||||
//region OS
|
//region OS
|
||||||
OS_SystemInfo :: struct {
|
OS_SystemInfo :: struct { target_page_size: int }
|
||||||
target_page_size: int,
|
OS_Windows_State :: struct { system_info: OS_SystemInfo }
|
||||||
}
|
@(private) os_windows_info: OS_Windows_State
|
||||||
OS_Windows_State :: struct {
|
|
||||||
system_info: OS_SystemInfo,
|
|
||||||
}
|
|
||||||
@(private)
|
|
||||||
os_windows_info: OS_Windows_State
|
|
||||||
|
|
||||||
// Windows API constants
|
// Windows API constants
|
||||||
MS_INVALID_HANDLE_VALUE :: ~uintptr(0)
|
MS_INVALID_HANDLE_VALUE :: ~uintptr(0)
|
||||||
@@ -537,12 +491,7 @@ os_enable_large_pages :: proc() {
|
|||||||
{
|
{
|
||||||
priv := MS_TOKEN_PRIVILEGES {
|
priv := MS_TOKEN_PRIVILEGES {
|
||||||
privilege_count = 1,
|
privilege_count = 1,
|
||||||
privileges = {
|
privileges = { { luid = luid, attributes = MS_SE_PRIVILEGE_ENABLED, }, },
|
||||||
{
|
|
||||||
luid = luid,
|
|
||||||
attributes = MS_SE_PRIVILEGE_ENABLED,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
AdjustTokenPrivileges(token, 0, &priv, size_of(MS_TOKEN_PRIVILEGES), nil, nil)
|
AdjustTokenPrivileges(token, 0, &priv, size_of(MS_TOKEN_PRIVILEGES), nil, nil)
|
||||||
}
|
}
|
||||||
@@ -554,25 +503,19 @@ os_init :: proc() {
|
|||||||
info := &os_windows_info.system_info
|
info := &os_windows_info.system_info
|
||||||
info.target_page_size = int(GetLargePageMinimum())
|
info.target_page_size = int(GetLargePageMinimum())
|
||||||
}
|
}
|
||||||
os_system_info :: proc() -> ^OS_SystemInfo {
|
os_system_info :: #force_inline proc "contextless" () -> ^OS_SystemInfo { return & os_windows_info.system_info }
|
||||||
return &os_windows_info.system_info
|
os_vmem_commit :: #force_inline proc "contextless" (vm: rawptr, size: int, no_large_pages: b32 = false) -> b32 {
|
||||||
}
|
|
||||||
os_vmem_commit :: proc(vm: rawptr, size: int, no_large_pages: b32 = false) -> b32 {
|
|
||||||
// Large pages disabled for now (not failing gracefully in original C)
|
// Large pages disabled for now (not failing gracefully in original C)
|
||||||
result := VirtualAlloc(vm, uintptr(size), MS_MEM_COMMIT, MS_PAGE_READWRITE) != nil
|
return cast(b32) VirtualAlloc(vm, uintptr(size), MS_MEM_COMMIT, MS_PAGE_READWRITE) != nil
|
||||||
return b32(result)
|
|
||||||
}
|
}
|
||||||
os_vmem_reserve :: proc(size: int, base_addr: int = 0, no_large_pages: b32 = false) -> rawptr {
|
os_vmem_reserve :: #force_inline proc "contextless" (size: int, base_addr: int = 0, no_large_pages: b32 = false) -> rawptr {
|
||||||
result := VirtualAlloc(rawptr(uintptr(base_addr)), uintptr(size),
|
return VirtualAlloc(rawptr(uintptr(base_addr)), uintptr(size),
|
||||||
MS_MEM_RESERVE,
|
MS_MEM_RESERVE,
|
||||||
// MS_MEM_COMMIT
|
// MS_MEM_COMMIT
|
||||||
// | (no_large_pages ? 0 : MS_MEM_LARGE_PAGES), // Large pages disabled
|
// | (no_large_pages ? 0 : MS_MEM_LARGE_PAGES), // Large pages disabled
|
||||||
MS_PAGE_READWRITE)
|
MS_PAGE_READWRITE)
|
||||||
return result
|
|
||||||
}
|
|
||||||
os_vmem_release :: proc(vm: rawptr, size: int) {
|
|
||||||
VirtualFree(vm, 0, MS_MEM_RELEASE)
|
|
||||||
}
|
}
|
||||||
|
os_vmem_release :: #force_inline proc "contextless" (vm: rawptr, size: int) { VirtualFree(vm, 0, MS_MEM_RELEASE) }
|
||||||
//endregion OS
|
//endregion OS
|
||||||
|
|
||||||
//region VArena
|
//region VArena
|
||||||
@@ -646,17 +589,6 @@ varena_push :: proc(va: ^VArena, $Type: typeid, amount: int, alignment: int = ME
|
|||||||
va.commit_used = to_be_used
|
va.commit_used = to_be_used
|
||||||
return slice(transmute([^]Type) uintptr(current_offset), amount)
|
return slice(transmute([^]Type) uintptr(current_offset), amount)
|
||||||
}
|
}
|
||||||
varena_release :: proc(va: ^VArena) {
|
|
||||||
os_vmem_release(va, va.reserve)
|
|
||||||
}
|
|
||||||
varena_rewind :: proc(va: ^VArena, save_point: AllocatorSP) {
|
|
||||||
assert(va != nil)
|
|
||||||
assert(save_point.type_sig == varena_allocator_proc)
|
|
||||||
va.commit_used = max(save_point.slot, size_of(VArena))
|
|
||||||
}
|
|
||||||
varena_reset :: proc(va: ^VArena) {
|
|
||||||
va.commit_used = size_of(VArena)
|
|
||||||
}
|
|
||||||
varena_shrink :: proc(va: ^VArena, old_allocation: []byte, requested_size: int, alignment: int = MEMORY_ALIGNMENT_DEFAULT) -> []byte {
|
varena_shrink :: proc(va: ^VArena, old_allocation: []byte, requested_size: int, alignment: int = MEMORY_ALIGNMENT_DEFAULT) -> []byte {
|
||||||
assert(va != nil)
|
assert(va != nil)
|
||||||
current_offset := va.reserve_start + va.commit_used
|
current_offset := va.reserve_start + va.commit_used
|
||||||
@@ -668,6 +600,13 @@ varena_shrink :: proc(va: ^VArena, old_allocation: []byte, requested_size: int,
|
|||||||
va.commit_used -= shrink_amount
|
va.commit_used -= shrink_amount
|
||||||
return old_allocation[:requested_size]
|
return old_allocation[:requested_size]
|
||||||
}
|
}
|
||||||
|
varena_release :: #force_inline proc(va: ^VArena) { os_vmem_release(va, va.reserve) }
|
||||||
|
varena_reset :: #force_inline proc(va: ^VArena) { va.commit_used = size_of(VArena) }
|
||||||
|
varena_rewind :: #force_inline proc(va: ^VArena, save_point: AllocatorSP) {
|
||||||
|
assert(va != nil)
|
||||||
|
assert(save_point.type_sig == varena_allocator_proc)
|
||||||
|
va.commit_used = max(save_point.slot, size_of(VArena))
|
||||||
|
}
|
||||||
varena_save :: #force_inline proc "contextless" (va: ^VArena) -> AllocatorSP { return AllocatorSP { type_sig = varena_allocator_proc, slot = va.commit_used } }
|
varena_save :: #force_inline proc "contextless" (va: ^VArena) -> AllocatorSP { return AllocatorSP { type_sig = varena_allocator_proc, slot = va.commit_used } }
|
||||||
varena_allocator_proc :: proc(input: AllocatorProc_In, output: ^AllocatorProc_Out) {
|
varena_allocator_proc :: proc(input: AllocatorProc_In, output: ^AllocatorProc_Out) {
|
||||||
assert(output != nil)
|
assert(output != nil)
|
||||||
@@ -785,7 +724,7 @@ arena_push :: proc(arena: ^Arena, $Type: typeid, amount: int, alignment: int = M
|
|||||||
active.pos = pos_pst
|
active.pos = pos_pst
|
||||||
return slice(result_ptr, amount)
|
return slice(result_ptr, amount)
|
||||||
}
|
}
|
||||||
arena_release :: proc(arena: ^Arena) {
|
arena_release :: #force_inline proc(arena: ^Arena) {
|
||||||
assert(arena != nil)
|
assert(arena != nil)
|
||||||
curr := arena.current
|
curr := arena.current
|
||||||
for curr != nil {
|
for curr != nil {
|
||||||
@@ -794,9 +733,7 @@ arena_release :: proc(arena: ^Arena) {
|
|||||||
curr = prev
|
curr = prev
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
arena_reset :: proc(arena: ^Arena) {
|
arena_reset :: #force_inline proc(arena: ^Arena) { arena_rewind(arena, AllocatorSP { type_sig = arena_allocator_proc, slot = 0 }) }
|
||||||
arena_rewind(arena, AllocatorSP { type_sig = arena_allocator_proc, slot = 0 })
|
|
||||||
}
|
|
||||||
arena_rewind :: proc(arena: ^Arena, save_point: AllocatorSP) {
|
arena_rewind :: proc(arena: ^Arena, save_point: AllocatorSP) {
|
||||||
assert(arena != nil)
|
assert(arena != nil)
|
||||||
assert(save_point.type_sig == arena_allocator_proc)
|
assert(save_point.type_sig == arena_allocator_proc)
|
||||||
@@ -1025,11 +962,7 @@ kt1cx_clear :: proc(kt: KT1CX_Byte, m: KT1CX_ByteMeta) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
kt1cx_slot_id :: proc(kt: KT1CX_Byte, key: u64, m: KT1CX_ByteMeta) -> u64 {
|
kt1cx_slot_id :: #force_inline proc(kt: KT1CX_Byte, key: u64, m: KT1CX_ByteMeta) -> u64 { return key % u64(len(kt.table)) }
|
||||||
cell_size := m.cell_size // dummy value
|
|
||||||
hash_index := key % u64(len(kt.table))
|
|
||||||
return hash_index
|
|
||||||
}
|
|
||||||
kt1cx_get :: proc(kt: KT1CX_Byte, key: u64, m: KT1CX_ByteMeta) -> ^byte {
|
kt1cx_get :: proc(kt: KT1CX_Byte, key: u64, m: KT1CX_ByteMeta) -> ^byte {
|
||||||
hash_index := kt1cx_slot_id(kt, key, m)
|
hash_index := kt1cx_slot_id(kt, key, m)
|
||||||
cell_offset := uintptr(hash_index) * uintptr(m.cell_size)
|
cell_offset := uintptr(hash_index) * uintptr(m.cell_size)
|
||||||
@@ -1100,28 +1033,22 @@ kt1cx_set :: proc(kt: KT1CX_Byte, key: u64, value: []byte, backing_cells: Alloca
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
kt1cx_assert :: proc(kt: $type / KT1CX) {
|
kt1cx_assert :: #force_inline proc(kt: $type / KT1CX) { slice_assert(kt.table) }
|
||||||
slice_assert(kt.table)
|
kt1cx_byte :: #force_inline proc(kt: $type / KT1CX) -> KT1CX_Byte { return { slice( transmute([^]byte) cursor(kt.table), len(kt.table)) } }
|
||||||
}
|
|
||||||
kt1cx_byte :: proc(kt: $type / KT1CX) -> KT1CX_Byte { return {
|
|
||||||
slice( transmute([^]byte) cursor(kt.table), len(kt.table))
|
|
||||||
} }
|
|
||||||
//endregion Key Table 1-Layer Chained-Chunked-Cells (KT1CX)
|
//endregion Key Table 1-Layer Chained-Chunked-Cells (KT1CX)
|
||||||
|
|
||||||
//region String Operations
|
//region String Operations
|
||||||
char_is_upper :: proc(c: u8) -> b32 { return('A' <= c && c <= 'Z') }
|
char_is_upper :: #force_inline proc(c: u8) -> b32 { return('A' <= c && c <= 'Z') }
|
||||||
char_to_lower :: proc(c: u8) -> u8 { c:=c; if (char_is_upper(c)) { c += ('a' - 'A') }; return (c) }
|
char_to_lower :: #force_inline proc(c: u8) -> u8 { c:=c; if (char_is_upper(c)) { c += ('a' - 'A') }; return (c) }
|
||||||
|
|
||||||
integer_symbols :: proc(value: u8) -> u8 {
|
integer_symbols :: #force_inline proc(value: u8) -> u8 {
|
||||||
@static lookup_table: [16]u8 = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F', };
|
@static lookup_table: [16]u8 = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F', };
|
||||||
return lookup_table[value];
|
return lookup_table[value];
|
||||||
}
|
}
|
||||||
|
|
||||||
str8_to_cstr_capped :: proc(content: string, mem: []byte) -> cstring {
|
str8_to_cstr_capped :: #force_inline proc(content: string, mem: []byte) -> cstring {
|
||||||
copy_len := min(len(content), len(mem) - 1)
|
copy_len := min(len(content), len(mem) - 1)
|
||||||
if copy_len > 0 {
|
if copy_len > 0 { copy(mem[:copy_len], transmute([]byte) content) }
|
||||||
copy(mem[:copy_len], transmute([]byte) content)
|
|
||||||
}
|
|
||||||
mem[copy_len] = 0
|
mem[copy_len] = 0
|
||||||
return transmute(cstring) raw_data(mem)
|
return transmute(cstring) raw_data(mem)
|
||||||
}
|
}
|
||||||
@@ -1184,7 +1111,6 @@ str8_from_u32 :: proc(ainfo: AllocatorInfo, num: u32, radix: u32 = 10, min_digit
|
|||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
str8_fmt_kt1l :: proc(ainfo: AllocatorInfo, _buffer: ^[]byte, table: []KTL_Slot(string), fmt_template: string) -> string {
|
str8_fmt_kt1l :: proc(ainfo: AllocatorInfo, _buffer: ^[]byte, table: []KTL_Slot(string), fmt_template: string) -> string {
|
||||||
buffer := _buffer^
|
buffer := _buffer^
|
||||||
slice_assert(buffer)
|
slice_assert(buffer)
|
||||||
@@ -1264,15 +1190,14 @@ str8_fmt_kt1l :: proc(ainfo: AllocatorInfo, _buffer: ^[]byte, table: []KTL_Slot(
|
|||||||
result := transmute(string) slice(cursor(buffer), len(buffer) - buffer_remaining)
|
result := transmute(string) slice(cursor(buffer), len(buffer) - buffer_remaining)
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
str8_fmt_backed :: #force_inline proc(tbl_ainfo, buf_ainfo: AllocatorInfo, fmt_template: string, entries: [][2]string) -> string {
|
||||||
str8_fmt_backed :: proc(tbl_ainfo, buf_ainfo: AllocatorInfo, fmt_template: string, entries: [][2]string) -> string {
|
|
||||||
kt: []KTL_Slot(string); ktl_populate_slice_a2_str(& kt, tbl_ainfo, entries)
|
kt: []KTL_Slot(string); ktl_populate_slice_a2_str(& kt, tbl_ainfo, entries)
|
||||||
buf_size := Kilo * 64
|
buf_size := Kilo * 64
|
||||||
buffer := mem_alloc(buf_ainfo, buf_size)
|
buffer := mem_alloc(buf_ainfo, buf_size)
|
||||||
result := str8_fmt_kt1l(buf_ainfo, & buffer, kt, fmt_template)
|
result := str8_fmt_kt1l(buf_ainfo, & buffer, kt, fmt_template)
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
str8_fmt_tmp :: proc(fmt_template: string, entries: [][2]string) -> string {
|
str8_fmt_tmp :: #force_inline proc(fmt_template: string, entries: [][2]string) -> string {
|
||||||
@static tbl_mem: [Kilo * 32]byte; tbl_arena := farena_make(tbl_mem[:])
|
@static tbl_mem: [Kilo * 32]byte; tbl_arena := farena_make(tbl_mem[:])
|
||||||
@static buf_mem: [Kilo * 64]byte; buffer := buf_mem[:]
|
@static buf_mem: [Kilo * 64]byte; buffer := buf_mem[:]
|
||||||
kt: []KTL_Slot(string); ktl_populate_slice_a2_str(& kt, ainfo(& tbl_arena), entries)
|
kt: []KTL_Slot(string); ktl_populate_slice_a2_str(& kt, ainfo(& tbl_arena), entries)
|
||||||
@@ -1317,7 +1242,7 @@ str8cache_init :: proc(cache: ^Str8Cache, str_reserve, cell_reserve, tbl_backing
|
|||||||
kt1cx_init(info, m, transmute(^KT1CX_Byte) & cache.kt)
|
kt1cx_init(info, m, transmute(^KT1CX_Byte) & cache.kt)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
str8cache_make :: proc(str_reserve, cell_reserve, tbl_backing: AllocatorInfo, cell_pool_size, table_size: int) -> Str8Cache {
|
str8cache_make :: #force_inline proc(str_reserve, cell_reserve, tbl_backing: AllocatorInfo, cell_pool_size, table_size: int) -> Str8Cache {
|
||||||
cache : Str8Cache; str8cache_init(& cache, str_reserve, cell_reserve, tbl_backing, cell_pool_size, table_size); return cache
|
cache : Str8Cache; str8cache_init(& cache, str_reserve, cell_reserve, tbl_backing, cell_pool_size, table_size); return cache
|
||||||
}
|
}
|
||||||
str8cache_clear :: proc(kt: KT1CX_Str8) {
|
str8cache_clear :: proc(kt: KT1CX_Str8) {
|
||||||
@@ -1368,11 +1293,10 @@ str8cache_set :: proc(kt: KT1CX_Str8, key: u64, value: string, str_reserve, cell
|
|||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
cache_str8 :: proc(cache: ^Str8Cache, str: string) -> string {
|
cache_str8 :: #force_inline proc(cache: ^Str8Cache, str: string) -> string {
|
||||||
assert(cache != nil)
|
assert(cache != nil)
|
||||||
key: u64 = 0; hash64_fnv1a(& key, transmute([]byte) str)
|
key: u64 = 0; hash64_fnv1a(& key, transmute([]byte) str)
|
||||||
result := str8cache_set(cache.kt, key, str, cache.str_reserve, cache.cell_reserve)
|
return str8cache_set(cache.kt, key, str, cache.str_reserve, cache.cell_reserve) ^
|
||||||
return result ^
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Str8Gen :: struct {
|
Str8Gen :: struct {
|
||||||
@@ -1389,9 +1313,9 @@ str8gen_init :: proc(gen: ^Str8Gen, ainfo: AllocatorInfo) {
|
|||||||
gen.len = 0
|
gen.len = 0
|
||||||
gen.cap = Kilo * 4
|
gen.cap = Kilo * 4
|
||||||
}
|
}
|
||||||
str8gen_make :: proc(ainfo: AllocatorInfo) -> Str8Gen { gen: Str8Gen; str8gen_init(& gen, ainfo); return gen }
|
str8gen_make :: #force_inline proc(ainfo: AllocatorInfo) -> Str8Gen { gen: Str8Gen; str8gen_init(& gen, ainfo); return gen }
|
||||||
str8gen_to_bytes :: proc(gen: Str8Gen) -> []byte { return transmute([]byte) SliceByte {data = gen.ptr, len = gen.cap} }
|
str8gen_to_bytes :: #force_inline proc(gen: Str8Gen) -> []byte { return transmute([]byte) SliceByte {data = gen.ptr, len = gen.cap} }
|
||||||
str8_from_str8gen :: proc(gen: Str8Gen) -> string { return transmute(string) SliceByte {data = gen.ptr, len = gen.len} }
|
str8_from_str8gen :: #force_inline proc(gen: Str8Gen) -> string { return transmute(string) SliceByte {data = gen.ptr, len = gen.len} }
|
||||||
|
|
||||||
str8gen_append_str8 :: proc(gen: ^Str8Gen, str: string) {
|
str8gen_append_str8 :: proc(gen: ^Str8Gen, str: string) {
|
||||||
result := mem_grow(gen.backing, str8gen_to_bytes(gen ^), len(str) + gen.len)
|
result := mem_grow(gen.backing, str8gen_to_bytes(gen ^), len(str) + gen.len)
|
||||||
@@ -1515,9 +1439,8 @@ api_file_read_contents :: proc(result: ^FileOpInfo, path: string, backing: Alloc
|
|||||||
result.content = slice(cursor(buffer), cast(int) file_size.QuadPart)
|
result.content = slice(cursor(buffer), cast(int) file_size.QuadPart)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
file_read_contents_stack :: proc(path: string, backing: AllocatorInfo, zero_backing: b32 = false) -> FileOpInfo {
|
file_read_contents_stack :: #force_inline proc(path: string, backing: AllocatorInfo, zero_backing: b32 = false) -> FileOpInfo {
|
||||||
result : FileOpInfo; api_file_read_contents(& result, path, backing, zero_backing)
|
result: FileOpInfo; api_file_read_contents(& result, path, backing, zero_backing) return result
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
file_write_str8 :: proc(path, content: string) {
|
file_write_str8 :: proc(path, content: string) {
|
||||||
string_assert(path)
|
string_assert(path)
|
||||||
@@ -1604,55 +1527,54 @@ api_watl_lex :: proc(info: ^WATL_LexInfo, source: string,
|
|||||||
alloc_tok :: #force_inline proc(ainfo: AllocatorInfo) -> ^Raw_String {
|
alloc_tok :: #force_inline proc(ainfo: AllocatorInfo) -> ^Raw_String {
|
||||||
return alloc_type(ainfo, Raw_String, align_of(Raw_String), true)
|
return alloc_type(ainfo, Raw_String, align_of(Raw_String), true)
|
||||||
}
|
}
|
||||||
#partial switch cast(WATL_TokKind) code
|
#partial switch cast(WATL_TokKind) code {
|
||||||
{
|
case .Space: fallthrough
|
||||||
case .Space: fallthrough
|
case .Tab:
|
||||||
case .Tab:
|
if prev[0] != src_cursor[0] {
|
||||||
if prev[0] != src_cursor[0] {
|
new_tok := alloc_tok(ainfo_toks); if cursor(new_tok)[-1:] != tok && tok != nil {
|
||||||
new_tok := alloc_tok(ainfo_toks); if cursor(new_tok)[-1:] != tok && tok != nil {
|
slice_constraint_fail(info, ainfo_msgs, new_tok, & msg_last);
|
||||||
slice_constraint_fail(info, ainfo_msgs, new_tok, & msg_last);
|
|
||||||
return
|
|
||||||
}
|
|
||||||
tok = new_tok
|
|
||||||
tok^ = transmute(Raw_String) slice(src_cursor, 0)
|
|
||||||
was_formatting = true
|
|
||||||
num += 1
|
|
||||||
}
|
|
||||||
src_cursor = src_cursor[1:]
|
|
||||||
tok.len += 1
|
|
||||||
case .Line_Feed:
|
|
||||||
new_tok := alloc_tok(ainfo_toks); if cursor(new_tok)[-1:] != tok && tok != nil{
|
|
||||||
slice_constraint_fail(info, ainfo_msgs, new_tok, & msg_last);
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
tok = new_tok
|
tok = new_tok
|
||||||
tok^ = transmute(Raw_String) slice(src_cursor, 1)
|
tok^ = transmute(Raw_String) slice(src_cursor, 0)
|
||||||
src_cursor = src_cursor[1:]
|
|
||||||
was_formatting = true
|
was_formatting = true
|
||||||
num += 1
|
num += 1
|
||||||
case .Carriage_Return:
|
}
|
||||||
|
src_cursor = src_cursor[1:]
|
||||||
|
tok.len += 1
|
||||||
|
case .Line_Feed:
|
||||||
|
new_tok := alloc_tok(ainfo_toks); if cursor(new_tok)[-1:] != tok && tok != nil{
|
||||||
|
slice_constraint_fail(info, ainfo_msgs, new_tok, & msg_last);
|
||||||
|
return
|
||||||
|
}
|
||||||
|
tok = new_tok
|
||||||
|
tok^ = transmute(Raw_String) slice(src_cursor, 1)
|
||||||
|
src_cursor = src_cursor[1:]
|
||||||
|
was_formatting = true
|
||||||
|
num += 1
|
||||||
|
case .Carriage_Return:
|
||||||
|
new_tok := alloc_tok(ainfo_toks); if cursor(new_tok)[-1:] != tok && tok != nil {
|
||||||
|
slice_constraint_fail(info, ainfo_msgs, new_tok, & msg_last);
|
||||||
|
return
|
||||||
|
}
|
||||||
|
tok = new_tok
|
||||||
|
tok^ = transmute(Raw_String) slice(src_cursor, 2)
|
||||||
|
src_cursor = src_cursor[1:]
|
||||||
|
was_formatting = true
|
||||||
|
num += 1
|
||||||
|
case:
|
||||||
|
if (was_formatting) {
|
||||||
new_tok := alloc_tok(ainfo_toks); if cursor(new_tok)[-1:] != tok && tok != nil {
|
new_tok := alloc_tok(ainfo_toks); if cursor(new_tok)[-1:] != tok && tok != nil {
|
||||||
slice_constraint_fail(info, ainfo_msgs, new_tok, & msg_last);
|
slice_constraint_fail(info, ainfo_msgs, new_tok, & msg_last);
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
tok = new_tok
|
tok = new_tok
|
||||||
tok^ = transmute(Raw_String) slice(src_cursor, 2)
|
tok^ = transmute(Raw_String) slice(src_cursor, 0)
|
||||||
src_cursor = src_cursor[1:]
|
was_formatting = false;
|
||||||
was_formatting = true
|
|
||||||
num += 1
|
num += 1
|
||||||
case:
|
}
|
||||||
if (was_formatting) {
|
src_cursor = src_cursor[1:]
|
||||||
new_tok := alloc_tok(ainfo_toks); if cursor(new_tok)[-1:] != tok && tok != nil {
|
tok.len += 1
|
||||||
slice_constraint_fail(info, ainfo_msgs, new_tok, & msg_last);
|
|
||||||
return
|
|
||||||
}
|
|
||||||
tok = new_tok
|
|
||||||
tok^ = transmute(Raw_String) slice(src_cursor, 0)
|
|
||||||
was_formatting = false;
|
|
||||||
num += 1
|
|
||||||
}
|
|
||||||
src_cursor = src_cursor[1:]
|
|
||||||
tok.len += 1
|
|
||||||
}
|
}
|
||||||
prev = src_cursor[-1:]
|
prev = src_cursor[-1:]
|
||||||
code = src_cursor[0]
|
code = src_cursor[0]
|
||||||
@@ -1729,28 +1651,25 @@ api_watl_parse :: proc(info: ^WATL_ParseInfo, tokens: []WATL_Tok,
|
|||||||
info_lines ^ = { transmute([^]WATL_Node) line, 0 }
|
info_lines ^ = { transmute([^]WATL_Node) line, 0 }
|
||||||
for & token in tokens
|
for & token in tokens
|
||||||
{
|
{
|
||||||
#partial switch cast(WATL_TokKind) token[0]
|
#partial switch cast(WATL_TokKind) token[0] {
|
||||||
{
|
case .Carriage_Return: fallthrough
|
||||||
case .Carriage_Return: fallthrough
|
case .Line_Feed:
|
||||||
case .Line_Feed:
|
new_line := alloc_type(ainfo_lines, WATL_Line); if cursor(new_line)[-1:] != transmute(^[]string)line {
|
||||||
new_line := alloc_type(ainfo_lines, WATL_Line); if cursor(new_line)[-1:] != transmute(^[]string)line {
|
info.signal |= { .MemFail_SliceConstraintFail }
|
||||||
info.signal |= { .MemFail_SliceConstraintFail }
|
msg := alloc_type(ainfo_msgs, WATL_ParseMsg)
|
||||||
msg := alloc_type(ainfo_msgs, WATL_ParseMsg)
|
msg.content = "Line slice allocation was not contiguous"
|
||||||
msg.content = "Line slice allocation was not contiguous"
|
msg.pos = { cast(i32) len(info.lines), cast(i32) line.len }
|
||||||
msg.pos = { cast(i32) len(info.lines), cast(i32) line.len }
|
msg.line = transmute(^[]WATL_Node) line
|
||||||
msg.line = transmute(^[]WATL_Node) line
|
msg.tok = & token
|
||||||
msg.tok = & token
|
sll_queue_push_n(& info.msgs, & msg_last, & msg)
|
||||||
sll_queue_push_n(& info.msgs, & msg_last, & msg)
|
assert(failon_slice_constraint_fail == false)
|
||||||
assert(failon_slice_constraint_fail == false)
|
return
|
||||||
return
|
}
|
||||||
}
|
line = transmute(^SliceRaw(WATL_Node)) new_line
|
||||||
line = transmute(^SliceRaw(WATL_Node)) new_line
|
line.data = curr
|
||||||
line.data = curr
|
info_lines.len += 1
|
||||||
info_lines.len += 1
|
continue
|
||||||
continue
|
case: break;
|
||||||
|
|
||||||
case:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
curr ^ = cache_str8(str_cache, token)
|
curr ^ = cache_str8(str_cache, token)
|
||||||
new_node := alloc_type(ainfo_nodes, WATL_Node); if cursor(new_node)[-1:] != curr {
|
new_node := alloc_type(ainfo_nodes, WATL_Node); if cursor(new_node)[-1:] != curr {
|
||||||
@@ -1799,11 +1718,10 @@ watl_dump_listing :: proc(buffer: AllocatorInfo, lines: []WATL_Line) -> string {
|
|||||||
for chunk in line
|
for chunk in line
|
||||||
{
|
{
|
||||||
id : string
|
id : string
|
||||||
#partial switch cast(WATL_TokKind) chunk[0]
|
#partial switch cast(WATL_TokKind) chunk[0] {
|
||||||
{
|
case .Space: id = "Space"
|
||||||
case .Space: id = "Space"
|
case .Tab: id = "Tab"
|
||||||
case .Tab: id = "Tab"
|
case: id = "Visible"
|
||||||
case: id = "Visible"
|
|
||||||
}
|
}
|
||||||
str8gen_append_fmt(& result, "\t<id>(<size>): '<chunk>'\n", {
|
str8gen_append_fmt(& result, "\t<id>(<size>): '<chunk>'\n", {
|
||||||
{ "id", id },
|
{ "id", id },
|
||||||
|
|||||||
@@ -118,8 +118,8 @@ $compiler_args += $flag_full_src_path
|
|||||||
# $compiler_args += $flag_optimize_speed_max
|
# $compiler_args += $flag_optimize_speed_max
|
||||||
# $compiler_args += $flag_optimize_fast
|
# $compiler_args += $flag_optimize_fast
|
||||||
# $compiler_args += $flag_optimize_size
|
# $compiler_args += $flag_optimize_size
|
||||||
# $compiler_args += $flag_optimize_intrinsics
|
$compiler_args += $flag_optimize_intrinsics
|
||||||
$compiler_args += $flag_no_optimization
|
# $compiler_args += $flag_no_optimization
|
||||||
|
|
||||||
# Debug setup
|
# Debug setup
|
||||||
$compiler_args += ($flag_define + 'BUILD_DEBUG')
|
$compiler_args += ($flag_define + 'BUILD_DEBUG')
|
||||||
|
|||||||
@@ -118,8 +118,8 @@ $compiler_args += $flag_full_src_path
|
|||||||
# $compiler_args += $flag_optimize_speed_max
|
# $compiler_args += $flag_optimize_speed_max
|
||||||
# $compiler_args += $flag_optimize_fast
|
# $compiler_args += $flag_optimize_fast
|
||||||
# $compiler_args += $flag_optimize_size
|
# $compiler_args += $flag_optimize_size
|
||||||
# $compiler_args += $flag_optimize_intrinsics
|
$compiler_args += $flag_optimize_intrinsics
|
||||||
$compiler_args += $flag_no_optimization
|
# $compiler_args += $flag_no_optimization
|
||||||
|
|
||||||
# Debug setup
|
# Debug setup
|
||||||
$compiler_args += ($flag_define + 'BUILD_DEBUG')
|
$compiler_args += ($flag_define + 'BUILD_DEBUG')
|
||||||
|
|||||||
@@ -117,8 +117,8 @@ $compiler_args += $flag_full_src_path
|
|||||||
# $compiler_args += $flag_optimize_speed_max
|
# $compiler_args += $flag_optimize_speed_max
|
||||||
# $compiler_args += $flag_optimize_fast
|
# $compiler_args += $flag_optimize_fast
|
||||||
# $compiler_args += $flag_optimize_size
|
# $compiler_args += $flag_optimize_size
|
||||||
# $compiler_args += $flag_optimize_intrinsics
|
$compiler_args += $flag_optimize_intrinsics
|
||||||
$compiler_args += $flag_no_optimization
|
# $compiler_args += $flag_no_optimization
|
||||||
|
|
||||||
# Debug setup
|
# Debug setup
|
||||||
$compiler_args += ($flag_define + 'BUILD_DEBUG')
|
$compiler_args += ($flag_define + 'BUILD_DEBUG')
|
||||||
@@ -139,7 +139,10 @@ $compiler_args += $flag_compile, $unit
|
|||||||
$compiler_args | ForEach-Object { Write-Host $_ }
|
$compiler_args | ForEach-Object { Write-Host $_ }
|
||||||
|
|
||||||
# Compile the unit
|
# Compile the unit
|
||||||
& $compiler $compiler_args
|
$compilation_time = Measure-Command {
|
||||||
|
& $compiler $compiler_args
|
||||||
|
}
|
||||||
|
write-host "Compilation took $($compilation_time.TotalMilliseconds)ms"
|
||||||
write-host
|
write-host
|
||||||
|
|
||||||
$binary = join-path $path_build "$unit_name.exe"
|
$binary = join-path $path_build "$unit_name.exe"
|
||||||
@@ -168,8 +171,9 @@ if ($true) {
|
|||||||
# Diagnoistc print for the args
|
# Diagnoistc print for the args
|
||||||
$linker_args | ForEach-Object { Write-Host $_ }
|
$linker_args | ForEach-Object { Write-Host $_ }
|
||||||
|
|
||||||
& $linker $linker_args
|
$linking_time = Measure-Command { & $linker $linker_args }
|
||||||
# & $radlink $linker_args
|
# & $radlink $linker_args
|
||||||
|
write-host "Linking took $($linking_time.TotalMilliseconds)ms"
|
||||||
write-host
|
write-host
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user