diff --git a/core/hash/hash.odin b/core/hash/hash.odin index 87274e8e1..391fc09f7 100644 --- a/core/hash/hash.odin +++ b/core/hash/hash.odin @@ -71,7 +71,7 @@ murmur32 :: proc(data: []byte) -> u32 { h1: u32 = 0; nblocks := len(data)/4; - p := &data[0]; + p := raw_data(data); p1 := mem.ptr_offset(p, 4*nblocks); for ; p < p1; p = mem.ptr_offset(p, 4) { @@ -122,7 +122,7 @@ murmur64 :: proc(data: []byte) -> u64 { r :: 47; h: u64 = SEED ~ (u64(len(data)) * m); - data64 := mem.slice_ptr(cast(^u64)&data[0], len(data)/size_of(u64)); + data64 := mem.slice_ptr(cast(^u64)raw_data(data), len(data)/size_of(u64)); for _, i in data64 { k := data64[i]; @@ -158,7 +158,7 @@ murmur64 :: proc(data: []byte) -> u64 { h1 := u32(SEED) ~ u32(len(data)); h2 := u32(SEED) >> 32; - data32 := mem.slice_ptr(cast(^u32)&data[0], len(data)/size_of(u32)); + data32 := mem.slice_ptr(cast(^u32)raw_data(data), len(data)/size_of(u32)); len := len(data); i := 0; diff --git a/core/math/linalg/general.odin b/core/math/linalg/general.odin index c7b455781..05bfb6697 100644 --- a/core/math/linalg/general.odin +++ b/core/math/linalg/general.odin @@ -392,10 +392,10 @@ mul :: proc{ quaternion256_mul_vector3, }; -vector_to_ptr :: proc(v: ^$V/[$N]$E) -> ^E where IS_NUMERIC(E) { +vector_to_ptr :: proc(v: ^$V/[$N]$E) -> ^E where IS_NUMERIC(E), N > 0 #no_bounds_check { return &v[0]; } -matrix_to_ptr :: proc(m: ^$A/[$I][$J]$E) -> ^E where IS_NUMERIC(E) { +matrix_to_ptr :: proc(m: ^$A/[$I][$J]$E) -> ^E where IS_NUMERIC(E), I > 0, J > 0 #no_bounds_check { return &m[0][0]; } diff --git a/core/mem/allocators.odin b/core/mem/allocators.odin index 805f5728d..9b31df818 100644 --- a/core/mem/allocators.odin +++ b/core/mem/allocators.odin @@ -247,7 +247,7 @@ stack_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, } raw_alloc :: proc(s: ^Stack, size, alignment: int) -> rawptr { - curr_addr := uintptr(&s.data[0]) + uintptr(s.curr_offset); + curr_addr := uintptr(raw_data(s.data)) + uintptr(s.curr_offset); padding := calc_padding_with_header(curr_addr, uintptr(alignment), size_of(Stack_Allocation_Header)); if s.curr_offset + padding + size > len(s.data) { return nil; @@ -274,7 +274,7 @@ stack_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, if old_memory == nil { return nil; } - start := uintptr(&s.data[0]); + start := uintptr(raw_data(s.data)); end := start + uintptr(len(s.data)); curr_addr := uintptr(old_memory); @@ -288,7 +288,7 @@ stack_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, } header := (^Stack_Allocation_Header)(curr_addr - size_of(Stack_Allocation_Header)); - old_offset := int(curr_addr - uintptr(header.padding) - uintptr(&s.data[0])); + old_offset := int(curr_addr - uintptr(header.padding) - uintptr(raw_data(s.data))); if old_offset != int(header.prev_offset) { panic("Out of order stack allocator free"); @@ -310,7 +310,7 @@ stack_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, return nil; } - start := uintptr(&s.data[0]); + start := uintptr(raw_data(s.data)); end := start + uintptr(len(s.data)); curr_addr := uintptr(old_memory); if !(start <= curr_addr && curr_addr < end) { @@ -327,7 +327,7 @@ stack_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, } header := (^Stack_Allocation_Header)(curr_addr - size_of(Stack_Allocation_Header)); - old_offset := int(curr_addr - uintptr(header.padding) - uintptr(&s.data[0])); + old_offset := int(curr_addr - uintptr(header.padding) - uintptr(raw_data(s.data))); if old_offset != int(header.prev_offset) { ptr := raw_alloc(s, size, alignment); @@ -392,7 +392,7 @@ small_stack_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, align := clamp(alignment, 1, 8*size_of(Stack_Allocation_Header{}.padding)/2); raw_alloc :: proc(s: ^Small_Stack, size, alignment: int) -> rawptr { - curr_addr := uintptr(&s.data[0]) + uintptr(s.offset); + curr_addr := uintptr(raw_data(s.data)) + uintptr(s.offset); padding := calc_padding_with_header(curr_addr, uintptr(alignment), size_of(Small_Stack_Allocation_Header)); if s.offset + padding + size > len(s.data) { return nil; @@ -417,7 +417,7 @@ small_stack_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, if old_memory == nil { return nil; } - start := uintptr(&s.data[0]); + start := uintptr(raw_data(s.data)); end := start + uintptr(len(s.data)); curr_addr := uintptr(old_memory); @@ -431,7 +431,7 @@ small_stack_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, } header := (^Small_Stack_Allocation_Header)(curr_addr - size_of(Small_Stack_Allocation_Header)); - old_offset := int(curr_addr - uintptr(header.padding) - uintptr(&s.data[0])); + old_offset := int(curr_addr - uintptr(header.padding) - uintptr(raw_data(s.data))); s.offset = int(old_offset); @@ -446,7 +446,7 @@ small_stack_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, return nil; } - start := uintptr(&s.data[0]); + start := uintptr(raw_data(s.data)); end := start + uintptr(len(s.data)); curr_addr := uintptr(old_memory); if !(start <= curr_addr && curr_addr < end) { diff --git a/core/mem/mem.odin b/core/mem/mem.odin index b67616ca2..fc15d2c47 100644 --- a/core/mem/mem.odin +++ b/core/mem/mem.odin @@ -13,9 +13,7 @@ zero_item :: inline proc(item: $P/^$T) { set(item, 0, size_of(T)); } zero_slice :: proc(data: $T/[]$E) { - if n := len(data); n > 0 { - zero(&data[0], size_of(E)*n); - } + zero(raw_data(data), size_of(E)*n); } @@ -26,9 +24,7 @@ copy_non_overlapping :: proc(dst, src: rawptr, len: int) -> rawptr { return runtime.mem_copy_non_overlapping(dst, src, len); } compare :: inline proc(a, b: []byte) -> int { - // NOTE(tetra): no-abc is okay here because if the slices are empty, `&a[0]` is just nil+0 == nil, which - // compare_byte_ptrs handles fine when the passed length is also zero. - res := #no_bounds_check compare_byte_ptrs(&a[0], &b[0], min(len(a), len(b))); + res := compare_byte_ptrs(raw_data(a), raw_data(b), min(len(a), len(b))); if res == 0 && len(a) != len(b) { return len(a) <= len(b) ? -1 : +1; } else if len(a) == 0 && len(b) == 0 { @@ -38,6 +34,17 @@ compare :: inline proc(a, b: []byte) -> int { } compare_byte_ptrs :: proc(a, b: ^byte, n: int) -> int #no_bounds_check { + switch { + case a == b: + return 0; + case a == nil: + return -1; + case b == nil: + return -1; + case n == 0: + return 0; + } + x := slice_ptr(a, n); y := slice_ptr(b, n); @@ -121,11 +128,10 @@ slice_to_components :: proc(slice: $E/[]$T) -> (data: ^T, len: int) { } buffer_from_slice :: inline proc(backing: $T/[]$E) -> [dynamic]E { - s := transmute(Raw_Slice)backing; return transmute([dynamic]E)Raw_Dynamic_Array{ - data = s.data, + data = raw_data(s), len = 0, - cap = s.len, + cap = len(s), allocator = nil_allocator(), }; } diff --git a/core/mem/raw.odin b/core/mem/raw.odin index 97cd71e7a..2551122f5 100644 --- a/core/mem/raw.odin +++ b/core/mem/raw.odin @@ -42,6 +42,9 @@ make_any :: inline proc(data: rawptr, id: typeid) -> any { return transmute(any)Raw_Any{data, id}; } +raw_array_data :: proc(a: $P/^($T/[$N]$E)) -> ^E { + return (^E)(a); +} raw_string_data :: inline proc(s: $T/string) -> ^byte { return (transmute(Raw_String)s).data; } @@ -52,6 +55,6 @@ raw_dynamic_array_data :: inline proc(a: $T/[dynamic]$E) -> ^E { return cast(^E)(transmute(Raw_Dynamic_Array)a).data; } -raw_data :: proc{raw_string_data, raw_slice_data, raw_dynamic_array_data}; +raw_data :: proc{raw_array_data, raw_string_data, raw_slice_data, raw_dynamic_array_data}; diff --git a/core/os/os_darwin.odin b/core/os/os_darwin.odin index d3ad5bf66..f9380f11f 100644 --- a/core/os/os_darwin.odin +++ b/core/os/os_darwin.odin @@ -317,7 +317,7 @@ write :: proc(fd: Handle, data: []u8) -> (int, Errno) { if len(data) == 0 { return 0, 0; } - bytes_written := _unix_write(fd, &data[0], len(data)); + bytes_written := _unix_write(fd, raw_data(data), len(data)); if(bytes_written == -1) { return 0, 1; } @@ -327,7 +327,7 @@ write :: proc(fd: Handle, data: []u8) -> (int, Errno) { read :: proc(fd: Handle, data: []u8) -> (int, Errno) { assert(fd != -1); - bytes_read := _unix_read(fd, &data[0], len(data)); + bytes_read := _unix_read(fd, raw_data(data), len(data)); if bytes_read == -1 { return 0, 1; } @@ -406,7 +406,7 @@ get_current_directory :: proc() -> string { page_size := get_page_size(); // NOTE(tetra): See note in os_linux.odin/get_current_directory. buf := make([dynamic]u8, page_size); for { - cwd := _unix_getcwd(cstring(#no_bounds_check &buf[0]), c.size_t(len(buf))); + cwd := _unix_getcwd(cstring(raw_data(buf)), c.size_t(len(buf))); if cwd != nil { return string(cwd); } diff --git a/core/os/os_windows.odin b/core/os/os_windows.odin index aa2ae88b4..9b1be3493 100644 --- a/core/os/os_windows.odin +++ b/core/os/os_windows.odin @@ -322,7 +322,7 @@ _alloc_command_line_arguments :: proc() -> []string { buf := make([]byte, int(olen)); n := win32.WideCharToMultiByte(win32.CP_UTF8, 0, wc_str, -1, - &buf[0], olen, nil, nil); + raw_data(buf), olen, nil, nil); if n > 0 { n -= 1; } diff --git a/core/runtime/core.odin b/core/runtime/core.odin index 5f4ecc7fc..dcee6f4c7 100644 --- a/core/runtime/core.odin +++ b/core/runtime/core.odin @@ -510,16 +510,16 @@ default_assertion_failure_proc :: proc(prefix, message: string, loc: Source_Code @builtin copy_slice :: proc "contextless" (dst, src: $T/[]$E) -> int { n := max(0, min(len(dst), len(src))); - #no_bounds_check if n > 0 do mem_copy(&dst[0], &src[0], n*size_of(E)); + if n > 0 { + mem_copy(raw_data(dst), raw_data(src), n*size_of(E)); + } return n; } @builtin copy_from_string :: proc "contextless" (dst: $T/[]$E/u8, src: $S/string) -> int { n := max(0, min(len(dst), len(src))); if n > 0 { - d := (transmute(Raw_Slice)dst).data; - s := (transmute(Raw_String)src).data; - mem_copy(d, s, n); + mem_copy(raw_data(dst), raw_data(src), n); } return n; } @@ -615,7 +615,7 @@ free_all :: proc{mem_free_all}; @builtin delete_string :: proc(str: string, allocator := context.allocator, loc := #caller_location) { - mem_free((transmute(Raw_String)str).data, allocator, loc); + mem_free(raw_data(str), allocator, loc); } @builtin delete_cstring :: proc(str: cstring, allocator := context.allocator, loc := #caller_location) { @@ -623,11 +623,11 @@ delete_cstring :: proc(str: cstring, allocator := context.allocator, loc := #cal } @builtin delete_dynamic_array :: proc(array: $T/[dynamic]$E, loc := #caller_location) { - mem_free((transmute(Raw_Dynamic_Array)array).data, array.allocator, loc); + mem_free(raw_data(array), array.allocator, loc); } @builtin delete_slice :: proc(array: $T/[]$E, allocator := context.allocator, loc := #caller_location) { - mem_free((transmute(Raw_Slice)array).data, allocator, loc); + mem_free(raw_data(array), allocator, loc); } @builtin delete_map :: proc(m: $T/map[$K]$V, loc := #caller_location) { @@ -1114,6 +1114,9 @@ card :: proc(s: $S/bit_set[$E; $U]) -> int { } else when size_of(S) == 8 { foreign { @(link_name="llvm.ctpop.i64") count_ones :: proc(i: u64) -> u64 --- } return int(count_ones(transmute(u64)s)); + } else when size_of(S) == 16 { + foreign { @(link_name="llvm.ctpop.i128") count_ones :: proc(i: u128) -> u128 --- } + return int(count_ones(transmute(u128)s)); } else { #assert(false); return 0; @@ -1122,6 +1125,27 @@ card :: proc(s: $S/bit_set[$E; $U]) -> int { +@builtin +raw_array_data :: proc(a: $P/^($T/[$N]$E)) -> ^E { + return (^E)(a); +} +@builtin +raw_slice_data :: proc(s: $S/[]$E) -> ^E { + ptr := (transmute(Raw_Slice)s).data; + return (^E)(ptr); +} +@builtin +raw_dynamic_array_data :: proc(s: $S/[dynamic]$E) -> ^E { + ptr := (transmute(Raw_Dynamic_Array)s).data; + return (^E)(ptr); +} +@builtin +raw_string_data :: proc(s: $S/string) -> ^u8 { + return (transmute(Raw_String)s).data; +} + +@builtin +raw_data :: proc{raw_array_data, raw_slice_data, raw_dynamic_array_data, raw_string_data}; diff --git a/core/runtime/procs_unix.odin b/core/runtime/procs_unix.odin index 9ad3cdb21..14d1d5692 100644 --- a/core/runtime/procs_unix.odin +++ b/core/runtime/procs_unix.odin @@ -3,6 +3,9 @@ package runtime @(link_name="memset") memset :: proc "c" (ptr: rawptr, val: i32, len: int) -> rawptr { + if ptr == nil || len == 0 { + return ptr; + } b := byte(val); p_start := uintptr(ptr); diff --git a/core/runtime/procs_wasm32.odin b/core/runtime/procs_wasm32.odin index 689c1ba77..79197d85b 100644 --- a/core/runtime/procs_wasm32.odin +++ b/core/runtime/procs_wasm32.odin @@ -2,6 +2,9 @@ package runtime @(link_name="memset") memset :: proc "c" (ptr: rawptr, val: i32, len: int) -> rawptr { + if ptr == nil || len == 0 { + return ptr; + } b := byte(val); p_start := uintptr(ptr); diff --git a/core/runtime/procs_windows_386.odin b/core/runtime/procs_windows_386.odin index b2597ad67..d484addb8 100644 --- a/core/runtime/procs_windows_386.odin +++ b/core/runtime/procs_windows_386.odin @@ -15,6 +15,9 @@ memcpy :: proc "c" (dst, src: rawptr, len: int) -> rawptr { foreign kernel32 { RtlCopyMemory :: proc "c" (dst, src: rawptr, len: int) --- } + if dst == nil || src == nil || len == 0 { + return dst; + } RtlCopyMemory(dst, src, len); return dst; } @@ -24,12 +27,18 @@ memmove :: proc "c" (dst, src: rawptr, len: int) -> rawptr { foreign kernel32 { RtlMoveMemory :: proc "c" (dst, src: rawptr, len: int) --- } + if dst == nil || src == nil || len == 0 { + return dst; + } RtlMoveMemory(dst, src, len); return dst; } @(link_name="memset") memset :: proc "c" (ptr: rawptr, val: i32, len: int) -> rawptr { + if ptr == nil || len == 0 { + return ptr; + } d := uintptr(ptr); b := byte(val); for i in 0.. rawptr { foreign kernel32 { RtlCopyMemory :: proc "c" (dst, src: rawptr, len: int) --- } + if dst == nil || src == nil || len == 0 { + return dst; + } RtlCopyMemory(dst, src, len); return dst; } @@ -41,12 +44,19 @@ memmove :: proc "c" (dst, src: rawptr, len: int) -> rawptr { foreign kernel32 { RtlMoveMemory :: proc "c" (dst, src: rawptr, len: int) --- } + if dst == nil || src == nil || len == 0 { + return dst; + } RtlMoveMemory(dst, src, len); return dst; } // @(link_name="memset") memset :: proc "c" (ptr: rawptr, val: i32, len: int) -> rawptr { + if ptr == nil || len == 0 { + return ptr; + } + b := byte(val); p_start := uintptr(ptr); diff --git a/core/sync/channel.odin b/core/sync/channel.odin index ae9a196c5..be8a96f47 100644 --- a/core/sync/channel.odin +++ b/core/sync/channel.odin @@ -6,6 +6,39 @@ import "core:math/rand" _, _ :: time, rand; +chan :: struct(T: typeid) { + qlen: uint, + qcap: uint, + closed: b32, + sendx: uint, + recvx: uint, + mutex: Blocking_Mutex, + allocator: mem.Allocator, + + buf: [0]T, +} + +makechan :: proc($T: typeid, cap: int, allocator := context.allocator) -> ^chan(T) { + chan_size :: size_of(chan(T)); + chan_align :: align_of(chan(T)); + + mem := uintptr(cap) * size_of(T); + c := cast(^chan(T))mem.alloc(chan_size+mem, chan_align, allocator); + c.allocator = allocator; + c.qlen = 0; + c.qcap = uint(cap); + blocking_mutex_init(&c.mutex); + return c; +} +chanbuf :: proc(c: ^$C/chan($T)) -> []T #no_bounds_check { + return c.buf[0:c.qcap]; +} + + + + +/* + Channel :: struct(T: typeid) { using internal: ^_Channel_Internal(T), } @@ -255,3 +288,4 @@ channel_select_read :: proc(readers: []$C/Channel($T)) -> (index: int) { _, index = channel_select(readers, []C{}, nil); return; } +*/ diff --git a/core/thread/thread_pool.odin b/core/thread/thread_pool.odin index 8b6b15ece..64cd8ea38 100644 --- a/core/thread/thread_pool.odin +++ b/core/thread/thread_pool.odin @@ -116,9 +116,8 @@ pool_try_and_pop_task :: proc(pool: ^Pool) -> (task: Task, got_task: bool = fals if sync.mutex_try_lock(&pool.mutex) { if len(pool.tasks) != 0 { intrinsics.atomic_add(&pool.processing_task_count, 1); - task = pool.tasks[0]; + task = pop_front(&pool.tasks); got_task = true; - ordered_remove(&pool.tasks, 0); } sync.mutex_unlock(&pool.mutex); } diff --git a/core/time/time_unix.odin b/core/time/time_unix.odin index 28a6d6a9f..780d211ab 100644 --- a/core/time/time_unix.odin +++ b/core/time/time_unix.odin @@ -77,4 +77,4 @@ nanosleep :: proc(nanoseconds: i64) -> int { requested := TimeSpec{tv_nsec = nanoseconds}; remaining: TimeSpec; // NOTE(tetra): Do we need to initialize this? return int(_unix_nanosleep(&requested, &remaining)); -} \ No newline at end of file +}