diff --git a/core/runtime/default_allocators.odin b/core/runtime/default_allocators.odin index b47e60659..7d13f2a32 100644 --- a/core/runtime/default_allocators.odin +++ b/core/runtime/default_allocators.odin @@ -15,7 +15,46 @@ when ODIN_DEFAULT_TO_NIL_ALLOCATOR || ODIN_OS == "freestanding" { data = nil, }; } -} else when ODIN_OS != "windows" { + +} else when ODIN_OS == "windows" { + default_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, + size, alignment: int, + old_memory: rawptr, old_size: int, loc := #caller_location) -> ([]byte, Allocator_Error) { + switch mode { + case .Alloc: + return _windows_default_alloc(size, alignment); + + case .Free: + _windows_default_free(old_memory); + + case .Free_All: + // NOTE(tetra): Do nothing. + + case .Resize: + return _windows_default_resize(old_memory, old_size, size, alignment); + + case .Query_Features: + set := (^Allocator_Mode_Set)(old_memory); + if set != nil { + set^ = {.Alloc, .Free, .Resize, .Query_Features}; + } + return nil, nil; + + case .Query_Info: + return nil, nil; + } + + return nil, nil; + } + + default_allocator :: proc() -> Allocator { + return Allocator{ + procedure = default_allocator_proc, + data = nil, + }; + } + +} else { // TODO(bill): reimplement these procedures in the os_specific stuff import "core:os" diff --git a/core/runtime/os_specific.odin b/core/runtime/os_specific.odin index 0ba11d0e6..03acf4279 100644 --- a/core/runtime/os_specific.odin +++ b/core/runtime/os_specific.odin @@ -1,3 +1,11 @@ package runtime _OS_Errno :: distinct int; + +os_write :: proc "contextless" (data: []byte) -> (int, _OS_Errno) { + return _os_write(data); +} + +current_thread_id :: proc "contextless" () -> int { + return _current_thread_id(); +} diff --git a/core/runtime/os_specific_any.odin b/core/runtime/os_specific_any.odin index 2e52490ec..9c2686661 100644 --- a/core/runtime/os_specific_any.odin +++ b/core/runtime/os_specific_any.odin @@ -6,12 +6,12 @@ import "core:os" // TODO(bill): reimplement `os.write` so that it does not rely on package os // NOTE: Use os_specific_linux.odin, os_specific_darwin.odin, etc -os_write :: proc "contextless" (data: []byte) -> (int, _OS_Errno) { +_os_write :: proc "contextless" (data: []byte) -> (int, _OS_Errno) { context = default_context(); n, err := os.write(os.stderr, data); return int(n), _OS_Errno(err); } -current_thread_id :: proc "contextless" () -> int { +_current_thread_id :: proc "contextless" () -> int { return os.current_thread_id(); } diff --git a/core/runtime/os_specific_freestanding.odin b/core/runtime/os_specific_freestanding.odin index 2c715ccb7..cae41daae 100644 --- a/core/runtime/os_specific_freestanding.odin +++ b/core/runtime/os_specific_freestanding.odin @@ -2,10 +2,10 @@ package runtime // TODO(bill): reimplement `os.write` -os_write :: proc "contextless" (data: []byte) -> (int, _OS_Errno) { +_os_write :: proc "contextless" (data: []byte) -> (int, _OS_Errno) { return 0, -1; } -current_thread_id :: proc "contextless" () -> int { +_current_thread_id :: proc "contextless" () -> int { return 0; } diff --git a/core/runtime/os_specific_windows.odin b/core/runtime/os_specific_windows.odin index 0cf9d28f4..f5a9d744d 100644 --- a/core/runtime/os_specific_windows.odin +++ b/core/runtime/os_specific_windows.odin @@ -1,3 +1,4 @@ +//+private //+build windows package runtime @@ -24,7 +25,7 @@ foreign kernel32 { HeapFree :: proc(hHeap: rawptr, dwFlags: u32, lpMem: rawptr) -> b32 --- } -os_write :: proc "contextless" (data: []byte) -> (n: int, err: _OS_Errno) { +_os_write :: proc "contextless" (data: []byte) -> (n: int, err: _OS_Errno) { if len(data) == 0 { return 0, 0; } @@ -58,7 +59,7 @@ os_write :: proc "contextless" (data: []byte) -> (n: int, err: _OS_Errno) { return; } -current_thread_id :: proc "contextless" () -> int { +_current_thread_id :: proc "contextless" () -> int { return int(GetCurrentThreadId()); } @@ -86,89 +87,58 @@ heap_free :: proc "contextless" (ptr: rawptr) { HeapFree(GetProcessHeap(), 0, ptr); } -default_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, - size, alignment: int, - old_memory: rawptr, old_size: int, loc := #caller_location) -> ([]byte, Allocator_Error) { - // - // NOTE(tetra, 2020-01-14): The heap doesn't respect alignment. - // Instead, we overallocate by `alignment + size_of(rawptr) - 1`, and insert - // padding. We also store the original pointer returned by heap_alloc right before - // the pointer we return to the user. - // +// +// NOTE(tetra, 2020-01-14): The heap doesn't respect alignment. +// Instead, we overallocate by `alignment + size_of(rawptr) - 1`, and insert +// padding. We also store the original pointer returned by heap_alloc right before +// the pointer we return to the user. +// - aligned_alloc :: proc "contextless" (size, alignment: int, old_ptr: rawptr = nil) -> ([]byte, Allocator_Error) { - a := max(alignment, align_of(rawptr)); - space := size + a - 1; - allocated_mem: rawptr; - if old_ptr != nil { - original_old_ptr := ptr_offset((^rawptr)(old_ptr), -1)^; - allocated_mem = heap_resize(original_old_ptr, space+size_of(rawptr)); - } else { - allocated_mem = heap_alloc(space+size_of(rawptr)); - } - aligned_mem := rawptr(ptr_offset((^u8)(allocated_mem), size_of(rawptr))); - ptr := uintptr(aligned_mem); - aligned_ptr := (ptr - 1 + uintptr(a)) & -uintptr(a); - diff := int(aligned_ptr - ptr); - if (size + diff) > space { - return nil, .Out_Of_Memory; - } - - aligned_mem = rawptr(aligned_ptr); - ptr_offset((^rawptr)(aligned_mem), -1)^ = allocated_mem; - - return byte_slice(aligned_mem, size), nil; - } - - aligned_free :: proc "contextless" (p: rawptr) { - if p != nil { - heap_free(ptr_offset((^rawptr)(p), -1)^); - } - } - - aligned_resize :: proc "contextless" (p: rawptr, old_size: int, new_size: int, new_alignment: int) -> ([]byte, Allocator_Error) { - if p == nil { - return nil, nil; - } - return aligned_alloc(new_size, new_alignment, p); - } - - switch mode { - case .Alloc: - return aligned_alloc(size, alignment); - - case .Free: - aligned_free(old_memory); - - case .Free_All: - // NOTE(tetra): Do nothing. - - case .Resize: - if old_memory == nil { - return aligned_alloc(size, alignment); - } - return aligned_resize(old_memory, old_size, size, alignment); - - case .Query_Features: - set := (^Allocator_Mode_Set)(old_memory); - if set != nil { - set^ = {.Alloc, .Free, .Resize, .Query_Features}; - } - return nil, nil; - - case .Query_Info: +_windows_default_alloc_or_resize :: proc "contextless" (size, alignment: int, old_ptr: rawptr = nil) -> ([]byte, Allocator_Error) { + if size == 0 { + _windows_default_free(old_ptr); return nil, nil; } - return nil, nil; + a := max(alignment, align_of(rawptr)); + space := size + a - 1; + + allocated_mem: rawptr; + if old_ptr != nil { + original_old_ptr := ptr_offset((^rawptr)(old_ptr), -1)^; + allocated_mem = heap_resize(original_old_ptr, space+size_of(rawptr)); + } else { + allocated_mem = heap_alloc(space+size_of(rawptr)); + } + aligned_mem := rawptr(ptr_offset((^u8)(allocated_mem), size_of(rawptr))); + + ptr := uintptr(aligned_mem); + aligned_ptr := (ptr - 1 + uintptr(a)) & -uintptr(a); + diff := int(aligned_ptr - ptr); + if (size + diff) > space { + return nil, .Out_Of_Memory; + } + + aligned_mem = rawptr(aligned_ptr); + ptr_offset((^rawptr)(aligned_mem), -1)^ = allocated_mem; + + return byte_slice(aligned_mem, size), nil; } -default_allocator :: proc() -> Allocator { - return Allocator{ - procedure = default_allocator_proc, - data = nil, - }; +_windows_default_alloc :: proc "contextless" (size, alignment: int) -> ([]byte, Allocator_Error) { + return _windows_default_alloc_or_resize(size, alignment, nil); +} + + +_windows_default_free :: proc "contextless" (ptr: rawptr) { + if ptr != nil { + heap_free(ptr_offset((^rawptr)(ptr), -1)^); + } +} + +_windows_default_resize :: proc "contextless" (p: rawptr, old_size: int, new_size: int, new_alignment: int) -> ([]byte, Allocator_Error) { + return _windows_default_alloc_or_resize(new_size, new_alignment, p); } diff --git a/core/runtime/procs_essence.odin b/core/runtime/procs_essence.odin index a2cd26df6..6e6020b83 100644 --- a/core/runtime/procs_essence.odin +++ b/core/runtime/procs_essence.odin @@ -1,18 +1,22 @@ package runtime -import "core:sys/es" - @(link_name="memset") memset :: proc "c" (ptr: rawptr, val: i32, len: int) -> rawptr { - return es.CRTmemset(ptr, val, len); + addr := 0x1000 + 196 * size_of(int); + fp := (rawptr(((^uintptr)(uintptr(addr)))^)); + return ((proc "c" (rawptr, i32, int) -> rawptr)(fp))(ptr, val, len); } @(link_name="memmove") memmove :: proc "c" (dst, src: rawptr, len: int) -> rawptr { - return es.CRTmemmove(dst, src, len); + addr := 0x1000 + 195 * size_of(int); + fp := (rawptr(((^uintptr)(uintptr(addr)))^)); + return ((proc "c" (rawptr, rawptr, int) -> rawptr)(fp))(dst, src, len); } @(link_name="memcpy") memcpy :: proc "c" (dst, src: rawptr, len: int) -> rawptr { - return es.CRTmemcpy(dst, src, len); + addr := 0x1000 + 194 * size_of(int); + fp := (rawptr(((^uintptr)(uintptr(addr)))^)); + return ((proc "c" (rawptr, rawptr, int) -> rawptr)(fp))(dst, src, len); }