diff options
Diffstat (limited to 'core/runtime')
| -rw-r--r-- | core/runtime/core.odin | 10 | ||||
| -rw-r--r-- | core/runtime/core_builtin.odin | 115 | ||||
| -rw-r--r-- | core/runtime/dynamic_array_internal.odin | 10 | ||||
| -rw-r--r-- | core/runtime/dynamic_map_internal.odin | 13 | ||||
| -rw-r--r-- | core/runtime/internal.odin | 100 | ||||
| -rw-r--r-- | core/runtime/print.odin | 3 | ||||
| -rw-r--r-- | core/runtime/procs.odin | 28 |
7 files changed, 170 insertions, 109 deletions
diff --git a/core/runtime/core.odin b/core/runtime/core.odin index 8fb3d7210..0310aff6d 100644 --- a/core/runtime/core.odin +++ b/core/runtime/core.odin @@ -176,6 +176,9 @@ Type_Info_Matrix :: struct { column_count: int, // Total element count = column_count * elem_stride } +Type_Info_Soa_Pointer :: struct { + elem: ^Type_Info, +} Type_Info_Flag :: enum u8 { Comparable = 0, @@ -217,6 +220,7 @@ Type_Info :: struct { Type_Info_Relative_Pointer, Type_Info_Relative_Slice, Type_Info_Matrix, + Type_Info_Soa_Pointer, }, } @@ -403,6 +407,12 @@ Raw_Cstring :: struct { data: [^]byte, } +Raw_Soa_Pointer :: struct { + data: rawptr, + index: int, +} + + /* // Defined internally by the compiler diff --git a/core/runtime/core_builtin.odin b/core/runtime/core_builtin.odin index 4f698a270..e3960088d 100644 --- a/core/runtime/core_builtin.odin +++ b/core/runtime/core_builtin.odin @@ -143,7 +143,7 @@ free_all :: proc{mem_free_all} @builtin delete_string :: proc(str: string, allocator := context.allocator, loc := #caller_location) -> Allocator_Error { - return mem_free(raw_data(str), allocator, loc) + return mem_free_with_size(raw_data(str), len(str), allocator, loc) } @builtin delete_cstring :: proc(str: cstring, allocator := context.allocator, loc := #caller_location) -> Allocator_Error { @@ -151,17 +151,24 @@ delete_cstring :: proc(str: cstring, allocator := context.allocator, loc := #cal } @builtin delete_dynamic_array :: proc(array: $T/[dynamic]$E, loc := #caller_location) -> Allocator_Error { - return mem_free(raw_data(array), array.allocator, loc) + return mem_free_with_size(raw_data(array), cap(array)*size_of(E), array.allocator, loc) } @builtin delete_slice :: proc(array: $T/[]$E, allocator := context.allocator, loc := #caller_location) -> Allocator_Error { - return mem_free(raw_data(array), allocator, loc) + return mem_free_with_size(raw_data(array), len(array)*size_of(E), allocator, loc) } @builtin delete_map :: proc(m: $T/map[$K]$V, loc := #caller_location) -> Allocator_Error { + Entry :: struct { + hash: uintptr, + next: int, + key: K, + value: V, + } + raw := transmute(Raw_Map)m err := delete_slice(raw.hashes, raw.entries.allocator, loc) - err1 := mem_free(raw.entries.data, raw.entries.allocator, loc) + err1 := mem_free_with_size(raw.entries.data, raw.entries.cap*size_of(Entry), raw.entries.allocator, loc) if err == nil { err = err1 } @@ -335,68 +342,80 @@ delete_key :: proc(m: ^$T/map[$K]$V, key: K) -> (deleted_key: K, deleted_value: @builtin -append_elem :: proc(array: ^$T/[dynamic]$E, arg: E, loc := #caller_location) { +append_elem :: proc(array: ^$T/[dynamic]$E, arg: E, loc := #caller_location) -> int { if array == nil { - return - } - - if cap(array) < len(array)+1 { - cap := 2 * cap(array) + max(8, 1) - _ = reserve(array, cap, loc) + return 0 } - if cap(array)-len(array) > 0 { - a := (^Raw_Dynamic_Array)(array) - when size_of(E) != 0 { - data := ([^]E)(a.data) - assert(condition=data != nil, loc=loc) - data[a.len] = arg + when size_of(E) == 0 { + array.len += 1 + return 1 + } else { + if cap(array) < len(array)+1 { + cap := 2 * cap(array) + max(8, 1) + _ = reserve(array, cap, loc) } - a.len += 1 + if cap(array)-len(array) > 0 { + a := (^Raw_Dynamic_Array)(array) + when size_of(E) != 0 { + data := ([^]E)(a.data) + assert(condition=data != nil, loc=loc) + data[a.len] = arg + } + a.len += 1 + return 1 + } + return 0 } } @builtin -append_elems :: proc(array: ^$T/[dynamic]$E, args: ..E, loc := #caller_location) { +append_elems :: proc(array: ^$T/[dynamic]$E, args: ..E, loc := #caller_location) -> int { if array == nil { - return + return 0 } arg_len := len(args) if arg_len <= 0 { - return + return 0 } - - if cap(array) < len(array)+arg_len { - cap := 2 * cap(array) + max(8, arg_len) - _ = reserve(array, cap, loc) - } - arg_len = min(cap(array)-len(array), arg_len) - if arg_len > 0 { - a := (^Raw_Dynamic_Array)(array) - when size_of(E) != 0 { - data := ([^]E)(a.data) - assert(condition=data != nil, loc=loc) - intrinsics.mem_copy(&data[a.len], raw_data(args), size_of(E) * arg_len) + when size_of(E) == 0 { + array.len += arg_len + return arg_len + } else { + if cap(array) < len(array)+arg_len { + cap := 2 * cap(array) + max(8, arg_len) + _ = reserve(array, cap, loc) } - a.len += arg_len + arg_len = min(cap(array)-len(array), arg_len) + if arg_len > 0 { + a := (^Raw_Dynamic_Array)(array) + when size_of(E) != 0 { + data := ([^]E)(a.data) + assert(condition=data != nil, loc=loc) + intrinsics.mem_copy(&data[a.len], raw_data(args), size_of(E) * arg_len) + } + a.len += arg_len + } + return arg_len } } // The append_string built-in procedure appends a string to the end of a [dynamic]u8 like type @builtin -append_elem_string :: proc(array: ^$T/[dynamic]$E/u8, arg: $A/string, loc := #caller_location) { +append_elem_string :: proc(array: ^$T/[dynamic]$E/u8, arg: $A/string, loc := #caller_location) -> int { args := transmute([]E)arg - append_elems(array=array, args=args, loc=loc) + return append_elems(array=array, args=args, loc=loc) } // The append_string built-in procedure appends multiple strings to the end of a [dynamic]u8 like type @builtin -append_string :: proc(array: ^$T/[dynamic]$E/u8, args: ..string, loc := #caller_location) { +append_string :: proc(array: ^$T/[dynamic]$E/u8, args: ..string, loc := #caller_location) -> (n: int) { for arg in args { - append(array = array, args = transmute([]E)(arg), loc = loc) + n += append(array = array, args = transmute([]E)(arg), loc = loc) } + return } // The append built-in procedure appends elements to the end of a dynamic array @@ -404,11 +423,13 @@ append_string :: proc(array: ^$T/[dynamic]$E/u8, args: ..string, loc := #caller_ @builtin -append_nothing :: proc(array: ^$T/[dynamic]$E, loc := #caller_location) { +append_nothing :: proc(array: ^$T/[dynamic]$E, loc := #caller_location) -> int { if array == nil { - return + return 0 } + prev_len := len(array) resize(array, len(array)+1) + return len(array)-prev_len } @@ -779,17 +800,3 @@ unimplemented :: proc(message := "", loc := #caller_location) -> ! { } p("not yet implemented", message, loc) } - -@builtin -@(disabled=ODIN_DISABLE_ASSERT) -unreachable :: proc(message := "", loc := #caller_location) -> ! { - p := context.assertion_failure_proc - if p == nil { - p = default_assertion_failure_proc - } - if message != "" { - p("internal error", message, loc) - } else { - p("internal error", "entered unreachable code", loc) - } -} diff --git a/core/runtime/dynamic_array_internal.odin b/core/runtime/dynamic_array_internal.odin index d39c2dd0b..b6a685fcf 100644 --- a/core/runtime/dynamic_array_internal.odin +++ b/core/runtime/dynamic_array_internal.odin @@ -29,11 +29,15 @@ __dynamic_array_reserve :: proc(array_: rawptr, elem_size, elem_align: int, cap: new_size := cap * elem_size allocator := array.allocator - new_data, err := allocator.procedure(allocator.data, .Resize, new_size, elem_align, array.data, old_size, loc) + new_data, err := mem_resize(array.data, old_size, new_size, elem_align, allocator, loc) if err != nil { return false } - if new_data != nil || elem_size == 0 { + if elem_size == 0 { + array.data = raw_data(new_data) + array.cap = cap + return true + } else if new_data != nil { array.data = raw_data(new_data) array.cap = min(cap, len(new_data)/elem_size) return true @@ -59,7 +63,7 @@ __dynamic_array_shrink :: proc(array_: rawptr, elem_size, elem_align: int, new_c new_size := new_cap * elem_size allocator := array.allocator - new_data, err := allocator.procedure(allocator.data, .Resize, new_size, elem_align, array.data, old_size, loc) + new_data, err := mem_resize(array.data, old_size, new_size, elem_align, allocator, loc) if err != nil { return } diff --git a/core/runtime/dynamic_map_internal.odin b/core/runtime/dynamic_map_internal.odin index fee0f570f..35b42d488 100644 --- a/core/runtime/dynamic_map_internal.odin +++ b/core/runtime/dynamic_map_internal.odin @@ -194,12 +194,15 @@ __slice_resize :: proc(array_: ^$T/[]$E, new_count: int, allocator: Allocator, l new_size := new_count*size_of(T) new_data, err := mem_resize(array.data, old_size, new_size, align_of(T), allocator, loc) - if new_data == nil || err != nil { + if err != nil { return false } - array.data = new_data - array.len = new_count - return true + if new_data != nil || size_of(E) == 0 { + array.data = raw_data(new_data) + array.len = new_count + return true + } + return false } __dynamic_map_reset_entries :: proc(using header: Map_Header, loc := #caller_location) { @@ -207,7 +210,7 @@ __dynamic_map_reset_entries :: proc(using header: Map_Header, loc := #caller_loc m.hashes[i] = -1 } - for i in 0 ..< m.entries.len { + for i in 0..<m.entries.len { entry_header := __dynamic_map_get_entry(header, i) entry_hash := __get_map_hash_from_entry(header, entry_header) entry_header.next = -1 diff --git a/core/runtime/internal.odin b/core/runtime/internal.odin index 30798f623..048bff7ca 100644 --- a/core/runtime/internal.odin +++ b/core/runtime/internal.odin @@ -103,7 +103,7 @@ mem_zero :: proc "contextless" (data: rawptr, len: int) -> rawptr { if data == nil { return nil } - if len < 0 { + if len <= 0 { return data } intrinsics.mem_zero(data, len) @@ -111,22 +111,18 @@ mem_zero :: proc "contextless" (data: rawptr, len: int) -> rawptr { } mem_copy :: proc "contextless" (dst, src: rawptr, len: int) -> rawptr { - if src == nil { - return dst + if src != nil && dst != src && len > 0 { + // NOTE(bill): This _must_ be implemented like C's memmove + intrinsics.mem_copy(dst, src, len) } - - // NOTE(bill): This _must_ be implemented like C's memmove - intrinsics.mem_copy(dst, src, len) return dst } mem_copy_non_overlapping :: proc "contextless" (dst, src: rawptr, len: int) -> rawptr { - if src == nil { - return dst + if src != nil && dst != src && len > 0 { + // NOTE(bill): This _must_ be implemented like C's memcpy + intrinsics.mem_copy_non_overlapping(dst, src, len) } - - // NOTE(bill): This _must_ be implemented like C's memcpy - intrinsics.mem_copy_non_overlapping(dst, src, len) return dst } @@ -142,28 +138,38 @@ mem_alloc_bytes :: #force_inline proc(size: int, alignment: int = DEFAULT_ALIGNM return allocator.procedure(allocator.data, .Alloc, size, alignment, nil, 0, loc) } -mem_alloc :: #force_inline proc(size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> (rawptr, Allocator_Error) { - if size == 0 { +mem_alloc :: #force_inline proc(size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> ([]byte, Allocator_Error) { + if size == 0 || allocator.procedure == nil { return nil, nil } - if allocator.procedure == nil { - return nil, nil - } - data, err := allocator.procedure(allocator.data, .Alloc, size, alignment, nil, 0, loc) - return raw_data(data), err + return allocator.procedure(allocator.data, .Alloc, size, alignment, nil, 0, loc) } mem_free :: #force_inline proc(ptr: rawptr, allocator := context.allocator, loc := #caller_location) -> Allocator_Error { - if ptr == nil { - return .None - } - if allocator.procedure == nil { - return .None + if ptr == nil || allocator.procedure == nil { + return nil } _, err := allocator.procedure(allocator.data, .Free, 0, 0, ptr, 0, loc) return err } +mem_free_with_size :: #force_inline proc(ptr: rawptr, byte_count: int, allocator := context.allocator, loc := #caller_location) -> Allocator_Error { + if ptr == nil || allocator.procedure == nil { + return nil + } + _, err := allocator.procedure(allocator.data, .Free, 0, 0, ptr, byte_count, loc) + return err +} + +mem_free_bytes :: #force_inline proc(bytes: []byte, allocator := context.allocator, loc := #caller_location) -> Allocator_Error { + if bytes == nil || allocator.procedure == nil { + return nil + } + _, err := allocator.procedure(allocator.data, .Free, 0, 0, raw_data(bytes), len(bytes), loc) + return err +} + + mem_free_all :: #force_inline proc(allocator := context.allocator, loc := #caller_location) -> (err: Allocator_Error) { if allocator.procedure != nil { _, err = allocator.procedure(allocator.data, .Free_All, 0, 0, nil, 0, loc) @@ -171,21 +177,34 @@ mem_free_all :: #force_inline proc(allocator := context.allocator, loc := #calle return } -mem_resize :: #force_inline proc(ptr: rawptr, old_size, new_size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> (new_ptr: rawptr, err: Allocator_Error) { - new_data: []byte - switch { - case allocator.procedure == nil: - return - case new_size == 0: - new_data, err = allocator.procedure(allocator.data, .Free, 0, 0, ptr, 0, loc) - case ptr == nil: - new_data, err = allocator.procedure(allocator.data, .Alloc, new_size, alignment, nil, 0, loc) - case: - new_data, err = allocator.procedure(allocator.data, .Resize, new_size, alignment, ptr, old_size, loc) - } - new_ptr = raw_data(new_data) - return +mem_resize :: proc(ptr: rawptr, old_size, new_size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> ([]byte, Allocator_Error) { + if allocator.procedure == nil { + return nil, nil + } + if new_size == 0 { + if ptr != nil { + _, err := allocator.procedure(allocator.data, .Free, 0, 0, ptr, old_size, loc) + return nil, err + } + return nil, nil + } else if ptr == nil { + return allocator.procedure(allocator.data, .Alloc, new_size, alignment, nil, 0, loc) + } else if old_size == new_size && uintptr(ptr) % uintptr(alignment) == 0 { + return ([^]byte)(ptr)[:old_size], nil + } + + data, err := allocator.procedure(allocator.data, .Resize, new_size, alignment, ptr, old_size, loc) + if err == .Mode_Not_Implemented { + data, err = allocator.procedure(allocator.data, .Alloc, new_size, alignment, nil, 0, loc) + if err != nil { + return data, err + } + copy(data, ([^]byte)(ptr)[:old_size]) + _, err = allocator.procedure(allocator.data, .Free, 0, 0, ptr, old_size, loc) + } + return data, err } + memory_equal :: proc "contextless" (x, y: rawptr, n: int) -> bool { switch { case n == 0: return true @@ -341,7 +360,12 @@ string_eq :: proc "contextless" (lhs, rhs: string) -> bool { string_cmp :: proc "contextless" (a, b: string) -> int { x := transmute(Raw_String)a y := transmute(Raw_String)b - return memory_compare(x.data, y.data, min(x.len, y.len)) + + ret := memory_compare(x.data, y.data, min(x.len, y.len)) + if ret == 0 && x.len != y.len { + return -1 if x.len < y.len else +1 + } + return ret } string_ne :: #force_inline proc "contextless" (a, b: string) -> bool { return !string_eq(a, b) } diff --git a/core/runtime/print.odin b/core/runtime/print.odin index 89c196fc2..959dad3a9 100644 --- a/core/runtime/print.odin +++ b/core/runtime/print.odin @@ -228,6 +228,9 @@ print_type :: proc "contextless" (ti: ^Type_Info) { case Type_Info_Multi_Pointer: print_string("[^]") print_type(info.elem) + case Type_Info_Soa_Pointer: + print_string("#soa ^") + print_type(info.elem) case Type_Info_Procedure: print_string("proc") if info.params == nil { diff --git a/core/runtime/procs.odin b/core/runtime/procs.odin index 782efa773..510abcbb9 100644 --- a/core/runtime/procs.odin +++ b/core/runtime/procs.odin @@ -6,7 +6,7 @@ when ODIN_NO_CRT && ODIN_OS == .Windows { @(private="file") @(default_calling_convention="stdcall") foreign lib { - RtlMoveMemory :: proc(dst, src: rawptr, length: int) --- + RtlMoveMemory :: proc(dst, s: rawptr, length: int) --- RtlFillMemory :: proc(dst: rawptr, length: int, fill: i32) --- } @@ -40,24 +40,34 @@ when ODIN_NO_CRT && ODIN_OS == .Windows { @(link_name="memmove", linkage="strong", require) memmove :: proc "c" (dst, src: rawptr, len: int) -> rawptr { - if dst != src { - d, s := ([^]byte)(dst), ([^]byte)(src) + d, s := ([^]byte)(dst), ([^]byte)(src) + if d == s || len == 0 { + return dst + } + if d > s && uintptr(d)-uintptr(s) < uintptr(len) { for i := len-1; i >= 0; i -= 1 { d[i] = s[i] } + return dst } - return dst - + + if s > d && uintptr(s)-uintptr(d) < uintptr(len) { + for i := 0; i < len; i += 1 { + d[i] = s[i] + } + return dst + } + return memcpy(dst, src, len) } @(link_name="memcpy", linkage="strong", require) memcpy :: proc "c" (dst, src: rawptr, len: int) -> rawptr { - if dst != src { - d, s := ([^]byte)(dst), ([^]byte)(src) - for i := len-1; i >= 0; i -= 1 { + d, s := ([^]byte)(dst), ([^]byte)(src) + if d != s { + for i := 0; i < len; i += 1 { d[i] = s[i] } } - return dst + return d } } else { |