aboutsummaryrefslogtreecommitdiff
path: root/core/runtime
diff options
context:
space:
mode:
Diffstat (limited to 'core/runtime')
-rw-r--r--core/runtime/core.odin10
-rw-r--r--core/runtime/core_builtin.odin115
-rw-r--r--core/runtime/dynamic_array_internal.odin10
-rw-r--r--core/runtime/dynamic_map_internal.odin13
-rw-r--r--core/runtime/internal.odin100
-rw-r--r--core/runtime/print.odin3
-rw-r--r--core/runtime/procs.odin28
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 {