mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-03 22:28:46 +00:00
Merge tag 'dev-2025-11'
This commit is contained in:
@@ -244,6 +244,11 @@ constant_utf16_cstring :: proc($literal: string) -> [^]u16 ---
|
||||
|
||||
constant_log2 :: proc($v: $T) -> T where type_is_integer(T) ---
|
||||
|
||||
constant_floor :: proc($v: $T) -> T where type_is_integer(T) || type_is_float(T) ---
|
||||
constant_trunc :: proc($v: $T) -> T where type_is_integer(T) || type_is_float(T) ---
|
||||
constant_ceil :: proc($v: $T) -> T where type_is_integer(T) || type_is_float(T) ---
|
||||
constant_round :: proc($v: $T) -> T where type_is_integer(T) || type_is_float(T) ---
|
||||
|
||||
// SIMD related
|
||||
simd_add :: proc(a, b: #simd[N]T) -> #simd[N]T ---
|
||||
simd_sub :: proc(a, b: #simd[N]T) -> #simd[N]T ---
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
//
|
||||
// IMPORTANT NOTE(bill): `type_info_of` cannot be used within a
|
||||
// #shared_global_scope due to the internals of the compiler.
|
||||
// This could change at a later date if the all these data structures are
|
||||
// This could change at a later date if all these data structures are
|
||||
// implemented within the compiler rather than in this "preload" file
|
||||
//
|
||||
#+no-instrumentation
|
||||
|
||||
@@ -504,6 +504,121 @@ append_soa :: proc{
|
||||
}
|
||||
|
||||
|
||||
// `append_nothing_soa` appends an empty value to a dynamic SOA array. It returns `1, nil` if successful, and `0, err` when it was not possible,
|
||||
// whatever `err` happens to be.
|
||||
@builtin
|
||||
append_nothing_soa :: proc(array: ^$T/#soa[dynamic]$E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_allocator_error {
|
||||
if array == nil {
|
||||
return 0, nil
|
||||
}
|
||||
prev_len := len(array)
|
||||
resize_soa(array, len(array)+1, loc) or_return
|
||||
return len(array)-prev_len, nil
|
||||
}
|
||||
|
||||
|
||||
// `inject_at_elem_soa` injects an element in a dynamic SOA array at a specified index and moves the previous elements after that index "across"
|
||||
@builtin
|
||||
inject_at_elem_soa :: proc(array: ^$T/#soa[dynamic]$E, #any_int index: int, #no_broadcast arg: E, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error {
|
||||
when !ODIN_NO_BOUNDS_CHECK {
|
||||
ensure(index >= 0, "Index must be positive.", loc)
|
||||
}
|
||||
if array == nil {
|
||||
return
|
||||
}
|
||||
n := max(len(array), index)
|
||||
m :: 1
|
||||
new_len := n + m
|
||||
|
||||
resize_soa(array, new_len, loc) or_return
|
||||
|
||||
when size_of(E) != 0 {
|
||||
ti := type_info_base(type_info_of(typeid_of(T)))
|
||||
si := &ti.variant.(Type_Info_Struct)
|
||||
|
||||
field_count := len(E) when intrinsics.type_is_array(E) else intrinsics.type_struct_field_count(E)
|
||||
|
||||
item_offset := 0
|
||||
|
||||
arg_copy := arg
|
||||
arg_ptr := &arg_copy
|
||||
|
||||
for i in 0..<field_count {
|
||||
data := (^uintptr)(uintptr(array) + uintptr(si.offsets[i]))^
|
||||
type := si.types[i].variant.(Type_Info_Multi_Pointer).elem
|
||||
item_offset = align_forward_int(item_offset, type.align)
|
||||
|
||||
src := data + uintptr(index * type.size)
|
||||
dst := data + uintptr((index + m) * type.size)
|
||||
mem_copy(rawptr(dst), rawptr(src), (n - index) * type.size)
|
||||
|
||||
mem_copy(rawptr(src), rawptr(uintptr(arg_ptr) + uintptr(item_offset)), type.size)
|
||||
|
||||
item_offset += type.size
|
||||
}
|
||||
}
|
||||
|
||||
ok = true
|
||||
return
|
||||
}
|
||||
|
||||
// `inject_at_elems_soa` injects multiple elements in a dynamic SOA array at a specified index and moves the previous elements after that index "across"
|
||||
@builtin
|
||||
inject_at_elems_soa :: proc(array: ^$T/#soa[dynamic]$E, #any_int index: int, #no_broadcast args: ..E, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #no_bounds_check #optional_allocator_error {
|
||||
when !ODIN_NO_BOUNDS_CHECK {
|
||||
ensure(index >= 0, "Index must be positive.", loc)
|
||||
}
|
||||
if array == nil {
|
||||
return
|
||||
}
|
||||
if len(args) == 0 {
|
||||
ok = true
|
||||
return
|
||||
}
|
||||
|
||||
n := max(len(array), index)
|
||||
m := len(args)
|
||||
new_len := n + m
|
||||
|
||||
resize_soa(array, new_len, loc) or_return
|
||||
|
||||
when size_of(E) != 0 {
|
||||
ti := type_info_base(type_info_of(typeid_of(T)))
|
||||
si := &ti.variant.(Type_Info_Struct)
|
||||
|
||||
field_count := len(E) when intrinsics.type_is_array(E) else intrinsics.type_struct_field_count(E)
|
||||
|
||||
item_offset := 0
|
||||
|
||||
args_ptr := &args[0]
|
||||
|
||||
for i in 0..<field_count {
|
||||
data := (^uintptr)(uintptr(array) + uintptr(si.offsets[i]))^
|
||||
type := si.types[i].variant.(Type_Info_Multi_Pointer).elem
|
||||
item_offset = align_forward_int(item_offset, type.align)
|
||||
|
||||
src := data + uintptr(index * type.size)
|
||||
dst := data + uintptr((index + m) * type.size)
|
||||
mem_copy(rawptr(dst), rawptr(src), (n - index) * type.size)
|
||||
|
||||
for j in 0..<len(args) {
|
||||
d := rawptr(src + uintptr(j*type.size))
|
||||
s := rawptr(uintptr(args_ptr) + uintptr(item_offset) + uintptr(j*size_of(E)))
|
||||
mem_copy(d, s, type.size)
|
||||
}
|
||||
|
||||
item_offset += type.size
|
||||
}
|
||||
}
|
||||
|
||||
ok = true
|
||||
return
|
||||
}
|
||||
|
||||
// `inject_at_soa` injects something into a dynamic SOA array at a specified index and moves the previous elements after that index "across"
|
||||
@builtin inject_at_soa :: proc{inject_at_elem_soa, inject_at_elems_soa}
|
||||
|
||||
|
||||
delete_soa_slice :: proc(array: $T/#soa[]$E, allocator := context.allocator, loc := #caller_location) -> Allocator_Error {
|
||||
field_count :: len(E) when intrinsics.type_is_array(E) else intrinsics.type_struct_field_count(E)
|
||||
when field_count != 0 {
|
||||
|
||||
@@ -6,8 +6,6 @@ _ :: intrinsics
|
||||
// High performance, cache-friendly, open-addressed Robin Hood hashing hash map
|
||||
// data structure with various optimizations for Odin.
|
||||
//
|
||||
// Copyright 2022 (c) Dale Weiler
|
||||
//
|
||||
// The core of the hash map data structure is the Raw_Map struct which is a
|
||||
// type-erased representation of the map. This type-erased representation is
|
||||
// used in two ways: static and dynamic. When static type information is known,
|
||||
|
||||
@@ -5,3 +5,7 @@ _OS_Errno :: distinct int
|
||||
stderr_write :: proc "contextless" (data: []byte) -> (int, _OS_Errno) {
|
||||
return _stderr_write(data)
|
||||
}
|
||||
|
||||
exit :: proc "contextless" (code: int) -> ! {
|
||||
_exit(code)
|
||||
}
|
||||
@@ -24,3 +24,11 @@ _stderr_write :: proc "contextless" (data: []byte) -> (int, _OS_Errno) {
|
||||
}
|
||||
return int(ret), 0
|
||||
}
|
||||
|
||||
_exit :: proc "contextless" (code: int) -> ! {
|
||||
@(default_calling_convention="c")
|
||||
foreign libc {
|
||||
exit :: proc(status: i32) -> ! ---
|
||||
}
|
||||
exit(i32(code))
|
||||
}
|
||||
@@ -26,3 +26,13 @@ _stderr_write :: proc "contextless" (data: []byte) -> (int, _OS_Errno) {
|
||||
return 0, _OS_Errno(__error()^)
|
||||
}
|
||||
}
|
||||
|
||||
foreign import libc "system:System"
|
||||
|
||||
_exit :: proc "contextless" (code: int) -> ! {
|
||||
@(default_calling_convention="c")
|
||||
foreign libc {
|
||||
exit :: proc(status: i32) -> ! ---
|
||||
}
|
||||
exit(i32(code))
|
||||
}
|
||||
@@ -6,3 +6,7 @@ package runtime
|
||||
_stderr_write :: proc "contextless" (data: []byte) -> (int, _OS_Errno) {
|
||||
return 0, -1
|
||||
}
|
||||
|
||||
_exit :: proc "contextless" (code: int) -> ! {
|
||||
trap()
|
||||
}
|
||||
@@ -19,3 +19,9 @@ _stderr_write :: proc "contextless" (data: []byte) -> (int, _OS_Errno) {
|
||||
}
|
||||
return int(ret), 0
|
||||
}
|
||||
|
||||
|
||||
|
||||
_exit :: proc "contextless" (code: int) -> ! {
|
||||
trap()
|
||||
}
|
||||
@@ -11,3 +11,8 @@ _stderr_write :: proc "contextless" (data: []byte) -> (int, _OS_Errno) {
|
||||
write(1, data)
|
||||
return len(data), 0
|
||||
}
|
||||
|
||||
|
||||
_exit :: proc "contextless" (code: int) -> ! {
|
||||
trap()
|
||||
}
|
||||
@@ -24,3 +24,17 @@ _stderr_write :: proc "contextless" (data: []byte) -> (int, _OS_Errno) {
|
||||
}
|
||||
return ret, 0
|
||||
}
|
||||
|
||||
|
||||
_exit :: proc "contextless" (code: int) -> ! {
|
||||
SYS_exit_group ::
|
||||
231 when ODIN_ARCH == .amd64 else
|
||||
248 when ODIN_ARCH == .arm32 else
|
||||
94 when ODIN_ARCH == .arm64 else
|
||||
252 when ODIN_ARCH == .i386 else
|
||||
94 when ODIN_ARCH == .riscv64 else
|
||||
0
|
||||
|
||||
intrinsics.syscall(uintptr(SYS_exit_group), uintptr(i32(code)))
|
||||
unreachable()
|
||||
}
|
||||
|
||||
@@ -41,3 +41,8 @@ _stderr_write :: proc "contextless" (data: []byte) -> (int, _OS_Errno) {
|
||||
|
||||
return len(data), 0
|
||||
}
|
||||
|
||||
|
||||
_exit :: proc "contextless" (code: int) -> ! {
|
||||
trap()
|
||||
}
|
||||
@@ -23,6 +23,9 @@ foreign wasi {
|
||||
argv: [^]cstring,
|
||||
argv_buf: [^]byte,
|
||||
) -> u16 ---
|
||||
|
||||
@(private="file")
|
||||
proc_exit :: proc(rval: u32) -> ! ---
|
||||
}
|
||||
|
||||
_stderr_write :: proc "contextless" (data: []byte) -> (int, _OS_Errno) {
|
||||
@@ -53,3 +56,8 @@ _wasi_setup_args :: proc() {
|
||||
delete(args_buf)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
_exit :: proc "contextless" (code: int) -> ! {
|
||||
proc_exit(u32(code))
|
||||
}
|
||||
@@ -14,6 +14,8 @@ foreign kernel32 {
|
||||
SetHandleInformation :: proc(hObject: rawptr, dwMask: u32, dwFlags: u32) -> b32 ---
|
||||
WriteFile :: proc(hFile: rawptr, lpBuffer: rawptr, nNumberOfBytesToWrite: u32, lpNumberOfBytesWritten: ^u32, lpOverlapped: rawptr) -> b32 ---
|
||||
GetLastError :: proc() -> u32 ---
|
||||
|
||||
ExitProcess :: proc(code: u32) -> ! ---
|
||||
}
|
||||
|
||||
_stderr_write :: proc "contextless" (data: []byte) -> (n: int, err: _OS_Errno) #no_bounds_check {
|
||||
@@ -49,3 +51,7 @@ _stderr_write :: proc "contextless" (data: []byte) -> (n: int, err: _OS_Errno) #
|
||||
n = int(total_write)
|
||||
return
|
||||
}
|
||||
|
||||
_exit :: proc "contextless" (code: int) -> ! {
|
||||
ExitProcess(u32(code))
|
||||
}
|
||||
Reference in New Issue
Block a user