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 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 (325)
- 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
- conditional_mem_zero
- container_of
- copy_from_string
- copy_from_string16
- copy_slice
- copy_slice_raw
- 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, }
Default_Temp_Allocator is an Arena based type of allocator. See runtime.Arena for its implementation.
The default context.temp_allocator is typically called with free_all(context.temp_allocator) once per "frame-loop"
to prevent it from "leaking" memory.
Note: Default_Temp_Allocator is a nil_allocator when NO_DEFAULT_TEMP_ALLOCATOR is true.
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_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
Related Procedures With Parameters
- align_forward_uintptr
- default_hasher
- default_hasher_complex128
- default_hasher_cstring
- default_hasher_f64
- default_hasher_quaternion256
- default_hasher_string
- is_power_of_two_uintptr
- map_alloc_dynamic
- map_cell_index_dynamic
- map_cell_index_dynamic_const
- map_cell_index_static
- map_desired_position
- map_erase_dynamic
- map_exists_dynamic
- map_hash_is_deleted
- map_hash_is_empty
- map_hash_is_valid
- map_insert_hash_dynamic
- map_insert_hash_dynamic_with_key
- map_load_factor
- map_lookup_dynamic
- map_probe_distance
- map_reserve_dynamic
- map_seed_from_map_data
- map_total_allocation_size
- print_uintptr
- align_forward (procedure groups)
- is_power_of_two (procedure groups)
Related Procedures With Returns
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
Example:
// 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
Example:
// 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
Example:
// Defined internally by the compiler
Odin_Endian_Type :: enum int {
Unknown, Little, Big,
}
Odin_OS_Type ¶
Odin_OS_Type :: .Odin_OS_Type
Example:
// 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
Example:
// 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
Example:
// 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
Example:
// 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
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.
align_forward_int ¶
Related Procedure Groups
align_forward_uint ¶
Related Procedure Groups
align_forward_uintptr ¶
Related Procedure Groups
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 appends an element to the end of a dynamic array.
Related Procedure Groups
append_elem_string ¶
append_elem_string :: proc(array: ^[dynamic]u8, arg: string, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_ok {…}
append_elem_string appends a string to the end of a dynamic array of bytes
Note: Prefer using the procedure group append.
Related Procedure Groups
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_elems appends args to the end of a dynamic array.
Note: Prefer using the procedure group append.
Related Procedure Groups
append_nothing ¶
append_nothing :: proc(array: ^$T/[dynamic]$E, loc := #caller_location) -> (n: int, err: Allocator_Error) #optional_ok {…}
append_nothing appends an empty value to a dynamic array. It returns 1, nil if successful, and 0, err when it was not possible,
whatever err happens to be.
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 {…}
Related Procedure Groups
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 {…}
Related Procedure Groups
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
Note: Prefer using the procedure group append.
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) {…}
Evaluates the condition and panics the program iff the condition is false.
This uses the context.assertion_failure_procedure to assert.
This routine will be ignored when ODIN_DISABLE_ASSERT is true.
assert_contextless ¶
assert_contextless :: proc "contextless" (condition: bool, message: string = #caller_expression(condition), loc := #caller_location) {…}
Evaluates the condition and panics the program iff the condition is false.
This uses the default_assertion_contextless_failure_proc to assert.
This routine will be ignored when ODIN_DISABLE_ASSERT is true.
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 assigns a value at a given index. If the requested index is smaller than the current
size of the dynamic array, it will attempt to resize the a new length of index+1 and then assign as index.
Related Procedure Groups
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_elem_string assigns a string at a given index. If the requested index is smaller than the current
size of the dynamic array, it will attempt to resize the a new length of index+len(arg) and then assign as index.
Related Procedure Groups
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 {…}
assign_at_elems assigns a values at a given index. If the requested index is smaller than the current
size of the dynamic array, it will attempt to resize the a new length of index+len(args) and then assign as index.
Related Procedure Groups
bounds_check_error_loc ¶
bounds_check_error_loc :: proc "contextless" (loc := #caller_location, index, count: int) {…}
bounds_trap ¶
bounds_trap :: proc "contextless" () {…}
card ¶
card :: proc "contextless" (s: $T/bit_set[$E]) -> int {…}
card returns the number of bits that are set in a bit_set—its cardinality
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.
Related Procedure Groups
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
Related Procedure Groups
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.
Related Procedure Groups
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.
Related Procedure Groups
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.
Related Procedure Groups
debug_trap ¶
debug_trap :: intrinsics.debug_trap
debug_trap :: proc() {…}
A call intended to cause an execution trap with the intention of requesting a debugger's attention.
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 {…}
Returns the default context
default_logger ¶
default_logger :: proc() -> Logger {…}
Returns the default logger used by context.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.
Related Procedure Groups
delete_cstring16 ¶
delete_cstring16 :: proc(str: cstring16, allocator := context.allocator, loc := #caller_location) -> Allocator_Error {…}
Related Procedure Groups
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.
Related Procedure Groups
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.
Related Procedure Groups
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.
Related Procedure Groups
delete_soa_dynamic_array ¶
delete_soa_dynamic_array :: proc(array: $T/#soa[dynamic]$E, loc := #caller_location) -> Allocator_Error {…}
Related Procedure Groups
delete_soa_slice ¶
delete_soa_slice :: proc(array: $T/#soa[]$E, allocator := context.allocator, loc := #caller_location) -> Allocator_Error {…}
Related Procedure Groups
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.
Related Procedure Groups
delete_string16 ¶
delete_string16 :: proc(str: string16, allocator := context.allocator, loc := #caller_location) -> Allocator_Error {…}
Related Procedure Groups
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 panics the program iff the condition is false.
This uses the context.assertion_failure_procedure to assert.
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) {…}
Evaluates the condition and panics the program iff the condition is false.
This uses the default_assertion_contextless_failure_proc to assert.
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) {…}
Initializes the global temporary allocator used as the default context.temp_allocator.
This is ignored when NO_DEFAULT_TEMP_ALLOCATOR is true.
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 injects an element in a dynamic array at a specified index and moves the previous elements after that index "across"
Related Procedure Groups
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_elem_string injects a string into a dynamic array at a specified index and moves the previous elements after that index "across"
Related Procedure Groups
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 {…}
inject_at_elems injects multiple elements in a dynamic array at a specified index and moves the previous elements after that index "across"
Related Procedure Groups
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
is_power_of_two_int ¶
Related Procedure Groups
is_power_of_two_uint ¶
Related Procedure Groups
is_power_of_two_uintptr ¶
Related Procedure Groups
make_aligned ¶
make_aligned :: proc($T: typeid/[]$E, #any_int len: int, alignment: int, allocator := context.allocator, loc := #caller_location) -> (res: T, err: Allocator_Error) #optional_ok {…}
make_dynamic_array ¶
make_dynamic_array :: proc($T: typeid/[dynamic]$E, allocator := context.allocator, loc := #caller_location) -> (array: T, err: Allocator_Error) #optional_ok {…}
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.
Related Procedure Groups
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) -> (array: T, err: Allocator_Error) #optional_ok {…}
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.
Related Procedure Groups
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.
Related Procedure Groups
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.
Related Procedure Groups
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.
Related Procedure Groups
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.
Related Procedure Groups
make_slice ¶
make_slice :: proc($T: typeid/[]$E, #any_int len: int, allocator := context.allocator, loc := #caller_location) -> (res: T, err: Allocator_Error) #optional_ok {…}
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.
Related Procedure Groups
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($T: typeid) -> ^runtime.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
map_info :: proc($T: typeid/map[$K]$V) -> ^runtime.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 {…}
Related Procedure Groups
mem_free_all ¶
mem_free_all :: proc(allocator := context.allocator, loc := #caller_location) -> (err: Allocator_Error) {…}
Related Procedure Groups
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) -> (t: ^typeid, err: Allocator_Error) #optional_ok {…}
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 returns an allocator which will return nil for any result.
* .Alloc, .Alloc_Non_Zero, .Resize, .Resize_Non_Zeroed will return nil, .Out_Of_Memory
* .Free will return nil, .None
* .Free_All will return nil, .Mode_Not_Implemented
* .Query_Features, .Query_Info will return nil, .Mode_Not_Implemented
This is extremely useful for creating a dynamic array from a buffer which does not nothing on a resize/reserve beyond the originally allocated memory.
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 appends an element to the end of a dynamic array, without zeroing any reserved memory
Note: Prefer using the procedure group `non_zero_append
Related Procedure Groups
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_elem_string appends a string to the end of a dynamic array of bytes, without zeroing any reserved memory
Note: Prefer using the procedure group non_zero_append.
Related Procedure Groups
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_elems appends args to the end of a dynamic array, without zeroing any reserved memory
Note: Prefer using the procedure group `non_zero_append
Related Procedure Groups
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 {…}
Related Procedure Groups
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 {…}
Related Procedure Groups
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_dynamic_array will try to reserve memory of a passed dynamic array or map to the requested element count (setting the cap).
When a memory resize allocation is required, the memory will be asked to not be zeroed (i.e. it calls non_zero_mem_resize).
Note: Prefer the procedure group non_zero_reserve.
Related Procedure Groups
non_zero_reserve_soa ¶
non_zero_reserve_soa :: proc(array: ^$T/#soa[dynamic]$E, #any_int capacity: int, loc := #caller_location) -> Allocator_Error {…}
Related Procedure Groups
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_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).
When a memory resize allocation is required, the memory will be asked to not be zeroed (i.e. it calls non_zero_mem_resize).
Note: Prefer the procedure group non_zero_resize
Related Procedure Groups
non_zero_resize_soa ¶
non_zero_resize_soa :: proc(array: ^$T/#soa[dynamic]$E, #any_int length: int, loc := #caller_location) -> Allocator_Error {…}
Related Procedure Groups
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) -> ! {…}
Panics the program with a message.
This uses the context.assertion_failure_procedure to panic.
panic_allocator ¶
panic_allocator :: proc() -> Allocator {…}
panic_allocator returns an allocator which will panic for any non-zero-sized allocation or query_info
This is extremely useful for to check when something does a memory operation when it should not, and thus panic.
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) -> ! {…}
Panics the program with a message to indicate something has yet to be implemented.
This uses the default_assertion_contextless_failure_proc to assert.
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) {…}
Related Procedure Groups
raw_soa_footer_slice ¶
raw_soa_footer_slice :: proc(array: ^$T/#soa[]$E) -> (footer: ^Raw_SOA_Footer_Slice) {…}
Related Procedure Groups
read_cycle_counter ¶
read_cycle_counter :: intrinsics.read_cycle_counter
read_cycle_counter :: proc() -> i64 {…}
This provides access to the cycle counter register (or similar low latency, high accuracy clocks) on the targets that support it. On i386/amd64, it should map to the rdtsc instruction. On arm64, it should map to the cntvct_el0 instruction.
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_dynamic_array will try to reserve memory of a passed dynamic array or map to the requested element count (setting the cap).
When a memory resize allocation is required, the memory will be asked to be zeroed (i.e. it calls mem_resize).
Note: Prefer the procedure group reserve.
Related Procedure Groups
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
Related Procedure Groups
reserve_soa ¶
reserve_soa :: proc(array: ^$T/#soa[dynamic]$E, #any_int capacity: int, loc := #caller_location) -> Allocator_Error {…}
Related Procedure Groups
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).
When a memory resize allocation is required, the memory will be asked to be zeroed (i.e. it calls mem_resize).
Note: Prefer the procedure group resize
Related Procedure Groups
resize_soa ¶
resize_soa :: proc(array: ^$T/#soa[dynamic]$E, #any_int length: int, loc := #caller_location) -> Allocator_Error {…}
Related Procedure Groups
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
Related Procedure Groups
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
Related Procedure Groups
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
trap :: proc() -> ! {…}
Lowered to a target dependent trap instruction.
type_assertion_trap ¶
type_assertion_trap :: proc "contextless" () {…}
type_info_base ¶
type_info_base returns the base-type of a ^Type_Info stripping the distinctness from the first level
type_info_base_without_enum ¶
type_info_base_without_enum :: type_info_core
type_info_core returns the core-type of a ^Type_Info stripping the distinctness from the first level AND/OR
returns the backing integer type of an enum or bit_set ^Type_Info.
This is also aliased as type_info_base_without_enum
type_info_core ¶
type_info_core returns the core-type of a ^Type_Info stripping the distinctness from the first level AND/OR
returns the backing integer type of an enum or bit_set ^Type_Info.
This is also aliased as type_info_base_without_enum
typeid_base ¶
typeid_base returns the base-type of a typeid stripping the distinctness from the first level
typeid_base_without_enum ¶
typeid_base_without_enum :: typeid_core
typeid_core returns the core-type of a typeid stripping the distinctness from the first level AND/OR
returns the backing integer type of an enum or bit_set typeid.
This is also aliased as typeid_base_without_enum
typeid_core ¶
typeid_core returns the core-type of a typeid stripping the distinctness from the first level AND/OR
returns the backing integer type of an enum or bit_set typeid.
This is also aliased as typeid_base_without_enum
unimplemented ¶
unimplemented :: proc(message: string = "", loc := #caller_location) -> ! {…}
Panics the program with a message to indicate something has yet to be implemented.
This uses the context.assertion_failure_procedure to assert.
unimplemented_contextless ¶
unimplemented_contextless :: proc "contextless" (message: string = "", loc := #caller_location) -> ! {…}
Panics the program with a message.
This uses the default_assertion_contextless_failure_proc to assert.
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, }
assign_at assigns a value at a given index. If the requested index is smaller than the current
size of the dynamic array, it will attempt to resize the a new length of index+size_needed and then assign as index.
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, }
inject_at injects something into a dynamic array at a specified index and moves the previous elements after that index "across"
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-10 (vendor "odin") Windows_amd64 @ 2025-10-27 21:13:13.980758300 +0000 UTC