package base:runtime
Overview
This is the runtime code required by the compiler IMPORTANT NOTE(bill): Do not change the order of any of this data The compiler relies upon this _exact_ order
Naming Conventions: In general, Ada_Case for types and snake_case for values
Package Name: snake_case (but prefer single word) Import Name: snake_case (but prefer single word) Types: Ada_Case Enum Values: Ada_Case Procedures: snake_case Local Variables: snake_case Constant Variables: SCREAMING_SNAKE_CASE
IMPORTANT NOTE(bill): type_info_of
cannot be used within a
#shared_global_scope due to the internals of the compiler.
This could change at a later date if the all these data structures are
implemented within the compiler rather than in this "preload" file
Declarations which are required by the compiler
Descriptions of files
There are a lot of files in this package and below is described roughly what kind of functionality is placed in different files:
| File pattern | Description
|----------------------|------------------------------------------------------|
| core.odin
| Contains the declarations that compiler will require to be present. Contains context-related declarations, Type_Info
declarations and some other types used to implement the runtime and other packages. |
| core_builtin*.odin
| Contain @(builtin)
declarations that can be used without importing the package. Most of them aren't required by the compiler |
| default_*.odin
| Contain default implementations for context allocators |
| entry_*.odin
| Contain OS-specific entry points |
| os_specific_*.odin
| Contain OS-specific utility procedures |
| *internal*.odin
| Contain implementations for internal procedures that can be called by the compiler |
Implementing custom runtime
For embedded and kernel development it might be required to re-implement parts
of the base:runtime
package. This can include changing the default printing
procedures that handle console output when the program panics, custom
entry-points, tailored for a specific platform or execution environment, or
simply switching up implementations of some procedures.
In case this is required, the following is suggested:
1. Define $ODIN_ROOT
environment variable to point to a directory within your
project that contains the following directories: base/
, core/
and vendor/
.
2. Inside the $ODIN_ROOT/base
subdirectory, implement the *necessary
declarations*.
What constitutes the necessary definitions is described below.
Context-related
The compiler will require these declarations as they concern the context
variable.
Maybe
Source_Code_Location
Context
Allocator
Random_Generator
Logger
__init_context
Runtime initialization/cleanup
These are not strictly required for compilation, but if global variables or
@(init)
/@(fini)
blocks are used, these procedures need to be called inside
the entry point.
_startup_runtime
_cleanup_runtime
Type assertion check
These procedures are called every time .(Type)
expressions are used in order
to check the union tag or the underlying type of any
before returning the
value of the underlying type. These are not required if -no-type-assert
is
specified.
type_assertion_check
type_assertion_check2
(takes in typeid)
Bounds checking procedures
These procedures are called every time index or slicing expression are used in
order to perform bounds-checking before the actual operation. These are not
required if the -no-bounds-check
option is specified.
bounds_check_error
matrix_bounds_check_error
slice_expr_error_hi
slice_expr_error_lo_hi
multi_pointer_slice_expr_error
cstring calls
If cstring
or cstring16
types are used, these procedures are required.
cstring_to_string
cstring_len
cstring16_to_string16
cstring16_len
Comparison
These procedures are required for comparison operators between strings and other
compound types to function properly. If strings, structs nor unions are compared,
only string_eq
procedure is required.
memory_equal
memory_compare
memory_compare_zero
cstring_eq
cstring16_eq
cstring_ne
cstring16_ne
cstring_lt
cstring16_lt
cstring_gt
cstring16_gt
cstring_le
cstring16_le
cstring_ge
cstring16_ge
string_eq
string16_eq
string_ne
string16_ne
string_lt
string16_lt
string_gt
string16_gt
string_le
string16_le
string_ge
string16_ge
complex32_eq
complex32_ne
complex64_eq
complex64_ne
complex128_eq
complex128_ne
quaternion64_eq
quaternion64_ne
quaternion128_eq
quaternion128_ne
quaternion256_eq
quaternion256_ne
for-in string
type
These procedures are required to iterate strings using for ... in
loop. If this
kind of loop isn't used, these procedures aren't required.
string_decode_rune
string_decode_last_rune
(for #reverse for
)
Required when RTTI is enabled (the vast majority of targets)
These declarations are required unless the -no-rtti
compiler option is
specified. Note that in order to be useful, some other procedures need to be
implemented. Those procedures aren't mentioned here as the compiler won't
complain if they're missing.
Type_Info
type_table
__type_info_of
Hashing
Required if maps are used
default_hasher
default_hasher_cstring
default_hasher_string
Pseudo-CRT required procedured due to LLVM but useful in general
memset
memcpy
memove
Procedures required by the LLVM backend if u128/i128 is used
umodti3
udivti3
modti3
divti3
fixdfti
fixunsdfti
fixunsdfdi
floattidf
floattidf_unsigned
truncsfhf2
truncdfhf2
gnu_h2f_ieee
gnu_f2h_ieee
extendhfsf2
Procedures required by the LLVM backend if f16 is used (WASM only)
__ashlti3
__multi3
When -no-crt is defined (windows only)
_tls_index
_fltused
Arithmetic
quo_complex32
quo_complex64
quo_complex128
mul_quaternion64
mul_quaternion128
mul_quaternion256
quo_quaternion64
quo_quaternion128
quo_quaternion256
abs_complex32
abs_complex64
abs_complex128
abs_quaternion64
abs_quaternion128
abs_quaternion256
Map specific calls
map_seed_from_map_data
__dynamic_map_check_grow
(for static map calls)
map_insert_hash_dynamic
(for static map calls)
__dynamic_map_get
(for dynamic map calls)
__dynamic_map_set
(for dynamic map calls)
Dynamic literals ([dynamic]T
and map[K]V
) (can be disabled with -no-dynamic-literals
)
__dynamic_array_reserve
__dynamic_array_append
__dynamic_map_reserve
Objective-C specific
objc_lookUpClass
sel_registerName
objc_allocateClassPair
Other required declarations
This is required without conditions.
Load_Directory_File
Index
Types (104)
- Allocator
- Allocator_Error
- Allocator_Mode
- Allocator_Mode_Set
- Allocator_Proc
- Allocator_Query_Info
- Arena
- Arena_Temp
- Assertion_Failure_Proc
- Calling_Convention
- Context
- DLL_Forward_Reason
- Default_Random_State
- Default_Temp_Allocator
- Equal_Proc
- Hasher_Proc
- Load_Directory_File
- Logger
- Logger_Level
- Logger_Option
- Logger_Options
- Logger_Proc
- Map_Cell
- Map_Cell_Info
- Map_Hash
- Map_Info
- Maybe
- Memory_Block
- Objc_Block
- Odin_Arch_Type
- Odin_Arch_Types
- Odin_Build_Mode_Type
- Odin_Endian_Type
- Odin_OS_Type
- Odin_OS_Types
- Odin_Optimization_Mode
- Odin_Platform_Subtarget_Type
- Odin_Platform_Subtarget_Types
- Odin_Sanitizer_Flags
- Platform_Endianness
- Random_Generator
- Random_Generator_Mode
- Random_Generator_Proc
- Random_Generator_Query_Info
- Random_Generator_Query_Info_Flag
- Raw_Any
- Raw_Complex128
- Raw_Complex32
- Raw_Complex64
- Raw_Cstring
- Raw_Cstring16
- Raw_Dynamic_Array
- Raw_Map
- Raw_Quaternion128
- Raw_Quaternion128_Vector_Scalar
- Raw_Quaternion256
- Raw_Quaternion256_Vector_Scalar
- Raw_Quaternion64
- Raw_Quaternion64_Vector_Scalar
- Raw_SOA_Footer_Dynamic_Array
- Raw_SOA_Footer_Slice
- Raw_Slice
- Raw_Soa_Pointer
- Raw_String
- Raw_String16
- Source_Code_Location
- Thread_Local_Cleaner
- Thread_Local_Cleaner_Contextless
- Thread_Local_Cleaner_Odin
- Type_Info
- Type_Info_Any
- Type_Info_Array
- Type_Info_Bit_Field
- Type_Info_Bit_Set
- Type_Info_Boolean
- Type_Info_Complex
- Type_Info_Dynamic_Array
- Type_Info_Enum
- Type_Info_Enum_Value
- Type_Info_Enumerated_Array
- Type_Info_Flag
- Type_Info_Flags
- Type_Info_Float
- Type_Info_Integer
- Type_Info_Map
- Type_Info_Matrix
- Type_Info_Multi_Pointer
- Type_Info_Named
- Type_Info_Parameters
- Type_Info_Pointer
- Type_Info_Procedure
- Type_Info_Quaternion
- Type_Info_Rune
- Type_Info_Simd_Vector
- Type_Info_Slice
- Type_Info_Soa_Pointer
- Type_Info_String
- Type_Info_String_Encoding_Kind
- Type_Info_Struct
- Type_Info_Struct_Flag
- Type_Info_Struct_Flags
- Type_Info_Struct_Soa_Kind
- Type_Info_Type_Id
- Type_Info_Union
Constants (24)
- ALL_ODIN_ARCH_TYPES
- ALL_ODIN_OS_TYPES
- Byte
- DEFAULT_ALIGNMENT
- DEFAULT_ARENA_GROWING_MINIMUM_BLOCK_SIZE
- DEFAULT_DYNAMIC_ARRAY_CAPACITY
- DEFAULT_TEMP_ALLOCATOR_BACKING_SIZE
- Exabyte
- Gigabyte
- HASH_MASK
- HAS_HARDWARE_SIMD
- INITIAL_HASH_SEED
- Kilobyte
- MAP_CACHE_LINE_LOG2
- MAP_CACHE_LINE_SIZE
- MAP_LOAD_FACTOR
- MAP_MIN_LOG2_CAPACITY
- Megabyte
- NO_DEFAULT_TEMP_ALLOCATOR
- ODIN_PLATFORM_SUBTARGET_IOS
- Petabyte
- RUNTIME_REQUIRE
- TOMBSTONE_MASK
- Terabyte
Procedures (323)
- DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD
- abs_complex128
- abs_complex32
- abs_complex64
- abs_quaternion128
- abs_quaternion256
- abs_quaternion64
- add_thread_local_cleaner
- aeabi_d2h
- align_forward_int
- align_forward_uint
- align_forward_uintptr
- alloc_from_memory_block
- append_elem
- append_elem_string
- append_elems
- append_nothing
- append_soa_elem
- append_soa_elems
- append_string
- arena_alloc
- arena_allocator
- arena_allocator_proc
- arena_check_temp
- arena_destroy
- arena_free_all
- arena_free_last_memory_block
- arena_init
- arena_temp_begin
- arena_temp_end
- arena_temp_ignore
- assert
- assert_contextless
- assign_at_elem
- assign_at_elem_string
- assign_at_elems
- bounds_check_error
- bounds_check_error_loc
- bounds_trap
- card
- clear_dynamic_array
- clear_map
- clear_soa_dynamic_array
- complex128_eq
- complex128_ne
- complex32_eq
- complex32_ne
- complex64_eq
- complex64_ne
- container_of
- copy_from_string
- copy_from_string16
- copy_slice
- cstring16_cmp
- cstring16_eq
- cstring16_ge
- cstring16_gt
- cstring16_le
- cstring16_len
- cstring16_lt
- cstring16_ne
- cstring16_to_string16
- cstring_cmp
- cstring_eq
- cstring_ge
- cstring_gt
- cstring_le
- cstring_len
- cstring_lt
- cstring_ne
- cstring_to_string
- debug_trap
- default_allocator
- default_allocator_proc
- default_assertion_contextless_failure_proc
- default_assertion_failure_proc
- default_context
- default_hasher
- default_hasher_complex128
- default_hasher_cstring
- default_hasher_f64
- default_hasher_quaternion256
- default_hasher_string
- default_logger
- default_logger_proc
- default_random_generator
- default_random_generator_proc
- default_temp_allocator
- default_temp_allocator_destroy
- default_temp_allocator_init
- default_temp_allocator_proc
- default_temp_allocator_temp_begin
- default_temp_allocator_temp_end
- delete_cstring
- delete_cstring16
- delete_dynamic_array
- delete_key
- delete_map
- delete_slice
- delete_soa_dynamic_array
- delete_soa_slice
- delete_string
- delete_string16
- divmodti4
- divti3
- dynamic_array_expr_error
- dynamic_array_expr_error_loc
- encode_rune
- ensure
- ensure_contextless
- extendhfsf2
- fixdfti
- fixunsdfdi
- fixunsdfti
- floattidf
- floattidf_unsigned
- gnu_f2h_ieee
- gnu_h2f_ieee
- heap_alloc
- heap_allocator
- heap_allocator_proc
- heap_free
- heap_resize
- init_global_temporary_allocator
- inject_at_elem
- inject_at_elem_string
- inject_at_elems
- into_dynamic_soa
- is_power_of_two_int
- is_power_of_two_uint
- is_power_of_two_uintptr
- make_aligned
- make_dynamic_array
- make_dynamic_array_error_loc
- make_dynamic_array_len
- make_dynamic_array_len_cap
- make_map
- make_map_cap
- make_map_expr_error_loc
- make_multi_pointer
- make_slice
- make_slice_error_loc
- make_soa_aligned
- make_soa_dynamic_array
- make_soa_dynamic_array_len
- make_soa_dynamic_array_len_cap
- make_soa_slice
- map_alloc_dynamic
- map_cap
- map_cell_index_dynamic
- map_cell_index_dynamic_const
- map_cell_index_static
- map_cell_info
- map_clear_dynamic
- map_data
- map_desired_position
- map_entry
- map_erase_dynamic
- map_exists_dynamic
- map_free_dynamic
- map_get
- map_grow_dynamic
- map_hash_is_deleted
- map_hash_is_empty
- map_hash_is_valid
- map_info
- map_insert
- map_insert_hash_dynamic
- map_insert_hash_dynamic_with_key
- map_kvh_data_dynamic
- map_kvh_data_static
- map_kvh_data_values_dynamic
- map_len
- map_load_factor
- map_log2_cap
- map_lookup_dynamic
- map_probe_distance
- map_reserve_dynamic
- map_resize_threshold
- map_seed
- map_seed_from_map_data
- map_shrink_dynamic
- map_total_allocation_size
- map_total_allocation_size_from_value
- map_upsert
- matrix_bounds_check_error
- mem_alloc
- mem_alloc_bytes
- mem_alloc_non_zeroed
- mem_copy
- mem_copy_non_overlapping
- mem_free
- mem_free_all
- mem_free_bytes
- mem_free_with_size
- mem_resize
- mem_zero
- memory_block_alloc
- memory_block_dealloc
- memory_compare
- memory_compare_zero
- memory_equal
- memory_prefix_length
- memset
- modti3
- mul_quaternion128
- mul_quaternion256
- mul_quaternion64
- multi_pointer_slice_expr_error
- multi_pointer_slice_handle_error
- new
- new_aligned
- new_clone
- nil_allocator
- nil_allocator_proc
- non_zero_append_elem
- non_zero_append_elem_string
- non_zero_append_elems
- non_zero_append_soa_elem
- non_zero_append_soa_elems
- non_zero_mem_resize
- non_zero_reserve_dynamic_array
- non_zero_reserve_soa
- non_zero_resize_dynamic_array
- non_zero_resize_soa
- ordered_remove
- ordered_remove_soa
- panic
- panic_allocator
- panic_allocator_proc
- panic_contextless
- pop
- pop_front
- pop_front_safe
- pop_safe
- print_any_single
- print_byte
- print_caller_location
- print_encoded_rune
- print_i64
- print_int
- print_rune
- print_string
- print_strings
- print_type
- print_typeid
- print_u64
- print_uint
- print_uintptr
- println_any
- quaternion128_eq
- quaternion128_ne
- quaternion256_eq
- quaternion256_ne
- quaternion64_eq
- quaternion64_ne
- quo_complex128
- quo_complex32
- quo_complex64
- quo_quaternion128
- quo_quaternion256
- quo_quaternion64
- random_generator_query_info
- random_generator_read_bytes
- random_generator_read_ptr
- random_generator_reset_bytes
- random_generator_reset_u64
- raw_soa_footer_dynamic_array
- raw_soa_footer_slice
- read_cycle_counter
- remove_range
- reserve_dynamic_array
- reserve_map
- reserve_soa
- resize_dynamic_array
- resize_soa
- run_thread_local_cleaners
- shrink_dynamic_array
- shrink_map
- slice_expr_error_hi
- slice_expr_error_hi_loc
- slice_expr_error_lo_hi
- slice_expr_error_lo_hi_loc
- slice_handle_error
- stderr_write
- string16_cmp
- string16_decode_last_rune
- string16_decode_rune
- string16_eq
- string16_ge
- string16_gt
- string16_le
- string16_lt
- string16_ne
- string_cmp
- string_decode_last_rune
- string_decode_rune
- string_eq
- string_ge
- string_gt
- string_le
- string_lt
- string_ne
- trap
- truncdfhf2
- truncsfhf2
- type_assertion_check
- type_assertion_check2
- type_assertion_trap
- type_info_base
- type_info_base_without_enum
- type_info_core
- typeid_base
- typeid_base_without_enum
- typeid_core
- udivmod128
- udivmodti4
- udivti3
- umodti3
- unimplemented
- unimplemented_contextless
- unordered_remove
- unordered_remove_soa
Types
Allocator ¶
Allocator :: struct { procedure: Allocator_Proc, data: rawptr, }
Related Procedures With Parameters
- arena_init
- default_temp_allocator_init
- delete_cstring
- delete_cstring16
- delete_slice
- delete_soa_slice
- delete_string
- delete_string16
- init_global_temporary_allocator
- make_aligned
- make_dynamic_array
- make_dynamic_array_len
- make_dynamic_array_len_cap
- make_map
- make_map_cap
- make_multi_pointer
- make_slice
- make_soa_aligned
- make_soa_dynamic_array
- make_soa_dynamic_array_len
- make_soa_dynamic_array_len_cap
- make_soa_slice
- map_alloc_dynamic
- mem_alloc
- mem_alloc_bytes
- mem_alloc_non_zeroed
- mem_free
- mem_free_all
- mem_free_bytes
- mem_free_with_size
- mem_resize
- memory_block_alloc
- new
- new_aligned
- new_clone
- non_zero_mem_resize
- delete (procedure groups)
- delete_soa (procedure groups)
- free (procedure groups)
- free_all (procedure groups)
- make (procedure groups)
- make_soa (procedure groups)
Related Procedures With Returns
Allocator_Error ¶
Allocator_Error :: enum u8 { None = 0, Out_Of_Memory = 1, Invalid_Pointer = 2, Invalid_Argument = 3, Mode_Not_Implemented = 4, }
Related Procedures With Returns
- alloc_from_memory_block
- append_elem
- append_elem_string
- append_elems
- append_nothing
- append_soa_elem
- append_soa_elems
- append_string
- arena_alloc
- arena_allocator_proc
- arena_init
- assign_at_elem
- assign_at_elem_string
- assign_at_elems
- default_temp_allocator_proc
- delete_cstring
- delete_cstring16
- delete_dynamic_array
- delete_map
- delete_slice
- delete_soa_dynamic_array
- delete_soa_slice
- delete_string
- delete_string16
- heap_allocator_proc
- inject_at_elem
- inject_at_elem_string
- inject_at_elems
- make_aligned
- make_dynamic_array
- make_dynamic_array_len
- make_dynamic_array_len_cap
- make_map_cap
- make_multi_pointer
- make_slice
- make_soa_aligned
- make_soa_dynamic_array
- make_soa_dynamic_array_len
- make_soa_dynamic_array_len_cap
- make_soa_slice
- map_alloc_dynamic
- map_entry
- map_free_dynamic
- map_grow_dynamic
- map_reserve_dynamic
- map_shrink_dynamic
- mem_alloc
- mem_alloc_bytes
- mem_alloc_non_zeroed
- mem_free
- mem_free_all
- mem_free_bytes
- mem_free_with_size
- mem_resize
- memory_block_alloc
- new
- new_aligned
- new_clone
- nil_allocator_proc
- non_zero_append_elem
- non_zero_append_elem_string
- non_zero_append_elems
- non_zero_append_soa_elem
- non_zero_append_soa_elems
- non_zero_mem_resize
- non_zero_reserve_dynamic_array
- non_zero_reserve_soa
- non_zero_resize_dynamic_array
- non_zero_resize_soa
- panic_allocator_proc
- reserve_dynamic_array
- reserve_map
- reserve_soa
- resize_dynamic_array
- resize_soa
- shrink_dynamic_array
- shrink_map
- append (procedure groups)
- append_soa (procedure groups)
- assign_at (procedure groups)
- delete (procedure groups)
- delete_soa (procedure groups)
- free (procedure groups)
- free_all (procedure groups)
- inject_at (procedure groups)
- make (procedure groups)
- make_soa (procedure groups)
- non_zero_append (procedure groups)
- non_zero_reserve (procedure groups)
- non_zero_resize (procedure groups)
- reserve (procedure groups)
- resize (procedure groups)
- shrink (procedure groups)
Allocator_Mode ¶
Allocator_Mode :: enum u8 { Alloc, Free, Free_All, Resize, Query_Features, Query_Info, Alloc_Non_Zeroed, Resize_Non_Zeroed, }
Allocation Stuff
Related Procedures With Parameters
Allocator_Mode_Set ¶
Allocator_Mode_Set :: distinct bit_set[Allocator_Mode]
Allocator_Proc ¶
Allocator_Proc :: proc(allocator_data: rawptr, mode: Allocator_Mode, size, alignment: int, old_memory: rawptr, old_size: int, location := #caller_location) -> ([]u8, Allocator_Error)
Arena ¶
Arena :: struct { backing_allocator: Allocator, curr_block: ^Memory_Block, total_used: uint, total_capacity: uint, minimum_block_size: uint, temp_count: uint, }
NOTE: This is a growing arena that is only used for the default temp allocator.
For your own growing arena needs, prefer Arena
from core:mem/virtual
.
Related Procedures With Parameters
Arena_Temp ¶
Arena_Temp :: struct { arena: ^Arena, block: ^Memory_Block, used: uint, }
Related Procedures With Parameters
Related Procedures With Returns
Assertion_Failure_Proc ¶
Assertion_Failure_Proc :: proc(prefix, message: string, loc: Source_Code_Location) -> !
Allocation Stuff
Calling_Convention ¶
Calling_Convention :: enum u8 { Invalid = 0, Odin = 1, Contextless = 2, CDecl = 3, Std_Call = 4, Fast_Call = 5, None = 6, Naked = 7, Win64 = 9, SysV = 10, }
NOTE(bill): This must match the compiler's
Context ¶
Context :: struct { allocator: Allocator, temp_allocator: Allocator, assertion_failure_proc: Assertion_Failure_Proc, logger: Logger, random_generator: Random_Generator, user_ptr: rawptr, user_index: int, // Internal use only _internal: rawptr, }
Related Procedures With Returns
DLL_Forward_Reason ¶
DLL_Forward_Reason :: enum u32 { Process_Detach = 0, // About to unload DLL Process_Attach = 1, // Entry point Thread_Attach = 2, Thread_Detach = 3, }
Default_Random_State ¶
Related Procedures With Parameters
Default_Temp_Allocator ¶
Default_Temp_Allocator :: struct { arena: Arena, }
Related Procedures With Parameters
Equal_Proc ¶
Procedure type to test whether two values of the same type are equal
Hasher_Proc ¶
Procedure type to hash a value, default seed value is 0
Load_Directory_File ¶
Used by the built-in directory #load_directory(path: string) -> []Load_Directory_File
Logger ¶
Logger :: struct { procedure: Logger_Proc, data: rawptr, lowest_level: Logger_Level, options: bit_set[Logger_Option], }
Related Procedures With Returns
Logger_Level ¶
Logger_Level :: enum uint { Debug = 0, Info = 10, Warning = 20, Error = 30, Fatal = 40, }
Related Procedures With Parameters
Logger_Option ¶
Logger_Option :: enum int { Level, Date, Time, Short_File_Path, Long_File_Path, Line, Procedure, Terminal_Color, Thread_Id, }
Logger_Options ¶
Logger_Options :: bit_set[Logger_Option]
Logger_Proc ¶
Logger_Proc :: proc(data: rawptr, level: Logger_Level, text: string, options: bit_set[Logger_Option], location := #caller_location)
Map_Cell ¶
Map_Cell :: struct($T: typeid) #align (MAP_CACHE_LINE_SIZE) { … // See source for fields }
Map_Cell type that packs multiple T in such a way to ensure that each T stays aligned by align_of(T) and such that align_of(Map_Cell(T)) % MAP_CACHE_LINE_SIZE == 0
This means a value of type T will never straddle a cache-line.
When multiple Ts can fit in a single cache-line the data array will have more than one element. When it cannot, the data array will have one element and an array of Map_Cell(T) will be padded to stay a multiple of MAP_CACHE_LINE_SIZE.
We rely on the type system to do all the arithmetic and padding for us here.
The usual array[index] indexing for []T backed by a []Map_Cell(T) becomes a bit more involved as there now may be internal padding. The indexing now becomes
N :: len(Map_Cell(T){}.data) i := index / N j := index % N cell[i].data[j]
However, since len(Map_Cell(T){}.data) is a compile-time constant, there are some optimizations we can do to eliminate the need for any divisions as N will be bounded by [1, 64).
In the optimal case, len(Map_Cell(T){}.data) = 1 so the cell array can be treated as a regular array of T, which is the case for hashes.
Related Procedures With Parameters
Related Procedures With Returns
Map_Cell_Info ¶
Map_Cell_Info :: struct { size_of_type: uintptr, // 8-bytes on 64-bit, 4-bytes on 32-bits align_of_type: uintptr, // 8-bytes on 64-bit, 4-bytes on 32-bits size_of_cell: uintptr, // 8-bytes on 64-bit, 4-bytes on 32-bits elements_per_cell: uintptr, }
So we can operate on a cell data structure at runtime without any type information, we have a simple table that stores some traits about the cell.
32-bytes on 64-bit 16-bytes on 32-bit
Related Procedures With Parameters
Map_Hash ¶
Map_Hash :: uintptr
Map_Info ¶
Map_Info :: struct { ks: ^Map_Cell_Info, // 8-bytes on 64-bit, 4-bytes on 32-bit vs: ^Map_Cell_Info, // 8-bytes on 64-bit, 4-bytes on 32-bit key_hasher: proc "contextless" (key: rawptr, seed: uintptr) -> uintptr, // 8-bytes on 64-bit, 4-bytes on 32-bit key_equal: proc "contextless" (lhs, rhs: rawptr) -> bool, }
When working with the type-erased structure at runtime we need information about the map to make working with it possible. This info structure stores that.
Map_Info
and Map_Cell_Info
are read only data structures and cannot be
modified after creation
32-bytes on 64-bit 16-bytes on 32-bit
Related Procedures With Parameters
Memory_Block ¶
Memory_Block :: struct { prev: ^Memory_Block, allocator: Allocator, base: [^]u8, used: uint, capacity: uint, }
Related Procedures With Parameters
Related Procedures With Returns
Objc_Block ¶
Objc_Block :: struct($T: typeid) { … // See source for fields }
Represents an Objective-C block with a given procedure signature T
Odin_Arch_Type ¶
Odin_Arch_Type :: .Odin_Arch_Type
// Defined internally by the compiler Odin_Arch_Type :: enum int {
Unknown, amd64, i386, arm32, arm64, wasm32, wasm64p32, riscv64,
}
Odin_Build_Mode_Type ¶
Odin_Build_Mode_Type :: .Odin_Build_Mode_Type
// Defined internally by the compiler Odin_Build_Mode_Type :: enum int {
Executable, Dynamic, Static, Object, Assembly, LLVM_IR,
}
Odin_Endian_Type ¶
Odin_Endian_Type :: .Odin_Endian_Type
// Defined internally by the compiler Odin_Endian_Type :: enum int {
Unknown, Little, Big,
}
Odin_OS_Type ¶
Odin_OS_Type :: .Odin_OS_Type
// Defined internally by the compiler Odin_OS_Type :: enum int {
Unknown, Windows, Darwin, Linux, Essence, FreeBSD, OpenBSD, NetBSD, Haiku, WASI, JS, Orca, Freestanding,
}
Odin_Optimization_Mode ¶
Odin_Optimization_Mode :: .Odin_Optimization_Mode
// Defined internally by the compiler Odin_Optimization_Mode :: enum int {
None = -1, Minimal = 0, Size = 1, Speed = 2, Aggressive = 3,
}
ODIN_OPTIMIZATION_MODE // is a constant
Odin_Platform_Subtarget_Type ¶
Odin_Platform_Subtarget_Type :: .Odin_Platform_Subtarget_Type
// Defined internally by the compiler Odin_Platform_Subtarget_Type :: enum int {
Default, iPhone, iPhoneSimulator Android,
}
Odin_Platform_Subtarget_Types ¶
Odin_Platform_Subtarget_Types :: bit_set[.Odin_Platform_Subtarget_Type]
Odin_Sanitizer_Flags ¶
Odin_Sanitizer_Flags :: .Odin_Sanitizer_Flags
// Defined internally by the compiler Odin_Sanitizer_Flag :: enum u32 {
Address = 0, Memory = 1, Thread = 2,
} Odin_Sanitizer_Flags :: distinct bit_set[Odin_Sanitizer_Flag; u32]
ODIN_SANITIZER_FLAGS // is a constant
Platform_Endianness ¶
Platform_Endianness :: enum u8 { Platform = 0, Little = 1, Big = 2, }
Random_Generator ¶
Random_Generator :: struct { procedure: Random_Generator_Proc, data: rawptr, }
Related Procedures With Parameters
- random_generator_query_info
- random_generator_read_bytes
- random_generator_read_ptr
- random_generator_reset_bytes
- random_generator_reset_u64
Related Procedures With Returns
Random_Generator_Mode ¶
Random_Generator_Mode :: enum int { Read, Reset, Query_Info, }
Related Procedures With Parameters
Random_Generator_Proc ¶
Random_Generator_Proc :: proc(data: rawptr, mode: Random_Generator_Mode, p: []u8)
Random_Generator_Query_Info ¶
Random_Generator_Query_Info :: distinct bit_set[Random_Generator_Query_Info_Flag; u32]
Related Procedures With Returns
Random_Generator_Query_Info_Flag ¶
Random_Generator_Query_Info_Flag :: enum u32 { Cryptographic, Uniform, External_Entropy, Resettable, }
Raw_Cstring ¶
Raw_Cstring :: struct { data: [^]u8, }
Raw_Cstring16 ¶
Raw_Cstring16 :: struct { data: [^]u16, }
Raw_Map ¶
Raw_Map :: struct { // A single allocation spanning all keys, values, and hashes. // { // k: Map_Cell(K) * (capacity / ks_per_cell) // v: Map_Cell(V) * (capacity / vs_per_cell) // h: Map_Cell(H) * (capacity / hs_per_cell) // } // // The data is allocated assuming 64-byte alignment, meaning the address is // always a multiple of 64. This means we have 6 bits of zeros in the pointer // to store the capacity. We can store a value as large as 2^6-1 or 63 in // there. This conveniently is the maximum log2 capacity we can have for a map // as Odin uses signed integers to represent capacity. // // Since the hashes are backed by Map_Hash, which is just a 64-bit unsigned // integer, the cell structure for hashes is unnecessary because 64/8 is 8 and // requires no padding, meaning it can be indexed as a regular array of // Map_Hash directly, though for consistency sake it's written as if it were // an array of Map_Cell(Map_Hash). data: uintptr, // 8-bytes on 64-bits, 4-bytes on 32-bits len: uintptr, // 8-bytes on 64-bits, 4-bytes on 32-bits allocator: Allocator, }
The raw, type-erased representation of a map.
32-bytes on 64-bit 16-bytes on 32-bit
Related Procedures With Parameters
- map_cap
- map_clear_dynamic
- map_data
- map_desired_position
- map_erase_dynamic
- map_exists_dynamic
- map_free_dynamic
- map_grow_dynamic
- map_insert_hash_dynamic
- map_insert_hash_dynamic_with_key
- map_kvh_data_dynamic
- map_kvh_data_values_dynamic
- map_len
- map_log2_cap
- map_lookup_dynamic
- map_probe_distance
- map_reserve_dynamic
- map_resize_threshold
- map_seed
- map_shrink_dynamic
Related Procedures With Returns
Raw_SOA_Footer_Dynamic_Array ¶
Related Procedures With Returns
- raw_soa_footer_dynamic_array
- raw_soa_footer (procedure groups)
Raw_SOA_Footer_Slice ¶
Raw_SOA_Footer_Slice :: struct { len: int, }
Related Procedures With Returns
- raw_soa_footer_slice
- raw_soa_footer (procedure groups)
Source_Code_Location ¶
Related Procedures With Parameters
- DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD
- append_elem
- append_elem_string
- append_elems
- append_nothing
- append_soa_elem
- append_soa_elems
- append_string
- arena_alloc
- arena_allocator_proc
- arena_check_temp
- arena_destroy
- arena_free_all
- arena_free_last_memory_block
- arena_init
- arena_temp_begin
- arena_temp_end
- arena_temp_ignore
- assert
- assert_contextless
- assign_at_elem
- assign_at_elem_string
- assign_at_elems
- bounds_check_error_loc
- default_assertion_contextless_failure_proc
- default_assertion_failure_proc
- default_logger_proc
- default_temp_allocator_proc
- default_temp_allocator_temp_begin
- default_temp_allocator_temp_end
- delete_cstring
- delete_cstring16
- delete_dynamic_array
- delete_map
- delete_slice
- delete_soa_dynamic_array
- delete_soa_slice
- delete_string
- delete_string16
- dynamic_array_expr_error_loc
- ensure
- ensure_contextless
- heap_allocator_proc
- inject_at_elem
- inject_at_elem_string
- inject_at_elems
- make_aligned
- make_dynamic_array
- make_dynamic_array_error_loc
- make_dynamic_array_len
- make_dynamic_array_len_cap
- make_map
- make_map_cap
- make_map_expr_error_loc
- make_multi_pointer
- make_slice
- make_slice_error_loc
- make_soa_aligned
- make_soa_dynamic_array
- make_soa_dynamic_array_len
- make_soa_dynamic_array_len_cap
- make_soa_slice
- map_alloc_dynamic
- map_entry
- map_free_dynamic
- map_grow_dynamic
- map_insert
- map_reserve_dynamic
- map_shrink_dynamic
- map_upsert
- mem_alloc
- mem_alloc_bytes
- mem_alloc_non_zeroed
- mem_free
- mem_free_all
- mem_free_bytes
- mem_free_with_size
- mem_resize
- memory_block_alloc
- memory_block_dealloc
- new
- new_aligned
- new_clone
- nil_allocator_proc
- non_zero_append_elem
- non_zero_append_elem_string
- non_zero_append_elems
- non_zero_append_soa_elem
- non_zero_append_soa_elems
- non_zero_mem_resize
- non_zero_reserve_dynamic_array
- non_zero_reserve_soa
- non_zero_resize_dynamic_array
- non_zero_resize_soa
- ordered_remove
- ordered_remove_soa
- panic
- panic_allocator_proc
- panic_contextless
- pop
- pop_front
- print_caller_location
- remove_range
- reserve_dynamic_array
- reserve_map
- reserve_soa
- resize_dynamic_array
- resize_soa
- shrink_dynamic_array
- shrink_map
- slice_expr_error_hi_loc
- slice_expr_error_lo_hi_loc
- unimplemented
- unimplemented_contextless
- unordered_remove
- unordered_remove_soa
- append (procedure groups)
- append_soa (procedure groups)
- assign_at (procedure groups)
- delete (procedure groups)
- delete_soa (procedure groups)
- free (procedure groups)
- free_all (procedure groups)
- inject_at (procedure groups)
- make (procedure groups)
- make_soa (procedure groups)
- non_zero_append (procedure groups)
- non_zero_reserve (procedure groups)
- non_zero_resize (procedure groups)
- reserve (procedure groups)
- resize (procedure groups)
- shrink (procedure groups)
Thread_Local_Cleaner ¶
Thread_Local_Cleaner :: union { Thread_Local_Cleaner_Odin, Thread_Local_Cleaner_Contextless, }
Related Procedures With Parameters
Thread_Local_Cleaner_Contextless ¶
Thread_Local_Cleaner_Contextless :: proc "contextless" ()
Thread_Local_Cleaner_Odin ¶
Thread_Local_Cleaner_Odin :: proc()
Type_Info ¶
Type_Info :: struct { size: int, align: int, flags: Type_Info_Flags, id: typeid, variant: union { Type_Info_Named, Type_Info_Integer, Type_Info_Rune, Type_Info_Float, Type_Info_Complex, Type_Info_Quaternion, Type_Info_String, Type_Info_Boolean, Type_Info_Any, Type_Info_Type_Id, Type_Info_Pointer, Type_Info_Multi_Pointer, Type_Info_Procedure, Type_Info_Array, Type_Info_Enumerated_Array, Type_Info_Dynamic_Array, Type_Info_Slice, Type_Info_Parameters, Type_Info_Struct, Type_Info_Union, Type_Info_Enum, Type_Info_Map, Type_Info_Bit_Set, Type_Info_Simd_Vector, Type_Info_Matrix, Type_Info_Soa_Pointer, Type_Info_Bit_Field, }, }
Related Procedures With Parameters
Type_Info_Any ¶
Type_Info_Any :: struct {}
Type_Info_Boolean ¶
Type_Info_Boolean :: struct {}
Type_Info_Complex ¶
Type_Info_Complex :: struct {}
Type_Info_Enum ¶
Type_Info_Enum :: struct { base: ^Type_Info, names: []string, values: []Type_Info_Enum_Value, }
Type_Info_Enum_Value ¶
Type_Info_Enum_Value :: distinct i64
Type_Info_Enumerated_Array ¶
Type_Info_Enumerated_Array :: struct { elem: ^Type_Info, index: ^Type_Info, elem_size: int, count: int, min_value: Type_Info_Enum_Value, max_value: Type_Info_Enum_Value, is_sparse: bool, }
Type_Info_Flag ¶
Type_Info_Flag :: enum u8 { Comparable = 0, Simple_Compare = 1, }
Type_Info_Flags ¶
Type_Info_Flags :: distinct bit_set[Type_Info_Flag; u32]
Type_Info_Float ¶
Type_Info_Float :: struct { endianness: Platform_Endianness, }
Type_Info_Integer ¶
Type_Info_Integer :: struct { signed: bool, endianness: Platform_Endianness, }
Type_Info_Multi_Pointer ¶
Type_Info_Multi_Pointer :: struct { elem: ^Type_Info, }
Type_Info_Named ¶
Type_Info_Named :: struct { name: string, base: ^Type_Info, pkg: string, loc: ^Source_Code_Location, }
Variant Types
Type_Info_Pointer ¶
Type_Info_Pointer :: struct { elem: ^Type_Info, }
Type_Info_Procedure ¶
Type_Info_Procedure :: struct { params: ^Type_Info, // Type_Info_Parameters results: ^Type_Info, // Type_Info_Parameters variadic: bool, convention: Calling_Convention, }
Type_Info_Quaternion ¶
Type_Info_Quaternion :: struct {}
Type_Info_Rune ¶
Type_Info_Rune :: struct {}
Type_Info_Soa_Pointer ¶
Type_Info_Soa_Pointer :: struct { elem: ^Type_Info, }
Type_Info_String ¶
Type_Info_String :: struct { is_cstring: bool, encoding: Type_Info_String_Encoding_Kind, }
Type_Info_String_Encoding_Kind ¶
Type_Info_String_Encoding_Kind :: enum u8 { UTF_8 = 0, UTF_16 = 1, }
Type_Info_Struct ¶
Type_Info_Struct :: struct { // Slice these with `field_count` types: [^]^Type_Info `fmt:"v,field_count"`, names: [^]string `fmt:"v,field_count"`, offsets: [^]uintptr `fmt:"v,field_count"`, usings: [^]bool `fmt:"v,field_count"`, tags: [^]string `fmt:"v,field_count"`, field_count: i32, flags: Type_Info_Struct_Flags, // These are only set iff this structure is an SOA structure soa_kind: Type_Info_Struct_Soa_Kind, soa_len: i32, soa_base_type: ^Type_Info, equal: Equal_Proc, }
Type_Info_Struct_Flag ¶
Type_Info_Struct_Flag :: enum u8 { packed = 0, raw_union = 1, align = 3, }
Type_Info_Struct_Flags ¶
Type_Info_Struct_Flags :: distinct bit_set[Type_Info_Struct_Flag; u8]
Type_Info_Struct_Soa_Kind ¶
Type_Info_Struct_Soa_Kind :: enum u8 { None = 0, Fixed = 1, Slice = 2, Dynamic = 3, }
Type_Info_Type_Id ¶
Type_Info_Type_Id :: struct {}
Constants
ALL_ODIN_ARCH_TYPES ¶
ALL_ODIN_ARCH_TYPES: bit_set[.Odin_Arch_Type] : Odin_Arch_Types{.amd64, .i386, .arm32, .arm64, .wasm32, .wasm64p32, .riscv64}
ALL_ODIN_OS_TYPES ¶
ALL_ODIN_OS_TYPES: bit_set[.Odin_OS_Type] : Odin_OS_Types{.Windows, .Darwin, .Linux, .Essence, .FreeBSD, .OpenBSD, .NetBSD, .Haiku, .WASI, .JS, .Orca, .Freestanding}
DEFAULT_ALIGNMENT ¶
DEFAULT_ALIGNMENT: int : 2 * align_of(rawptr)
DEFAULT_ARENA_GROWING_MINIMUM_BLOCK_SIZE ¶
DEFAULT_ARENA_GROWING_MINIMUM_BLOCK_SIZE :: uint(DEFAULT_TEMP_ALLOCATOR_BACKING_SIZE)
DEFAULT_DYNAMIC_ARRAY_CAPACITY ¶
DEFAULT_DYNAMIC_ARRAY_CAPACITY: int : 8
DEFAULT_TEMP_ALLOCATOR_BACKING_SIZE ¶
DEFAULT_TEMP_ALLOCATOR_BACKING_SIZE: int : #config(DEFAULT_TEMP_ALLOCATOR_BACKING_SIZE, 4 * Megabyte)
Gigabyte ¶
Gigabyte: int : 1024 * Megabyte
HASH_MASK ¶
HASH_MASK: int : 1 << (8 * size_of(uintptr) - 1) - 1
HAS_HARDWARE_SIMD ¶
HAS_HARDWARE_SIMD: bool : false when (ODIN_ARCH == .amd64 || ODIN_ARCH == .i386) && !intrinsics.has_target_feature("sse2") else false when (ODIN_ARCH == .arm64 || ODIN_ARCH == .arm32) && !intrinsics.has_target_feature("neon") else false when (ODIN_ARCH == .wasm64p32 || ODIN_ARCH == .wasm32) && !intrinsics.has_target_feature("simd128") else false when (ODIN_ARCH == .riscv64) && !intrinsics.has_target_feature("v") else true
INITIAL_HASH_SEED ¶
INITIAL_HASH_SEED: int : 0xcbf29ce484222325
Kilobyte ¶
Kilobyte: int : 1024 * Byte
MAP_CACHE_LINE_LOG2 ¶
MAP_CACHE_LINE_LOG2: int : 6
This is safe to change. The log2 size of a cache-line. At minimum it has to be six though. Higher cache line sizes are permitted.
MAP_LOAD_FACTOR ¶
MAP_LOAD_FACTOR: int : 75
With Robin Hood hashing a maximum load factor of 75% is ideal.
Megabyte ¶
Megabyte: int : 1024 * Kilobyte
NO_DEFAULT_TEMP_ALLOCATOR ¶
NO_DEFAULT_TEMP_ALLOCATOR: bool : ODIN_OS == .Freestanding || ODIN_DEFAULT_TO_NIL_ALLOCATOR
ODIN_PLATFORM_SUBTARGET_IOS ¶
ODIN_PLATFORM_SUBTARGET_IOS: bool : ODIN_PLATFORM_SUBTARGET == .iPhone || ODIN_PLATFORM_SUBTARGET == .iPhoneSimulator
Petabyte ¶
Petabyte: int : 1024 * Terabyte
TOMBSTONE_MASK ¶
TOMBSTONE_MASK: int : 1 << (size_of(Map_Hash) * 8 - 1)
Terabyte ¶
Terabyte: int : 1024 * Gigabyte
Variables
dll_forward_reason ¶
dll_forward_reason: DLL_Forward_Reason
dll_instance ¶
dll_instance: rawptr
global_default_temp_allocator_data ¶
@(thread_local) global_default_temp_allocator_data: Default_Temp_Allocator
type_table ¶
type_table: []^Type_Info
NOTE(bill): only the ones that are needed (not all types) This will be set by the compiler
Procedures
DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD ¶
DEFAULT_TEMP_ALLOCATOR_TEMP_GUARD :: proc(ignore: bool = false, loc := #caller_location) -> (Arena_Temp, Source_Code_Location) {…}
abs_complex128 ¶
abs_complex128 :: proc "contextless" (x: complex128) -> f64 {…}
abs_quaternion128 ¶
abs_quaternion128 :: proc "contextless" (x: quaternion128) -> f32 {…}
abs_quaternion256 ¶
abs_quaternion256 :: proc "contextless" (x: quaternion256) -> f64 {…}
abs_quaternion64 ¶
abs_quaternion64 :: proc "contextless" (x: quaternion64) -> f16 {…}
add_thread_local_cleaner ¶
add_thread_local_cleaner :: proc "contextless" (p: Thread_Local_Cleaner) {…}
Add a procedure that will be run at the end of a thread for the purpose of
deallocating state marked as thread_local
.
Intended to be called in an init
procedure of a package with
dynamically-allocated memory that is stored in thread_local
variables.
alloc_from_memory_block ¶
alloc_from_memory_block :: proc(block: ^Memory_Block, min_size, alignment: uint) -> (data: []u8, err: Allocator_Error) {…}
append_elem ¶
append_elem :: proc(array: ^$T/[dynamic]$E, #no_broadcast arg: $E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_ok {…}
append_elem_string ¶
append_elem_string :: proc(array: ^[dynamic]u8, arg: string, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_ok {…}
append_elems ¶
append_elems :: proc(array: ^$T/[dynamic]$E, .. #no_broadcast args: $T/..$E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_ok {…}
append_nothing ¶
append_nothing :: proc(array: ^$T/[dynamic]$E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_ok {…}
append_soa_elem ¶
append_soa_elem :: proc(array: ^$T/#soa[dynamic]$E, #no_broadcast arg: $E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_ok {…}
append_soa_elems ¶
append_soa_elems :: proc(array: ^$T/#soa[dynamic]$E, .. #no_broadcast args: $T/..$E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_ok {…}
append_string ¶
append_string :: proc(array: ^[dynamic]u8, .. args: ..string, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_ok {…}
The append_string built-in procedure appends multiple strings to the end of a [dynamic]u8 like type
arena_alloc ¶
arena_alloc :: proc(arena: ^Arena, size, alignment: uint, loc := #caller_location) -> (data: []u8, err: Allocator_Error) {…}
arena_allocator_proc ¶
arena_allocator_proc :: proc( allocator_data: rawptr, mode: Allocator_Mode, size, alignment: int, old_memory: rawptr, old_size: int, location := #caller_location, ) -> (data: []u8, err: Allocator_Error) {…}
arena_check_temp ¶
arena_check_temp :: proc(arena: ^Arena, loc := #caller_location) {…}
arena_destroy ¶
arena_destroy :: proc "contextless" (arena: ^Arena, loc := #caller_location) {…}
arena_free_all ¶
arena_free_all :: proc(arena: ^Arena, loc := #caller_location) {…}
arena_free_all
will free all but the first memory block, and then reset the memory block
arena_free_last_memory_block ¶
arena_free_last_memory_block :: proc(arena: ^Arena, loc := #caller_location) {…}
arena_init ¶
arena_init :: proc(arena: ^Arena, size: uint, backing_allocator: Allocator, loc := #caller_location) -> Allocator_Error {…}
arena_init
will initialize the arena with a usable block.
This procedure is not necessary to use the Arena as the default zero as arena_alloc
will set things up if necessary
arena_temp_begin ¶
arena_temp_begin :: proc(arena: ^Arena, loc := #caller_location) -> (temp: Arena_Temp) {…}
arena_temp_end ¶
arena_temp_end :: proc(temp: Arena_Temp, loc := #caller_location) {…}
arena_temp_ignore ¶
arena_temp_ignore :: proc(temp: Arena_Temp, loc := #caller_location) {…}
Ignore the use of a arena_temp_begin
entirely
assert ¶
assert :: proc(condition: bool, message: string = #caller_expression(condition), loc := #caller_location) {…}
assert_contextless ¶
assert_contextless :: proc "contextless" (condition: bool, message: string = #caller_expression(condition), loc := #caller_location) {…}
assign_at_elem ¶
assign_at_elem :: proc(array: ^$T/[dynamic]$E, #any_int index: int, #no_broadcast arg: $E, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #optional_ok {…}
assign_at_elem_string ¶
assign_at_elem_string :: proc(array: ^[dynamic]u8, #any_int index: int, arg: string, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #optional_ok {…}
assign_at_elems ¶
assign_at_elems :: proc(array: ^$T/[dynamic]$E, #any_int index: int, .. #no_broadcast args: $T/..$E, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #optional_ok {…}
bounds_check_error_loc ¶
bounds_check_error_loc :: proc "contextless" (loc := #caller_location, index, count: int) {…}
bounds_trap ¶
bounds_trap :: proc "contextless" () {…}
clear_dynamic_array ¶
clear_dynamic_array :: proc "contextless" (array: ^$T/[dynamic]$E) {…}
clear_dynamic_array
will set the length of a passed dynamic array to 0
Note: Prefer the procedure group clear
.
clear_map ¶
clear_map :: proc "contextless" (m: ^$T/map[$K]$V) {…}
clear_map
will set the length of a passed map to 0
Note: Prefer the procedure group clear
clear_soa_dynamic_array ¶
clear_soa_dynamic_array :: proc(array: ^$T/#soa[dynamic]$E) {…}
complex128_eq ¶
complex128_eq :: proc "contextless" (a, b: complex128) -> bool {…}
complex128_ne ¶
complex128_ne :: proc "contextless" (a, b: complex128) -> bool {…}
container_of ¶
container_of :: proc "contextless" (ptr: $P/^$Field_Type, $T: typeid, $field_name: string) -> ^typeid {…}
Recovers the containing/parent struct from a pointer to one of its fields. Works by "walking back" to the struct's starting address using the offset between the field and the struct.
Inputs:
ptr: Pointer to the field of a container struct
T: The type of the container struct
field_name: The name of the field in the T
struct
Returns:
A pointer to the container struct based on a pointer to a field in it
Example:
package container_of
import "base:runtime"
Node :: struct {
value: int,
prev: ^Node,
next: ^Node,
}
main :: proc() {
node: Node
field_ptr := &node.next
container_struct_ptr: ^Node = runtime.container_of(field_ptr, Node, "next")
assert(container_struct_ptr == &node)
assert(uintptr(field_ptr) - uintptr(container_struct_ptr) == size_of(node.value) + size_of(node.prev))
}
^Node
copy_from_string ¶
copy_from_string
is a built-in procedure that copies elements from a source string src
to a destination slice dst
.
The source and destination may overlap. Copy returns the number of elements copied, which will be the minimum
of len(src) and len(dst).
Prefer the procedure group copy
.
copy_from_string16 ¶
copy_from_string16
is a built-in procedure that copies elements from a source string src
to a destination slice dst
.
The source and destination may overlap. Copy returns the number of elements copied, which will be the minimum
of len(src) and len(dst).
Prefer the procedure group copy
.
copy_slice ¶
copy_slice :: proc "contextless" (dst, src: $T/[]$E) -> int {…}
copy_slice
is a built-in procedure that copies elements from a source slice src
to a destination slice dst
.
The source and destination may overlap. Copy returns the number of elements copied, which will be the minimum
of len(src) and len(dst).
Prefer the procedure group copy
.
debug_trap ¶
debug_trap :: intrinsics.debug_trap
default_allocator ¶
default_allocator :: heap_allocator
default_allocator_proc ¶
default_allocator_proc :: heap_allocator_proc
default_assertion_contextless_failure_proc ¶
default_assertion_contextless_failure_proc :: proc "contextless" (prefix, message: string, loc: Source_Code_Location) -> ! {…}
default_assertion_failure_proc ¶
default_assertion_failure_proc :: proc(prefix, message: string, loc: Source_Code_Location) -> ! {…}
default_context ¶
default_context :: proc "contextless" () -> Context {…}
default_logger ¶
default_logger :: proc() -> Logger {…}
default_logger_proc ¶
default_logger_proc :: proc(data: rawptr, level: Logger_Level, text: string, options: bit_set[Logger_Option], location := #caller_location) {…}
default_random_generator ¶
default_random_generator :: proc "contextless" (state: ^Default_Random_State = nil) -> Random_Generator {…}
default_random_generator_proc ¶
default_random_generator_proc :: proc(data: rawptr, mode: Random_Generator_Mode, p: []u8) {…}
default_temp_allocator ¶
default_temp_allocator :: proc(allocator: ^Default_Temp_Allocator) -> Allocator {…}
default_temp_allocator_destroy ¶
default_temp_allocator_destroy :: proc "contextless" (s: ^Default_Temp_Allocator) {…}
default_temp_allocator_init ¶
default_temp_allocator_init :: proc(s: ^Default_Temp_Allocator, size: int, backing_allocator := context.allocator) {…}
default_temp_allocator_proc ¶
default_temp_allocator_proc :: proc( allocator_data: rawptr, mode: Allocator_Mode, size, alignment: int, old_memory: rawptr, old_size: int, loc := #caller_location, ) -> (data: []u8, err: Allocator_Error) {…}
default_temp_allocator_temp_begin ¶
default_temp_allocator_temp_begin :: proc(loc := #caller_location) -> (temp: Arena_Temp) {…}
default_temp_allocator_temp_end ¶
default_temp_allocator_temp_end :: proc(temp: Arena_Temp, loc := #caller_location) {…}
delete_cstring ¶
delete_cstring :: proc(str: cstring, allocator := context.allocator, loc := #caller_location) -> Allocator_Error {…}
delete_cstring
will try to free the underlying data of the passed string, with the given allocator
if the allocator supports this operation.
Note: Prefer the procedure group delete
.
delete_cstring16 ¶
delete_cstring16 :: proc(str: cstring16, allocator := context.allocator, loc := #caller_location) -> Allocator_Error {…}
delete_dynamic_array ¶
delete_dynamic_array :: proc(array: $T/[dynamic]$E, loc := #caller_location) -> Allocator_Error {…}
delete_dynamic_array
will try to free the underlying data of the passed dynamic array, with the given allocator
if the allocator supports this operation.
Note: Prefer the procedure group delete
.
delete_key ¶
delete_key :: proc(m: ^$T/map[$K]$V, key: $K) -> (deleted_key: $K, deleted_value: $V) {…}
The delete_key built-in procedure deletes the element with the specified key (m[key]) from the map. If m is nil, or there is no such element, this procedure is a no-op
delete_map ¶
delete_map :: proc(m: $T/map[$K]$V, loc := #caller_location) -> Allocator_Error {…}
delete_map
will try to free the underlying data of the passed map, with the given allocator
if the allocator supports this operation.
Note: Prefer the procedure group delete
.
delete_slice ¶
delete_slice :: proc(array: $T/[]$E, allocator := context.allocator, loc := #caller_location) -> Allocator_Error {…}
delete_slice
will try to free the underlying data of the passed sliced, with the given allocator
if the allocator supports this operation.
Note: Prefer the procedure group delete
.
delete_soa_dynamic_array ¶
delete_soa_dynamic_array :: proc(array: $T/#soa[dynamic]$E, loc := #caller_location) -> Allocator_Error {…}
delete_soa_slice ¶
delete_soa_slice :: proc(array: $T/#soa[]$E, allocator := context.allocator, loc := #caller_location) -> Allocator_Error {…}
delete_string ¶
delete_string :: proc(str: string, allocator := context.allocator, loc := #caller_location) -> Allocator_Error {…}
delete_string
will try to free the underlying data of the passed string, with the given allocator
if the allocator supports this operation.
Note: Prefer the procedure group delete
.
delete_string16 ¶
delete_string16 :: proc(str: string16, allocator := context.allocator, loc := #caller_location) -> Allocator_Error {…}
dynamic_array_expr_error_loc ¶
dynamic_array_expr_error_loc :: proc "contextless" (loc := #caller_location, low, high, max: int) {…}
ensure ¶
ensure :: proc(condition: bool, message: string = #caller_expression(condition), loc := #caller_location) {…}
Evaluates the condition and aborts the program iff the condition is
false. This routine ignores ODIN_DISABLE_ASSERT
, and will always
execute.
ensure_contextless ¶
ensure_contextless :: proc "contextless" (condition: bool, message: string = #caller_expression(condition), loc := #caller_location) {…}
heap_allocator ¶
heap_allocator :: proc() -> Allocator {…}
heap_allocator_proc ¶
heap_allocator_proc :: proc( allocator_data: rawptr, mode: Allocator_Mode, size, alignment: int, old_memory: rawptr, old_size: int, loc := #caller_location, ) -> ([]u8, Allocator_Error) {…}
heap_free ¶
heap_free :: proc "contextless" (ptr: rawptr) {…}
init_global_temporary_allocator ¶
init_global_temporary_allocator :: proc(size: int, backup_allocator := context.allocator) {…}
inject_at_elem ¶
inject_at_elem :: proc(array: ^$T/[dynamic]$E, #any_int index: int, #no_broadcast arg: $E, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #optional_ok {…}
inject_at_elem_string ¶
inject_at_elem_string :: proc(array: ^[dynamic]u8, #any_int index: int, arg: string, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #optional_ok {…}
inject_at_elems ¶
inject_at_elems :: proc(array: ^$T/[dynamic]$E, #any_int index: int, .. #no_broadcast args: $T/..$E, loc := #caller_location) -> (ok: bool, err: Allocator_Error) #optional_ok {…}
into_dynamic_soa ¶
into_dynamic_soa :: proc(array: $T/#soa[]$E) -> $T/#soa[dynamic]$E {…}
Converts soa slice into a soa dynamic array without cloning or allocating memory
make_aligned ¶
make_aligned :: proc($T: typeid/[]$E, #any_int len: int, alignment: int, allocator := context.allocator, loc := #caller_location) -> (T, Allocator_Error) #optional_ok {…}
make_dynamic_array ¶
make_dynamic_array :: proc($T: typeid/[dynamic]$E, allocator := context.allocator, loc := #caller_location) -> (T, Allocator_Error) {…}
make_dynamic_array
allocates and initializes a dynamic array. Like new
, the first 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.
Note: Prefer using the procedure group make
.
make_dynamic_array_error_loc ¶
make_dynamic_array_error_loc :: proc "contextless" (loc := #caller_location, len, cap: int) {…}
make_dynamic_array_len ¶
make_dynamic_array_len :: proc($T: typeid/[dynamic]$E, #any_int len: int, allocator := context.allocator, loc := #caller_location) -> (T, Allocator_Error) {…}
make_dynamic_array_len
allocates and initializes a dynamic array. Like new
, the first 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.
Note: Prefer using the procedure group make
.
make_dynamic_array_len_cap ¶
make_dynamic_array_len_cap :: proc($T: typeid/[dynamic]$E, #any_int len: int, #any_int cap: int, allocator := context.allocator, loc := #caller_location) -> (array: T, err: Allocator_Error) {…}
make_dynamic_array_len_cap
allocates and initializes a dynamic array. Like new
, the first 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.
Note: Prefer using the procedure group make
.
make_map ¶
make_map :: proc($T: typeid/map[$K]$E, allocator := context.allocator, loc := #caller_location) -> (m: $/map[$K]$E) {…}
make_map
initializes a map with an allocator. Like new
, the first 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.
Note: Prefer using the procedure group make
.
make_map_cap ¶
make_map_cap :: proc($T: typeid/map[$K]$E, #any_int capacity: int, allocator := context.allocator, loc := #caller_location) -> (m: $/map[$K]$E, err: Allocator_Error) #optional_ok {…}
make_map_cap
initializes a map with an allocator and allocates space using capacity
.
Like new
, the first 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.
Note: Prefer using the procedure group make
.
make_map_expr_error_loc ¶
make_map_expr_error_loc :: proc "contextless" (loc := #caller_location, cap: int) {…}
make_multi_pointer ¶
make_multi_pointer :: proc($T: typeid/[^]$E, #any_int len: int, allocator := context.allocator, loc := #caller_location) -> (mp: $/[^]$E, err: Allocator_Error) {…}
make_multi_pointer
allocates and initializes a multi-pointer. Like new
, the first 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.
This is "similar" to doing raw_data(make([]E, len, allocator))
.
Note: Prefer using the procedure group make
.
make_slice ¶
make_slice :: proc($T: typeid/[]$E, #any_int len: int, allocator := context.allocator, loc := #caller_location) -> (T, Allocator_Error) {…}
make_slice
allocates and initializes a slice. Like new
, the first 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.
Note: Prefer using the procedure group make
.
make_slice_error_loc ¶
make_slice_error_loc :: proc "contextless" (loc := #caller_location, len: int) {…}
make_soa_aligned ¶
make_soa_aligned :: proc($T: typeid/#soa[]$E, #any_int length, #any_int alignment: int, allocator := context.allocator, loc := #caller_location) -> (array: T, err: Allocator_Error) #optional_ok {…}
make_soa_dynamic_array ¶
make_soa_dynamic_array :: proc($T: typeid/#soa[dynamic]$E, allocator := context.allocator, loc := #caller_location) -> (array: T, err: Allocator_Error) {…}
make_soa_dynamic_array_len ¶
make_soa_dynamic_array_len :: proc($T: typeid/#soa[dynamic]$E, #any_int length: int, allocator := context.allocator, loc := #caller_location) -> (array: T, err: Allocator_Error) #optional_ok {…}
make_soa_dynamic_array_len_cap ¶
make_soa_dynamic_array_len_cap :: proc($T: typeid/#soa[dynamic]$E, #any_int length, #any_int capacity: int, allocator := context.allocator, loc := #caller_location) -> (array: T, err: Allocator_Error) #optional_ok {…}
make_soa_slice ¶
make_soa_slice :: proc($T: typeid/#soa[]$E, #any_int length: int, allocator := context.allocator, loc := #caller_location) -> (array: T, err: Allocator_Error) #optional_ok {…}
map_alloc_dynamic ¶
map_alloc_dynamic :: proc(info: ^Map_Info, log2_capacity: uintptr, allocator := context.allocator, loc := #caller_location) -> (result: Raw_Map, err: Allocator_Error) {…}
The only procedure which needs access to the context is the one which allocates the map.
map_cell_index_dynamic ¶
map_cell_index_dynamic :: proc "contextless" (base: uintptr, #no_alias info: ^Map_Cell_Info, index: uintptr) -> uintptr {…}
Same as the above procedure but at runtime with the cell Map_Cell_Info value.
map_cell_index_dynamic_const ¶
map_cell_index_dynamic_const :: proc "contextless" (base: uintptr, #no_alias info: ^Map_Cell_Info, $INDEX: uintptr) -> uintptr {…}
Same as above procedure but with compile-time constant index.
map_cell_index_static ¶
We always round the capacity to a power of two so this becomes [16]Foo, which works out to [4]Cell(Foo).
The following compile-time procedure indexes such a [N]Cell(T) structure as if it were a flat array accounting for the internal padding introduced by the Cell structure.
map_cell_info ¶
map_cell_info :: intrinsics.type_map_cell_info
map_cell_info :: proc "contextless" ($T: typeid) -> ^Map_Cell_Info {...}
map_data ¶
Canonicalize the data by removing the tagged capacity stored in the lower six bits of the data uintptr.
map_desired_position ¶
Computes the desired position in the array. This is just index % capacity, but a procedure as there's some math involved here to recover the capacity.
map_entry ¶
map_entry :: proc(m: ^$T/map[$K]$V, key: $K, loc := #caller_location) -> (key_ptr: ^$K, value_ptr: ^$V, just_inserted: bool, err: Allocator_Error) {…}
Retrieves a pointer to the key and value for a possibly just inserted entry into the map.
If the key
was not in the map m
, an entry is inserted with the zero value and just_inserted
will be true
.
Otherwise the existing entry is left untouched and pointers to its key and value are returned.
If the map has to grow in order to insert the entry and the allocation fails, err
is set and returned.
If err
is nil
, key_ptr
and value_ptr
are valid pointers and will not be nil
.
WARN: User modification of the key pointed at by key_ptr
should only be done if the new key is equal to (in hash) the old key.
If that is not the case you will corrupt the map.
map_free_dynamic ¶
map_free_dynamic :: proc(m: Raw_Map, info: ^Map_Info, loc := #caller_location) -> Allocator_Error {…}
map_get ¶
map_get :: proc "contextless" (m: $T/map[$K]$V, key: $K) -> (stored_key: $K, stored_value: $V, ok: bool) {…}
map_grow_dynamic ¶
map_grow_dynamic :: proc(#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, loc := #caller_location) -> Allocator_Error {…}
map_hash_is_empty ¶
Procedure to check if a slot is empty for a given hash. This is represented by the zero value to make the zero value useful. This is a procedure just for prose reasons.
map_info ¶
map_info :: intrinsics.type_map_info
The Map_Info structure is basically a pseudo-table of information for a given K and V pair. map_info :: proc "contextless" ($T: typeid/map[$K]$V) -> ^Map_Info {...}
map_insert ¶
map_insert :: proc(m: ^$T/map[$K]$V, key: $K, value: $V, loc := #caller_location) -> (ptr: ^$V) {…}
map_insert_hash_dynamic_with_key ¶
map_insert_hash_dynamic_with_key :: proc(#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, h: uintptr, ik: uintptr, iv: uintptr) -> (key: uintptr, result: uintptr) {…}
This procedure has to stack allocate storage to store local keys during the Robin Hood hashing technique where elements are swapped in the backing arrays to reduce variance. This swapping can only be done with memcpy since there is no type information.
This procedure returns the address of the just inserted value, and will return 'nil' if there was no room to insert the entry
map_load_factor ¶
Query the load factor of the map. This is not actually configurable, but some math is needed to compute it. Compute it as a fixed point percentage to avoid floating point operations. This division can be optimized out by multiplying by the multiplicative inverse of 100.
map_log2_cap ¶
The data stores the log2 capacity in the lower six bits. This is primarily used in the implementation rather than map_cap since the check for data = 0 isn't necessary in the implementation. cap() on the otherhand needs to work when called on an empty map.
map_reserve_dynamic ¶
map_reserve_dynamic :: proc(#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, new_capacity: uintptr, loc := #caller_location) -> Allocator_Error {…}
map_seed_from_map_data ¶
splitmix for uintptr
map_shrink_dynamic ¶
map_shrink_dynamic :: proc(#no_alias m: ^Raw_Map, #no_alias info: ^Map_Info, loc := #caller_location) -> (did_shrink: bool, err: Allocator_Error) {…}
map_total_allocation_size_from_value ¶
map_total_allocation_size_from_value :: proc "contextless" (m: $T/map[$K]$V) -> uintptr {…}
map_upsert ¶
map_upsert :: proc(m: ^$T/map[$K]$V, key: $K, value: $V, loc := #caller_location) -> (prev_key: $K, value_ptr: ^$V, found_previous: bool) {…}
Explicitly inserts a key and value into a map m
, the same as map_insert
, but the return values differ.
prev_key
will return the previous pointer of a key if it exists, check found_previous
if was previously found
value_ptr
will return the pointer of the memory where the insertion happens, and nil
if the map failed to resize
found_previous
will be true a previous key was found
mem_alloc ¶
mem_alloc :: proc(size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> ([]u8, Allocator_Error) {…}
mem_alloc_bytes ¶
mem_alloc_bytes :: proc(size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> ([]u8, Allocator_Error) {…}
mem_alloc_non_zeroed ¶
mem_alloc_non_zeroed :: proc(size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> ([]u8, Allocator_Error) {…}
mem_free ¶
mem_free :: proc(ptr: rawptr, allocator := context.allocator, loc := #caller_location) -> Allocator_Error {…}
mem_free_all ¶
mem_free_all :: proc(allocator := context.allocator, loc := #caller_location) -> (err: Allocator_Error) {…}
mem_free_bytes ¶
mem_free_bytes :: proc(bytes: []u8, allocator := context.allocator, loc := #caller_location) -> Allocator_Error {…}
mem_free_with_size ¶
mem_free_with_size :: proc(ptr: rawptr, byte_count: int, allocator := context.allocator, loc := #caller_location) -> Allocator_Error {…}
mem_resize ¶
mem_resize :: proc( ptr: rawptr, old_size: int, new_size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location, ) -> (data: []u8, err: Allocator_Error) {…}
memory_block_alloc ¶
memory_block_alloc :: proc(allocator: Allocator, capacity: uint, alignment: uint, loc := #caller_location) -> (block: ^Memory_Block, err: Allocator_Error) {…}
memory_block_dealloc ¶
memory_block_dealloc :: proc "contextless" (block_to_free: ^Memory_Block, loc := #caller_location) {…}
mul_quaternion128 ¶
mul_quaternion128 :: proc "contextless" (q, r: quaternion128) -> quaternion128 {…}
mul_quaternion256 ¶
mul_quaternion256 :: proc "contextless" (q, r: quaternion256) -> quaternion256 {…}
mul_quaternion64 ¶
mul_quaternion64 :: proc "contextless" (q, r: quaternion64) -> quaternion64 {…}
new ¶
new :: proc($T: typeid, allocator := context.allocator, loc := #caller_location) -> (^typeid, Allocator_Error) {…}
The new built-in procedure allocates memory. The first argument is a type, not a value, and the value return is a pointer to a newly allocated value of that type using the specified allocator, default is context.allocator
new_aligned ¶
new_aligned :: proc($T: typeid, alignment: int, allocator := context.allocator, loc := #caller_location) -> (t: ^typeid, err: Allocator_Error) {…}
new_clone ¶
new_clone :: proc(data: $T, allocator := context.allocator, loc := #caller_location) -> (t: ^$T, err: Allocator_Error) {…}
nil_allocator ¶
nil_allocator :: proc "contextless" () -> Allocator {…}
nil_allocator_proc ¶
nil_allocator_proc :: proc( allocator_data: rawptr, mode: Allocator_Mode, size, alignment: int, old_memory: rawptr, old_size: int, loc := #caller_location, ) -> ([]u8, Allocator_Error) {…}
non_zero_append_elem ¶
non_zero_append_elem :: proc(array: ^$T/[dynamic]$E, #no_broadcast arg: $E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_ok {…}
non_zero_append_elem_string ¶
non_zero_append_elem_string :: proc(array: ^[dynamic]u8, arg: string, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_ok {…}
non_zero_append_elems ¶
non_zero_append_elems :: proc(array: ^$T/[dynamic]$E, .. #no_broadcast args: $T/..$E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_ok {…}
non_zero_append_soa_elem ¶
non_zero_append_soa_elem :: proc(array: ^$T/#soa[dynamic]$E, #no_broadcast arg: $E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_ok {…}
non_zero_append_soa_elems ¶
non_zero_append_soa_elems :: proc(array: ^$T/#soa[dynamic]$E, .. #no_broadcast args: $T/..$E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_ok {…}
non_zero_mem_resize ¶
non_zero_mem_resize :: proc( ptr: rawptr, old_size: int, new_size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location, ) -> (data: []u8, err: Allocator_Error) {…}
non_zero_reserve_dynamic_array ¶
non_zero_reserve_dynamic_array :: proc(array: ^$T/[dynamic]$E, #any_int capacity: int, loc := #caller_location) -> Allocator_Error {…}
non_zero_reserve_soa ¶
non_zero_reserve_soa :: proc(array: ^$T/#soa[dynamic]$E, #any_int capacity: int, loc := #caller_location) -> Allocator_Error {…}
non_zero_resize_dynamic_array ¶
non_zero_resize_dynamic_array :: proc(array: ^$T/[dynamic]$E, #any_int length: int, loc := #caller_location) -> Allocator_Error {…}
non_zero_resize_soa ¶
non_zero_resize_soa :: proc(array: ^$T/#soa[dynamic]$E, #any_int length: int, loc := #caller_location) -> Allocator_Error {…}
ordered_remove ¶
ordered_remove :: proc(array: ^[dynamic]$T, #any_int index: int, loc := #caller_location) {…}
ordered_remove
removed the element at the specified index
whilst keeping the order of the other elements.
Note: This is an O(N) operation.
Note: If the elements do not have to remain in their order, prefer unordered_remove
.
Note: If the index is out of bounds, this procedure will panic.
ordered_remove_soa ¶
ordered_remove_soa :: proc(array: ^$T/#soa[dynamic]$E, #any_int index: int, loc := #caller_location) {…}
ordered_remove_soa
removed the element at the specified index
whilst keeping the order of the other elements.
Note: This is an O(N) operation.
Note: If you the elements do not have to remain in their order, prefer unordered_remove_soa
.
Note: If the index is out of bounds, this procedure will panic.
panic ¶
panic :: proc(message: string, loc := #caller_location) -> ! {…}
panic_allocator ¶
panic_allocator :: proc() -> Allocator {…}
panic_allocator_proc ¶
panic_allocator_proc :: proc( allocator_data: rawptr, mode: Allocator_Mode, size, alignment: int, old_memory: rawptr, old_size: int, loc := #caller_location, ) -> ([]u8, Allocator_Error) {…}
panic_contextless ¶
panic_contextless :: proc "contextless" (message: string, loc := #caller_location) -> ! {…}
pop ¶
pop :: proc(array: ^$T/[dynamic]$E, loc := #caller_location) -> (res: $E) {…}
pop
will remove and return the end value of dynamic array array
and reduces the length of array
by 1.
Note: If the dynamic array has no elements (len(array) == 0
), this procedure will panic.
pop_front ¶
pop_front :: proc(array: ^$T/[dynamic]$E, loc := #caller_location) -> (res: $E) {…}
pop_front
will remove and return the first value of dynamic array array
and reduces the length of array
by 1.
Note: If the dynamic array as no elements (len(array) == 0
), this procedure will panic.
pop_front_safe ¶
pop_front_safe :: proc "contextless" (array: ^$T/[dynamic]$E) -> (res: $E, ok: bool) {…}
pop_front_safe
trys to return and remove the first value of dynamic array array
and reduces the length of array
by 1.
If the operation is not possible, it will return false.
pop_safe ¶
pop_safe :: proc "contextless" (array: ^$T/[dynamic]$E) -> (res: $E, ok: bool) {…}
pop_safe
trys to remove and return the end value of dynamic array array
and reduces the length of array
by 1.
If the operation is not possible, it will return false.
print_any_single ¶
print_any_single :: proc "contextless" (arg: any) {…}
print_caller_location ¶
print_caller_location :: proc "contextless" (loc: Source_Code_Location) {…}
print_encoded_rune ¶
print_encoded_rune :: proc "contextless" (r: untyped rune) {…}
print_i64 ¶
print_i64 :: proc "contextless" (x: i64) {…}
print_int ¶
print_int :: proc "contextless" (x: int) {…}
print_rune ¶
print_rune :: proc "contextless" (r: untyped rune) -> int {…}
print_type ¶
print_type :: proc "contextless" (ti: ^Type_Info) {…}
print_typeid ¶
print_typeid :: proc "contextless" (id: typeid) {…}
print_u64 ¶
print_u64 :: proc "contextless" (x: u64) {…}
print_uint ¶
print_uint :: proc "contextless" (x: uint) {…}
print_uintptr ¶
print_uintptr :: proc "contextless" (x: uintptr) {…}
println_any ¶
println_any :: proc "contextless" (.. args: ..any) {…}
quaternion128_eq ¶
quaternion128_eq :: proc "contextless" (a, b: quaternion128) -> bool {…}
quaternion128_ne ¶
quaternion128_ne :: proc "contextless" (a, b: quaternion128) -> bool {…}
quaternion256_eq ¶
quaternion256_eq :: proc "contextless" (a, b: quaternion256) -> bool {…}
quaternion256_ne ¶
quaternion256_ne :: proc "contextless" (a, b: quaternion256) -> bool {…}
quaternion64_eq ¶
quaternion64_eq :: proc "contextless" (a, b: quaternion64) -> bool {…}
quaternion64_ne ¶
quaternion64_ne :: proc "contextless" (a, b: quaternion64) -> bool {…}
quo_complex128 ¶
quo_complex128 :: proc "contextless" (n, m: complex128) -> complex128 {…}
quo_quaternion128 ¶
quo_quaternion128 :: proc "contextless" (q, r: quaternion128) -> quaternion128 {…}
quo_quaternion256 ¶
quo_quaternion256 :: proc "contextless" (q, r: quaternion256) -> quaternion256 {…}
quo_quaternion64 ¶
quo_quaternion64 :: proc "contextless" (q, r: quaternion64) -> quaternion64 {…}
random_generator_query_info ¶
random_generator_query_info :: proc(rg: Random_Generator) -> (info: Random_Generator_Query_Info) {…}
random_generator_read_bytes ¶
random_generator_read_bytes :: proc(rg: Random_Generator, p: []u8) -> bool {…}
random_generator_read_ptr ¶
random_generator_read_ptr :: proc(rg: Random_Generator, p: rawptr, len: uint) -> bool {…}
random_generator_reset_bytes ¶
random_generator_reset_bytes :: proc(rg: Random_Generator, p: []u8) {…}
random_generator_reset_u64 ¶
random_generator_reset_u64 :: proc(rg: Random_Generator, p: u64) {…}
raw_soa_footer_dynamic_array ¶
raw_soa_footer_dynamic_array :: proc(array: ^$T/#soa[dynamic]$E) -> (footer: ^Raw_SOA_Footer_Dynamic_Array) {…}
raw_soa_footer_slice ¶
raw_soa_footer_slice :: proc(array: ^$T/#soa[]$E) -> (footer: ^Raw_SOA_Footer_Slice) {…}
read_cycle_counter ¶
read_cycle_counter :: intrinsics.read_cycle_counter
remove_range ¶
remove_range :: proc(array: ^[dynamic]$T, #any_int lo, #any_int hi: int, loc := #caller_location) {…}
remove_range
removes a range of elements specified by the range lo
and hi
, whilst keeping the order of the other elements.
Note: This is an O(N) operation. Note: If the range is out of bounds, this procedure will panic.
reserve_dynamic_array ¶
reserve_dynamic_array :: proc(array: ^$T/[dynamic]$E, #any_int capacity: int, loc := #caller_location) -> Allocator_Error {…}
reserve_map ¶
reserve_map :: proc(m: ^$T/map[$K]$V, #any_int capacity: int, loc := #caller_location) -> Allocator_Error {…}
reserve_map
will try to reserve memory of a passed map to the requested element count (setting the cap
).
Note: Prefer the procedure group reserve
reserve_soa ¶
reserve_soa :: proc(array: ^$T/#soa[dynamic]$E, #any_int capacity: int, loc := #caller_location) -> Allocator_Error {…}
resize_dynamic_array ¶
resize_dynamic_array :: proc(array: ^$T/[dynamic]$E, #any_int length: int, loc := #caller_location) -> Allocator_Error {…}
resize_dynamic_array
will try to resize memory of a passed dynamic array or map to the requested element count (setting the len
, and possibly cap
).
Note: Prefer the procedure group resize
resize_soa ¶
resize_soa :: proc(array: ^$T/#soa[dynamic]$E, #any_int length: int, loc := #caller_location) -> Allocator_Error {…}
run_thread_local_cleaners ¶
run_thread_local_cleaners :: proc() {…}
Run all of the thread-local cleaner procedures.
Intended to be called by the internals of a threading API at the end of a thread's lifetime.
shrink_dynamic_array ¶
shrink_dynamic_array :: proc(array: ^$T/[dynamic]$E, #any_int new_cap: int = -1, loc := #caller_location) -> (did_shrink: bool, err: Allocator_Error) {…}
Shrinks the capacity of a dynamic array down to the current length, or the given capacity.
If new_cap
is negative, then len(array)
is used.
Returns false if cap(array) < new_cap
, or the allocator report failure.
If len(array) < new_cap
, then len(array)
will be left unchanged.
Note: Prefer the procedure group shrink
shrink_map ¶
shrink_map :: proc(m: ^$T/map[$K]$V, loc := #caller_location) -> (did_shrink: bool, err: Allocator_Error) {…}
Shrinks the capacity of a map down to the current length.
Note: Prefer the procedure group shrink
slice_expr_error_hi_loc ¶
slice_expr_error_hi_loc :: proc "contextless" (loc := #caller_location, hi: int, len: int) {…}
slice_expr_error_lo_hi_loc ¶
slice_expr_error_lo_hi_loc :: proc "contextless" (loc := #caller_location, lo, hi: int, len: int) {…}
trap ¶
trap :: intrinsics.trap
type_assertion_trap ¶
type_assertion_trap :: proc "contextless" () {…}
type_info_base_without_enum ¶
type_info_base_without_enum :: type_info_core
typeid_base_without_enum ¶
typeid_base_without_enum :: typeid_core
unimplemented ¶
unimplemented :: proc(message: string = "", loc := #caller_location) -> ! {…}
unimplemented_contextless ¶
unimplemented_contextless :: proc "contextless" (message: string = "", loc := #caller_location) -> ! {…}
unordered_remove ¶
unordered_remove :: proc(array: ^[dynamic]$T, #any_int index: int, loc := #caller_location) {…}
unordered_remove
removed the element at the specified index
. It does so by replacing the current end value
with the old value, and reducing the length of the dynamic array by 1.
Note: This is an O(1) operation.
Note: If you want the elements to remain in their order, use ordered_remove
.
Note: If the index is out of bounds, this procedure will panic.
unordered_remove_soa ¶
unordered_remove_soa :: proc(array: ^$T/#soa[dynamic]$E, #any_int index: int, loc := #caller_location) {…}
unordered_remove_soa
removed the element at the specified index
. It does so by replacing the current end value
with the old value, and reducing the length of the dynamic array by 1.
Note: This is an O(1) operation.
Note: If you the elements to remain in their order, use ordered_remove_soa
.
Note: If the index is out of bounds, this procedure will panic.
Procedure Groups
align_forward ¶
align_forward :: proc{ align_forward_int, align_forward_uint, align_forward_uintptr, }
append ¶
append :: proc{ append_elem, append_elems, append_elem_string, append_soa_elem, append_soa_elems, }
The append built-in procedure appends elements to the end of a dynamic array
append_soa ¶
append_soa :: proc{ append_soa_elem, append_soa_elems, }
The append_soa built-in procedure appends elements to the end of an #soa dynamic array
assign_at ¶
assign_at :: proc{ assign_at_elem, assign_at_elems, assign_at_elem_string, }
clear ¶
clear :: proc{ clear_dynamic_array, clear_map, clear_soa_dynamic_array, }
clear
will set the length of a passed dynamic array or map to 0
clear_soa ¶
clear_soa :: proc{ clear_soa_dynamic_array, }
copy ¶
copy :: proc{ copy_slice, copy_from_string, copy_from_string16, }
copy
is a built-in procedure that copies elements from a source slice/string src
to a destination slice dst
.
The source and destination may overlap. Copy returns the number of elements copied, which will be the minimum
of len(src) and len(dst).
delete ¶
delete :: proc{ delete_string, delete_cstring, delete_dynamic_array, delete_slice, delete_map, delete_soa_slice, delete_soa_dynamic_array, delete_string16, delete_cstring16, }
delete
will try to free the underlying data of the passed built-in data structure (string, cstring, dynamic array, slice, or map), with the given allocator
if the allocator supports this operation.
Note: Prefer delete
over the specific delete_*
procedures where possible.
delete_soa ¶
delete_soa :: proc{ delete_soa_slice, delete_soa_dynamic_array, }
free ¶
free :: proc{ mem_free, }
free
will try to free the passed pointer, with the given allocator
if the allocator supports this operation.
free_all ¶
free_all :: proc{ mem_free_all, }
free_all
will try to free/reset all of the memory of the given allocator
if the allocator supports this operation.
inject_at ¶
inject_at :: proc{ inject_at_elem, inject_at_elems, inject_at_elem_string, }
is_power_of_two ¶
is_power_of_two :: proc{ is_power_of_two_int, is_power_of_two_uint, is_power_of_two_uintptr, }
make ¶
make :: proc{ make_slice, make_dynamic_array, make_dynamic_array_len, make_dynamic_array_len_cap, make_map, make_map_cap, make_multi_pointer, make_soa_slice, make_soa_dynamic_array, make_soa_dynamic_array_len, make_soa_dynamic_array_len_cap, }
make
built-in procedure allocates and initializes a value of type slice, dynamic array, map, or multi-pointer (only).
Similar to new
, the first argument is a type, not a value. Unlike new, make's return type is the same as the
type of its argument, not a pointer to it.
Make uses the specified allocator, default is context.allocator.
make_soa ¶
make_soa :: proc{ make_soa_slice, make_soa_dynamic_array, make_soa_dynamic_array_len, make_soa_dynamic_array_len_cap, }
non_zero_append ¶
non_zero_append :: proc{ non_zero_append_elem, non_zero_append_elems, non_zero_append_elem_string, non_zero_append_soa_elem, non_zero_append_soa_elems, }
non_zero_reserve ¶
non_zero_reserve :: proc{ non_zero_reserve_dynamic_array, non_zero_reserve_soa, }
non_zero_resize ¶
non_zero_resize :: proc{ non_zero_resize_dynamic_array, non_zero_resize_soa, }
raw_soa_footer ¶
raw_soa_footer :: proc{ raw_soa_footer_slice, raw_soa_footer_dynamic_array, }
reserve ¶
reserve :: proc{ reserve_dynamic_array, reserve_map, reserve_soa, }
reserve
will try to reserve memory of a passed dynamic array or map to the requested element count (setting the cap
).
resize ¶
resize :: proc{ resize_dynamic_array, resize_soa, }
resize
will try to resize memory of a passed dynamic array to the requested element count (setting the len
, and possibly cap
).
shrink ¶
shrink :: proc{ shrink_dynamic_array, shrink_map, }
Shrinks the capacity of a dynamic array or map down to the current length, or the given capacity.
Source Files
- core.odin
- core_builtin.odin
- core_builtin_soa.odin
- default_allocators_general.odin
- default_allocators_nil.odin
- default_temp_allocator_arena.odin
- default_temporary_allocator.odin
- doc.odin
- dynamic_array_internal.odin
- dynamic_map_internal.odin
- error_checks.odin
- heap_allocator.odin
- internal.odin
- os_specific.odin
- print.odin
- procs.odin
- random_generator.odin
- thread_management.odin
- udivmod128.odin
- (hidden platform specific files)
Generation Information
Generated with odin version dev-2025-08 (vendor "odin") Windows_amd64 @ 2025-08-27 21:12:25.332117000 +0000 UTC