Merge tag 'dev-2025-08'

# Conflicts:
#	.gitignore
This commit is contained in:
ed
2025-08-09 09:50:50 -04:00
144 changed files with 5490 additions and 1995 deletions
+1 -1
View File
@@ -6,7 +6,7 @@ jobs:
name: NetBSD Build, Check, and Test name: NetBSD Build, Check, and Test
runs-on: ubuntu-latest runs-on: ubuntu-latest
env: env:
PKGSRC_BRANCH: 2024Q3 PKGSRC_BRANCH: 2025Q2
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Build, Check, and Test - name: Build, Check, and Test
+5
View File
@@ -298,3 +298,8 @@ build.sh
tests/issues/build/* tests/issues/build/*
misc/featuregen/featuregen misc/featuregen/featuregen
codegen/build/gen_src.map codegen/build/gen_src.map
# Clangd stuff
.cache/
.clangd
compile_commands.json
+1 -1
View File
@@ -145,7 +145,7 @@ ODIN_OS_STRING :: ODIN_OS_STRING
/* /*
An `enum` value indicating the platform subtarget, chosen using the `-subtarget` switch. An `enum` value indicating the platform subtarget, chosen using the `-subtarget` switch.
Possible values are: `.Default` `.iOS`, and `.Android`. Possible values are: `.Default` `.iPhone`, .iPhoneSimulator, and `.Android`.
*/ */
ODIN_PLATFORM_SUBTARGET :: ODIN_PLATFORM_SUBTARGET ODIN_PLATFORM_SUBTARGET :: ODIN_PLATFORM_SUBTARGET
+7
View File
@@ -32,6 +32,7 @@ trap :: proc() -> ! ---
alloca :: proc(size, align: int) -> [^]u8 --- alloca :: proc(size, align: int) -> [^]u8 ---
cpu_relax :: proc() --- cpu_relax :: proc() ---
read_cycle_counter :: proc() -> i64 --- read_cycle_counter :: proc() -> i64 ---
read_cycle_counter_frequency :: proc() -> i64 ---
count_ones :: proc(x: $T) -> T where type_is_integer(T) || type_is_simd_vector(T) --- count_ones :: proc(x: $T) -> T where type_is_integer(T) || type_is_simd_vector(T) ---
count_zeros :: proc(x: $T) -> T where type_is_integer(T) || type_is_simd_vector(T) --- count_zeros :: proc(x: $T) -> T where type_is_integer(T) || type_is_simd_vector(T) ---
@@ -213,6 +214,10 @@ type_is_subtype_of :: proc($T, $U: typeid) -> bool ---
type_field_index_of :: proc($T: typeid, $name: string) -> uintptr --- type_field_index_of :: proc($T: typeid, $name: string) -> uintptr ---
// "Contiguous" means that the set of enum constants, when sorted, have a difference of either 0 or 1 between consecutive values.
// This is the exact opposite of "sparse".
type_enum_is_contiguous :: proc($T: typeid) -> bool where type_is_enum(T) ---
type_equal_proc :: proc($T: typeid) -> (equal: proc "contextless" (rawptr, rawptr) -> bool) where type_is_comparable(T) --- type_equal_proc :: proc($T: typeid) -> (equal: proc "contextless" (rawptr, rawptr) -> bool) where type_is_comparable(T) ---
type_hasher_proc :: proc($T: typeid) -> (hasher: proc "contextless" (data: rawptr, seed: uintptr) -> uintptr) where type_is_comparable(T) --- type_hasher_proc :: proc($T: typeid) -> (hasher: proc "contextless" (data: rawptr, seed: uintptr) -> uintptr) where type_is_comparable(T) ---
@@ -310,6 +315,7 @@ simd_indices :: proc($T: typeid/#simd[$N]$E) -> T where type_is_numeric(T) ---
simd_shuffle :: proc(a, b: #simd[N]T, indices: ..int) -> #simd[len(indices)]T --- simd_shuffle :: proc(a, b: #simd[N]T, indices: ..int) -> #simd[len(indices)]T ---
simd_select :: proc(cond: #simd[N]boolean_or_integer, true, false: #simd[N]T) -> #simd[N]T --- simd_select :: proc(cond: #simd[N]boolean_or_integer, true, false: #simd[N]T) -> #simd[N]T ---
simd_runtime_swizzle :: proc(table: #simd[N]T, indices: #simd[N]T) -> #simd[N]T where type_is_integer(T) ---
// Lane-wise operations // Lane-wise operations
simd_ceil :: proc(a: #simd[N]any_float) -> #simd[N]any_float --- simd_ceil :: proc(a: #simd[N]any_float) -> #simd[N]any_float ---
@@ -357,6 +363,7 @@ x86_cpuid :: proc(ax, cx: u32) -> (eax, ebx, ecx, edx: u32) ---
x86_xgetbv :: proc(cx: u32) -> (eax, edx: u32) --- x86_xgetbv :: proc(cx: u32) -> (eax, edx: u32) ---
// Darwin targets only // Darwin targets only
objc_object :: struct{} objc_object :: struct{}
objc_selector :: struct{} objc_selector :: struct{}
+5 -2
View File
@@ -115,7 +115,7 @@ Type_Info_Struct_Flags :: distinct bit_set[Type_Info_Struct_Flag; u8]
Type_Info_Struct_Flag :: enum u8 { Type_Info_Struct_Flag :: enum u8 {
packed = 0, packed = 0,
raw_union = 1, raw_union = 1,
no_copy = 2, _ = 2,
align = 3, align = 3,
} }
@@ -557,7 +557,8 @@ ALL_ODIN_OS_TYPES :: Odin_OS_Types{
// Defined internally by the compiler // Defined internally by the compiler
Odin_Platform_Subtarget_Type :: enum int { Odin_Platform_Subtarget_Type :: enum int {
Default, Default,
iOS, iPhone,
iPhoneSimulator
Android, Android,
} }
*/ */
@@ -565,6 +566,8 @@ Odin_Platform_Subtarget_Type :: type_of(ODIN_PLATFORM_SUBTARGET)
Odin_Platform_Subtarget_Types :: bit_set[Odin_Platform_Subtarget_Type] Odin_Platform_Subtarget_Types :: bit_set[Odin_Platform_Subtarget_Type]
@(builtin)
ODIN_PLATFORM_SUBTARGET_IOS :: ODIN_PLATFORM_SUBTARGET == .iPhone || ODIN_PLATFORM_SUBTARGET == .iPhoneSimulator
/* /*
// Defined internally by the compiler // Defined internally by the compiler
+2 -1
View File
@@ -3,6 +3,7 @@ bits 64
extern _start_odin extern _start_odin
global _start global _start
section .note.GNU-stack
section .text section .text
;; Entry point for programs that specify -no-crt option ;; Entry point for programs that specify -no-crt option
@@ -35,7 +36,7 @@ _start:
xor rbp, rbp xor rbp, rbp
;; Load argc into 1st param reg, argv into 2nd param reg ;; Load argc into 1st param reg, argv into 2nd param reg
pop rdi pop rdi
mov rdx, rsi mov rsi, rsp
;; Align stack pointer down to 16-bytes (sysv calling convention) ;; Align stack pointer down to 16-bytes (sysv calling convention)
and rsp, -16 and rsp, -16
;; Call into odin entry point ;; Call into odin entry point
+1 -1
View File
@@ -3,7 +3,7 @@
package runtime package runtime
when ODIN_OS == .Darwin { when ODIN_OS == .Darwin {
foreign import libc "system:System.framework" foreign import libc "system:System"
} else { } else {
foreign import libc "system:c" foreign import libc "system:c"
} }
+1 -1
View File
@@ -403,7 +403,7 @@ print_type :: #force_no_inline proc "contextless" (ti: ^Type_Info) {
print_string("struct ") print_string("struct ")
if .packed in info.flags { print_string("#packed ") } if .packed in info.flags { print_string("#packed ") }
if .raw_union in info.flags { print_string("#raw_union ") } if .raw_union in info.flags { print_string("#raw_union ") }
if .no_copy in info.flags { print_string("#no_copy ") } // if .no_copy in info.flags { print_string("#no_copy ") }
if .align in info.flags { if .align in info.flags {
print_string("#align(") print_string("#align(")
print_u64(u64(ti.align)) print_u64(u64(ti.align))
+1
View File
@@ -31,5 +31,6 @@ foreign ObjC {
class_getInstanceVariable :: proc "c" (cls : objc_Class, name: cstring) -> objc_Ivar --- class_getInstanceVariable :: proc "c" (cls : objc_Class, name: cstring) -> objc_Ivar ---
class_getInstanceSize :: proc "c" (cls : objc_Class) -> uint --- class_getInstanceSize :: proc "c" (cls : objc_Class) -> uint ---
ivar_getOffset :: proc "c" (v: objc_Ivar) -> uintptr --- ivar_getOffset :: proc "c" (v: objc_Ivar) -> uintptr ---
object_getClass :: proc "c" (obj: objc_id) -> objc_Class ---
} }
+1 -1
View File
@@ -5,7 +5,7 @@ package libc
when ODIN_OS == .Windows { when ODIN_OS == .Windows {
foreign import libc "system:libucrt.lib" foreign import libc "system:libucrt.lib"
} else when ODIN_OS == .Darwin { } else when ODIN_OS == .Darwin {
foreign import libc "system:System.framework" foreign import libc "system:System"
} else { } else {
foreign import libc "system:c" foreign import libc "system:c"
} }
+1 -1
View File
@@ -3,7 +3,7 @@ package libc
when ODIN_OS == .Windows { when ODIN_OS == .Windows {
foreign import libc "system:libucrt.lib" foreign import libc "system:libucrt.lib"
} else when ODIN_OS == .Darwin { } else when ODIN_OS == .Darwin {
foreign import libc "system:System.framework" foreign import libc "system:System"
} else { } else {
foreign import libc "system:c" foreign import libc "system:c"
} }
+1 -1
View File
@@ -5,7 +5,7 @@ package libc
when ODIN_OS == .Windows { when ODIN_OS == .Windows {
foreign import libc "system:libucrt.lib" foreign import libc "system:libucrt.lib"
} else when ODIN_OS == .Darwin { } else when ODIN_OS == .Darwin {
foreign import libc "system:System.framework" foreign import libc "system:System"
} else { } else {
foreign import libc "system:c" foreign import libc "system:c"
} }
+1 -1
View File
@@ -5,7 +5,7 @@ import "core:c"
when ODIN_OS == .Windows { when ODIN_OS == .Windows {
foreign import libc "system:libucrt.lib" foreign import libc "system:libucrt.lib"
} else when ODIN_OS == .Darwin { } else when ODIN_OS == .Darwin {
foreign import libc "system:System.framework" foreign import libc "system:System"
} else { } else {
foreign import libc "system:c" foreign import libc "system:c"
} }
+1 -1
View File
@@ -7,7 +7,7 @@ import "base:intrinsics"
when ODIN_OS == .Windows { when ODIN_OS == .Windows {
foreign import libc "system:libucrt.lib" foreign import libc "system:libucrt.lib"
} else when ODIN_OS == .Darwin { } else when ODIN_OS == .Darwin {
foreign import libc "system:System.framework" foreign import libc "system:System"
} else { } else {
foreign import libc "system:c" foreign import libc "system:c"
} }
+1 -1
View File
@@ -5,7 +5,7 @@ package libc
when ODIN_OS == .Windows { when ODIN_OS == .Windows {
foreign import libc "system:libucrt.lib" foreign import libc "system:libucrt.lib"
} else when ODIN_OS == .Darwin { } else when ODIN_OS == .Darwin {
foreign import libc "system:System.framework" foreign import libc "system:System"
} else { } else {
foreign import libc "system:c" foreign import libc "system:c"
} }
+1 -1
View File
@@ -5,7 +5,7 @@ package libc
when ODIN_OS == .Windows { when ODIN_OS == .Windows {
foreign import libc "system:libucrt.lib" foreign import libc "system:libucrt.lib"
} else when ODIN_OS == .Darwin { } else when ODIN_OS == .Darwin {
foreign import libc "system:System.framework" foreign import libc "system:System"
} else { } else {
foreign import libc "system:c" foreign import libc "system:c"
} }
+1 -1
View File
@@ -9,7 +9,7 @@ when ODIN_OS == .Windows {
"system:legacy_stdio_definitions.lib", "system:legacy_stdio_definitions.lib",
} }
} else when ODIN_OS == .Darwin { } else when ODIN_OS == .Darwin {
foreign import libc "system:System.framework" foreign import libc "system:System"
} else { } else {
foreign import libc "system:c" foreign import libc "system:c"
} }
+1 -1
View File
@@ -5,7 +5,7 @@ package libc
when ODIN_OS == .Windows { when ODIN_OS == .Windows {
foreign import libc "system:libucrt.lib" foreign import libc "system:libucrt.lib"
} else when ODIN_OS == .Darwin { } else when ODIN_OS == .Darwin {
foreign import libc "system:System.framework" foreign import libc "system:System"
} else { } else {
foreign import libc "system:c" foreign import libc "system:c"
} }
+1 -1
View File
@@ -7,7 +7,7 @@ import "base:runtime"
when ODIN_OS == .Windows { when ODIN_OS == .Windows {
foreign import libc "system:libucrt.lib" foreign import libc "system:libucrt.lib"
} else when ODIN_OS == .Darwin { } else when ODIN_OS == .Darwin {
foreign import libc "system:System.framework" foreign import libc "system:System"
} else { } else {
foreign import libc "system:c" foreign import libc "system:c"
} }
+1 -1
View File
@@ -5,7 +5,7 @@ package libc
when ODIN_OS == .Windows { when ODIN_OS == .Windows {
foreign import libc "system:libucrt.lib" foreign import libc "system:libucrt.lib"
} else when ODIN_OS == .Darwin { } else when ODIN_OS == .Darwin {
foreign import libc "system:System.framework" foreign import libc "system:System"
} else { } else {
foreign import libc "system:c" foreign import libc "system:c"
} }
+1 -1
View File
@@ -5,7 +5,7 @@ package libc
when ODIN_OS == .Windows { when ODIN_OS == .Windows {
foreign import libc "system:libucrt.lib" foreign import libc "system:libucrt.lib"
} else when ODIN_OS == .Darwin { } else when ODIN_OS == .Darwin {
foreign import libc "system:System.framework" foreign import libc "system:System"
} else { } else {
foreign import libc "system:c" foreign import libc "system:c"
} }
+1 -1
View File
@@ -5,7 +5,7 @@ package libc
when ODIN_OS == .Windows { when ODIN_OS == .Windows {
foreign import libc "system:libucrt.lib" foreign import libc "system:libucrt.lib"
} else when ODIN_OS == .Darwin { } else when ODIN_OS == .Darwin {
foreign import libc "system:System.framework" foreign import libc "system:System"
} else { } else {
foreign import libc "system:c" foreign import libc "system:c"
} }
+1 -1
View File
@@ -5,7 +5,7 @@ package libc
when ODIN_OS == .Windows { when ODIN_OS == .Windows {
foreign import libc "system:libucrt.lib" foreign import libc "system:libucrt.lib"
} else when ODIN_OS == .Darwin { } else when ODIN_OS == .Darwin {
foreign import libc "system:System.framework" foreign import libc "system:System"
} else { } else {
foreign import libc "system:c" foreign import libc "system:c"
} }
+2 -3
View File
@@ -21,8 +21,7 @@ hash_string :: proc(algorithm: Algorithm, data: string, allocator := context.all
// in a newly allocated slice. // in a newly allocated slice.
hash_bytes :: proc(algorithm: Algorithm, data: []byte, allocator := context.allocator) -> []byte { hash_bytes :: proc(algorithm: Algorithm, data: []byte, allocator := context.allocator) -> []byte {
dst := make([]byte, DIGEST_SIZES[algorithm], allocator) dst := make([]byte, DIGEST_SIZES[algorithm], allocator)
hash_bytes_to_buffer(algorithm, data, dst) return hash_bytes_to_buffer(algorithm, data, dst)
return dst
} }
// hash_string_to_buffer will hash the given input and assign the // hash_string_to_buffer will hash the given input and assign the
@@ -46,7 +45,7 @@ hash_bytes_to_buffer :: proc(algorithm: Algorithm, data, hash: []byte) -> []byte
update(&ctx, data) update(&ctx, data)
final(&ctx, hash) final(&ctx, hash)
return hash return hash[:DIGEST_SIZES[algorithm]]
} }
// hash_stream will incrementally fully consume a stream, and return the // hash_stream will incrementally fully consume a stream, and return the
+1 -1
View File
@@ -127,7 +127,7 @@ jenkins :: proc "contextless" (data: []byte, seed := u32(0)) -> u32 {
} }
@(optimization_mode="favor_size") @(optimization_mode="favor_size")
murmur32 :: proc "contextless" (data: []byte, seed := u32(0)) -> u32 { murmur32 :: proc "contextless" (data: []byte, seed := u32(0x9747b28c)) -> u32 {
c1_32: u32 : 0xcc9e2d51 c1_32: u32 : 0xcc9e2d51
c2_32: u32 : 0x1b873593 c2_32: u32 : 0x1b873593
+32
View File
@@ -101,3 +101,35 @@ XXH64_read64 :: #force_inline proc(buf: []u8, alignment := Alignment.Unaligned)
return u64(b) return u64(b)
} }
} }
XXH64_read64_simd :: #force_inline proc(buf: []$E, $W: uint, alignment := Alignment.Unaligned) -> (res: #simd[W]u64) {
if alignment == .Aligned {
res = (^#simd[W]u64)(raw_data(buf))^
} else {
res = intrinsics.unaligned_load((^#simd[W]u64)(raw_data(buf)))
}
when ODIN_ENDIAN == .Big {
bytes := transmute(#simd[W*8]u8)res
bytes = intrinsics.simd_lanes_reverse(bytes)
res = transmute(#simd[W]u64)bytes
res = intrinsics.simd_lanes_reverse(res)
}
return
}
XXH64_write64_simd :: #force_inline proc(buf: []$E, value: $V/#simd[$W]u64, alignment := Alignment.Unaligned) {
value := value
when ODIN_ENDIAN == .Big {
bytes := transmute(#simd[W*8]u8)value
bytes = intrinsics.simd_lanes_reverse(bytes)
value = transmute(#simd[W]u64)bytes
value = intrinsics.simd_lanes_reverse(value)
}
if alignment == .Aligned {
(^V)(raw_data(buf))^ = value
} else {
intrinsics.unaligned_store((^V)(raw_data(buf)), value)
}
}
+100 -33
View File
@@ -52,6 +52,7 @@ XXH3_SECRET_SIZE_MIN :: 136
#assert(len(XXH3_kSecret) == 192 && len(XXH3_kSecret) > XXH3_SECRET_SIZE_MIN) #assert(len(XXH3_kSecret) == 192 && len(XXH3_kSecret) > XXH3_SECRET_SIZE_MIN)
XXH_ACC_ALIGN :: 8 /* scalar */ XXH_ACC_ALIGN :: 8 /* scalar */
XXH_MAX_WIDTH :: #config(XXH_MAX_WIDTH, 512) / 64
/* /*
This is the optimal update size for incremental hashing. This is the optimal update size for incremental hashing.
@@ -62,10 +63,11 @@ XXH3_INTERNAL_BUFFER_SIZE :: 256
Streaming state. Streaming state.
IMPORTANT: This structure has a strict alignment requirement of 64 bytes!! ** IMPORTANT: This structure has a strict alignment requirement of 64 bytes!! **
Do not allocate this with `make()` or `new`, it will not be sufficiently aligned. Default allocators will align it correctly if created via `new`, as will
Use`XXH3_create_state` and `XXH3_destroy_state, or stack allocation. placing this struct on the stack, but if using a custom allocator make sure
that it handles the alignment correctly!
*/ */
XXH3_state :: struct { XXH3_state :: struct #align(64) {
acc: [8]u64, acc: [8]u64,
custom_secret: [XXH_SECRET_DEFAULT_SIZE]u8, custom_secret: [XXH_SECRET_DEFAULT_SIZE]u8,
buffer: [XXH3_INTERNAL_BUFFER_SIZE]u8, buffer: [XXH3_INTERNAL_BUFFER_SIZE]u8,
@@ -380,7 +382,6 @@ XXH3_INIT_ACC :: [XXH_ACC_NB]xxh_u64{
XXH_SECRET_MERGEACCS_START :: 11 XXH_SECRET_MERGEACCS_START :: 11
@(optimization_mode="favor_size")
XXH3_hashLong_128b_internal :: #force_inline proc( XXH3_hashLong_128b_internal :: #force_inline proc(
input: []u8, input: []u8,
secret: []u8, secret: []u8,
@@ -408,7 +409,6 @@ XXH3_hashLong_128b_internal :: #force_inline proc(
/* /*
* It's important for performance that XXH3_hashLong is not inlined. * It's important for performance that XXH3_hashLong is not inlined.
*/ */
@(optimization_mode="favor_size")
XXH3_hashLong_128b_default :: #force_no_inline proc(input: []u8, seed: xxh_u64, secret: []u8) -> (res: XXH3_128_hash) { XXH3_hashLong_128b_default :: #force_no_inline proc(input: []u8, seed: xxh_u64, secret: []u8) -> (res: XXH3_128_hash) {
return XXH3_hashLong_128b_internal(input, XXH3_kSecret[:], XXH3_accumulate_512, XXH3_scramble_accumulator) return XXH3_hashLong_128b_internal(input, XXH3_kSecret[:], XXH3_accumulate_512, XXH3_scramble_accumulator)
} }
@@ -416,12 +416,10 @@ XXH3_hashLong_128b_default :: #force_no_inline proc(input: []u8, seed: xxh_u64,
/* /*
* It's important for performance that XXH3_hashLong is not inlined. * It's important for performance that XXH3_hashLong is not inlined.
*/ */
@(optimization_mode="favor_size")
XXH3_hashLong_128b_withSecret :: #force_no_inline proc(input: []u8, seed: xxh_u64, secret: []u8) -> (res: XXH3_128_hash) { XXH3_hashLong_128b_withSecret :: #force_no_inline proc(input: []u8, seed: xxh_u64, secret: []u8) -> (res: XXH3_128_hash) {
return XXH3_hashLong_128b_internal(input, secret, XXH3_accumulate_512, XXH3_scramble_accumulator) return XXH3_hashLong_128b_internal(input, secret, XXH3_accumulate_512, XXH3_scramble_accumulator)
} }
@(optimization_mode="favor_size")
XXH3_hashLong_128b_withSeed_internal :: #force_inline proc( XXH3_hashLong_128b_withSeed_internal :: #force_inline proc(
input: []u8, seed: xxh_u64, secret: []u8, input: []u8, seed: xxh_u64, secret: []u8,
f_acc512: XXH3_accumulate_512_f, f_acc512: XXH3_accumulate_512_f,
@@ -442,7 +440,6 @@ XXH3_hashLong_128b_withSeed_internal :: #force_inline proc(
/* /*
* It's important for performance that XXH3_hashLong is not inlined. * It's important for performance that XXH3_hashLong is not inlined.
*/ */
@(optimization_mode="favor_size")
XXH3_hashLong_128b_withSeed :: #force_no_inline proc(input: []u8, seed: xxh_u64, secret: []u8) -> (res: XXH3_128_hash) { XXH3_hashLong_128b_withSeed :: #force_no_inline proc(input: []u8, seed: xxh_u64, secret: []u8) -> (res: XXH3_128_hash) {
return XXH3_hashLong_128b_withSeed_internal(input, seed, secret, XXH3_accumulate_512, XXH3_scramble_accumulator , XXH3_init_custom_secret) return XXH3_hashLong_128b_withSeed_internal(input, seed, secret, XXH3_accumulate_512, XXH3_scramble_accumulator , XXH3_init_custom_secret)
} }
@@ -477,7 +474,7 @@ XXH3_128bits_internal :: #force_inline proc(
/* === Public XXH128 API === */ /* === Public XXH128 API === */
@(optimization_mode="favor_size") @(optimization_mode="favor_size")
XXH3_128_default :: proc(input: []u8) -> (hash: XXH3_128_hash) { XXH3_128_default :: proc(input: []u8) -> (hash: XXH3_128_hash) {
return XXH3_128bits_internal(input, 0, XXH3_kSecret[:], XXH3_hashLong_128b_withSeed) return XXH3_128bits_internal(input, 0, XXH3_kSecret[:], XXH3_hashLong_128b_default)
} }
@(optimization_mode="favor_size") @(optimization_mode="favor_size")
@@ -733,10 +730,6 @@ XXH3_accumulate_512_f :: #type proc(acc: []xxh_u64, input: []u8, secret:
XXH3_scramble_accumulator_f :: #type proc(acc: []xxh_u64, secret: []u8) XXH3_scramble_accumulator_f :: #type proc(acc: []xxh_u64, secret: []u8)
XXH3_init_custom_secret_f :: #type proc(custom_secret: []u8, seed64: xxh_u64) XXH3_init_custom_secret_f :: #type proc(custom_secret: []u8, seed64: xxh_u64)
XXH3_accumulate_512 : XXH3_accumulate_512_f = XXH3_accumulate_512_scalar
XXH3_scramble_accumulator : XXH3_scramble_accumulator_f = XXH3_scramble_accumulator_scalar
XXH3_init_custom_secret : XXH3_init_custom_secret_f = XXH3_init_custom_secret_scalar
/* scalar variants - universal */ /* scalar variants - universal */
@(optimization_mode="favor_size") @(optimization_mode="favor_size")
XXH3_accumulate_512_scalar :: #force_inline proc(acc: []xxh_u64, input: []u8, secret: []u8) { XXH3_accumulate_512_scalar :: #force_inline proc(acc: []xxh_u64, input: []u8, secret: []u8) {
@@ -751,7 +744,7 @@ XXH3_accumulate_512_scalar :: #force_inline proc(acc: []xxh_u64, input: []u8, se
sec := XXH64_read64(xsecret[8 * i:]) sec := XXH64_read64(xsecret[8 * i:])
data_key := data_val ~ sec data_key := data_val ~ sec
xacc[i ~ 1] += data_val /* swap adjacent lanes */ xacc[i ~ 1] += data_val /* swap adjacent lanes */
xacc[i ] += u64(u128(u32(data_key)) * u128(u64(data_key >> 32))) xacc[i ] += u64(u32(data_key)) * u64(data_key >> 32)
} }
} }
@@ -785,6 +778,87 @@ XXH3_init_custom_secret_scalar :: #force_inline proc(custom_secret: []u8, seed64
} }
} }
/* generalized SIMD variants */
XXH3_accumulate_512_simd_generic :: #force_inline proc(acc: []xxh_u64, input: []u8, secret: []u8, $W: uint) {
u32xW :: #simd[W]u32
u64xW :: #simd[W]u64
#no_bounds_check for i in uint(0)..<XXH_ACC_NB/W {
data_val := XXH64_read64_simd(input[8 * W * i:], W)
sec := XXH64_read64_simd(secret[8 * W * i:], W)
data_key := data_val ~ sec
// Swap adjacent lanes
when W == 2 {
data_val = swizzle(data_val, 1, 0)
} else when W == 4 {
data_val = swizzle(data_val, 1, 0, 3, 2)
} else when W == 8 {
data_val = swizzle(data_val, 1, 0, 3, 2, 5, 4, 7, 6)
} else {
#panic("Unsupported vector size!")
}
a := XXH64_read64_simd(acc[W * i:], W)
a += data_val
a += u64xW(u32xW(data_key)) * intrinsics.simd_shr(data_key, 32)
XXH64_write64_simd(acc[W * i:], a)
}
}
XXH3_scramble_accumulator_simd_generic :: #force_inline proc(acc: []xxh_u64, secret: []u8, $W: uint) {
u64xW :: #simd[W]u64
#no_bounds_check for i in uint(0)..<XXH_ACC_NB/W {
key64 := XXH64_read64_simd(secret[8 * W * i:], W)
acc64 := XXH64_read64_simd(acc[W * i:], W)
acc64 ~= intrinsics.simd_shr(acc64, 47)
acc64 ~= key64
acc64 *= XXH_PRIME32_1
XXH64_write64_simd(acc[W * i:], acc64)
}
}
XXH3_init_custom_secret_simd_generic :: #force_inline proc(custom_secret: []u8, seed64: xxh_u64, $W: uint) {
u64xW :: #simd[W]u64
seedVec := u64xW(seed64)
for i in 0..<W/2 {
j := 2*i + 1
seedVec = intrinsics.simd_replace(seedVec, j, -intrinsics.simd_extract(seedVec, j))
}
nbRounds := XXH_SECRET_DEFAULT_SIZE / 8 / W
#no_bounds_check for i in uint(0)..<nbRounds {
block := XXH64_read64_simd(XXH3_kSecret[8 * W * i:], W)
block += seedVec
XXH64_write64_simd(custom_secret[8 * W * i:], block)
}
}
XXH3_accumulate_512 :: #force_inline proc(acc: []xxh_u64, input: []u8, secret: []u8) {
when XXH_NATIVE_WIDTH > 1 {
XXH3_accumulate_512_simd_generic(acc, input, secret, XXH_NATIVE_WIDTH)
} else {
XXH3_accumulate_512_scalar(acc, input, secret)
}
}
XXH3_scramble_accumulator :: #force_inline proc(acc: []xxh_u64, secret: []u8) {
when XXH_NATIVE_WIDTH > 1 {
XXH3_scramble_accumulator_simd_generic(acc, secret, XXH_NATIVE_WIDTH)
} else {
XXH3_scramble_accumulator_scalar(acc, secret)
}
}
XXH3_init_custom_secret :: #force_inline proc(custom_secret: []u8, seed64: xxh_u64) {
when XXH_NATIVE_WIDTH > 1 {
XXH3_init_custom_secret_simd_generic(custom_secret, seed64, XXH_NATIVE_WIDTH)
} else {
XXH3_init_custom_secret_scalar(custom_secret, seed64)
}
}
XXH_PREFETCH_DIST :: 320 XXH_PREFETCH_DIST :: 320
/* /*
@@ -796,7 +870,7 @@ XXH_PREFETCH_DIST :: 320
XXH3_accumulate :: #force_inline proc( XXH3_accumulate :: #force_inline proc(
acc: []xxh_u64, input: []u8, secret: []u8, nbStripes: uint, f_acc512: XXH3_accumulate_512_f) { acc: []xxh_u64, input: []u8, secret: []u8, nbStripes: uint, f_acc512: XXH3_accumulate_512_f) {
for n := uint(0); n < nbStripes; n += 1 { #no_bounds_check for n := uint(0); n < nbStripes; n += 1 {
when !XXH_DISABLE_PREFETCH { when !XXH_DISABLE_PREFETCH {
in_ptr := &input[n * XXH_STRIPE_LEN] in_ptr := &input[n * XXH_STRIPE_LEN]
prefetch(in_ptr, XXH_PREFETCH_DIST) prefetch(in_ptr, XXH_PREFETCH_DIST)
@@ -869,7 +943,6 @@ XXH3_hashLong_64b_internal :: #force_inline proc(input: []u8, secret: []u8,
/* /*
It's important for performance that XXH3_hashLong is not inlined. It's important for performance that XXH3_hashLong is not inlined.
*/ */
@(optimization_mode="favor_size")
XXH3_hashLong_64b_withSecret :: #force_no_inline proc(input: []u8, seed64: xxh_u64, secret: []u8) -> (hash: xxh_u64) { XXH3_hashLong_64b_withSecret :: #force_no_inline proc(input: []u8, seed64: xxh_u64, secret: []u8) -> (hash: xxh_u64) {
return XXH3_hashLong_64b_internal(input, secret, XXH3_accumulate_512, XXH3_scramble_accumulator) return XXH3_hashLong_64b_internal(input, secret, XXH3_accumulate_512, XXH3_scramble_accumulator)
} }
@@ -881,24 +954,11 @@ XXH3_hashLong_64b_withSecret :: #force_no_inline proc(input: []u8, seed64: xxh_u
This variant enforces that the compiler can detect that, This variant enforces that the compiler can detect that,
and uses this opportunity to streamline the generated code for better performance. and uses this opportunity to streamline the generated code for better performance.
*/ */
@(optimization_mode="favor_size")
XXH3_hashLong_64b_default :: #force_no_inline proc(input: []u8, seed64: xxh_u64, secret: []u8) -> (hash: xxh_u64) { XXH3_hashLong_64b_default :: #force_no_inline proc(input: []u8, seed64: xxh_u64, secret: []u8) -> (hash: xxh_u64) {
return XXH3_hashLong_64b_internal(input, XXH3_kSecret[:], XXH3_accumulate_512, XXH3_scramble_accumulator) return XXH3_hashLong_64b_internal(input, XXH3_kSecret[:], XXH3_accumulate_512, XXH3_scramble_accumulator)
} }
/* XXH3_hashLong_64b_withSeed_internal :: #force_inline proc(
XXH3_hashLong_64b_withSeed():
Generate a custom key based on alteration of default XXH3_kSecret with the seed,
and then use this key for long mode hashing.
This operation is decently fast but nonetheless costs a little bit of time.
Try to avoid it whenever possible (typically when seed==0).
It's important for performance that XXH3_hashLong is not inlined. Not sure
why (uop cache maybe?), but the difference is large and easily measurable.
*/
@(optimization_mode="favor_size")
XXH3_hashLong_64b_withSeed_internal :: #force_no_inline proc(
input: []u8, input: []u8,
seed: xxh_u64, seed: xxh_u64,
f_acc512: XXH3_accumulate_512_f, f_acc512: XXH3_accumulate_512_f,
@@ -915,9 +975,16 @@ XXH3_hashLong_64b_withSeed_internal :: #force_no_inline proc(
} }
/* /*
It's important for performance that XXH3_hashLong is not inlined. XXH3_hashLong_64b_withSeed():
Generate a custom key based on alteration of default XXH3_kSecret with the seed,
and then use this key for long mode hashing.
This operation is decently fast but nonetheless costs a little bit of time.
Try to avoid it whenever possible (typically when seed==0).
It's important for performance that XXH3_hashLong is not inlined. Not sure
why (uop cache maybe?), but the difference is large and easily measurable.
*/ */
@(optimization_mode="favor_size")
XXH3_hashLong_64b_withSeed :: #force_no_inline proc(input: []u8, seed: xxh_u64, secret: []u8) -> (hash: xxh_u64) { XXH3_hashLong_64b_withSeed :: #force_no_inline proc(input: []u8, seed: xxh_u64, secret: []u8) -> (hash: xxh_u64) {
return XXH3_hashLong_64b_withSeed_internal(input, seed, XXH3_accumulate_512, XXH3_scramble_accumulator, XXH3_init_custom_secret) return XXH3_hashLong_64b_withSeed_internal(input, seed, XXH3_accumulate_512, XXH3_scramble_accumulator, XXH3_init_custom_secret)
} }
@@ -926,7 +993,7 @@ XXH3_hashLong_64b_withSeed :: #force_no_inline proc(input: []u8, seed: xxh_u64,
XXH3_hashLong64_f :: #type proc(input: []u8, seed: xxh_u64, secret: []u8) -> (res: xxh_u64) XXH3_hashLong64_f :: #type proc(input: []u8, seed: xxh_u64, secret: []u8) -> (res: xxh_u64)
@(optimization_mode="favor_size") @(optimization_mode="favor_size")
XXH3_64bits_internal :: proc(input: []u8, seed: xxh_u64, secret: []u8, f_hashLong: XXH3_hashLong64_f) -> (hash: xxh_u64) { XXH3_64bits_internal :: #force_inline proc(input: []u8, seed: xxh_u64, secret: []u8, f_hashLong: XXH3_hashLong64_f) -> (hash: xxh_u64) {
assert(len(secret) >= XXH3_SECRET_SIZE_MIN) assert(len(secret) >= XXH3_SECRET_SIZE_MIN)
/* /*
If an action is to be taken if len(secret) condition is not respected, it should be done here. If an action is to be taken if len(secret) condition is not respected, it should be done here.
+13
View File
@@ -0,0 +1,13 @@
#+build amd64, i386
package xxhash
import "base:intrinsics"
@(private="file") SSE2_FEATURES :: "sse2"
@(private="file") AVX2_FEATURES :: "avx2"
@(private="file") AVX512_FEATURES :: "avx512dq,evex512"
XXH_NATIVE_WIDTH :: min(XXH_MAX_WIDTH,
8 when intrinsics.has_target_feature(AVX512_FEATURES) else
4 when intrinsics.has_target_feature(AVX2_FEATURES) else
2 when intrinsics.has_target_feature(SSE2_FEATURES) else 1)
+8
View File
@@ -0,0 +1,8 @@
#+build !amd64
#+build !i386
package xxhash
import "base:runtime"
XXH_NATIVE_WIDTH :: min(XXH_MAX_WIDTH,
2 when runtime.HAS_HARDWARE_SIMD else 1)
+4 -1
View File
@@ -2223,6 +2223,9 @@ Initialize a buddy allocator.
This procedure initializes the buddy allocator `b` with a backing buffer `data` This procedure initializes the buddy allocator `b` with a backing buffer `data`
and block alignment specified by `alignment`. and block alignment specified by `alignment`.
`alignment` may be any power of two, but the backing buffer must be aligned to
at least `size_of(Buddy_Block)`.
*/ */
buddy_allocator_init :: proc(b: ^Buddy_Allocator, data: []byte, alignment: uint, loc := #caller_location) { buddy_allocator_init :: proc(b: ^Buddy_Allocator, data: []byte, alignment: uint, loc := #caller_location) {
assert(data != nil) assert(data != nil)
@@ -2233,7 +2236,7 @@ buddy_allocator_init :: proc(b: ^Buddy_Allocator, data: []byte, alignment: uint,
alignment = size_of(Buddy_Block) alignment = size_of(Buddy_Block)
} }
ptr := raw_data(data) ptr := raw_data(data)
assert(uintptr(ptr) % uintptr(alignment) == 0, "data is not aligned to minimum alignment", loc) assert(uintptr(ptr) % uintptr(alignment) == 0, "The data is not aligned to the minimum alignment, which must be at least `size_of(Buddy_Block)`.", loc)
b.head = (^Buddy_Block)(ptr) b.head = (^Buddy_Block)(ptr)
b.head.size = len(data) b.head.size = len(data)
b.head.is_free = true b.head.is_free = true
+11
View File
@@ -20,6 +20,17 @@ new_aligned :: proc(arena: ^Arena, $T: typeid, alignment: uint, loc := #caller_l
return return
} }
// The `new_clone` procedure allocates memory for a type `T` from a `virtual.Arena`. The second argument is a value that
// is to be copied to the allocated data. The value returned is a pointer to a newly allocated value of that type using the specified allocator.
@(require_results)
new_clone :: proc(arena: ^Arena, data: $T, loc := #caller_location) -> (ptr: ^T, err: Allocator_Error) {
ptr, err = new_aligned(arena, T, align_of(T), loc)
if ptr != nil && err == nil {
ptr^ = data
}
return
}
// `make_slice` allocates and initializes a slice. Like `new`, the second argument is a type, not a value. // `make_slice` allocates and initializes a slice. Like `new`, the second argument is a type, not a value.
// Unlike `new`, `make`'s return value is the same as the type of its argument, not a pointer to it. // Unlike `new`, `make`'s return value is the same as the type of its argument, not a pointer to it.
// //
+2 -2
View File
@@ -89,8 +89,8 @@ memory_block_alloc :: proc(committed, reserved: uint, alignment: uint = 0, flags
reserved = align_formula(reserved, page_size) reserved = align_formula(reserved, page_size)
committed = clamp(committed, 0, reserved) committed = clamp(committed, 0, reserved)
total_size := uint(reserved + max(alignment, size_of(Platform_Memory_Block))) total_size := reserved + alignment + size_of(Platform_Memory_Block)
base_offset := uintptr(max(alignment, size_of(Platform_Memory_Block))) base_offset := mem.align_forward_uintptr(size_of(Platform_Memory_Block), max(uintptr(alignment), align_of(Platform_Memory_Block)))
protect_offset := uintptr(0) protect_offset := uintptr(0)
do_protection := false do_protection := false
+1 -1
View File
@@ -23,7 +23,7 @@ package net
import "core:strings" import "core:strings"
import "core:sys/posix" import "core:sys/posix"
foreign import lib "system:System.framework" foreign import lib "system:System"
@(private) @(private)
_enumerate_interfaces :: proc(allocator := context.allocator) -> (interfaces: []Network_Interface, err: Interfaces_Error) { _enumerate_interfaces :: proc(allocator := context.allocator) -> (interfaces: []Network_Interface, err: Interfaces_Error) {
+23 -20
View File
@@ -348,27 +348,30 @@ consume_comment_group :: proc(p: ^Parser, n: int) -> (comments: ^ast.Comment_Gro
} }
consume_comment_groups :: proc(p: ^Parser, prev: tokenizer.Token) { consume_comment_groups :: proc(p: ^Parser, prev: tokenizer.Token) {
if p.curr_tok.kind == .Comment { if p.curr_tok.kind != .Comment {
comment: ^ast.Comment_Group return
end_line := 0
if p.curr_tok.pos.line == prev.pos.line {
comment, end_line = consume_comment_group(p, 0)
if p.curr_tok.pos.line != end_line || p.curr_tok.kind == .EOF {
p.line_comment = comment
}
}
end_line = -1
for p.curr_tok.kind == .Comment {
comment, end_line = consume_comment_group(p, 1)
}
if end_line+1 >= p.curr_tok.pos.line || end_line < 0 {
p.lead_comment = comment
}
assert(p.curr_tok.kind != .Comment)
} }
comment: ^ast.Comment_Group
end_line := 0
if p.curr_tok.pos.line == prev.pos.line {
comment, end_line = consume_comment_group(p, 0)
if p.curr_tok.pos.line != end_line ||
p.curr_tok.pos.line == prev.pos.line+1 ||
p.curr_tok.kind == .EOF {
p.line_comment = comment
}
}
end_line = -1
for p.curr_tok.kind == .Comment {
comment, end_line = consume_comment_group(p, 1)
}
if end_line+1 >= p.curr_tok.pos.line || end_line < 0 {
p.lead_comment = comment
}
assert(p.curr_tok.kind != .Comment)
} }
advance_token :: proc(p: ^Parser) -> tokenizer.Token { advance_token :: proc(p: ^Parser) -> tokenizer.Token {
+3 -3
View File
@@ -249,9 +249,9 @@ _destroy :: proc(f: ^File_Impl) -> Error {
a := f.allocator a := f.allocator
err0 := free(f.wname, a) err0 := free(f.wname, a)
err1 := delete(f.name, a) err1 := delete(f.name, a)
err2 := free(f, a) err2 := delete(f.r_buf, a)
err3 := delete(f.r_buf, a) err3 := delete(f.w_buf, a)
err4 := delete(f.w_buf, a) err4 := free(f, a)
err0 or_return err0 or_return
err1 or_return err1 or_return
err2 or_return err2 or_return
+1 -1
View File
@@ -10,7 +10,7 @@ import "core:sys/posix"
import "core:sys/unix" import "core:sys/unix"
import "core:time" import "core:time"
foreign import lib "system:System.framework" foreign import lib "system:System"
foreign lib { foreign lib {
sysctl :: proc( sysctl :: proc(
+2 -2
View File
@@ -1,8 +1,8 @@
package os package os
foreign import dl "system:dl" foreign import dl "system:dl"
foreign import libc "system:System.framework" foreign import libc "system:System"
foreign import pthread "system:System.framework" foreign import pthread "system:System"
import "base:runtime" import "base:runtime"
import "core:strings" import "core:strings"
+2 -2
View File
@@ -967,8 +967,8 @@ _processor_core_count :: proc() -> int {
@(private, require_results) @(private, require_results)
_alloc_command_line_arguments :: proc() -> []string { _alloc_command_line_arguments :: proc() -> []string {
res := make([]string, len(runtime.args__)) res := make([]string, len(runtime.args__))
for arg, i in runtime.args__ { for _, i in res {
res[i] = string(arg) res[i] = string(runtime.args__[i])
} }
return res return res
} }
+2 -2
View File
@@ -1100,8 +1100,8 @@ _processor_core_count :: proc() -> int {
@(private, require_results) @(private, require_results)
_alloc_command_line_arguments :: proc() -> []string { _alloc_command_line_arguments :: proc() -> []string {
res := make([]string, len(runtime.args__)) res := make([]string, len(runtime.args__))
for arg, i in runtime.args__ { for _, i in res {
res[i] = string(arg) res[i] = string(runtime.args__[i])
} }
return res return res
} }
+2 -2
View File
@@ -1017,8 +1017,8 @@ _processor_core_count :: proc() -> int {
@(private, require_results) @(private, require_results)
_alloc_command_line_arguments :: proc() -> []string { _alloc_command_line_arguments :: proc() -> []string {
res := make([]string, len(runtime.args__)) res := make([]string, len(runtime.args__))
for arg, i in runtime.args__ { for _, i in res {
res[i] = string(arg) res[i] = string(runtime.args__[i])
} }
return res return res
} }
+2 -2
View File
@@ -917,8 +917,8 @@ _processor_core_count :: proc() -> int {
@(private, require_results) @(private, require_results)
_alloc_command_line_arguments :: proc() -> []string { _alloc_command_line_arguments :: proc() -> []string {
res := make([]string, len(runtime.args__)) res := make([]string, len(runtime.args__))
for arg, i in runtime.args__ { for _, i in res {
res[i] = string(arg) res[i] = string(runtime.args__[i])
} }
return res return res
} }
+1
View File
@@ -1,4 +1,5 @@
#+build !wasi #+build !wasi
#+build !js
package filepath package filepath
import "core:os" import "core:os"
+1
View File
@@ -1,4 +1,5 @@
#+build !wasi #+build !wasi
#+build !js
package filepath package filepath
import "core:os" import "core:os"
+102 -40
View File
@@ -8,29 +8,36 @@ import "base:intrinsics"
MANUAL_MAGIC :: u64le(0x0BADF00D) MANUAL_MAGIC :: u64le(0x0BADF00D)
Manual_Header :: struct #packed { Manual_Stream_Header :: struct #packed {
magic: u64le, magic: u64le,
version: u64le, version: u64le,
timestamp_scale: f64le, timestamp_scale: f64le,
reserved: u64le, reserved: u64le,
} }
Manual_Buffer_Header :: struct #packed {
size: u32le,
tid: u32le,
pid: u32le,
first_ts: u64le,
}
Manual_Event_Type :: enum u8 { Manual_Event_Type :: enum u8 {
Invalid = 0, Invalid = 0,
Begin = 3, Begin = 3,
End = 4, End = 4,
Instant = 5, Instant = 5,
Pad_Skip = 7, Pad_Skip = 7,
Name_Process = 8,
Name_Thread = 9,
} }
Begin_Event :: struct #packed { Begin_Event :: struct #packed {
type: Manual_Event_Type, type: Manual_Event_Type,
category: u8, ts: u64le,
pid: u32le,
tid: u32le,
ts: f64le,
name_len: u8, name_len: u8,
args_len: u8, args_len: u8,
} }
@@ -38,9 +45,7 @@ BEGIN_EVENT_MAX :: size_of(Begin_Event) + 255 + 255
End_Event :: struct #packed { End_Event :: struct #packed {
type: Manual_Event_Type, type: Manual_Event_Type,
pid: u32le, ts: u64le,
tid: u32le,
ts: f64le,
} }
Pad_Skip :: struct #packed { Pad_Skip :: struct #packed {
@@ -48,6 +53,12 @@ Pad_Skip :: struct #packed {
size: u32le, size: u32le,
} }
Name_Event :: struct #packed {
type: Manual_Event_Type,
name_len: u8,
}
NAME_EVENT_MAX :: size_of(Name_Event) + 255
// User Interface // User Interface
Context :: struct { Context :: struct {
@@ -61,6 +72,7 @@ Buffer :: struct {
head: int, head: int,
tid: u32, tid: u32,
pid: u32, pid: u32,
first_ts: u64,
} }
BUFFER_DEFAULT_SIZE :: 0x10_0000 BUFFER_DEFAULT_SIZE :: 0x10_0000
@@ -76,8 +88,8 @@ context_create_with_scale :: proc(filename: string, precise_time: bool, timestam
ctx.precise_time = precise_time ctx.precise_time = precise_time
ctx.timestamp_scale = timestamp_scale ctx.timestamp_scale = timestamp_scale
temp := [size_of(Manual_Header)]u8{} temp := [size_of(Manual_Stream_Header)]u8{}
_build_header(temp[:], ctx.timestamp_scale) _build_stream_header(temp[:], ctx.timestamp_scale)
os.write(ctx.fd, temp[:]) os.write(ctx.fd, temp[:])
ok = true ok = true
return return
@@ -85,12 +97,13 @@ context_create_with_scale :: proc(filename: string, precise_time: bool, timestam
context_create_with_sleep :: proc(filename: string, sleep := 2 * time.Second) -> (ctx: Context, ok: bool) #optional_ok { context_create_with_sleep :: proc(filename: string, sleep := 2 * time.Second) -> (ctx: Context, ok: bool) #optional_ok {
freq, freq_ok := time.tsc_frequency(sleep) freq, freq_ok := time.tsc_frequency(sleep)
timestamp_scale: f64 = ((1 / f64(freq)) * 1_000_000) if freq_ok else 1 timestamp_scale: f64 = ((1 / f64(freq)) * 1_000_000_000) if freq_ok else 1
return context_create_with_scale(filename, freq_ok, timestamp_scale) return context_create_with_scale(filename, freq_ok, timestamp_scale)
} }
context_create :: proc{context_create_with_scale, context_create_with_sleep} context_create :: proc{context_create_with_scale, context_create_with_sleep}
@(no_instrumentation)
context_destroy :: proc(ctx: ^Context) { context_destroy :: proc(ctx: ^Context) {
if ctx == nil { if ctx == nil {
return return
@@ -102,25 +115,39 @@ context_destroy :: proc(ctx: ^Context) {
buffer_create :: proc(data: []byte, tid: u32 = 0, pid: u32 = 0) -> (buffer: Buffer, ok: bool) #optional_ok { buffer_create :: proc(data: []byte, tid: u32 = 0, pid: u32 = 0) -> (buffer: Buffer, ok: bool) #optional_ok {
assert(len(data) >= 1024) assert(len(data) >= 1024)
buffer.data = data buffer.data = data
buffer.tid = tid buffer.tid = tid
buffer.pid = pid buffer.pid = pid
buffer.head = 0 buffer.first_ts = 0
buffer.head = size_of(Manual_Buffer_Header)
ok = true ok = true
return return
} }
@(no_instrumentation) @(no_instrumentation)
buffer_flush :: proc "contextless" (ctx: ^Context, buffer: ^Buffer) #no_bounds_check /* bounds check would segfault instrumentation */ { buffer_flush :: proc "contextless" (ctx: ^Context, buffer: ^Buffer) #no_bounds_check /* bounds check would segfault instrumentation */ {
if len(buffer.data) == 0 {
return
}
buffer_size := buffer.head - size_of(Manual_Buffer_Header)
hdr := (^Manual_Buffer_Header)(raw_data(buffer.data))
hdr.size = u32le(buffer_size)
hdr.pid = u32le(buffer.pid)
hdr.tid = u32le(buffer.tid)
hdr.first_ts = u64le(buffer.first_ts)
start := _trace_now(ctx) start := _trace_now(ctx)
write(ctx.fd, buffer.data[:buffer.head]) write(ctx.fd, buffer.data[:buffer.head])
buffer.head = 0 buffer.head = size_of(Manual_Buffer_Header)
end := _trace_now(ctx) end := _trace_now(ctx)
buffer.head += _build_begin(buffer.data[buffer.head:], "Spall Trace Buffer Flush", "", start, buffer.tid, buffer.pid) buffer.head += _build_begin(buffer.data[buffer.head:], "Spall Trace Buffer Flush", "", start)
buffer.head += _build_end(buffer.data[buffer.head:], end, buffer.tid, buffer.pid) buffer.head += _build_end(buffer.data[buffer.head:], end)
buffer.first_ts = end
} }
@(no_instrumentation)
buffer_destroy :: proc(ctx: ^Context, buffer: ^Buffer) { buffer_destroy :: proc(ctx: ^Context, buffer: ^Buffer) {
buffer_flush(ctx, buffer) buffer_flush(ctx, buffer)
@@ -130,35 +157,37 @@ buffer_destroy :: proc(ctx: ^Context, buffer: ^Buffer) {
@(deferred_in=_scoped_buffer_end) @(deferred_in=_scoped_buffer_end)
@(no_instrumentation)
SCOPED_EVENT :: proc(ctx: ^Context, buffer: ^Buffer, name: string, args: string = "", location := #caller_location) -> bool { SCOPED_EVENT :: proc(ctx: ^Context, buffer: ^Buffer, name: string, args: string = "", location := #caller_location) -> bool {
_buffer_begin(ctx, buffer, name, args, location) _buffer_begin(ctx, buffer, name, args, location)
return true return true
} }
@(private) @(private)
@(no_instrumentation)
_scoped_buffer_end :: proc(ctx: ^Context, buffer: ^Buffer, _, _: string, _ := #caller_location) { _scoped_buffer_end :: proc(ctx: ^Context, buffer: ^Buffer, _, _: string, _ := #caller_location) {
_buffer_end(ctx, buffer) _buffer_end(ctx, buffer)
} }
@(no_instrumentation) @(no_instrumentation)
_trace_now :: proc "contextless" (ctx: ^Context) -> f64 { _trace_now :: proc "contextless" (ctx: ^Context) -> u64 {
if !ctx.precise_time { if !ctx.precise_time {
return f64(tick_now()) / 1_000 return u64(tick_now())
} }
return f64(intrinsics.read_cycle_counter()) return u64(intrinsics.read_cycle_counter())
} }
@(no_instrumentation) @(no_instrumentation)
_build_header :: proc "contextless" (buffer: []u8, timestamp_scale: f64) -> (header_size: int, ok: bool) #optional_ok { _build_stream_header :: proc "contextless" (buffer: []u8, timestamp_scale: f64) -> (header_size: int, ok: bool) #optional_ok {
header_size = size_of(Manual_Header) header_size = size_of(Manual_Stream_Header)
if header_size > len(buffer) { if header_size > len(buffer) {
return 0, false return 0, false
} }
hdr := (^Manual_Header)(raw_data(buffer)) hdr := (^Manual_Stream_Header)(raw_data(buffer))
hdr.magic = MANUAL_MAGIC hdr.magic = MANUAL_MAGIC
hdr.version = 1 hdr.version = 3
hdr.timestamp_scale = f64le(timestamp_scale) hdr.timestamp_scale = f64le(timestamp_scale)
hdr.reserved = 0 hdr.reserved = 0
ok = true ok = true
@@ -166,7 +195,7 @@ _build_header :: proc "contextless" (buffer: []u8, timestamp_scale: f64) -> (hea
} }
@(no_instrumentation) @(no_instrumentation)
_build_begin :: #force_inline proc "contextless" (buffer: []u8, name: string, args: string, ts: f64, tid: u32, pid: u32) -> (event_size: int, ok: bool) #optional_ok #no_bounds_check /* bounds check would segfault instrumentation */ { _build_begin :: #force_inline proc "contextless" (buffer: []u8, name: string, args: string, ts: u64) -> (event_size: int, ok: bool) #optional_ok #no_bounds_check /* bounds check would segfault instrumentation */ {
ev := (^Begin_Event)(raw_data(buffer)) ev := (^Begin_Event)(raw_data(buffer))
name_len := min(len(name), 255) name_len := min(len(name), 255)
args_len := min(len(args), 255) args_len := min(len(args), 255)
@@ -177,9 +206,7 @@ _build_begin :: #force_inline proc "contextless" (buffer: []u8, name: string, ar
} }
ev.type = .Begin ev.type = .Begin
ev.pid = u32le(pid) ev.ts = u64le(ts)
ev.tid = u32le(tid)
ev.ts = f64le(ts)
ev.name_len = u8(name_len) ev.name_len = u8(name_len)
ev.args_len = u8(args_len) ev.args_len = u8(args_len)
intrinsics.mem_copy_non_overlapping(raw_data(buffer[size_of(Begin_Event):]), raw_data(name), name_len) intrinsics.mem_copy_non_overlapping(raw_data(buffer[size_of(Begin_Event):]), raw_data(name), name_len)
@@ -190,7 +217,7 @@ _build_begin :: #force_inline proc "contextless" (buffer: []u8, name: string, ar
} }
@(no_instrumentation) @(no_instrumentation)
_build_end :: proc "contextless" (buffer: []u8, ts: f64, tid: u32, pid: u32) -> (event_size: int, ok: bool) #optional_ok { _build_end :: proc "contextless" (buffer: []u8, ts: u64) -> (event_size: int, ok: bool) #optional_ok {
ev := (^End_Event)(raw_data(buffer)) ev := (^End_Event)(raw_data(buffer))
event_size = size_of(End_Event) event_size = size_of(End_Event)
if event_size > len(buffer) { if event_size > len(buffer) {
@@ -198,9 +225,28 @@ _build_end :: proc "contextless" (buffer: []u8, ts: f64, tid: u32, pid: u32) ->
} }
ev.type = .End ev.type = .End
ev.pid = u32le(pid) ev.ts = u64le(ts)
ev.tid = u32le(tid) ok = true
ev.ts = f64le(ts)
return
}
@(no_instrumentation)
_build_name_event :: #force_inline proc "contextless" (buffer: []u8, name: string, type: Manual_Event_Type) -> (event_size: int, ok: bool) #optional_ok #no_bounds_check /* bounds check would segfault instrumentation */ {
ev := (^Name_Event)(raw_data(buffer))
name_len := min(len(name), 255)
event_size = size_of(Name_Event) + name_len
if event_size > len(buffer) {
return 0, false
}
if type != .Name_Process && type != .Name_Thread {
return 0, false
}
ev.type = type
ev.name_len = u8(name_len)
intrinsics.mem_copy_non_overlapping(raw_data(buffer[size_of(Name_Event):]), raw_data(name), name_len)
ok = true ok = true
return return
@@ -212,7 +258,7 @@ _buffer_begin :: proc "contextless" (ctx: ^Context, buffer: ^Buffer, name: strin
buffer_flush(ctx, buffer) buffer_flush(ctx, buffer)
} }
name := location.procedure if name == "" else name name := location.procedure if name == "" else name
buffer.head += _build_begin(buffer.data[buffer.head:], name, args, _trace_now(ctx), buffer.tid, buffer.pid) buffer.head += _build_begin(buffer.data[buffer.head:], name, args, _trace_now(ctx))
} }
@(no_instrumentation) @(no_instrumentation)
@@ -223,7 +269,23 @@ _buffer_end :: proc "contextless" (ctx: ^Context, buffer: ^Buffer) #no_bounds_ch
buffer_flush(ctx, buffer) buffer_flush(ctx, buffer)
} }
buffer.head += _build_end(buffer.data[buffer.head:], ts, buffer.tid, buffer.pid) buffer.head += _build_end(buffer.data[buffer.head:], ts)
}
@(no_instrumentation)
_buffer_name_thread :: proc "contextless" (ctx: ^Context, buffer: ^Buffer, name: string, location := #caller_location) #no_bounds_check /* bounds check would segfault instrumentation */ {
if buffer.head + NAME_EVENT_MAX > len(buffer.data) {
buffer_flush(ctx, buffer)
}
buffer.head += _build_name_event(buffer.data[buffer.head:], name, .Name_Thread)
}
@(no_instrumentation)
_buffer_name_process :: proc "contextless" (ctx: ^Context, buffer: ^Buffer, name: string, location := #caller_location) #no_bounds_check /* bounds check would segfault instrumentation */ {
if buffer.head + NAME_EVENT_MAX > len(buffer.data) {
buffer_flush(ctx, buffer)
}
buffer.head += _build_name_event(buffer.data[buffer.head:], name, .Name_Process)
} }
@(no_instrumentation) @(no_instrumentation)
+1 -1
View File
@@ -630,7 +630,7 @@ write_type_writer :: #force_no_inline proc(w: io.Writer, ti: ^Type_Info, n_writt
io.write_string(w, "struct ", &n) or_return io.write_string(w, "struct ", &n) or_return
if .packed in info.flags { io.write_string(w, "#packed ", &n) or_return } if .packed in info.flags { io.write_string(w, "#packed ", &n) or_return }
if .raw_union in info.flags { io.write_string(w, "#raw_union ", &n) or_return } if .raw_union in info.flags { io.write_string(w, "#raw_union ", &n) or_return }
if .no_copy in info.flags { io.write_string(w, "#no_copy ", &n) or_return } // if .no_copy in info.flags { io.write_string(w, "#no_copy ", &n) or_return }
if .align in info.flags { if .align in info.flags {
io.write_string(w, "#align(", &n) or_return io.write_string(w, "#align(", &n) or_return
io.write_i64(w, i64(ti.align), 10, &n) or_return io.write_i64(w, i64(ti.align), 10, &n) or_return
+51
View File
@@ -2440,6 +2440,57 @@ Graphically, the operation looks as follows. The `t` and `f` represent the
*/ */
select :: intrinsics.simd_select select :: intrinsics.simd_select
/*
Runtime Equivalent to Shuffle.
Performs element-wise table lookups using runtime indices.
Each element in the indices vector selects an element from the table vector.
The indices are automatically masked to prevent out-of-bounds access.
This operation is hardware-accelerated on most platforms when using 8-bit
integer vectors. For other element types or unsupported vector sizes, it
falls back to software emulation.
Inputs:
- `table`: The lookup table vector (should be power-of-2 size for correct masking).
- `indices`: The indices vector (automatically masked to valid range).
Returns:
- A vector where `result[i] = table[indices[i] & (table_size-1)]`.
Operation:
for i in 0 ..< len(indices) {
masked_index := indices[i] & (len(table) - 1)
result[i] = table[masked_index]
}
return result
Implementation:
| Platform | Lane Size | Implementation |
|-------------|-------------------------------------------|---------------------|
| x86-64 | pshufb (16B), vpshufb (32B), AVX512 (64B) | Single vector |
| ARM64 | tbl1 (16B), tbl2 (32B), tbl4 (64B) | Automatic splitting |
| ARM32 | vtbl1 (8B), vtbl2 (16B), vtbl4 (32B) | Automatic splitting |
| WebAssembly | i8x16.swizzle (16B), Emulation (>16B) | Mixed |
| Other | Emulation | Software |
Example:
import "core:simd"
import "core:fmt"
runtime_swizzle_example :: proc() {
table := simd.u8x16{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}
indices := simd.u8x16{15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}
result := simd.runtime_swizzle(table, indices)
fmt.println(result) // Expected: {15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}
}
*/
runtime_swizzle :: intrinsics.simd_runtime_swizzle
/* /*
Compute the square root of each lane in a SIMD vector. Compute the square root of each lane in a SIMD vector.
*/ */
+6 -12
View File
@@ -47,12 +47,12 @@ wait_group_add :: proc "contextless" (wg: ^Wait_Group, delta: int) {
guard(&wg.mutex) guard(&wg.mutex)
atomic_add(&wg.counter, delta) atomic_add(&wg.counter, delta)
if wg.counter < 0 { switch counter := atomic_load(&wg.counter); {
case counter < 0:
panic_contextless("sync.Wait_Group negative counter") panic_contextless("sync.Wait_Group negative counter")
} case wg.counter == 0:
if wg.counter == 0 {
cond_broadcast(&wg.cond) cond_broadcast(&wg.cond)
if wg.counter != 0 { if atomic_load(&wg.counter) != 0 {
panic_contextless("sync.Wait_Group misuse: sync.wait_group_add called concurrently with sync.wait_group_wait") panic_contextless("sync.Wait_Group misuse: sync.wait_group_add called concurrently with sync.wait_group_wait")
} }
} }
@@ -78,11 +78,8 @@ wait group's internal counter reaches zero.
wait_group_wait :: proc "contextless" (wg: ^Wait_Group) { wait_group_wait :: proc "contextless" (wg: ^Wait_Group) {
guard(&wg.mutex) guard(&wg.mutex)
if wg.counter != 0 { for atomic_load(&wg.counter) != 0 {
cond_wait(&wg.cond, &wg.mutex) cond_wait(&wg.cond, &wg.mutex)
if wg.counter != 0 {
panic_contextless("sync.Wait_Group misuse: sync.wait_group_add called concurrently with sync.wait_group_wait")
}
} }
} }
@@ -100,13 +97,10 @@ wait_group_wait_with_timeout :: proc "contextless" (wg: ^Wait_Group, duration: t
} }
guard(&wg.mutex) guard(&wg.mutex)
if wg.counter != 0 { for atomic_load(&wg.counter) != 0 {
if !cond_wait_with_timeout(&wg.cond, &wg.mutex, duration) { if !cond_wait_with_timeout(&wg.cond, &wg.mutex, duration) {
return false return false
} }
if wg.counter != 0 {
panic_contextless("sync.Wait_Group misuse: sync.wait_group_add called concurrently with sync.wait_group_wait")
}
} }
return true return true
} }
+1 -1
View File
@@ -6,7 +6,7 @@ import "core:c"
import "core:sys/darwin" import "core:sys/darwin"
import "core:time" import "core:time"
foreign import System "system:System.framework" foreign import System "system:System"
foreign System { foreign System {
// __ulock_wait is not available on 10.15 // __ulock_wait is not available on 10.15
+1 -1
View File
@@ -5,7 +5,7 @@ package sync
import "core:c" import "core:c"
import "base:intrinsics" import "base:intrinsics"
foreign import pthread "system:System.framework" foreign import pthread "system:System"
_current_thread_id :: proc "contextless" () -> int { _current_thread_id :: proc "contextless" () -> int {
tid: u64 tid: u64
+1 -1
View File
@@ -62,7 +62,7 @@ global_block_descriptor := Block_Descriptor{
size = size_of(Internal_Block_Literal), size = size_of(Internal_Block_Literal),
} }
foreign import libSystem "system:System.framework" foreign import libSystem "system:System"
foreign libSystem { foreign libSystem {
_NSConcreteGlobalBlock: intrinsics.objc_class _NSConcreteGlobalBlock: intrinsics.objc_class
_NSConcreteStackBlock: intrinsics.objc_class _NSConcreteStackBlock: intrinsics.objc_class
+1 -1
View File
@@ -4,7 +4,7 @@ package darwin
import "core:c" import "core:c"
@(export) @(export)
foreign import system "system:System.framework" foreign import system "system:System"
Bool :: b8 Bool :: b8
+336 -15
View File
@@ -1,19 +1,38 @@
package darwin package darwin
foreign import mach "system:System.framework" foreign import mach "system:System"
import "core:c" import "core:c"
import "base:intrinsics" import "base:intrinsics"
kern_return_t :: distinct c.int
mach_port_t :: distinct c.uint mach_port_t :: distinct c.uint
task_t :: mach_port_t
semaphore_t :: distinct u64
kern_return_t :: distinct c.int
thread_act_t :: distinct u64
thread_state_t :: distinct ^u32
thread_list_t :: [^]thread_act_t
vm_region_recurse_info_t :: distinct ^i32
task_info_t :: distinct ^i32
MACH_PORT_NULL :: 0
MACH_PORT_DEAD :: ~mach_port_t(0)
MACH_MSG_PORT_DESCRIPTOR :: 0
X86_THREAD_STATE32 :: 1
X86_THREAD_STATE64 :: 4
ARM_THREAD_STATE64 :: 6
mach_msg_option_t :: distinct i32
name_t :: distinct cstring
vm_map_t :: mach_port_t vm_map_t :: mach_port_t
mem_entry_name_port_t :: mach_port_t mem_entry_name_port_t :: mach_port_t
ipc_space_t :: mach_port_t ipc_space_t :: mach_port_t
thread_t :: mach_port_t thread_t :: mach_port_t
task_t :: mach_port_t
semaphore_t :: mach_port_t
vm_size_t :: distinct c.uintptr_t vm_size_t :: distinct c.uintptr_t
@@ -29,11 +48,279 @@ vm_inherit_t :: distinct c.uint
mach_port_name_t :: distinct c.uint mach_port_name_t :: distinct c.uint
mach_port_right_t :: distinct c.uint
sync_policy_t :: distinct c.int sync_policy_t :: distinct c.int
mach_msg_port_descriptor_t :: struct {
name: mach_port_t,
_: u32,
using _: bit_field u32 {
_: u32 | 16,
disposition: u32 | 8,
type: u32 | 8,
},
}
Task_Port_Type :: enum u32 {
Kernel = 1,
Host,
Name,
Bootstrap,
Seatbelt = 7,
Access = 9,
}
Bootstrap_Error :: enum u32 {
Success,
Not_Privileged = 1100,
Name_In_Use = 1101,
Unknown_Service = 1102,
Service_Active = 1103,
Bad_Count = 1104,
No_Memory = 1105,
No_Children = 1106,
}
Msg_Type :: enum u32 {
Unstructured = 0,
Bit = 0,
Boolean = 0,
Integer_16 = 1,
Integer_32 = 2,
Char = 8,
Byte = 9,
Integer_8 = 9,
Real = 10,
Integer_64 = 11,
String = 12,
String_C = 12,
Port_Name = 15,
Move_Receive = 16,
Port_Receive = 16,
Move_Send = 17,
Port_Send = 17,
Move_Send_Once = 18,
Port_Send_Once = 18,
Copy_Send = 19,
Make_Send = 20,
Make_Send_Once = 21,
}
Msg_Header_Bits :: enum u32 {
Zero = 0,
Remote_Mask = 0xff,
Local_Mask = 0xff00,
Migrated = 0x08000000,
Unused = 0x07ff0000,
Complex_Data = 0x10000000,
Complex_Ports = 0x20000000,
Circular = 0x40000000,
Complex = 0x80000000,
}
mach_msg_type_t :: struct {
using _: bit_field u32 {
name: u32 | 8,
size: u32 | 8,
number: u32 | 12,
inline: u32 | 1,
longform: u32 | 1,
deallocate: u32 | 1,
unused: u32 | 1,
},
}
mach_msg_header_t :: struct {
msgh_bits: u32,
msgh_size: u32,
msgh_remote_port: mach_port_t,
msgh_local_port: mach_port_t,
msgh_voucher_port: u32,
msgh_id: i32,
}
mach_msg_body_t :: struct {
msgh_descriptor_count: u32,
}
mach_msg_trailer_t :: struct {
msgh_trailer_type: u32,
msgh_trailer_size: u32,
}
x86_thread_state32_t :: struct {
eax: u32,
ebx: u32,
ecx: u32,
edx: u32,
edi: u32,
esi: u32,
ebp: u32,
esp: u32,
ss: u32,
eflags: u32,
eip: u32,
cs: u32,
ds: u32,
es: u32,
fs: u32,
gs: u32,
}
X86_THREAD_STATE32_COUNT :: size_of(x86_thread_state32_t) / size_of(u32)
x86_thread_state64_t :: struct #packed {
rax: u64,
rbx: u64,
rcx: u64,
rdx: u64,
rdi: u64,
rsi: u64,
rbp: u64,
rsp: u64,
r8: u64,
r9: u64,
r10: u64,
r11: u64,
r12: u64,
r13: u64,
r14: u64,
r15: u64,
rip: u64,
rflags: u64,
cs: u64,
fs: u64,
gs: u64,
}
X86_THREAD_STATE64_COUNT :: size_of(x86_thread_state64_t) / size_of(u32)
arm_thread_state64_t :: struct #packed {
x: [29]u64,
fp: u64,
lr: u64,
sp: u64,
pc: u64,
cpsr: u32,
pad: u32,
}
ARM_THREAD_STATE64_COUNT :: size_of(arm_thread_state64_t) / size_of(u32)
THREAD_IDENTIFIER_INFO :: 4
thread_identifier_info :: struct {
thread_id: u64,
thread_handler: u64,
dispatch_qaddr: u64,
}
THREAD_IDENTIFIER_INFO_COUNT :: size_of(thread_identifier_info) / size_of(u32)
vm_region_submap_info_64 :: struct {
protection: u32,
max_protection: u32,
inheritance: u32,
offset: u64,
user_tag: u32,
pages_residept: u32,
pages_shared_now_private: u32,
pages_swapped_out: u32,
pages_dirtied: u32,
ref_count: u32,
shadow_depth: u16,
external_pager: u8,
share_mode: u8,
is_submap: b32,
behavior: i32,
object_id: u32,
user_wired_count: u16,
pages_reusable: u32,
}
VM_REGION_SUBMAP_INFO_COUNT_64 :: size_of(vm_region_submap_info_64) / size_of(u32)
TASK_DYLD_INFO :: 17
task_dyld_info :: struct {
all_image_info_addr: u64,
all_image_info_size: u64,
all_image_info_format: i32,
}
TASK_DYLD_INFO_COUNT :: size_of(task_dyld_info) / size_of(u32)
dyld_image_info :: struct {
image_load_addr: u64,
image_file_path: cstring,
image_file_mod_date: u64,
}
dyld_uuid_info :: struct {
image_load_addr: u64,
image_uuid: [16]u8,
}
dyld_all_image_infos :: struct {
version: u32,
info_array_count: u32,
info_array: rawptr,
notification: rawptr,
process_detached_from_shared_region: b32,
libSystem_initialized: b32,
dyld_image_load_addr: u64,
jit_info: rawptr,
dyld_version: cstring,
error_message: cstring,
termination_flags: u64,
core_symbolication_shm_page: rawptr,
system_order_flag: u64,
uuid_array_count: u64,
uuid_array: rawptr,
dyld_all_image_infos_addr: u64,
initial_image_count: u64,
error_kind: u64,
error_client_of_dylib_path: cstring,
error_target_dylib_path: cstring,
error_symbol: cstring,
shared_cache_slide: u64,
shared_cache_uuid: [16]u8,
shared_cache_base_addr: u64,
info_array_change_timestamp: u64,
dyld_path: cstring,
notify_ports: [8]mach_port_t,
reserved: [7]u64,
shared_cache_fsid: u64,
shared_cache_fsobjid: u64,
compact_dyld_image_info_addr: u64,
compact_dyld_image_info_size: u64,
platform: u32,
aot_info_count: u32,
aot_info_array: rawptr,
aot_info_array_change_timestamp: u64,
aot_shared_cache_base_address: u64,
aot_shared_cache_uuid: [16]u8,
}
@(default_calling_convention="c") @(default_calling_convention="c")
foreign mach { foreign mach {
mach_task_self :: proc() -> mach_port_t --- mach_task_self :: proc() -> mach_port_t ---
mach_msg :: proc(header: rawptr, option: Msg_Option_Flags, send_size: u32, receive_limit: u32, receive_name: mach_port_t, timeout: u32, notify: mach_port_t) -> Kern_Return ---
mach_msg_send :: proc(header: rawptr) -> Kern_Return ---
mach_vm_allocate :: proc(target_task: task_t, adddress: u64, size: u64, flags: i32) -> Kern_Return ---
mach_vm_deallocate :: proc(target_task: task_t, adddress: ^u64, size: u64) -> Kern_Return ---
mach_vm_remap :: proc(target_task: task_t, page: rawptr, size: u64, mask: u64, flags: i32, src_task: task_t, src_address: u64, copy: b32, cur_protection: ^i32, max_protection: ^i32, inheritance: VM_Inherit) -> Kern_Return ---
mach_vm_region_recurse :: proc(target_task: task_t, address: ^u64, size: ^u64, depth: ^u32, info: vm_region_recurse_info_t, count: ^u32) -> Kern_Return ---
vm_page_size: u64
vm_page_mask: u64
vm_page_shift: i32
mach_port_allocate :: proc(task: task_t, right: Port_Right, name: rawptr) -> Kern_Return ---
mach_port_deallocate :: proc(task: task_t, name: u32) -> Kern_Return ---
mach_port_extract_right :: proc(task: task_t, name: u32, msgt_name: u32, poly: ^mach_port_t, poly_poly: ^mach_port_t) -> Kern_Return ---
task_get_special_port :: proc(task: task_t, port: i32, special_port: ^mach_port_t) -> Kern_Return ---
task_suspend :: proc(task: task_t) -> Kern_Return ---
task_resume :: proc(task: task_t) -> Kern_Return ---
task_threads :: proc(task: task_t, thread_list: ^thread_list_t, list_count: ^u32) -> Kern_Return ---
task_info :: proc(task: task_t, flavor: i32, info: task_info_t, count: ^u32) -> Kern_Return ---
task_terminate :: proc(task: task_t) -> Kern_Return ---
semaphore_create :: proc(task: task_t, semaphore: ^semaphore_t, policy: Sync_Policy, value: c.int) -> Kern_Return --- semaphore_create :: proc(task: task_t, semaphore: ^semaphore_t, policy: Sync_Policy, value: c.int) -> Kern_Return ---
semaphore_destroy :: proc(task: task_t, semaphore: semaphore_t) -> Kern_Return --- semaphore_destroy :: proc(task: task_t, semaphore: semaphore_t) -> Kern_Return ---
@@ -44,9 +331,11 @@ foreign mach {
semaphore_wait :: proc(semaphore: semaphore_t) -> Kern_Return --- semaphore_wait :: proc(semaphore: semaphore_t) -> Kern_Return ---
vm_allocate :: proc (target_task : vm_map_t, address: ^vm_address_t, size: vm_size_t, flags: VM_Flags) -> Kern_Return --- thread_get_state :: proc(thread: thread_act_t, flavor: i32, thread_state: thread_state_t, old_state_count: ^u32) -> Kern_Return ---
thread_info :: proc(thread: thread_act_t, flavor: u32, thread_info: ^thread_identifier_info, info_count: ^u32) -> Kern_Return ---
vm_deallocate :: proc(target_task: vm_map_t, address: vm_address_t, size: vm_size_t) -> Kern_Return --- bootstrap_register2 :: proc(bp: mach_port_t, service_name: name_t, sp: mach_port_t, flags: u64) -> Kern_Return ---
bootstrap_look_up :: proc(bp: mach_port_t, service_name: name_t, sp: ^mach_port_t) -> Kern_Return ---
vm_map :: proc( vm_map :: proc(
target_task: vm_map_t, target_task: vm_map_t,
@@ -70,15 +359,10 @@ foreign mach {
object_handle: ^mem_entry_name_port_t, object_handle: ^mem_entry_name_port_t,
parent_entry: mem_entry_name_port_t, parent_entry: mem_entry_name_port_t,
) -> Kern_Return --- ) -> Kern_Return ---
mach_port_deallocate :: proc(
task: ipc_space_t,
name: mach_port_name_t,
) -> Kern_Return ---
vm_page_size: vm_size_t
} }
Kern_Return :: enum kern_return_t { Kern_Return :: enum kern_return_t {
Success, Success,
@@ -500,6 +784,39 @@ VM_PROT_NONE :: VM_Prot_Flags{}
VM_PROT_DEFAULT :: VM_Prot_Flags{.Read, .Write} VM_PROT_DEFAULT :: VM_Prot_Flags{.Read, .Write}
VM_PROT_ALL :: VM_Prot_Flags{.Read, .Write, .Execute} VM_PROT_ALL :: VM_Prot_Flags{.Read, .Write, .Execute}
/*
* Mach msg options, defined as bits within the mach_msg_option_t type
*/
Msg_Option :: enum mach_msg_option_t {
Send_Msg,
Receive_Msg,
Send_Timeout = LOG2(0x10),
Send_Notify = LOG2(0x20),
Send_Interrupt = LOG2(0x40),
Send_Cancel = LOG2(0x80),
Receive_Timeout = LOG2(0x100),
Receive_Notify = LOG2(0x200),
Receive_Interrupt = LOG2(0x400),
Receive_Large = LOG2(0x800),
Send_Always = LOG2(0x10000),
}
Msg_Option_Flags :: distinct bit_set[Msg_Option; mach_msg_option_t]
/*
* Enumeration of valid values for mach_port_right_t
*/
Port_Right :: enum mach_port_right_t {
Send,
Receive,
Send_Once,
Port_Set,
Dead_Name,
}
/* /*
* Enumeration of valid values for vm_inherit_t. * Enumeration of valid values for vm_inherit_t.
*/ */
@@ -522,3 +839,7 @@ Sync_Policy :: enum sync_policy_t {
Lifo = Fifo | Reversed, Lifo = Fifo | Reversed,
} }
mach_vm_trunc_page :: proc(v: u64) -> u64 {
return v & ~vm_page_mask
}
+1 -1
View File
@@ -4,7 +4,7 @@ import "base:intrinsics"
import "core:sys/posix" import "core:sys/posix"
foreign import lib "system:System.framework" foreign import lib "system:System"
// Incomplete bindings to the proc API on MacOS, add to when needed. // Incomplete bindings to the proc API on MacOS, add to when needed.
+5 -15
View File
@@ -3,23 +3,13 @@ package darwin
// #define OS_WAIT_ON_ADDR_AVAILABILITY \ // #define OS_WAIT_ON_ADDR_AVAILABILITY \
// __API_AVAILABLE(macos(14.4), ios(17.4), tvos(17.4), watchos(10.4)) // __API_AVAILABLE(macos(14.4), ios(17.4), tvos(17.4), watchos(10.4))
when ODIN_OS == .Darwin { when ODIN_OS == .Darwin {
when ODIN_PLATFORM_SUBTARGET_IOS {
when ODIN_PLATFORM_SUBTARGET == .iOS && ODIN_MINIMUM_OS_VERSION >= 17_04_00 { WAIT_ON_ADDRESS_AVAILABLE :: ODIN_MINIMUM_OS_VERSION >= 17_04_00
WAIT_ON_ADDRESS_AVAILABLE :: true ULOCK_WAIT_2_AVAILABLE :: ODIN_MINIMUM_OS_VERSION >= 14_00_00
} else when ODIN_MINIMUM_OS_VERSION >= 14_04_00 {
WAIT_ON_ADDRESS_AVAILABLE :: true
} else { } else {
WAIT_ON_ADDRESS_AVAILABLE :: false WAIT_ON_ADDRESS_AVAILABLE :: ODIN_MINIMUM_OS_VERSION >= 14_04_00
ULOCK_WAIT_2_AVAILABLE :: ODIN_MINIMUM_OS_VERSION >= 11_00_00
} }
when ODIN_PLATFORM_SUBTARGET == .iOS && ODIN_MINIMUM_OS_VERSION >= 14_00_00 {
ULOCK_WAIT_2_AVAILABLE :: true
} else when ODIN_MINIMUM_OS_VERSION >= 11_00_00 {
ULOCK_WAIT_2_AVAILABLE :: true
} else {
ULOCK_WAIT_2_AVAILABLE :: false
}
} else { } else {
WAIT_ON_ADDRESS_AVAILABLE :: false WAIT_ON_ADDRESS_AVAILABLE :: false
ULOCK_WAIT_2_AVAILABLE :: false ULOCK_WAIT_2_AVAILABLE :: false
+1 -1
View File
@@ -28,7 +28,7 @@ init_platform :: proc() {
macos_version = {int(version.majorVersion), int(version.minorVersion), int(version.patchVersion)} macos_version = {int(version.majorVersion), int(version.minorVersion), int(version.patchVersion)}
when ODIN_PLATFORM_SUBTARGET == .iOS { when ODIN_PLATFORM_SUBTARGET_IOS {
os_version.platform = .iOS os_version.platform = .iOS
ws(&b, "iOS") ws(&b, "iOS")
} else { } else {
+1 -1
View File
@@ -2,7 +2,7 @@
package kqueue package kqueue
when ODIN_OS == .Darwin { when ODIN_OS == .Darwin {
foreign import lib "system:System.framework" foreign import lib "system:System"
} else { } else {
foreign import lib "system:c" foreign import lib "system:c"
} }
+1 -1
View File
@@ -4,7 +4,7 @@ package posix
import "core:c" import "core:c"
when ODIN_OS == .Darwin { when ODIN_OS == .Darwin {
foreign import lib "system:System.framework" foreign import lib "system:System"
} else when ODIN_OS == .Haiku { } else when ODIN_OS == .Haiku {
foreign import lib "system:network" foreign import lib "system:network"
} else { } else {
+1 -1
View File
@@ -4,7 +4,7 @@ package posix
import "core:c" import "core:c"
when ODIN_OS == .Darwin { when ODIN_OS == .Darwin {
foreign import lib "system:System.framework" foreign import lib "system:System"
} else { } else {
foreign import lib "system:c" foreign import lib "system:c"
} }
+1 -1
View File
@@ -4,7 +4,7 @@ package posix
import "core:c" import "core:c"
when ODIN_OS == .Darwin { when ODIN_OS == .Darwin {
foreign import lib "system:System.framework" foreign import lib "system:System"
} else when ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD { } else when ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD {
foreign import lib "system:dl" foreign import lib "system:dl"
} else { } else {
+1 -1
View File
@@ -4,7 +4,7 @@ package posix
import "core:c" import "core:c"
when ODIN_OS == .Darwin { when ODIN_OS == .Darwin {
foreign import lib "system:System.framework" foreign import lib "system:System"
} else { } else {
foreign import lib "system:c" foreign import lib "system:c"
} }
+1 -1
View File
@@ -4,7 +4,7 @@ package posix
import "core:c" import "core:c"
when ODIN_OS == .Darwin { when ODIN_OS == .Darwin {
foreign import lib "system:System.framework" foreign import lib "system:System"
} else { } else {
foreign import lib "system:c" foreign import lib "system:c"
} }
+1 -1
View File
@@ -4,7 +4,7 @@ package posix
import "core:c" import "core:c"
when ODIN_OS == .Darwin { when ODIN_OS == .Darwin {
foreign import lib "system:System.framework" foreign import lib "system:System"
} else { } else {
foreign import lib "system:c" foreign import lib "system:c"
} }
+1 -1
View File
@@ -4,7 +4,7 @@ package posix
import "core:c" import "core:c"
when ODIN_OS == .Darwin { when ODIN_OS == .Darwin {
foreign import lib "system:System.framework" foreign import lib "system:System"
} else { } else {
foreign import lib "system:c" foreign import lib "system:c"
} }
+1 -1
View File
@@ -4,7 +4,7 @@ package posix
import "core:c" import "core:c"
when ODIN_OS == .Darwin { when ODIN_OS == .Darwin {
foreign import lib "system:System.framework" foreign import lib "system:System"
} else { } else {
foreign import lib "system:c" foreign import lib "system:c"
} }
+1 -1
View File
@@ -2,7 +2,7 @@
package posix package posix
when ODIN_OS == .Darwin { when ODIN_OS == .Darwin {
foreign import lib "system:System.framework" foreign import lib "system:System"
} else { } else {
foreign import lib "system:c" foreign import lib "system:c"
} }
+1 -1
View File
@@ -4,7 +4,7 @@ package posix
import "core:c" import "core:c"
when ODIN_OS == .Darwin { when ODIN_OS == .Darwin {
foreign import lib "system:System.framework" foreign import lib "system:System"
} else { } else {
foreign import lib "system:c" foreign import lib "system:c"
} }
+1 -1
View File
@@ -4,7 +4,7 @@ package posix
import "core:c" import "core:c"
when ODIN_OS == .Darwin { when ODIN_OS == .Darwin {
foreign import lib "system:System.framework" foreign import lib "system:System"
} else { } else {
foreign import lib "system:c" foreign import lib "system:c"
} }
+1 -1
View File
@@ -4,7 +4,7 @@ package posix
import "core:c" import "core:c"
when ODIN_OS == .Darwin { when ODIN_OS == .Darwin {
foreign import lib "system:System.framework" foreign import lib "system:System"
} else { } else {
foreign import lib "system:c" foreign import lib "system:c"
} }
+1 -1
View File
@@ -4,7 +4,7 @@ package posix
import "core:c" import "core:c"
when ODIN_OS == .Darwin { when ODIN_OS == .Darwin {
foreign import lib "system:System.framework" foreign import lib "system:System"
} else { } else {
foreign import lib "system:c" foreign import lib "system:c"
} }
+1 -1
View File
@@ -6,7 +6,7 @@ import "base:intrinsics"
import "core:c" import "core:c"
when ODIN_OS == .Darwin { when ODIN_OS == .Darwin {
foreign import lib "system:System.framework" foreign import lib "system:System"
} else { } else {
foreign import lib "system:c" foreign import lib "system:c"
} }
+1 -1
View File
@@ -4,7 +4,7 @@ package posix
import "core:c" import "core:c"
when ODIN_OS == .Darwin { when ODIN_OS == .Darwin {
foreign import lib "system:System.framework" foreign import lib "system:System"
} else when ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .Linux { } else when ODIN_OS == .FreeBSD || ODIN_OS == .NetBSD || ODIN_OS == .Linux {
foreign import lib "system:pthread" foreign import lib "system:pthread"
} else { } else {
+1 -1
View File
@@ -4,7 +4,7 @@ package posix
import "core:c" import "core:c"
when ODIN_OS == .Darwin { when ODIN_OS == .Darwin {
foreign import lib "system:System.framework" foreign import lib "system:System"
} else { } else {
foreign import lib "system:c" foreign import lib "system:c"
} }
+1 -1
View File
@@ -4,7 +4,7 @@ package posix
import "core:c" import "core:c"
when ODIN_OS == .Darwin { when ODIN_OS == .Darwin {
foreign import lib "system:System.framework" foreign import lib "system:System"
} else { } else {
foreign import lib "system:c" foreign import lib "system:c"
} }
+1 -1
View File
@@ -4,7 +4,7 @@ package posix
import "core:c" import "core:c"
when ODIN_OS == .Darwin { when ODIN_OS == .Darwin {
foreign import lib "system:System.framework" foreign import lib "system:System"
} else { } else {
foreign import lib "system:c" foreign import lib "system:c"
} }
+1 -1
View File
@@ -6,7 +6,7 @@ import "base:intrinsics"
import "core:c" import "core:c"
when ODIN_OS == .Darwin { when ODIN_OS == .Darwin {
foreign import lib "system:System.framework" foreign import lib "system:System"
} else { } else {
foreign import lib "system:c" foreign import lib "system:c"
} }
+1 -1
View File
@@ -9,7 +9,7 @@ import "core:c/libc"
when ODIN_OS == .Windows { when ODIN_OS == .Windows {
foreign import lib "system:libucrt.lib" foreign import lib "system:libucrt.lib"
} else when ODIN_OS == .Darwin { } else when ODIN_OS == .Darwin {
foreign import lib "system:System.framework" foreign import lib "system:System"
} else { } else {
foreign import lib "system:c" foreign import lib "system:c"
} }
+20
View File
@@ -0,0 +1,20 @@
package posix
when ODIN_OS == .Darwin {
foreign import lib "system:System.framework"
} else {
foreign import lib "system:c"
}
foreign lib {
/*
Creates a child process from a provided filepath
spawnp searches directories on the path for the file
Returns: 0 on success, with the child pid returned in the pid argument, or error values on failure.
[[ More; https://pubs.opengroup.org/onlinepubs/9699919799/functions/posix_spawn.html ]]
*/
posix_spawn :: proc(pid: ^pid_t, path: cstring, file_actions: rawptr, attrp: rawptr, argv: [^]cstring, envp: [^]cstring) -> Errno ---
posix_spawnp :: proc(pid: ^pid_t, file: cstring, file_actions: rawptr, attrp: rawptr, argv: [^]cstring, envp: [^]cstring) -> Errno ---
}
+1 -1
View File
@@ -4,7 +4,7 @@ package posix
import "core:c" import "core:c"
when ODIN_OS == .Darwin { when ODIN_OS == .Darwin {
foreign import lib "system:System.framework" foreign import lib "system:System"
} else { } else {
foreign import lib "system:c" foreign import lib "system:c"
} }
+1 -1
View File
@@ -10,7 +10,7 @@ when ODIN_OS == .Windows {
"system:legacy_stdio_definitions.lib", "system:legacy_stdio_definitions.lib",
} }
} else when ODIN_OS == .Darwin { } else when ODIN_OS == .Darwin {
foreign import lib "system:System.framework" foreign import lib "system:System"
} else { } else {
foreign import lib "system:c" foreign import lib "system:c"
} }
+1 -1
View File
@@ -6,7 +6,7 @@ import "base:intrinsics"
import "core:c" import "core:c"
when ODIN_OS == .Darwin { when ODIN_OS == .Darwin {
foreign import lib "system:System.framework" foreign import lib "system:System"
} else { } else {
foreign import lib "system:c" foreign import lib "system:c"
} }
+1 -1
View File
@@ -9,7 +9,7 @@ import "core:c/libc"
when ODIN_OS == .Windows { when ODIN_OS == .Windows {
foreign import lib "system:libucrt.lib" foreign import lib "system:libucrt.lib"
} else when ODIN_OS == .Darwin { } else when ODIN_OS == .Darwin {
foreign import lib "system:System.framework" foreign import lib "system:System"
} else { } else {
foreign import lib "system:c" foreign import lib "system:c"
} }
+1 -1
View File
@@ -4,7 +4,7 @@ package posix
import "core:c" import "core:c"
when ODIN_OS == .Darwin { when ODIN_OS == .Darwin {
foreign import lib "system:System.framework" foreign import lib "system:System"
} else { } else {
foreign import lib "system:c" foreign import lib "system:c"
} }
+1 -1
View File
@@ -4,7 +4,7 @@ package posix
when ODIN_OS == .Windows { when ODIN_OS == .Windows {
foreign import lib "system:libucrt.lib" foreign import lib "system:libucrt.lib"
} else when ODIN_OS == .Darwin { } else when ODIN_OS == .Darwin {
foreign import lib "system:System.framework" foreign import lib "system:System"
} else { } else {
foreign import lib "system:c" foreign import lib "system:c"
} }
+1 -1
View File
@@ -4,7 +4,7 @@ package posix
import "core:c" import "core:c"
when ODIN_OS == .Darwin { when ODIN_OS == .Darwin {
foreign import lib "system:System.framework" foreign import lib "system:System"
} else { } else {
foreign import lib "system:c" foreign import lib "system:c"
} }
+1 -1
View File
@@ -4,7 +4,7 @@ package posix
import "core:c" import "core:c"
when ODIN_OS == .Darwin { when ODIN_OS == .Darwin {
foreign import lib "system:System.framework" foreign import lib "system:System"
} else { } else {
foreign import lib "system:c" foreign import lib "system:c"
} }
+1 -1
View File
@@ -4,7 +4,7 @@ package posix
import "core:c" import "core:c"
when ODIN_OS == .Darwin { when ODIN_OS == .Darwin {
foreign import lib "system:System.framework" foreign import lib "system:System"
} else { } else {
foreign import lib "system:c" foreign import lib "system:c"
} }
+1 -1
View File
@@ -4,7 +4,7 @@ package posix
import "core:c" import "core:c"
when ODIN_OS == .Darwin { when ODIN_OS == .Darwin {
foreign import lib "system:System.framework" foreign import lib "system:System"
} else { } else {
foreign import lib "system:c" foreign import lib "system:c"
} }
+1 -1
View File
@@ -6,7 +6,7 @@ import "base:intrinsics"
import "core:c" import "core:c"
when ODIN_OS == .Darwin { when ODIN_OS == .Darwin {
foreign import lib "system:System.framework" foreign import lib "system:System"
} else { } else {
foreign import lib "system:c" foreign import lib "system:c"
} }
+1 -1
View File
@@ -4,7 +4,7 @@ package posix
import "core:c" import "core:c"
when ODIN_OS == .Darwin { when ODIN_OS == .Darwin {
foreign import lib "system:System.framework" foreign import lib "system:System"
} else { } else {
foreign import lib "system:c" foreign import lib "system:c"
} }
+1 -1
View File
@@ -4,7 +4,7 @@ package posix
import "core:c" import "core:c"
when ODIN_OS == .Darwin { when ODIN_OS == .Darwin {
foreign import lib "system:System.framework" foreign import lib "system:System"
} else { } else {
foreign import lib "system:c" foreign import lib "system:c"
} }
+1 -1
View File
@@ -4,7 +4,7 @@ package posix
import "core:c" import "core:c"
when ODIN_OS == .Darwin { when ODIN_OS == .Darwin {
foreign import libc "system:System.framework" foreign import libc "system:System"
} else { } else {
foreign import libc "system:c" foreign import libc "system:c"
} }
+1 -1
View File
@@ -4,7 +4,7 @@ package posix
import "core:c" import "core:c"
when ODIN_OS == .Darwin { when ODIN_OS == .Darwin {
foreign import lib "system:System.framework" foreign import lib "system:System"
} else { } else {
foreign import lib "system:c" foreign import lib "system:c"
} }
+1 -1
View File
@@ -4,7 +4,7 @@ package posix
import "core:c" import "core:c"
when ODIN_OS == .Darwin { when ODIN_OS == .Darwin {
foreign import lib "system:System.framework" foreign import lib "system:System"
} else { } else {
foreign import lib "system:c" foreign import lib "system:c"
} }
+1 -1
View File
@@ -4,7 +4,7 @@ package posix
import "core:c" import "core:c"
when ODIN_OS == .Darwin { when ODIN_OS == .Darwin {
foreign import lib "system:System.framework" foreign import lib "system:System"
} else { } else {
foreign import lib "system:c" foreign import lib "system:c"
} }
+1 -1
View File
@@ -2,7 +2,7 @@
package posix package posix
when ODIN_OS == .Darwin { when ODIN_OS == .Darwin {
foreign import lib "system:System.framework" foreign import lib "system:System"
} else { } else {
foreign import lib "system:c" foreign import lib "system:c"
} }
+1 -1
View File
@@ -4,7 +4,7 @@ package posix
import "core:c" import "core:c"
when ODIN_OS == .Darwin { when ODIN_OS == .Darwin {
foreign import libc "system:System.framework" foreign import libc "system:System"
} else { } else {
foreign import libc "system:c" foreign import libc "system:c"
} }
+1 -1
View File
@@ -4,7 +4,7 @@ package posix
import "core:c" import "core:c"
when ODIN_OS == .Darwin { when ODIN_OS == .Darwin {
foreign import lib "system:System.framework" foreign import lib "system:System"
} else { } else {
foreign import lib "system:c" foreign import lib "system:c"
} }
+1 -1
View File
@@ -4,7 +4,7 @@ package posix
import "core:c" import "core:c"
when ODIN_OS == .Darwin { when ODIN_OS == .Darwin {
foreign import lib "system:System.framework" foreign import lib "system:System"
} else { } else {
foreign import lib "system:c" foreign import lib "system:c"
} }
+1 -1
View File
@@ -4,7 +4,7 @@ package posix
import "core:c" import "core:c"
when ODIN_OS == .Darwin { when ODIN_OS == .Darwin {
foreign import lib "system:System.framework" foreign import lib "system:System"
} else { } else {
foreign import lib "system:c" foreign import lib "system:c"
} }
+1 -1
View File
@@ -5,7 +5,7 @@ import "core:c"
import "core:c/libc" import "core:c/libc"
when ODIN_OS == .Darwin { when ODIN_OS == .Darwin {
foreign import lib "system:System.framework" foreign import lib "system:System"
} else { } else {
foreign import lib "system:c" foreign import lib "system:c"
} }

Some files were not shown because too many files have changed in this diff Show More