From b22e1ac0dbbd465c02ca9978b0c5f6f45f523e3e Mon Sep 17 00:00:00 2001 From: Krzosa Karol Date: Sun, 9 Oct 2022 10:34:23 +0200 Subject: [PATCH] Removing heap allocations, Porting to Unix --- README.md | 4 +- base.cpp | 286 +++++++++++++++--------------------- base_string.cpp | 8 +- c3_big_int.cpp | 1 + core_ast.cpp | 8 +- core_codegen_c_language.cpp | 12 +- core_compiler.cpp | 10 +- core_globals.cpp | 4 +- core_main.cpp | 64 +++----- core_parsing.cpp | 9 +- core_typechecking.cpp | 20 +-- core_types.cpp | 21 +-- os_windows.cpp | 82 +++++++++-- 13 files changed, 260 insertions(+), 269 deletions(-) diff --git a/README.md b/README.md index f75bc11..7f8023b 100644 --- a/README.md +++ b/README.md @@ -6,9 +6,7 @@ The language is currently **very debuggable**. It can produce readable C code wi ## Using Windows API example -* More examples can be found in /examples and /modules, especially checkout: - * examples/raymarcher.core - * examples/drawing_to_screen_using_windows_api.core +More examples can be found in /examples and /modules: ``` odin #import "KERNEL32.core" diff --git a/base.cpp b/base.cpp index 879a65c..9086e5d 100644 --- a/base.cpp +++ b/base.cpp @@ -1,7 +1,79 @@ -#define NOMINMAX -#define _CRT_SECURE_NO_WARNINGS -#include +#if defined(__clang__) +# define COMPILER_CLANG 1 +# if defined(_WIN32) +# define OS_WINDOWS 1 +# elif defined(__linux__) +# define OS_LINUX 1 +# else +# error Couldnt figure out the platform automatically +# endif +#elif defined(_MSC_VER) +# define COMPILER_MSVC 1 +# define OS_WINDOWS 1 +#elif defined(__GNUC__) +# define COMPILER_GCC 1 +# if defined(__linux__) +# define OS_LINUX 1 +# endif +#else +# error Couldnt figure out the compiler +#endif + +#if defined(OS_MAC) +#define OS_UNIX 1 +#endif +#if defined(OS_LINUX) +#define OS_UNIX 1 +#endif + +#if !defined(COMPILER_MSVC) +# define COMPILER_MSVC 0 +#endif +#if !defined(COMPILER_GCC) +# define COMPILER_GCC 0 +#endif +#if !defined(COMPILER_CLANG) +# define COMPILER_CLANG 0 +#endif +#if !defined(OS_WINDOWS) +# define OS_WINDOWS 0 +#endif +#if !defined(OS_LINUX) +# define OS_LINUX 0 +#endif +#if !defined(OS_MAC) +# define OS_MAC 0 +#endif +#if !defined(OS_UNIX) +# define OS_UNIX 0 +#endif + +#if OS_WINDOWS + #define OS_NAME "Win32"_s + #define OS_NAME_LOWER "win32"_s +#elif OS_LINUX + #define OS_NAME "Linux"_s + #define OS_NAME_LOWER "linux"_s +#elif OS_MAC + #define OS_NAME "Mac"_s + #define OS_NAME_LOWER "mac"_s +#else + #error Couldnt figure out the OS with C macros! +#endif + +#if OS_WINDOWS + #define NOMINMAX + #define _CRT_SECURE_NO_WARNINGS + #include + #define Breakpoint __debugbreak() + #define force_inline __forceinline +#else + #define Breakpoint (*(volatile int *)0 = 0) + #define force_inline inline +#endif + +#include #include #include typedef int8_t S8; @@ -16,12 +88,10 @@ typedef S8 B8; typedef S16 B16; typedef S32 B32; typedef S64 B64; -typedef U64 SizeU; -typedef S64 SizeS; + typedef float F32; typedef double F64; - #define U64MAX UINT64_MAX #define U32MAX UINT32_MAX #define U16MAX UINT16_MAX @@ -46,13 +116,12 @@ typedef double F64; #define api #define function static #define global static -#define force_inline __forceinline -#define assert(x) do{if(!(x))__debugbreak();}while(0) -#define assert_msg(x,...) assert(x) -#define invalid_codepath assert_msg(0, "Invalid codepath") -#define invalid_return do{assert_msg(0, "Invalid codepath"); return {};}while(0) +#define assert(x) do{if(!(x))Breakpoint;}while(0) +#define assert_message(x,...) assert(x) +#define invalid_codepath assert_message(0, "Invalid codepath") +#define invalid_return do{assert_message(0, "Invalid codepath"); return {};}while(0) #define invalid_default_case default: invalid_codepath -#define not_implemented assert_msg(0, "Not implemented") +#define not_implemented assert_message(0, "Not implemented") #define unused(x) ((void)x) #define buff_cap(x) (sizeof(x)/sizeof((x)[0])) #define is_flag_set(val,flag) ((val) & (flag)) @@ -66,59 +135,6 @@ typedef double F64; #define JOIN(X,Y) JOIN1(X,Y) #define string_expand(x) (int)x.len, x.str -#if defined(__clang__) -# define COMPILER_CLANG 1 -# if defined(_WIN32) -# define OS_WINDOWS 1 -# elif defined(__linux__) -# define OS_LINUX 1 -# else -# error Couldnt figure out the platform automatically -# endif -#elif defined(_MSC_VER) -# define COMPILER_MSVC 1 -# define OS_WINDOWS 1 -#elif defined(__GNUC__) -# define COMPILER_GCC 1 -# if defined(__linux__) -# define OS_LINUX 1 -# endif -#else -# error Couldnt figure out the compiler -#endif - -#if !defined(COMPILER_MSVC) -# define COMPILER_MSVC 0 -#endif -#if !defined(COMPILER_GCC) -# define COMPILER_GCC 0 -#endif -#if !defined(COMPILER_CLANG) -# define COMPILER_CLANG 0 -#endif -#if !defined(OS_WINDOWS) -# define OS_WINDOWS 0 -#endif -#if !defined(OS_LINUX) -# define OS_LINUX 0 -#endif -#if !defined(OS_MAC) -# define OS_MAC 0 -#endif - -#if OS_WINDOWS -#define OS_NAME "Win32"_s -#define OS_NAME_LOWER "win32"_s -#elif OS_LINUX -#define OS_NAME "Linux"_s -#define OS_NAME_LOWER "linux"_s -#elif OS_MAC -#define OS_NAME "Mac"_s -#define OS_NAME_LOWER "mac"_s -#else -#error Couldnt figure out the OS with C macros! -#endif - struct String{ U8 *str; S64 len; @@ -210,42 +226,42 @@ union Rect2I { //----------------------------------------------------------------------------- // Utilities //----------------------------------------------------------------------------- -function SizeU -get_align_offset(SizeU size, SizeU align){ - SizeU mask = align - 1; - SizeU val = size & mask; +function size_t +get_align_offset(size_t size, size_t align){ + size_t mask = align - 1; + size_t val = size & mask; if(val){ val = align - val; } return val; } -function SizeU -align_up(SizeU size, SizeU align){ - SizeU result = size + get_align_offset(size, align); +function size_t +align_up(size_t size, size_t align){ + size_t result = size + get_align_offset(size, align); return result; } -function SizeU -align_down(SizeU size, SizeU align){ +function size_t +align_down(size_t size, size_t align){ size += 1; // Make sure 8 when align is 8 doesn't get rounded down to 0 - SizeU result = size - (align - get_align_offset(size, align)); + size_t result = size - (align - get_align_offset(size, align)); return result; } function void -memory_copy(void *dst, void *src, SizeU size){ +memory_copy(void *dst, void *src, size_t size){ U8 *d = (U8*)dst; U8 *s = (U8*)src; - for(SizeU i = 0; i < size; i++){ + for(size_t i = 0; i < size; i++){ d[i] = s[i]; } } function void -memory_zero(void *p, SizeU size){ +memory_zero(void *p, size_t size){ U8 *pp = (U8 *)p; - for(SizeU i = 0; i < size; i++) + for(size_t i = 0; i < size; i++) pp[i] = 0; } @@ -480,47 +496,47 @@ enum Alloc_Flag{ }; struct Allocator; -typedef void *Allocator_Proc(Allocator*, Allocation_Kind, void *, SizeU); +typedef void *Allocator_Proc(Allocator*, Allocation_Kind, void *, size_t); struct Allocator{Allocator_Kind kind; Allocator_Proc *proc; String debug_name;}; //----------------------------------------------------------------------------- // Memory OS //----------------------------------------------------------------------------- struct OS_Memory{ - SizeU commit, reserve; + size_t commit, reserve; U8 *data; }; -function OS_Memory os_reserve(SizeU size); -function B32 os_commit(OS_Memory *m, SizeU size); +function OS_Memory os_reserve(size_t size); +function B32 os_commit(OS_Memory *m, size_t size); function void os_release(OS_Memory *m); -function B32 os_decommit_pos(OS_Memory *m, SizeU pos); +function B32 os_decommit_pos(OS_Memory *m, size_t pos); //----------------------------------------------------------------------------- // Memory arenas //----------------------------------------------------------------------------- -global const SizeU default_reserve_size = gib(4); -global const SizeU default_alignment = 8; -global const SizeU additional_commit_size = mib(1); +global const size_t default_reserve_size = gib(4); +global const size_t default_alignment = 8; +global const size_t additional_commit_size = mib(1); struct Arena:Allocator{ OS_Memory memory; - SizeU alignment; - SizeU len; + size_t alignment; + size_t len; // Personal arena memes so we can compute correct size when resizing // Also a pointer so that we can make sure it didn't change - SizeU old_size; + size_t old_size; void *debug_prev_pointer; }; function void arena_init(Arena *arena, String debug_name); function void -arena_pop_pos(Arena *arena, SizeU pos){ +arena_pop_pos(Arena *arena, size_t pos){ pos = clamp_top(pos, arena->len); arena->len = pos; } function void * -arena_pop(Arena *arena, SizeU size){ +arena_pop(Arena *arena, size_t size){ size = clamp_top(size, arena->len); arena->len -= size; return arena->memory.data + arena->len; @@ -537,8 +553,8 @@ arena_clear(Arena *arena){ } function void * -arena_push_size(Arena *a, SizeU size){ - SizeU generous_size = size + a->alignment; +arena_push_size(Arena *a, size_t size){ + size_t generous_size = size + a->alignment; if(a->len+generous_size>a->memory.commit){ if(a->memory.reserve == 0){ arena_init(a, "Zero initialized arena"_s); @@ -555,7 +571,7 @@ arena_push_size(Arena *a, SizeU size){ } force_inline void * -arena_allocator_proc(Allocator *a, Allocation_Kind kind, void *old_pointer, SizeU size){ +arena_allocator_proc(Allocator *a, Allocation_Kind kind, void *old_pointer, size_t size){ Arena *arena = (Arena *)a; switch(kind){ case Allocation_Alloc: return arena_push_size(arena, size); @@ -573,7 +589,7 @@ arena_allocator_proc(Allocator *a, Allocation_Kind kind, void *old_pointer, Size } force_inline void * -personal_arena_allocator_proc(Allocator *a, Allocation_Kind kind, void *old_pointer, SizeU size){ +personal_arena_allocator_proc(Allocator *a, Allocation_Kind kind, void *old_pointer, size_t size){ Arena *arena = (Arena *)a; arena->alignment = 1; @@ -614,59 +630,6 @@ arena_make_personal(String debug_name){ return arena; } -//----------------------------------------------------------------------------- -// OS Heap allocator -//----------------------------------------------------------------------------- -struct OS_Heap:Allocator{ - HANDLE handle; -}; - -function void * -os_heap_allocator_proc(Allocator *a, Allocation_Kind kind, void *old_pointer, SizeU size){ - OS_Heap *heap = (OS_Heap *)a; - switch(kind){ - case Allocation_FreeAll:{ - invalid_codepath; - return 0; - } - case Allocation_Destroy:{ - BOOL result = HeapDestroy(heap->handle); - assert(result != 0); - heap->handle = 0; - heap->proc = 0; - return 0; - } - case Allocation_Free:{ - BOOL result = HeapFree(heap->handle, 0, old_pointer); - assert(result != 0); - return 0; - } - case Allocation_Alloc:{ - void *result = HeapAlloc(heap->handle, 0, size); - assert(result); - return result; - } - case Allocation_Resize:{ - void *result = HeapReAlloc(heap->handle, 0, old_pointer, size); - assert(result); - return result; - } - default: invalid_codepath; - } - return 0; -} - -function OS_Heap // max_size == 0 == growing heap -win32_os_heap_create(B32 multithreaded, SizeU initial_size, SizeU max_size, String debug_name){ - OS_Heap result = {}; - result.debug_name = debug_name; - result.proc = os_heap_allocator_proc; - result.kind = Allocator_OSHeap; - result.handle = HeapCreate(multithreaded ? 0 : HEAP_NO_SERIALIZE, initial_size, max_size); - assert(result.handle); - return result; -} - enum Log_Kind{Log_Kind_Normal, Log_Kind_Error, Log_Kind_Trace}; typedef void Log_Proc(Log_Kind kind, String string, char *file, int line); //----------------------------------------------------------------------------- @@ -684,7 +647,6 @@ struct Thread_Ctx{ thread_local Thread_Ctx thread_ctx; global Arena pernament_arena; -global OS_Heap os_process_heap; #define REPORT_ALLOCATIONS 0 #define report_file_and_line() report__file_and_line(__FILE__, __LINE__) @@ -698,7 +660,7 @@ report__file_and_line(const char *file, int line){ // Implicit scratch stack //----------------------------------------------------------------------------- struct Scratch{ - SizeU saved_pos; + size_t saved_pos; Arena *arena; Scratch(Allocator *conflict = 0){ @@ -749,7 +711,7 @@ struct Scoped_Allocator{ #define exp_destroy(a) (report_file_and_line(), exp__destroy(a)) force_inline void * -exp__alloc(Allocator *a, SizeU size, Alloc_Flag flag = AF_None){ +exp__alloc(Allocator *a, size_t size, Alloc_Flag flag = AF_None){ #if REPORT_ALLOCATIONS printf("Alloc(%s) %s:%d %u\n", a->debug_name.str, thread_ctx.file, thread_ctx.line, (U32)size); #endif @@ -759,7 +721,7 @@ exp__alloc(Allocator *a, SizeU size, Alloc_Flag flag = AF_None){ return result; } force_inline void * -exp__resize(Allocator *a, void *pointer, SizeU size){ +exp__resize(Allocator *a, void *pointer, size_t size){ #if REPORT_ALLOCATIONS printf("Resize(%s) %s:%d %u\n", a->debug_name.str, thread_ctx.file, thread_ctx.line, (U32)size); #endif @@ -801,10 +763,6 @@ thread_ctx_init(){ arena_init(thread_ctx.scratch, "Scratch1"_s); arena_init(thread_ctx.scratch+1, "Scratch2"_s); arena_init(&pernament_arena, "Pernament Arena"_s); - os_process_heap.proc = os_heap_allocator_proc; - os_process_heap.handle = GetProcessHeap(); - os_process_heap.debug_name = "Win32 Process Heap"_s; - os_process_heap.kind = Allocator_OSHeap; } @@ -847,7 +805,7 @@ struct Array{ S64 get_index(T *item){ assert((data <= item) && ((data + len) > item)); - SizeU offset = item - data; + size_t offset = item - data; return (S64)offset; } @@ -1145,12 +1103,12 @@ function void map_test(){ Scratch scratch; Map map = {scratch}; - const SizeU size = 1025; - for(SizeU i = 1; i < size; i++){ + const size_t size = 1025; + for(size_t i = 1; i < size; i++){ map_insert(&map, i, (void *)i); } - for(SizeU i = 1; i < size; i++){ - SizeU val = (SizeU)map_get(&map, i); + for(size_t i = 1; i < size; i++){ + size_t val = (size_t)map_get(&map, i); assert(val == i); } } @@ -1208,7 +1166,7 @@ test_intern_table(){ } function Arena -arena_sub(Allocator *base, SizeU size, String debug_name) { +arena_sub(Allocator *base, size_t size, String debug_name) { Arena result = {}; result.memory.data = (U8 *)exp_alloc(base, size); result.memory.commit = size; @@ -1443,7 +1401,7 @@ T pop(List *list){ template T *merge(Arena *arena, List *list){ int len = length(list); - T *result = push_array(arena, T, len); + T *result = exp_alloc_array(arena, T, len); int i = 0; For_Linked_List(list->first){ diff --git a/base_string.cpp b/base_string.cpp index ec47bcb..f36986c 100644 --- a/base_string.cpp +++ b/base_string.cpp @@ -141,7 +141,7 @@ struct String_Builder{ assert(!last && !first); } - void push_block(SizeU size){ + void push_block(size_t size){ String_Builder_Block *block = 0; if(first_free){ block = first_free; @@ -218,7 +218,7 @@ function String string_flatten(Allocator *a, String_Builder *b, String_Builder_Flag flags = String_Builder_Flag_None){ // @Note(Krzosa): Compute size to allocate S64 size = 1; - if(is_flag_set(flags, String_Builder_Flag_AddSize)) size += sizeof(SizeU); + if(is_flag_set(flags, String_Builder_Flag_AddSize)) size += sizeof(size_t); For_Linked_List(b->first){ size += it->len; } @@ -308,8 +308,8 @@ string_get_prefix(String string, S64 len) { function String string_slice(String string, S64 first_index, S64 one_past_last_index) { - assert_msg(first_index < one_past_last_index, "string_slice, first_index is bigger then one_past_last_index"); - assert_msg(string.len > 0, "Slicing string of length 0! Might be an error!"); + assert_message(first_index < one_past_last_index, "string_slice, first_index is bigger then one_past_last_index"); + assert_message(string.len > 0, "Slicing string of length 0! Might be an error!"); String result = string; if (string.len > 0) { if (one_past_last_index > first_index) { diff --git a/c3_big_int.cpp b/c3_big_int.cpp index 86e3f96..5616f40 100644 --- a/c3_big_int.cpp +++ b/c3_big_int.cpp @@ -1,6 +1,7 @@ // Copyright (c) 2019 Christoffer Lerno. All rights reserved. // Use of this source code is governed by the GNU LGPLv3.0 license // a copy of which can be found in the LICENSE file. +#include #define Set_BigInt_Allocator(x) BigInt_Allocator bigint_allocator(x) struct BigInt_Allocator{ diff --git a/core_ast.cpp b/core_ast.cpp index 5b8270c..1be8162 100644 --- a/core_ast.cpp +++ b/core_ast.cpp @@ -236,7 +236,7 @@ How does current declaration order resolver works: struct Ast_Scope: Ast{ String debug_name; // Dont use List implicit_imports; - Array decls; + List decls; Array stmts; U32 visit_id; @@ -301,7 +301,7 @@ struct Ast_Decl: Ast{ #define ast_new(T,kind,pos,flags) (T *)_ast_new(sizeof(T), kind, pos, flags) function Ast * -_ast_new(SizeU size, Ast_Kind kind, Token *pos, Ast_Flag flags = 0){ +_ast_new(size_t size, Ast_Kind kind, Token *pos, Ast_Flag flags = 0){ Ast *result = (Ast *)exp_alloc(pctx->perm, size, AF_ZeroMemory); result->flags = flags; result->kind = kind; @@ -471,7 +471,6 @@ ast_array(Token *pos, Ast_Expr *expr){ function Ast_Scope * begin_decl_scope(Allocator *scratch, Token *pos){ AST_NEW(Scope, SCOPE, pos, AST_DECL); - result->decls = {scratch}; result->file = pctx->currently_parsed_file; result->module = pctx->currently_parsed_file->module; result->scope_id = pctx->scope_ids++; @@ -483,7 +482,6 @@ begin_decl_scope(Allocator *scratch, Token *pos){ function void finalize_decl_scope(Ast_Scope *scope){ - scope->decls = scope->decls.tight_copy(pctx->perm); pctx->currently_parsed_scope = scope->parent_scope; } @@ -491,7 +489,6 @@ function Ast_Scope * begin_stmt_scope(Allocator *scratch, Token *pos){ AST_NEW(Scope, SCOPE, pos, AST_STMT); result->stmts = {scratch}; - result->decls = {pctx->heap}; result->file = pctx->currently_parsed_file; result->module = pctx->currently_parsed_file->module; result->scope_id = pctx->scope_ids++; @@ -559,7 +556,6 @@ ast_type(Token *pos, Intern_String name, Ast_Type *type){ function Ast_Scope * ast_decl_scope(Token *pos, Allocator *allocator, Ast_File *file){ AST_NEW(Scope, SCOPE, pos, AST_DECL); - result->decls = {allocator}; result->file = file; result->scope_id = pctx->scope_ids++; diff --git a/core_codegen_c_language.cpp b/core_codegen_c_language.cpp index 85fbd6f..8a588e7 100644 --- a/core_codegen_c_language.cpp +++ b/core_codegen_c_language.cpp @@ -37,7 +37,7 @@ function String string_scope_name(Allocator *a, Ast_Scope *scope){ String string = {}; if(scope->parent_scope) string = string_scope_name(a, scope->parent_scope); - assert_msg(scope->scope_id != 0, "Scope id is equal to 0 which is invalid, scope didn't initialize id"); + assert_message(scope->scope_id != 0, "Scope id is equal to 0 which is invalid, scope didn't initialize id"); string = string_fmt(a, "%QS%u_", string, scope->scope_id); return string; } @@ -673,9 +673,9 @@ gen_ast(Ast *ast){ gen("%Q{", node->unique_name); global_indent++; is_inside_struct++; - For(node->scope->decls){ + Iter(&node->scope->decls){ genln(""); - gen_ast(it); + gen_ast(it.item[0]); } is_inside_struct--; @@ -688,10 +688,10 @@ gen_ast(Ast *ast){ gen("/*enum %Q{", node->name); // @todo add typespec global_indent++; - For(node->scope->decls){ - genln("%Q", it->name); + Iter(&node->scope->decls){ + genln("%Q", it.item[0]->name); gen(" = "); - gen_value(it->pos, it->value); + gen_value(it.item[0]->pos, it.item[0]->value); gen(","); } global_indent--; diff --git a/core_compiler.cpp b/core_compiler.cpp index f836889..c4f2e66 100644 --- a/core_compiler.cpp +++ b/core_compiler.cpp @@ -196,7 +196,6 @@ add_module(Token *pos, Intern_String filename, B32 command_line_module){ result->debug_name = string_skip_to_last_slash(result->absolute_file_path); result->module = result; // @warning: self referential result->file = result; // @warning: self referential - result->decls = {pctx->heap}; result->parent_scope = 0; result->scope_id = pctx->scope_ids++; @@ -210,11 +209,12 @@ resolve_everything_in_module(Ast_Module *module){ if(module->state == MODULE_RESOLVED) return; resolving_time_begin = os_time(); Iter_Named(&module->all_loaded_files, file){ - For(file.item[0]->decls){ - resolve_name(file.item[0], it->pos, it->name); + Iter(&file.item[0]->decls){ + Ast_Decl *decl = it.item[0]; + resolve_name(file.item[0], decl->pos, decl->name); - if(it->kind == AST_STRUCT){ - type_complete(it->type_val); + if(decl->kind == AST_STRUCT){ + type_complete(decl->type_val); } } } diff --git a/core_globals.cpp b/core_globals.cpp index 16b1544..8a41ebf 100644 --- a/core_globals.cpp +++ b/core_globals.cpp @@ -45,8 +45,8 @@ Intern_String intern_it; //----------------------------------------------------------------------------- // Type globals //----------------------------------------------------------------------------- -const SizeU pointer_size = sizeof(SizeU); -const SizeU pointer_align = __alignof(SizeU); +const uintptr_t pointer_size = sizeof(uintptr_t); +const uintptr_t pointer_align = __alignof(uintptr_t); global Ast_Type type__void = {TYPE_VOID}; global Ast_Type type__string = {TYPE_STRING, sizeof(String), __alignof(String)}; global Ast_Type type__bool = {TYPE_BOOL, sizeof(bool), __alignof(bool)}; diff --git a/core_main.cpp b/core_main.cpp index ac66296..89b46e7 100644 --- a/core_main.cpp +++ b/core_main.cpp @@ -1,10 +1,14 @@ /* -First doable version: +Current: + +- [ ] Foreign import that would link library +- [ ] String in Language.core +- [ ] Way to import and force evaluate #import_lazy #import ? +- [ ] Unix port - [ ] Imports are leaking names ! Multimedia leaks windows stuff - [ ] Test and bulletproof any, slices -- [ ] Include multiple pattern matched imports "unix_" and "linux_" both should be included on linux In the future @@ -12,7 +16,6 @@ In the future - [ ] Add ability to do i: int = 0 inside for loops for i: int = 0, i < 10, i+=1 - [ ] Complicated c declaration generation -- [ ] Way to import and force evaluate #import_lazy #import ? - [ ] Expand macros - [ ] Defer @@ -37,14 +40,15 @@ In the future - [ ] Parametric Polymorphism -- [ ] Conditional compilation #if (maybe just do something like a conditional load or import?) #import "windows.kl" when os == "windows" +Ideas +- [ ] #test construct that would gather all tests and run them on start of program or something +- [ ] Inject stack traces into the program +- [ ] Constant arrays that evaluate fully at compile time +- [ ] Rust like enum where you associate values(other structs) with key +- [ ] Cast from array to pointer? +- [ ] Ternary operator? +- [ ] Optionally pass size and alignment calculations to C ? -- [ ] Any - - [ ] Assigning to any values like ints etc. should work perhaps? But what type they should have? - - [ ] Slice of Any should work well - -Maybe later - - [ ] Optionally pass size and alignment calculations to C ? ------------------------------------------------------------------------------- @@ -117,36 +121,6 @@ For modules it's a bit different cause they should be distributed as valid. ------------------------------------------------------------------------------- -- [ ] Probably need to give Ast_Expr a Value field, then I can express Type nicely -- [ ] I would love for String, slice, Any etc. to have their struct declarations in source files, I also would want for stuff like string.str to work without weird special cases -- [ ] Var args with Any - -- [ ] #test construct that would gather all tests and run them on start of program or something -- [ ] Foreign import that would link library -- [ ] Kilobyte, Megabyte, Gigabyte -- [ ] Cast from array to pointer? -- [ ] Fix field access, cant cast, cant index -- [ ] Add parent_scope to Ast_Type, Add name to Ast_Type? - -- [ ] Optional function renaming in codegen -- [ ] Using in structs to embed members, then casting offsets to that embedded member - -- [ ] Comma notation when declaring variables thing1, thing2: S32 :: probably want to unify it with var unpacking -- [ ] Add single line lambda expressions -- [ ] Ternary operator -- [ ] Write up on order independent declarations - -- [ ] constructor => thing :: (i: S32) -> {i = i, thing = 10} -- [ ] Default values in structs??? Should compound stmts bring values from default values?? Maybe not? Whats the alternative - -@ideas -- [ ] Var args using Any array - args: []Any - delete vargs -- [ ] Constant arrays that evaluate fully at compile time -- [ ] Rust like enum where you associate values(other structs) with keys -- [ ] Compound that zeros values - .{} , Compound that assumes defaults from struct definition - {} -- [ ] Inject stack traces into the program - - ## Done @@ -247,7 +221,15 @@ For modules it's a bit different cause they should be distributed as valid. #include "base.cpp" #include "base_unicode.cpp" + +#if OS_WINDOWS #include "os_windows.cpp" +#elif OS_UNIX +#include "os_unix.cpp" +#else +#error Couldnt figure out OS using macros +#endif + #include "c3_big_int.h" #include "core_compiler.h" #include "core_types.h" @@ -307,5 +289,5 @@ int main(int argument_count, char **arguments){ compile_file(it.absolute_path, COMPILE_AND_RUN | COMPILE_TESTING); } } - __debugbreak(); + return 0; } diff --git a/core_parsing.cpp b/core_parsing.cpp index 69fd1c2..c3a5f7e 100644 --- a/core_parsing.cpp +++ b/core_parsing.cpp @@ -53,7 +53,7 @@ compiler_error(Token *token1, Token *token2, const char *str, ...){ if(token1) printf("\n%s:%d token_di:%u", token1->file.str, (S32)token1->line + 1, token1->di); if(token2) printf("\n%s:%d token_di:%u", token2->file.str, (S32)token2->line + 1, token2->di); - __debugbreak(); + Breakpoint; } function void @@ -72,7 +72,7 @@ compiler_error(Token *token, const char *str, ...){ if(token) printf("\n%s:%d token_di:%u", token->file.str, (S32)token->line + 1, token->di); - __debugbreak(); + Breakpoint; } function Token * @@ -678,7 +678,7 @@ parse_struct(Token *pos){ Ast_Decl *decl = ast_var(token, typespec, token->intern_val, 0); decl->flags = set_flag(decl->flags, AST_AGGREGATE_CHILD); - scope->decls.add(decl); + add(pctx->perm, &scope->decls, decl); }while(token_match(SAME_SCOPE)); token_expect(CLOSE_SCOPE); @@ -702,7 +702,7 @@ parse_enum(Token *pos){ if(token_match(TK_DoubleColon)) value = parse_expr(); Ast_Decl *member = ast_const(name, name->intern_val, value); member->flags = set_flag(member->flags, AST_AGGREGATE_CHILD); - scope->decls.add(member); + add(pctx->perm, &scope->decls, member); }while(token_match(SAME_SCOPE)); finalize_decl_scope(scope); token_expect(CLOSE_SCOPE); @@ -753,7 +753,6 @@ register_ast_file(Token *pos, String absolute_file_path, Ast_Module *module, B32 file->module = module; file->parent_scope = 0; file->file = file; // @warning: self referential! - file->decls = {pctx->heap}; file->pos = pos; file->debug_name = string_skip_to_last_slash(absolute_file_path); add(pctx->perm, &file->module->all_loaded_files, file); diff --git a/core_typechecking.cpp b/core_typechecking.cpp index 0512edd..2793ebe 100644 --- a/core_typechecking.cpp +++ b/core_typechecking.cpp @@ -443,9 +443,10 @@ inside_scope_search(Scope_Search *search, Ast_Scope *scope, int level){ scope->visit_id = search->scope_visit_id; // Search for declarations in current scope - For(scope->decls){ - if(it->name == search->name){ - search->results.add(it); + Iter(&scope->decls){ + Ast_Decl *decl = it.item[0]; + if(decl->name == search->name){ + search->results.add(decl); if(search->exit_on_find){ return; } @@ -591,7 +592,7 @@ insert_into_scope(Ast_Scope *scope, Ast_Decl *decl){ } } - scope->decls.add(decl); + add(pctx->perm, &scope->decls, decl); } // @@ -1686,13 +1687,14 @@ resolve_decl(Ast_Decl *ast){ node->type_val = type_enum(node, type_of_enum); S64 value = 1; - For(node->scope->decls){ + Iter(&node->scope->decls){ + Ast_Decl *decl = it.item[0]; Operand op = {}; - if(it->expr){ - op = require_const_int(it->expr, AST_CANT_BE_NULL); + if(decl->expr){ + op = require_const_int(decl->expr, AST_CANT_BE_NULL); value = bigint_as_signed(&op.big_int_val) + 1; } else{ - it->state = DECL_RESOLVED; + decl->state = DECL_RESOLVED; op.type = node->type_val; bigint_init_signed(&op.big_int_val, value); if(is_flag_set(node->flags, AST_FLAG)){ @@ -1702,7 +1704,7 @@ resolve_decl(Ast_Decl *ast){ } } - it->value = op.value; + decl->value = op.value; } BREAK(); } diff --git a/core_types.cpp b/core_types.cpp index 9f74006..8983b0f 100644 --- a/core_types.cpp +++ b/core_types.cpp @@ -58,7 +58,7 @@ force_inline B32 is_numeric(Ast_Type *type){ // Hash consed types //----------------------------------------------------------------------------- function Ast_Type * -type_new(Allocator *allocator, Ast_Type_Kind kind, SizeU size, SizeU align){ +type_new(Allocator *allocator, Ast_Type_Kind kind, size_t size, size_t align){ Ast_Type *result = exp_alloc_type(allocator, Ast_Type, AF_ZeroMemory); result->kind = kind; result->size = size; @@ -230,19 +230,20 @@ type_struct_complete(Ast_Type *type, Ast_Decl *node){ Array members = {scratch}; type->kind = TYPE_COMPLETING; size_t members_size = 0; - For(node->scope->decls){ - resolve_decl(it); - assert(it->type->kind != TYPE_INCOMPLETE); - assert(is_pow2(it->type->align)); + Iter(&node->scope->decls){ + Ast_Decl *decl = it.item[0]; + resolve_decl(decl); + assert(decl->type->kind != TYPE_INCOMPLETE); + assert(is_pow2(decl->type->align)); Ast_Resolved_Member m = {}; m.offset = type->size; - members_size += it->type->size; - type->align = max(type->align, it->type->align); - type->size = it->type->size + align_up(type->size, it->type->align); + members_size += decl->type->size; + type->align = max(type->align, decl->type->align); + type->size = decl->type->size + align_up(type->size, decl->type->align); - m.name = it->name; - m.value = it->value; + m.name = decl->name; + m.value = decl->value; members.add(m); } type->size = align_up(type->size, type->align); diff --git a/os_windows.cpp b/os_windows.cpp index 6dddc2a..72ba939 100644 --- a/os_windows.cpp +++ b/os_windows.cpp @@ -1,27 +1,28 @@ + //----------------------------------------------------------------------------- // Memory //----------------------------------------------------------------------------- -const SizeU os_page_size = 4096; +const size_t os_page_size = 4096; function OS_Memory -os_reserve(SizeU size){ +os_reserve(size_t size){ OS_Memory result = {}; - SizeU adjusted_size = align_up(size, os_page_size); + size_t adjusted_size = align_up(size, os_page_size); result.data = (U8*)VirtualAlloc(0, adjusted_size, MEM_RESERVE, PAGE_READWRITE); - assert_msg(result.data, "Failed to reserve virtual memory"); + assert_message(result.data, "Failed to reserve virtual memory"); result.reserve = adjusted_size; return result; } function B32 -os_commit(OS_Memory *m, SizeU size){ - SizeU commit = align_up(size, os_page_size); - SizeU total_commit = m->commit + commit; +os_commit(OS_Memory *m, size_t size){ + size_t commit = align_up(size, os_page_size); + size_t total_commit = m->commit + commit; total_commit = clamp_top(total_commit, m->reserve); - SizeU adjusted_commit = total_commit - m->commit; + size_t adjusted_commit = total_commit - m->commit; if(adjusted_commit != 0){ void *result = VirtualAlloc((U8*)m->data + m->commit, adjusted_commit, MEM_COMMIT, PAGE_READWRITE); - assert_msg(result, "Failed to commit more memory"); + assert_message(result, "Failed to commit more memory"); m->commit += adjusted_commit; return true; } @@ -31,7 +32,7 @@ os_commit(OS_Memory *m, SizeU size){ function void os_release(OS_Memory *m){ BOOL result = VirtualFree(m->data, 0, MEM_RELEASE); - assert_msg(result != 0, "Failed to release OS_Memory"); + assert_message(result != 0, "Failed to release OS_Memory"); if(result){ m->data = 0; m->commit = 0; @@ -40,10 +41,10 @@ os_release(OS_Memory *m){ } function B32 -os_decommit_pos(OS_Memory *m, SizeU pos){ - SizeU aligned = align_down(pos, os_page_size); - SizeU adjusted_pos = clamp_top(aligned, m->commit); - SizeU size_to_decommit = m->commit - adjusted_pos; +os_decommit_pos(OS_Memory *m, size_t pos){ + size_t aligned = align_down(pos, os_page_size); + size_t adjusted_pos = clamp_top(aligned, m->commit); + size_t size_to_decommit = m->commit - adjusted_pos; if(size_to_decommit){ U8 *base_address = m->data + adjusted_pos; BOOL result = VirtualFree(base_address, size_to_decommit, MEM_DECOMMIT); @@ -247,3 +248,56 @@ os_list_dir(Allocator *a, String dir, U32 flags = LIST_NO_FLAGS){ return result; } + +//----------------------------------------------------------------------------- +// OS Heap allocator +//----------------------------------------------------------------------------- +struct OS_Heap:Allocator{ + void *handle; +}; + +function void * +os_heap_allocator_proc(Allocator *a, Allocation_Kind kind, void *old_pointer, size_t size){ + OS_Heap *heap = (OS_Heap *)a; + switch(kind){ + case Allocation_FreeAll:{ + invalid_codepath; + return 0; + } + case Allocation_Destroy:{ + BOOL result = HeapDestroy(heap->handle); + assert(result != 0); + heap->handle = 0; + heap->proc = 0; + return 0; + } + case Allocation_Free:{ + BOOL result = HeapFree(heap->handle, 0, old_pointer); + assert(result != 0); + return 0; + } + case Allocation_Alloc:{ + void *result = HeapAlloc(heap->handle, 0, size); + assert(result); + return result; + } + case Allocation_Resize:{ + void *result = HeapReAlloc(heap->handle, 0, old_pointer, size); + assert(result); + return result; + } + default: invalid_codepath; + } + return 0; +} + +function OS_Heap // max_size == 0 == growing heap +win32_os_heap_create(B32 multithreaded, size_t initial_size, size_t max_size, String debug_name){ + OS_Heap result = {}; + result.debug_name = debug_name; + result.proc = os_heap_allocator_proc; + result.kind = Allocator_OSHeap; + result.handle = HeapCreate(multithreaded ? 0 : HEAP_NO_SERIALIZE, initial_size, max_size); + assert(result.handle); + return result; +} \ No newline at end of file