aboutsummaryrefslogtreecommitdiff
path: root/base
diff options
context:
space:
mode:
authorgingerBill <bill@gingerbill.org>2024-01-29 11:46:16 +0000
committergingerBill <bill@gingerbill.org>2024-01-29 11:46:16 +0000
commit3a4c82abf8459f88736c80c10d9be0a550fc266f (patch)
tree3b82e5d5ed170351b862c011398f93234319f5c9 /base
parent946cf52df1e6970b21e13ce01633aed40824678c (diff)
Move core:(builtin|intrinsics) to base:
Diffstat (limited to 'base')
-rw-r--r--base/builtin/builtin.odin128
-rw-r--r--base/intrinsics/intrinsics.odin316
2 files changed, 444 insertions, 0 deletions
diff --git a/base/builtin/builtin.odin b/base/builtin/builtin.odin
new file mode 100644
index 000000000..5cba3c8ea
--- /dev/null
+++ b/base/builtin/builtin.odin
@@ -0,0 +1,128 @@
+// This is purely for documentation
+package builtin
+
+nil :: nil
+false :: 0!=0
+true :: 0==0
+
+ODIN_OS :: ODIN_OS
+ODIN_ARCH :: ODIN_ARCH
+ODIN_ENDIAN :: ODIN_ENDIAN
+ODIN_VENDOR :: ODIN_VENDOR
+ODIN_VERSION :: ODIN_VERSION
+ODIN_ROOT :: ODIN_ROOT
+ODIN_DEBUG :: ODIN_DEBUG
+
+byte :: u8 // alias
+
+bool :: bool
+b8 :: b8
+b16 :: b16
+b32 :: b32
+b64 :: b64
+
+i8 :: i8
+u8 :: u8
+i16 :: i16
+u16 :: u16
+i32 :: i32
+u32 :: u32
+i64 :: i64
+u64 :: u64
+
+i128 :: i128
+u128 :: u128
+
+rune :: rune
+
+f16 :: f16
+f32 :: f32
+f64 :: f64
+
+complex32 :: complex32
+complex64 :: complex64
+complex128 :: complex128
+
+quaternion64 :: quaternion64
+quaternion128 :: quaternion128
+quaternion256 :: quaternion256
+
+int :: int
+uint :: uint
+uintptr :: uintptr
+
+rawptr :: rawptr
+string :: string
+cstring :: cstring
+any :: any
+
+typeid :: typeid
+
+// Endian Specific Types
+i16le :: i16le
+u16le :: u16le
+i32le :: i32le
+u32le :: u32le
+i64le :: i64le
+u64le :: u64le
+i128le :: i128le
+u128le :: u128le
+
+i16be :: i16be
+u16be :: u16be
+i32be :: i32be
+u32be :: u32be
+i64be :: i64be
+u64be :: u64be
+i128be :: i128be
+u128be :: u128be
+
+
+f16le :: f16le
+f32le :: f32le
+f64le :: f64le
+
+f16be :: f16be
+f32be :: f32be
+f64be :: f64be
+
+
+
+// Procedures
+len :: proc(array: Array_Type) -> int ---
+cap :: proc(array: Array_Type) -> int ---
+
+size_of :: proc($T: typeid) -> int ---
+align_of :: proc($T: typeid) -> int ---
+
+// e.g. offset_of(t.f), where t is an instance of the type T
+offset_of_selector :: proc(selector: $T) -> uintptr ---
+// e.g. offset_of(T, f), where T can be the type instead of a variable
+offset_of_member :: proc($T: typeid, member: $M) -> uintptr ---
+offset_of :: proc{offset_of_selector, offset_of_member}
+// e.g. offset_of(T, "f"), where T can be the type instead of a variable
+offset_of_by_string :: proc($T: typeid, member: string) -> uintptr ---
+
+type_of :: proc(x: expr) -> type ---
+type_info_of :: proc($T: typeid) -> ^runtime.Type_Info ---
+typeid_of :: proc($T: typeid) -> typeid ---
+
+swizzle :: proc(x: [N]T, indices: ..int) -> [len(indices)]T ---
+
+complex :: proc(real, imag: Float) -> Complex_Type ---
+quaternion :: proc(imag, jmag, kmag, real: Float) -> Quaternion_Type --- // fields must be named
+real :: proc(value: Complex_Or_Quaternion) -> Float ---
+imag :: proc(value: Complex_Or_Quaternion) -> Float ---
+jmag :: proc(value: Quaternion) -> Float ---
+kmag :: proc(value: Quaternion) -> Float ---
+conj :: proc(value: Complex_Or_Quaternion) -> Complex_Or_Quaternion ---
+
+expand_values :: proc(value: Struct_Or_Array) -> (A, B, C, ...) ---
+
+min :: proc(values: ..T) -> T ---
+max :: proc(values: ..T) -> T ---
+abs :: proc(value: T) -> T ---
+clamp :: proc(value, minimum, maximum: T) -> T ---
+
+soa_zip :: proc(slices: ...) -> #soa[]Struct ---
+soa_unzip :: proc(value: $S/#soa[]$E) -> (slices: ...) ---
diff --git a/base/intrinsics/intrinsics.odin b/base/intrinsics/intrinsics.odin
new file mode 100644
index 000000000..c23cbd473
--- /dev/null
+++ b/base/intrinsics/intrinsics.odin
@@ -0,0 +1,316 @@
+// This is purely for documentation
+//+build ignore
+package intrinsics
+
+// Package-Related
+is_package_imported :: proc(package_name: string) -> bool ---
+
+// Types
+soa_struct :: proc($N: int, $T: typeid) -> type/#soa[N]T
+
+// Volatile
+volatile_load :: proc(dst: ^$T) -> T ---
+volatile_store :: proc(dst: ^$T, val: T) ---
+
+non_temporal_load :: proc(dst: ^$T) -> T ---
+non_temporal_store :: proc(dst: ^$T, val: T) ---
+
+// Trapping
+debug_trap :: proc() ---
+trap :: proc() -> ! ---
+
+// Instructions
+
+alloca :: proc(size, align: int) -> [^]u8 ---
+cpu_relax :: proc() ---
+read_cycle_counter :: proc() -> i64 ---
+
+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_trailing_zeros :: proc(x: $T) -> T where type_is_integer(T) || type_is_simd_vector(T) ---
+count_leading_zeros :: proc(x: $T) -> T where type_is_integer(T) || type_is_simd_vector(T) ---
+reverse_bits :: proc(x: $T) -> T where type_is_integer(T) || type_is_simd_vector(T) ---
+byte_swap :: proc(x: $T) -> T where type_is_integer(T) || type_is_float(T) ---
+
+overflow_add :: proc(lhs, rhs: $T) -> (T, bool) #optional_ok ---
+overflow_sub :: proc(lhs, rhs: $T) -> (T, bool) #optional_ok ---
+overflow_mul :: proc(lhs, rhs: $T) -> (T, bool) #optional_ok ---
+
+sqrt :: proc(x: $T) -> T where type_is_float(T) || (type_is_simd_vector(T) && type_is_float(type_elem_type(T))) ---
+
+fused_mul_add :: proc(a, b, c: $T) -> T where type_is_float(T) || (type_is_simd_vector(T) && type_is_float(type_elem_type(T))) ---
+
+mem_copy :: proc(dst, src: rawptr, len: int) ---
+mem_copy_non_overlapping :: proc(dst, src: rawptr, len: int) ---
+mem_zero :: proc(ptr: rawptr, len: int) ---
+mem_zero_volatile :: proc(ptr: rawptr, len: int) ---
+
+// prefer [^]T operations if possible
+ptr_offset :: proc(ptr: ^$T, offset: int) -> ^T ---
+ptr_sub :: proc(a, b: ^$T) -> int ---
+
+unaligned_load :: proc(src: ^$T) -> T ---
+unaligned_store :: proc(dst: ^$T, val: T) -> T ---
+
+fixed_point_mul :: proc(lhs, rhs: $T, #const scale: uint) -> T where type_is_integer(T) ---
+fixed_point_div :: proc(lhs, rhs: $T, #const scale: uint) -> T where type_is_integer(T) ---
+fixed_point_mul_sat :: proc(lhs, rhs: $T, #const scale: uint) -> T where type_is_integer(T) ---
+fixed_point_div_sat :: proc(lhs, rhs: $T, #const scale: uint) -> T where type_is_integer(T) ---
+
+prefetch_read_instruction :: proc(address: rawptr, #const locality: i32 /* 0..=3 */) ---
+prefetch_read_data :: proc(address: rawptr, #const locality: i32 /* 0..=3 */) ---
+prefetch_write_instruction :: proc(address: rawptr, #const locality: i32 /* 0..=3 */) ---
+prefetch_write_data :: proc(address: rawptr, #const locality: i32 /* 0..=3 */) ---
+
+// Compiler Hints
+expect :: proc(val, expected_val: T) -> T ---
+
+// Linux and Darwin Only
+syscall :: proc(id: uintptr, args: ..uintptr) -> uintptr ---
+
+
+// Atomics
+Atomic_Memory_Order :: enum {
+ Relaxed = 0, // Unordered
+ Consume = 1, // Monotonic
+ Acquire = 2,
+ Release = 3,
+ Acq_Rel = 4,
+ Seq_Cst = 5,
+}
+
+atomic_type_is_lock_free :: proc($T: typeid) -> bool ---
+
+atomic_thread_fence :: proc(order: Atomic_Memory_Order) ---
+atomic_signal_fence :: proc(order: Atomic_Memory_Order) ---
+
+atomic_store :: proc(dst: ^$T, val: T) ---
+atomic_store_explicit :: proc(dst: ^$T, val: T, order: Atomic_Memory_Order) ---
+
+atomic_load :: proc(dst: ^$T) -> T ---
+atomic_load_explicit :: proc(dst: ^$T, order: Atomic_Memory_Order) -> T ---
+
+// fetch then operator
+atomic_add :: proc(dst: ^$T, val: T) -> T ---
+atomic_add_explicit :: proc(dst: ^$T, val: T, order: Atomic_Memory_Order) -> T ---
+atomic_sub :: proc(dst: ^$T, val: T) -> T ---
+atomic_sub_explicit :: proc(dst: ^$T, val: T, order: Atomic_Memory_Order) -> T ---
+atomic_and :: proc(dst: ^$T, val: T) -> T ---
+atomic_and_explicit :: proc(dst: ^$T, val: T, order: Atomic_Memory_Order) -> T ---
+atomic_nand :: proc(dst: ^$T, val: T) -> T ---
+atomic_nand_explicit :: proc(dst: ^$T, val: T, order: Atomic_Memory_Order) -> T ---
+atomic_or :: proc(dst: ^$T, val: T) -> T ---
+atomic_or_explicit :: proc(dst: ^$T, val: T, order: Atomic_Memory_Order) -> T ---
+atomic_xor :: proc(dst: ^$T, val: T) -> T ---
+atomic_xor_explicit :: proc(dst: ^$T, val: T, order: Atomic_Memory_Order) -> T ---
+atomic_exchange :: proc(dst: ^$T, val: T) -> T ---
+atomic_exchange_explicit :: proc(dst: ^$T, val: T, order: Atomic_Memory_Order) -> T ---
+
+atomic_compare_exchange_strong :: proc(dst: ^$T, old, new: T) -> (T, bool) #optional_ok ---
+atomic_compare_exchange_strong_explicit :: proc(dst: ^$T, old, new: T, success, failure: Atomic_Memory_Order) -> (T, bool) #optional_ok ---
+atomic_compare_exchange_weak :: proc(dst: ^$T, old, new: T) -> (T, bool) #optional_ok ---
+atomic_compare_exchange_weak_explicit :: proc(dst: ^$T, old, new: T, success, failure: Atomic_Memory_Order) -> (T, bool) #optional_ok ---
+
+
+// Constant type tests
+
+type_base_type :: proc($T: typeid) -> type ---
+type_core_type :: proc($T: typeid) -> type ---
+type_elem_type :: proc($T: typeid) -> type ---
+
+type_is_boolean :: proc($T: typeid) -> bool ---
+type_is_integer :: proc($T: typeid) -> bool ---
+type_is_rune :: proc($T: typeid) -> bool ---
+type_is_float :: proc($T: typeid) -> bool ---
+type_is_complex :: proc($T: typeid) -> bool ---
+type_is_quaternion :: proc($T: typeid) -> bool ---
+type_is_string :: proc($T: typeid) -> bool ---
+type_is_typeid :: proc($T: typeid) -> bool ---
+type_is_any :: proc($T: typeid) -> bool ---
+
+type_is_endian_platform :: proc($T: typeid) -> bool ---
+type_is_endian_little :: proc($T: typeid) -> bool ---
+type_is_endian_big :: proc($T: typeid) -> bool ---
+type_is_unsigned :: proc($T: typeid) -> bool ---
+type_is_numeric :: proc($T: typeid) -> bool ---
+type_is_ordered :: proc($T: typeid) -> bool ---
+type_is_ordered_numeric :: proc($T: typeid) -> bool ---
+type_is_indexable :: proc($T: typeid) -> bool ---
+type_is_sliceable :: proc($T: typeid) -> bool ---
+type_is_comparable :: proc($T: typeid) -> bool ---
+type_is_simple_compare :: proc($T: typeid) -> bool --- // easily compared using memcmp (== and !=)
+type_is_dereferenceable :: proc($T: typeid) -> bool ---
+type_is_valid_map_key :: proc($T: typeid) -> bool ---
+type_is_valid_matrix_elements :: proc($T: typeid) -> bool ---
+
+type_is_named :: proc($T: typeid) -> bool ---
+type_is_pointer :: proc($T: typeid) -> bool ---
+type_is_multi_pointer :: proc($T: typeid) -> bool ---
+type_is_array :: proc($T: typeid) -> bool ---
+type_is_enumerated_array :: proc($T: typeid) -> bool ---
+type_is_slice :: proc($T: typeid) -> bool ---
+type_is_dynamic_array :: proc($T: typeid) -> bool ---
+type_is_map :: proc($T: typeid) -> bool ---
+type_is_struct :: proc($T: typeid) -> bool ---
+type_is_union :: proc($T: typeid) -> bool ---
+type_is_enum :: proc($T: typeid) -> bool ---
+type_is_proc :: proc($T: typeid) -> bool ---
+type_is_bit_set :: proc($T: typeid) -> bool ---
+type_is_simd_vector :: proc($T: typeid) -> bool ---
+type_is_matrix :: proc($T: typeid) -> bool ---
+
+type_has_nil :: proc($T: typeid) -> bool ---
+
+type_is_specialization_of :: proc($T, $S: typeid) -> bool ---
+
+type_is_variant_of :: proc($U, $V: typeid) -> bool where type_is_union(U) ---
+type_union_tag_type :: proc($T: typeid) -> typeid where type_is_union(T) ---
+type_union_tag_offset :: proc($T: typeid) -> uintptr where type_is_union(T) ---
+type_union_base_tag_value :: proc($T: typeid) -> int where type_is_union(U) ---
+type_union_variant_count :: proc($T: typeid) -> int where type_is_union(T) ---
+type_variant_type_of :: proc($T: typeid, $index: int) -> typeid where type_is_union(T) ---
+type_variant_index_of :: proc($U, $V: typeid) -> int where type_is_union(U) ---
+
+type_has_field :: proc($T: typeid, $name: string) -> bool ---
+type_field_type :: proc($T: typeid, $name: string) -> typeid ---
+
+type_proc_parameter_count :: proc($T: typeid) -> int where type_is_proc(T) ---
+type_proc_return_count :: proc($T: typeid) -> int where type_is_proc(T) ---
+
+type_proc_parameter_type :: proc($T: typeid, index: int) -> typeid where type_is_proc(T) ---
+type_proc_return_type :: proc($T: typeid, index: int) -> typeid where type_is_proc(T) ---
+
+type_struct_field_count :: proc($T: typeid) -> int where type_is_struct(T) ---
+
+type_polymorphic_record_parameter_count :: proc($T: typeid) -> typeid ---
+type_polymorphic_record_parameter_value :: proc($T: typeid, index: int) -> $V ---
+
+type_is_specialized_polymorphic_record :: proc($T: typeid) -> bool ---
+type_is_unspecialized_polymorphic_record :: proc($T: typeid) -> bool ---
+
+type_is_subtype_of :: proc($T, $U: typeid) -> bool ---
+
+type_field_index_of :: proc($T: typeid, $name: string) -> uintptr ---
+
+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_map_info :: proc($T: typeid/map[$K]$V) -> ^runtime.Map_Info ---
+type_map_cell_info :: proc($T: typeid) -> ^runtime.Map_Cell_Info ---
+
+type_convert_variants_to_pointers :: proc($T: typeid) -> typeid where type_is_union(T) ---
+type_merge :: proc($U, $V: typeid) -> typeid where type_is_union(U), type_is_union(V) ---
+
+constant_utf16_cstring :: proc($literal: string) -> [^]u16 ---
+
+// SIMD related
+simd_add :: proc(a, b: #simd[N]T) -> #simd[N]T ---
+simd_sub :: proc(a, b: #simd[N]T) -> #simd[N]T ---
+simd_mul :: proc(a, b: #simd[N]T) -> #simd[N]T ---
+simd_div :: proc(a, b: #simd[N]T) -> #simd[N]T where type_is_float(T) ---
+
+// Keeps Odin's Behaviour
+// (x << y) if y <= mask else 0
+simd_shl :: proc(a: #simd[N]T, b: #simd[N]Unsigned_Integer) -> #simd[N]T ---
+simd_shr :: proc(a: #simd[N]T, b: #simd[N]Unsigned_Integer) -> #simd[N]T ---
+
+// Similar to C's Behaviour
+// x << (y & mask)
+simd_shl_masked :: proc(a: #simd[N]T, b: #simd[N]Unsigned_Integer) -> #simd[N]T ---
+simd_shr_masked :: proc(a: #simd[N]T, b: #simd[N]Unsigned_Integer) -> #simd[N]T ---
+
+simd_add_sat :: proc(a, b: #simd[N]T) -> #simd[N]T ---
+simd_sub_sat :: proc(a, b: #simd[N]T) -> #simd[N]T ---
+
+simd_bit_and :: proc(a, b: #simd[N]T) -> #simd[N]T ---
+simd_bit_or :: proc(a, b: #simd[N]T) -> #simd[N]T ---
+simd_bit_xor :: proc(a, b: #simd[N]T) -> #simd[N]T ---
+simd_bit_and_not :: proc(a, b: #simd[N]T) -> #simd[N]T ---
+
+simd_neg :: proc(a: #simd[N]T) -> #simd[N]T ---
+
+simd_abs :: proc(a: #simd[N]T) -> #simd[N]T ---
+
+simd_min :: proc(a, b: #simd[N]T) -> #simd[N]T ---
+simd_max :: proc(a, b: #simd[N]T) -> #simd[N]T ---
+simd_clamp :: proc(v, min, max: #simd[N]T) -> #simd[N]T ---
+
+// Return an unsigned integer of the same size as the input type
+// NOT A BOOLEAN
+// element-wise:
+// false => 0x00...00
+// true => 0xff...ff
+simd_lanes_eq :: proc(a, b: #simd[N]T) -> #simd[N]Integer ---
+simd_lanes_ne :: proc(a, b: #simd[N]T) -> #simd[N]Integer ---
+simd_lanes_lt :: proc(a, b: #simd[N]T) -> #simd[N]Integer ---
+simd_lanes_le :: proc(a, b: #simd[N]T) -> #simd[N]Integer ---
+simd_lanes_gt :: proc(a, b: #simd[N]T) -> #simd[N]Integer ---
+simd_lanes_ge :: proc(a, b: #simd[N]T) -> #simd[N]Integer ---
+
+simd_extract :: proc(a: #simd[N]T, idx: uint) -> T ---
+simd_replace :: proc(a: #simd[N]T, idx: uint, elem: T) -> #simd[N]T ---
+
+simd_reduce_add_ordered :: proc(a: #simd[N]T) -> T ---
+simd_reduce_mul_ordered :: proc(a: #simd[N]T) -> T ---
+simd_reduce_min :: proc(a: #simd[N]T) -> T ---
+simd_reduce_max :: proc(a: #simd[N]T) -> T ---
+simd_reduce_and :: proc(a: #simd[N]T) -> T ---
+simd_reduce_or :: proc(a: #simd[N]T) -> T ---
+simd_reduce_xor :: proc(a: #simd[N]T) -> 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 ---
+
+// Lane-wise operations
+simd_ceil :: proc(a: #simd[N]any_float) -> #simd[N]any_float ---
+simd_floor :: proc(a: #simd[N]any_float) -> #simd[N]any_float ---
+simd_trunc :: proc(a: #simd[N]any_float) -> #simd[N]any_float ---
+// rounding to the nearest integral value; if two values are equally near, rounds to the even one
+simd_nearest :: proc(a: #simd[N]any_float) -> #simd[N]any_float ---
+
+simd_to_bits :: proc(v: #simd[N]T) -> #simd[N]Integer where size_of(T) == size_of(Integer), type_is_unsigned(Integer) ---
+
+// equivalent a swizzle with descending indices, e.g. reserve(a, 3, 2, 1, 0)
+simd_reverse :: proc(a: #simd[N]T) -> #simd[N]T ---
+
+simd_rotate_left :: proc(a: #simd[N]T, $offset: int) -> #simd[N]T ---
+simd_rotate_right :: proc(a: #simd[N]T, $offset: int) -> #simd[N]T ---
+
+
+// WASM targets only
+wasm_memory_grow :: proc(index, delta: uintptr) -> int ---
+wasm_memory_size :: proc(index: uintptr) -> int ---
+
+// `timeout_ns` is maximum number of nanoseconds the calling thread will be blocked for
+// A negative value will be blocked forever
+// Return value:
+// 0 - indicates that the thread blocked and then was woken up
+// 1 - the loaded value from `ptr` did not match `expected`, the thread did not block
+// 2 - the thread blocked, but the timeout
+wasm_memory_atomic_wait32 :: proc(ptr: ^u32, expected: u32, timeout_ns: i64) -> u32 ---
+wasm_memory_atomic_notify32 :: proc(ptr: ^u32, waiters: u32) -> (waiters_woken_up: u32) ---
+
+// x86 Targets (i386, amd64)
+x86_cpuid :: proc(ax, cx: u32) -> (eax, ebx, ecx, edx: u32) ---
+x86_xgetbv :: proc(cx: u32) -> (eax, edx: u32) ---
+
+
+// Darwin targets only
+objc_object :: struct{}
+objc_selector :: struct{}
+objc_class :: struct{}
+objc_id :: ^objc_object
+objc_SEL :: ^objc_selector
+objc_Class :: ^objc_class
+
+objc_find_selector :: proc($name: string) -> objc_SEL ---
+objc_register_selector :: proc($name: string) -> objc_SEL ---
+objc_find_class :: proc($name: string) -> objc_Class ---
+objc_register_class :: proc($name: string) -> objc_Class ---
+
+
+valgrind_client_request :: proc(default: uintptr, request: uintptr, a0, a1, a2, a3, a4: uintptr) -> uintptr ---
+
+// Internal compiler use only
+
+__entry_point :: proc() ---