From: Brendan Hansen Date: Wed, 8 Sep 2021 03:19:02 +0000 (-0500) Subject: bugfixes in compiler and core libraries X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=8cad63f7d691af1c6ef20481895f32de1f51a66c;p=onyx.git bugfixes in compiler and core libraries --- diff --git a/.vimspector.json.old b/.vimspector.json.old new file mode 100644 index 00000000..b8923072 --- /dev/null +++ b/.vimspector.json.old @@ -0,0 +1,24 @@ +{ "configurations": { + "cpptools-run": { + "adapter": "vscode-cpptools", + "configuration": { + "type": "cppdbg", + "request": "launch", + "program": "/home/brendan/dev/c/onyx/bin/onyx-debug", + "args": ["-VVV", "-I", "/home/brendan/dev/c/onyx", "-o", "site/analyzer.wasm", "-r", "js", "--no-colors", "src/build.onyx", "--doc", "doc/source_reference" ], + "stopAtEntry": true, + "cwd": "/home/brendan/dev/onyx/wasm_analyzer", + "environment": [], + "externalConsole": false, + "MIMode": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + } + ] + } + } + } +} diff --git a/bin/onyx b/bin/onyx index 122314bb..8a4f175d 100755 Binary files a/bin/onyx and b/bin/onyx differ diff --git a/core/alloc/heap.onyx b/core/alloc/heap.onyx index 33722d0b..09645b8e 100644 --- a/core/alloc/heap.onyx +++ b/core/alloc/heap.onyx @@ -13,92 +13,118 @@ Enable_Debug :: false #load "core/intrinsics/wasm" -uintptr :: #type u32 +init :: () { + heap_state.free_list = null; + heap_state.next_alloc = cast(rawptr) (cast(uintptr) __heap_start + 8); + heap_state.remaining_space = (memory_size() << 16) - cast(u32) __heap_start; -use package core.intrinsics.wasm { - memory_size, memory_grow, - memory_copy, memory_fill, -} -#private_file memory :: package core.memory -#private_file math :: package core.math - -// The global heap state -#private_file -heap_state : struct { - free_list : ^heap_freed_block; - next_alloc : rawptr; - remaining_space : u32; + use package core.alloc { heap_allocator } + heap_allocator.data = ^heap_state; + heap_allocator.func = heap_alloc_proc; } -#private_file -heap_block :: struct { - size : u32; - magic_number : u32; -} +get_watermark :: () => cast(u32) heap_state.next_alloc; -#private_file -heap_freed_block :: struct { - use base: heap_block; - next : ^heap_freed_block; - prev : ^heap_freed_block; -} +#private_file { + use package core.intrinsics.wasm { + memory_size, memory_grow, + memory_copy, memory_fill, + } -#private_file -heap_allocated_block :: struct { - use base: heap_block; -} + memory :: package core.memory + math :: package core.math -#private_file Allocated_Flag :: 0x1 -#private_file Free_Block_Magic_Number :: 0xdeadbeef -#private_file Block_Split_Size :: 512 - -// FIX: This does not respect the choice of alignment -#private_file -heap_alloc :: (size_: u32, align: u32) -> rawptr { - if size_ == 0 do return null; - - size := size_ + sizeof heap_block; - size = math.max(size, sizeof heap_freed_block); - memory.align(~~^size, ~~align); - - prev := ^heap_state.free_list; - hb := heap_state.free_list; - while hb != null { - if hb.size >= size { - #if Enable_Debug { - assert(hb.size & Allocated_Flag == 0, "Allocated block in free list."); - assert(hb.magic_number == Free_Block_Magic_Number, "Malformed free block in free list."); - } + uintptr :: #type u32 - if hb.size - size >= Block_Split_Size { - hb.size = size; + // The global heap state + heap_state : struct { + free_list : ^heap_freed_block; + next_alloc : rawptr; + remaining_space : u32; + } - new_block := cast(^heap_freed_block) (cast(uintptr) hb + size); - new_block.size = hb.size - size; - new_block.next = hb.next; - new_block.prev = hb.prev; - new_block.magic_number = Free_Block_Magic_Number; + heap_block :: struct { + size : u32; + magic_number : u32; + } + + heap_freed_block :: struct { + use base: heap_block; + next : ^heap_freed_block; + prev : ^heap_freed_block; + } - if hb.next != null do hb.next.prev = new_block; - *prev = new_block; + heap_allocated_block :: struct { + use base: heap_block; + } - } else { - if hb.next != null do hb.next.prev = hb.prev; - *prev = hb.next; + Allocated_Flag :: 0x1 + Free_Block_Magic_Number :: 0xdeadbeef + Block_Split_Size :: 512 + + // FIX: This does not respect the choice of alignment + heap_alloc :: (size_: u32, align: u32) -> rawptr { + if size_ == 0 do return null; + + size := size_ + sizeof heap_block; + size = math.max(size, sizeof heap_freed_block); + memory.align(~~^size, ~~align); + + prev := ^heap_state.free_list; + hb := heap_state.free_list; + while hb != null { + if hb.size >= size { + #if Enable_Debug { + assert(hb.size & Allocated_Flag == 0, "Allocated block in free list."); + assert(hb.magic_number == Free_Block_Magic_Number, "Malformed free block in free list."); + } + + if hb.size - size >= Block_Split_Size { + hb.size = size; + + new_block := cast(^heap_freed_block) (cast(uintptr) hb + size); + new_block.size = hb.size - size; + new_block.next = hb.next; + new_block.prev = hb.prev; + new_block.magic_number = Free_Block_Magic_Number; + + if hb.next != null do hb.next.prev = new_block; + *prev = new_block; + + } else { + if hb.next != null do hb.next.prev = hb.prev; + *prev = hb.next; + } + + hb.next = null; + hb.prev = null; + hb.magic_number = 0; + hb.size |= Allocated_Flag; + return cast(rawptr) (cast(uintptr) hb + sizeof heap_allocated_block); } - hb.next = null; - hb.prev = null; - hb.magic_number = 0; - hb.size |= Allocated_Flag; - return cast(rawptr) (cast(uintptr) hb + sizeof heap_allocated_block); + prev = ^hb.next; + hb = hb.next; } - prev = ^hb.next; - hb = hb.next; - } + if size < heap_state.remaining_space { + ret := cast(^heap_allocated_block) heap_state.next_alloc; + ret.size = size; + ret.size |= Allocated_Flag; + + heap_state.next_alloc = cast(rawptr) (cast(uintptr) heap_state.next_alloc + size); + heap_state.remaining_space -= size; + + return cast(rawptr) (cast(uintptr) ret + sizeof heap_allocated_block); + } + + new_pages := ((size - heap_state.remaining_space) >> 16) + 1; + if memory_grow(new_pages) == -1 { + // out of memory + return null; + } + heap_state.remaining_space += new_pages << 16; - if size < heap_state.remaining_space { ret := cast(^heap_allocated_block) heap_state.next_alloc; ret.size = size; ret.size |= Allocated_Flag; @@ -109,128 +135,98 @@ heap_alloc :: (size_: u32, align: u32) -> rawptr { return cast(rawptr) (cast(uintptr) ret + sizeof heap_allocated_block); } - new_pages := ((size - heap_state.remaining_space) >> 16) + 1; - if memory_grow(new_pages) == -1 { - // out of memory - return null; - } - heap_state.remaining_space += new_pages << 16; - - ret := cast(^heap_allocated_block) heap_state.next_alloc; - ret.size = size; - ret.size |= Allocated_Flag; + heap_free :: (ptr: rawptr) { + #if Enable_Debug do assert(ptr != null, "Trying to free a null pointer."); - heap_state.next_alloc = cast(rawptr) (cast(uintptr) heap_state.next_alloc + size); - heap_state.remaining_space -= size; + hb_ptr := cast(^heap_freed_block) (cast(uintptr) ptr - sizeof heap_allocated_block); + #if Enable_Debug do assert(hb_ptr.size & Allocated_Flag == Allocated_Flag, "Corrupted heap on free. This could be due to a double free, or using memory past were you allocated it."); - return cast(rawptr) (cast(uintptr) ret + sizeof heap_allocated_block); -} - -#private_file -heap_free :: (ptr: rawptr) { - #if Enable_Debug do assert(ptr != null, "Trying to free a null pointer."); - - hb_ptr := cast(^heap_freed_block) (cast(uintptr) ptr - sizeof heap_allocated_block); - #if Enable_Debug do assert(hb_ptr.size & Allocated_Flag == Allocated_Flag, "Corrupted heap on free. This could be due to a double free, or using memory past were you allocated it."); - - hb_ptr.size &= ~Allocated_Flag; - orig_size := hb_ptr.size - sizeof heap_allocated_block; + hb_ptr.size &= ~Allocated_Flag; + orig_size := hb_ptr.size - sizeof heap_allocated_block; - #if Enable_Debug do memory_fill(ptr, ~~0xcc, orig_size); + #if Enable_Debug do memory_fill(ptr, ~~0xcc, orig_size); - // CLEANUP: This is not complete. This only checks if the block after the freed block is also free. - // There are three other cases related to the block before this one that need to be handled for - // the best efficiency and minimal fragmentation. - if cast(uintptr) hb_ptr + hb_ptr.size < cast(uintptr) heap_state.next_alloc { - next_block := cast(^heap_freed_block) (cast(uintptr) hb_ptr + hb_ptr.size); + // CLEANUP: This is not complete. This only checks if the block after the freed block is also free. + // There are three other cases related to the block before this one that need to be handled for + // the best efficiency and minimal fragmentation. + if cast(uintptr) hb_ptr + hb_ptr.size < cast(uintptr) heap_state.next_alloc { + next_block := cast(^heap_freed_block) (cast(uintptr) hb_ptr + hb_ptr.size); - if next_block.size & Allocated_Flag == 0 && next_block.magic_number == Free_Block_Magic_Number { - hb_ptr.size += next_block.size; + if next_block.size & Allocated_Flag == 0 && next_block.magic_number == Free_Block_Magic_Number { + hb_ptr.size += next_block.size; - if next_block.next != null do next_block.next.prev = next_block.prev; - if next_block.prev != null do next_block.prev.next = next_block.next; - else do heap_state.free_list = next_block.next; + if next_block.next != null do next_block.next.prev = next_block.prev; + if next_block.prev != null do next_block.prev.next = next_block.next; + else do heap_state.free_list = next_block.next; - next_block.next = null; - next_block.prev = null; + next_block.next = null; + next_block.prev = null; + } } - } - - hb_ptr.magic_number = Free_Block_Magic_Number; - hb_ptr.prev = null; - hb_ptr.next = heap_state.free_list; - if heap_state.free_list != null do heap_state.free_list.prev = hb_ptr; - heap_state.free_list = hb_ptr; -} + hb_ptr.magic_number = Free_Block_Magic_Number; + hb_ptr.prev = null; + hb_ptr.next = heap_state.free_list; -#private_file -heap_resize :: (ptr: rawptr, new_size_: u32, align: u32) -> rawptr { - if ptr == null do return null; + if heap_state.free_list != null do heap_state.free_list.prev = hb_ptr; + heap_state.free_list = hb_ptr; + } - new_size := new_size_ + sizeof heap_block; - new_size = math.max(new_size, sizeof heap_freed_block); - new_size = ~~memory.align(cast(u64) new_size, ~~align); - - hb_ptr := cast(^heap_allocated_block) (cast(uintptr) ptr - sizeof heap_allocated_block); - #if Enable_Debug do assert(hb_ptr.size & Allocated_Flag == Allocated_Flag, "Corrupted heap on resize."); - hb_ptr.size &= ~Allocated_Flag; + heap_resize :: (ptr: rawptr, new_size_: u32, align: u32) -> rawptr { + if ptr == null do return null; - old_size := hb_ptr.size; + new_size := new_size_ + sizeof heap_block; + new_size = math.max(new_size, sizeof heap_freed_block); + new_size = ~~memory.align(cast(u64) new_size, ~~align); + + hb_ptr := cast(^heap_allocated_block) (cast(uintptr) ptr - sizeof heap_allocated_block); + #if Enable_Debug do assert(hb_ptr.size & Allocated_Flag == Allocated_Flag, "Corrupted heap on resize."); + hb_ptr.size &= ~Allocated_Flag; - // If there is already enough space in the current allocated block, - // just return the block that already exists and has the memory in it. - if old_size >= new_size { - hb_ptr.size |= Allocated_Flag; - return ptr; - } + old_size := hb_ptr.size; - // If we are at the end of the allocation space, just extend it - if cast(uintptr) hb_ptr + hb_ptr.size >= cast(uintptr) heap_state.next_alloc { - needed_size := cast(u32) memory.align(cast(u64) (new_size - old_size), 16); + // If there is already enough space in the current allocated block, + // just return the block that already exists and has the memory in it. + if old_size >= new_size { + hb_ptr.size |= Allocated_Flag; + return ptr; + } - if needed_size >= heap_state.remaining_space { - new_pages := ((needed_size - heap_state.remaining_space) >> 16) + 1; - if memory_grow(new_pages) == -1 { - // out of memory - return null; + // If we are at the end of the allocation space, just extend it + if cast(uintptr) hb_ptr + hb_ptr.size >= cast(uintptr) heap_state.next_alloc { + needed_size := cast(u32) memory.align(cast(u64) (new_size - old_size), 16); + + if needed_size >= heap_state.remaining_space { + new_pages := ((needed_size - heap_state.remaining_space) >> 16) + 1; + if memory_grow(new_pages) == -1 { + // out of memory + return null; + } + heap_state.remaining_space += new_pages << 16; } - heap_state.remaining_space += new_pages << 16; + + hb_ptr.size = new_size; + hb_ptr.size |= Allocated_Flag; + heap_state.next_alloc = cast(rawptr) (cast(uintptr) heap_state.next_alloc + needed_size); + heap_state.remaining_space -= needed_size; + return ptr; } - hb_ptr.size = new_size; hb_ptr.size |= Allocated_Flag; - heap_state.next_alloc = cast(rawptr) (cast(uintptr) heap_state.next_alloc + needed_size); - heap_state.remaining_space -= needed_size; - return ptr; + new_ptr := heap_alloc(new_size_, align); + memory_copy(new_ptr, ptr, old_size - sizeof heap_block); + heap_free(ptr); + return new_ptr; } - hb_ptr.size |= Allocated_Flag; - new_ptr := heap_alloc(new_size_, align); - memory_copy(new_ptr, ptr, old_size - sizeof heap_block); - heap_free(ptr); - return new_ptr; -} + heap_alloc_proc :: (data: rawptr, aa: AllocationAction, size: u32, align: u32, oldptr: rawptr) -> rawptr { + switch aa { + case .Alloc do return heap_alloc(size, align); + case .Resize do return heap_resize(oldptr, size, align); + case .Free do heap_free(oldptr); + } -#private_file -heap_alloc_proc :: (data: rawptr, aa: AllocationAction, size: u32, align: u32, oldptr: rawptr) -> rawptr { - switch aa { - case .Alloc do return heap_alloc(size, align); - case .Resize do return heap_resize(oldptr, size, align); - case .Free do heap_free(oldptr); + return null; } - - return null; -} - -init :: () { - heap_state.free_list = null; - heap_state.next_alloc = cast(rawptr) (cast(uintptr) __heap_start + 8); - heap_state.remaining_space = (memory_size() << 16) - cast(u32) __heap_start; - - use package core.alloc { heap_allocator } - heap_allocator.data = ^heap_state; - heap_allocator.func = heap_alloc_proc; } -get_watermark :: () => cast(u32) heap_state.next_alloc; \ No newline at end of file diff --git a/core/random.onyx b/core/random.onyx index 97994808..85ba22c0 100644 --- a/core/random.onyx +++ b/core/random.onyx @@ -1,16 +1,19 @@ package core.random -#private_file seed : i32 = 8675309 +#private_file seed : i64 = 867530932187 -#private_file RANDOM_MULTIPLIER :: 1664525 -#private_file RANDOM_INCREMENT :: 1013904223 +#private_file RANDOM_MULTIPLIER :: 25214903917 +#private_file RANDOM_INCREMENT :: cast(i64) 11 // #private_file RANDOM_MODULUS :: 1 << 32 -set_seed :: (s: u32) do seed = s; +set_seed :: #match { + (s: u32) do seed = ~~s; , + (s: u64) do seed = s; , +} int :: (s := ^seed) -> u32 { *s = *s * RANDOM_MULTIPLIER + RANDOM_INCREMENT; - return *s; + return cast(u32) ((*s >> 16) & ~~0xffffffff); } between :: (lo: i32, hi: i32) -> i32 do return int () % (hi + 1 - lo) + lo; diff --git a/examples/11_map.onyx b/examples/11_map.onyx index bba7b9e4..5cab4dac 100644 --- a/examples/11_map.onyx +++ b/examples/11_map.onyx @@ -8,7 +8,7 @@ main :: (args: [] cstr) { // provide an 'any-to-any' hash map in it's core libraries. // To use it, simply create one like so: - ages : map.Map(str, u32); + ages : Map(str, u32); map.init(^ages, default=0, hash_count=16); defer map.free(^ages); @@ -29,7 +29,7 @@ main :: (args: [] cstr) { map.put(^ages, "Pam", 24); // To retrieve an entry's value, use the map.get procedure. - print_age :: (ages: ^map.Map(str, u32), name: str) { + print_age :: (ages: ^Map(str, u32), name: str) { age := map.get(ages, name); printf("{}'s age is {}.\n", name, age); } diff --git a/include/onyxutils.h b/include/onyxutils.h index cd726711..96957887 100644 --- a/include/onyxutils.h +++ b/include/onyxutils.h @@ -39,4 +39,4 @@ i32 string_process_escape_seqs(char* dest, char* src, i32 len); // :RelativeFiles This should lookup for the file relative to "relative_to" char* lookup_included_file(char* filename, char* relative_to, b32 add_onyx_suffix, b32 search_included_folders); -extern AstNode node_that_signals_a_yield; \ No newline at end of file +extern AstTyped node_that_signals_a_yield; diff --git a/modules/bmfont/position.onyx b/modules/bmfont/position.onyx index 85795384..6cd60255 100644 --- a/modules/bmfont/position.onyx +++ b/modules/bmfont/position.onyx @@ -1,32 +1,34 @@ package bmfont -#private_file math :: package core.math +#private_file { + math :: package core.math -#private_file Renderable_Glyph :: struct { - pos_x, pos_y : f32; - pos_w, pos_h : f32; + renderable_glyph: Renderable_Glyph; + Renderable_Glyph :: struct { + pos_x, pos_y : f32; + pos_w, pos_h : f32; - tex_x, tex_y : f32; - tex_w, tex_h : f32; + tex_x, tex_y : f32; + tex_w, tex_h : f32; - x_advance : f32; -} -#private_file renderable_glyph: Renderable_Glyph; + x_advance : f32; + } -#private_file Rendering_Context :: struct { - font : ^BMFont; - size : f32; + rendering_context: Rendering_Context; + Rendering_Context :: struct { + font : ^BMFont; + size : f32; - x, y : f32; + x, y : f32; - original_x : f32; - baseline : f32; - line_height : f32; + original_x : f32; + baseline : f32; + line_height : f32; - text : str; - text_position : u32; + text : str; + text_position : u32; + } } -#private_file rendering_context: Rendering_Context; @FontSizing // Currently, `size` is just a multipler for the baked font size. This should be changed to be height in pixels, or 'em's. @Rename @@ -99,4 +101,4 @@ get_character_positions :: (font: ^BMFont, size: f32, text: str, x: f32, y: f32) close = close, data = ^rendering_context, }; -} \ No newline at end of file +} diff --git a/modules/ui/ui.onyx b/modules/ui/ui.onyx index da3cc025..980cc8c7 100644 --- a/modules/ui/ui.onyx +++ b/modules/ui/ui.onyx @@ -5,14 +5,15 @@ use package core @Temporary DEFAULT_TEXT_SIZE :: 1.0f - UI_Id :: #type u32 -#private hot_item : UI_Id = 0 -#private active_item : UI_Id = 0 -#private hot_item_was_set := false +#private { + hot_item : UI_Id = 0 + active_item : UI_Id = 0 + hot_item_was_set := false -#private current_font : ^Font; + current_font : ^Font; +} init_ui :: () { map.init(^font_registry, hash_count=4); diff --git a/src/onyxchecker.c b/src/onyxchecker.c index 3ec91cf5..e2edab7a 100644 --- a/src/onyxchecker.c +++ b/src/onyxchecker.c @@ -223,6 +223,8 @@ CheckStatus check_for(AstFor* fornode) { resolve_expression_type(fornode->iter); Type* iter_type = fornode->iter->type; + if (iter_type == NULL) YIELD(fornode->token->pos, "Waiting for iteration expression type to be known."); + fornode->loop_type = For_Loop_Invalid; if (types_are_compatible(iter_type, &basic_types[Basic_Kind_I32])) { if (fornode->by_pointer) { diff --git a/src/onyxutils.c b/src/onyxutils.c index 5c35c5fd..e53256ce 100644 --- a/src/onyxutils.c +++ b/src/onyxutils.c @@ -249,7 +249,7 @@ void scope_clear(Scope* scope) { // HACK HACK HACK nocheckin static b32 flag_to_yield = 0; -AstNode node_that_signals_a_yield = { 0 }; +AstTyped node_that_signals_a_yield = { Ast_Kind_Function, 0 }; static void ensure_polyproc_cache_is_created(AstPolyProc* pp) { if (pp->concrete_funcs == NULL) {