mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-07 16:18:52 +00:00
Update builtin procedures to support the new allocator features (without breaking other code)
This commit is contained in:
@@ -34,6 +34,7 @@ Allocator_Error :: enum byte {
|
|||||||
None = 0,
|
None = 0,
|
||||||
Out_Of_Memory = 1,
|
Out_Of_Memory = 1,
|
||||||
Invalid_Pointer = 2,
|
Invalid_Pointer = 2,
|
||||||
|
Invalid_Argument = 3,
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
Allocator_Proc :: runtime.Allocator_Proc;
|
Allocator_Proc :: runtime.Allocator_Proc;
|
||||||
|
|||||||
@@ -313,7 +313,7 @@ stack_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
|
|||||||
s := cast(^Stack)allocator_data;
|
s := cast(^Stack)allocator_data;
|
||||||
|
|
||||||
if s.data == nil {
|
if s.data == nil {
|
||||||
return nil, .Out_Of_Memory;
|
return nil, .Invalid_Argument;
|
||||||
}
|
}
|
||||||
|
|
||||||
raw_alloc :: proc(s: ^Stack, size, alignment: int) -> ([]byte, Allocator_Error) {
|
raw_alloc :: proc(s: ^Stack, size, alignment: int) -> ([]byte, Allocator_Error) {
|
||||||
@@ -468,7 +468,7 @@ small_stack_allocator_proc :: proc(allocator_data: rawptr, mode: Allocator_Mode,
|
|||||||
s := cast(^Small_Stack)allocator_data;
|
s := cast(^Small_Stack)allocator_data;
|
||||||
|
|
||||||
if s.data == nil {
|
if s.data == nil {
|
||||||
return nil, .Out_Of_Memory;
|
return nil, .Invalid_Argument;
|
||||||
}
|
}
|
||||||
|
|
||||||
align := clamp(alignment, 1, 8*size_of(Stack_Allocation_Header{}.padding)/2);
|
align := clamp(alignment, 1, 8*size_of(Stack_Allocation_Header{}.padding)/2);
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ Proc_Tag :: enum {
|
|||||||
Bounds_Check,
|
Bounds_Check,
|
||||||
No_Bounds_Check,
|
No_Bounds_Check,
|
||||||
Optional_Ok,
|
Optional_Ok,
|
||||||
|
Optional_Second,
|
||||||
}
|
}
|
||||||
Proc_Tags :: distinct bit_set[Proc_Tag; u32];
|
Proc_Tags :: distinct bit_set[Proc_Tag; u32];
|
||||||
|
|
||||||
|
|||||||
@@ -1910,12 +1910,10 @@ parse_proc_tags :: proc(p: ^Parser) -> (tags: ast.Proc_Tags) {
|
|||||||
ident := expect_token(p, .Ident);
|
ident := expect_token(p, .Ident);
|
||||||
|
|
||||||
switch ident.text {
|
switch ident.text {
|
||||||
case "bounds_check":
|
case "bounds_check": tags |= {.Bounds_Check};
|
||||||
tags |= {.Bounds_Check};
|
case "no_bounds_check": tags |= {.No_Bounds_Check};
|
||||||
case "no_bounds_check":
|
case "optional_ok": tags |= {.Optional_Ok};
|
||||||
tags |= {.No_Bounds_Check};
|
case "optional_second": tags |= {.Optional_Second};
|
||||||
case "optional_ok":
|
|
||||||
tags |= {.Optional_Ok};
|
|
||||||
case:
|
case:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -274,6 +274,7 @@ Allocator_Error :: enum byte {
|
|||||||
None = 0,
|
None = 0,
|
||||||
Out_Of_Memory = 1,
|
Out_Of_Memory = 1,
|
||||||
Invalid_Pointer = 2,
|
Invalid_Pointer = 2,
|
||||||
|
Invalid_Argument = 3,
|
||||||
}
|
}
|
||||||
|
|
||||||
Allocator_Proc :: #type proc(allocator_data: rawptr, mode: Allocator_Mode,
|
Allocator_Proc :: #type proc(allocator_data: rawptr, mode: Allocator_Mode,
|
||||||
|
|||||||
@@ -127,26 +127,30 @@ free_all :: proc{mem_free_all};
|
|||||||
|
|
||||||
|
|
||||||
@builtin
|
@builtin
|
||||||
delete_string :: proc(str: string, allocator := context.allocator, loc := #caller_location) {
|
delete_string :: proc(str: string, allocator := context.allocator, loc := #caller_location) -> Allocator_Error {
|
||||||
mem_free(raw_data(str), allocator, loc);
|
return mem_free(raw_data(str), allocator, loc);
|
||||||
}
|
}
|
||||||
@builtin
|
@builtin
|
||||||
delete_cstring :: proc(str: cstring, allocator := context.allocator, loc := #caller_location) {
|
delete_cstring :: proc(str: cstring, allocator := context.allocator, loc := #caller_location) -> Allocator_Error {
|
||||||
mem_free((^byte)(str), allocator, loc);
|
return mem_free((^byte)(str), allocator, loc);
|
||||||
}
|
}
|
||||||
@builtin
|
@builtin
|
||||||
delete_dynamic_array :: proc(array: $T/[dynamic]$E, loc := #caller_location) {
|
delete_dynamic_array :: proc(array: $T/[dynamic]$E, loc := #caller_location) -> Allocator_Error {
|
||||||
mem_free(raw_data(array), array.allocator, loc);
|
return mem_free(raw_data(array), array.allocator, loc);
|
||||||
}
|
}
|
||||||
@builtin
|
@builtin
|
||||||
delete_slice :: proc(array: $T/[]$E, allocator := context.allocator, loc := #caller_location) {
|
delete_slice :: proc(array: $T/[]$E, allocator := context.allocator, loc := #caller_location) -> Allocator_Error {
|
||||||
mem_free(raw_data(array), allocator, loc);
|
return mem_free(raw_data(array), allocator, loc);
|
||||||
}
|
}
|
||||||
@builtin
|
@builtin
|
||||||
delete_map :: proc(m: $T/map[$K]$V, loc := #caller_location) {
|
delete_map :: proc(m: $T/map[$K]$V, loc := #caller_location) -> Allocator_Error {
|
||||||
raw := transmute(Raw_Map)m;
|
raw := transmute(Raw_Map)m;
|
||||||
delete_slice(raw.hashes, raw.entries.allocator, loc);
|
err := delete_slice(raw.hashes, raw.entries.allocator, loc);
|
||||||
mem_free(raw.entries.data, raw.entries.allocator, loc);
|
err1 := mem_free(raw.entries.data, raw.entries.allocator, loc);
|
||||||
|
if err == nil {
|
||||||
|
err = err1;
|
||||||
|
}
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -163,59 +167,57 @@ delete :: proc{
|
|||||||
// The new built-in procedure allocates memory. The first argument is a type, not a value, and the value
|
// 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
|
// return is a pointer to a newly allocated value of that type using the specified allocator, default is context.allocator
|
||||||
@builtin
|
@builtin
|
||||||
new :: proc($T: typeid, allocator := context.allocator, loc := #caller_location) -> ^T {
|
new :: proc($T: typeid, allocator := context.allocator, loc := #caller_location) -> (^T, Allocator_Error) #optional_second {
|
||||||
ptr := (^T)(mem_alloc(size_of(T), align_of(T), allocator, loc));
|
ptr, err := mem_alloc(size_of(T), align_of(T), allocator, loc);
|
||||||
if ptr != nil { ptr^ = T{}; }
|
return (^T)(ptr), err;
|
||||||
return ptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@builtin
|
@builtin
|
||||||
new_clone :: proc(data: $T, allocator := context.allocator, loc := #caller_location) -> ^T {
|
new_clone :: proc(data: $T, allocator := context.allocator, loc := #caller_location) -> (^T, Allocator_Error) #optional_second {
|
||||||
ptr := (^T)(mem_alloc(size_of(T), align_of(T), allocator, loc));
|
ptr, err := mem_alloc(size_of(T), align_of(T), allocator, loc);
|
||||||
if ptr != nil { ptr^ = data; }
|
res := (^T)(ptr);
|
||||||
return ptr;
|
if ptr != nil && err != .Out_Of_Memory {
|
||||||
|
res^ = data;
|
||||||
|
}
|
||||||
|
return res, err;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFAULT_RESERVE_CAPACITY :: 16;
|
DEFAULT_RESERVE_CAPACITY :: 16;
|
||||||
|
|
||||||
make_aligned :: proc($T: typeid/[]$E, auto_cast len: int, alignment: int, allocator := context.allocator, loc := #caller_location) -> T {
|
make_aligned :: proc($T: typeid/[]$E, auto_cast len: int, alignment: int, allocator := context.allocator, loc := #caller_location) -> (T, Allocator_Error) #optional_second {
|
||||||
make_slice_error_loc(loc, len);
|
make_slice_error_loc(loc, len);
|
||||||
data, err := mem_alloc_bytes(size_of(E)*len, alignment, allocator, loc);
|
data, err := mem_alloc_bytes(size_of(E)*len, alignment, allocator, loc);
|
||||||
switch {
|
if data == nil && size_of(E) != 0 {
|
||||||
case err != nil:
|
return nil, err;
|
||||||
return nil;
|
|
||||||
case data == nil && size_of(E) != 0:
|
|
||||||
return nil;
|
|
||||||
}
|
}
|
||||||
s := Raw_Slice{raw_data(data), len};
|
s := Raw_Slice{raw_data(data), len};
|
||||||
return transmute(T)s;
|
return transmute(T)s, err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@builtin
|
@builtin
|
||||||
make_slice :: proc($T: typeid/[]$E, auto_cast len: int, allocator := context.allocator, loc := #caller_location) -> T {
|
make_slice :: proc($T: typeid/[]$E, auto_cast len: int, allocator := context.allocator, loc := #caller_location) -> (T, Allocator_Error) #optional_second {
|
||||||
return make_aligned(T, len, align_of(E), allocator, loc);
|
return make_aligned(T, len, align_of(E), allocator, loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
@builtin
|
@builtin
|
||||||
make_dynamic_array :: proc($T: typeid/[dynamic]$E, allocator := context.allocator, loc := #caller_location) -> T {
|
make_dynamic_array :: proc($T: typeid/[dynamic]$E, allocator := context.allocator, loc := #caller_location) -> (T, Allocator_Error) #optional_second {
|
||||||
return make_dynamic_array_len_cap(T, 0, DEFAULT_RESERVE_CAPACITY, allocator, loc);
|
return make_dynamic_array_len_cap(T, 0, DEFAULT_RESERVE_CAPACITY, allocator, loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
@builtin
|
@builtin
|
||||||
make_dynamic_array_len :: proc($T: typeid/[dynamic]$E, auto_cast len: int, allocator := context.allocator, loc := #caller_location) -> T {
|
make_dynamic_array_len :: proc($T: typeid/[dynamic]$E, auto_cast len: int, allocator := context.allocator, loc := #caller_location) -> (T, Allocator_Error) #optional_second {
|
||||||
return make_dynamic_array_len_cap(T, len, len, allocator, loc);
|
return make_dynamic_array_len_cap(T, len, len, allocator, loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
@builtin
|
@builtin
|
||||||
make_dynamic_array_len_cap :: proc($T: typeid/[dynamic]$E, auto_cast len: int, auto_cast cap: int, allocator := context.allocator, loc := #caller_location) -> T {
|
make_dynamic_array_len_cap :: proc($T: typeid/[dynamic]$E, auto_cast len: int, auto_cast cap: int, allocator := context.allocator, loc := #caller_location) -> (T, Allocator_Error) #optional_second {
|
||||||
make_dynamic_array_error_loc(loc, len, cap);
|
make_dynamic_array_error_loc(loc, len, cap);
|
||||||
data := mem_alloc(size_of(E)*cap, align_of(E), allocator, loc);
|
data, err := mem_alloc(size_of(E)*cap, align_of(E), allocator, loc);
|
||||||
s := Raw_Dynamic_Array{data, len, cap, allocator};
|
s := Raw_Dynamic_Array{data, len, cap, allocator};
|
||||||
if data == nil && size_of(E) != 0 {
|
if data == nil && size_of(E) != 0 {
|
||||||
s.len, s.cap = 0, 0;
|
s.len, s.cap = 0, 0;
|
||||||
}
|
}
|
||||||
// mem_zero(data, size_of(E)*cap);
|
return transmute(T)s, err;
|
||||||
return transmute(T)s;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@builtin
|
@builtin
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ raw_soa_footer :: proc{
|
|||||||
|
|
||||||
|
|
||||||
@builtin
|
@builtin
|
||||||
make_soa_aligned :: proc($T: typeid/#soa[]$E, length: int, alignment: int, allocator := context.allocator, loc := #caller_location) -> (array: T) {
|
make_soa_aligned :: proc($T: typeid/#soa[]$E, length: int, alignment: int, allocator := context.allocator, loc := #caller_location) -> (array: T, err: Allocator_Error) #optional_second {
|
||||||
if length <= 0 {
|
if length <= 0 {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -106,13 +106,15 @@ make_soa_aligned :: proc($T: typeid/#soa[]$E, length: int, alignment: int, alloc
|
|||||||
}
|
}
|
||||||
assert(allocator.procedure != nil);
|
assert(allocator.procedure != nil);
|
||||||
|
|
||||||
new_data := allocator.procedure(
|
new_bytes: []byte;
|
||||||
|
new_bytes, err = allocator.procedure(
|
||||||
allocator.data, .Alloc, total_size, max_align,
|
allocator.data, .Alloc, total_size, max_align,
|
||||||
nil, 0, 0, loc,
|
nil, 0, loc,
|
||||||
);
|
);
|
||||||
if new_data == nil {
|
if new_bytes == nil || err != nil {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
new_data := raw_data(new_bytes);
|
||||||
|
|
||||||
data := uintptr(&array);
|
data := uintptr(&array);
|
||||||
offset := 0;
|
offset := 0;
|
||||||
@@ -131,7 +133,7 @@ make_soa_aligned :: proc($T: typeid/#soa[]$E, length: int, alignment: int, alloc
|
|||||||
}
|
}
|
||||||
|
|
||||||
@builtin
|
@builtin
|
||||||
make_soa_slice :: proc($T: typeid/#soa[]$E, length: int, allocator := context.allocator, loc := #caller_location) -> (array: T) {
|
make_soa_slice :: proc($T: typeid/#soa[]$E, length: int, allocator := context.allocator, loc := #caller_location) -> (array: T, err: Allocator_Error) #optional_second {
|
||||||
return make_soa_aligned(T, length, align_of(E), allocator, loc);
|
return make_soa_aligned(T, length, align_of(E), allocator, loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -169,16 +169,15 @@ mem_alloc_bytes :: #force_inline proc(size: int, alignment: int = DEFAULT_ALIGNM
|
|||||||
return allocator.procedure(allocator.data, .Alloc, size, alignment, nil, 0, loc);
|
return allocator.procedure(allocator.data, .Alloc, size, alignment, nil, 0, loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
mem_alloc :: #force_inline proc(size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> rawptr {
|
mem_alloc :: #force_inline proc(size: int, alignment: int = DEFAULT_ALIGNMENT, allocator := context.allocator, loc := #caller_location) -> (rawptr, Allocator_Error) {
|
||||||
if size == 0 {
|
if size == 0 {
|
||||||
return nil;
|
return nil, nil;
|
||||||
}
|
}
|
||||||
if allocator.procedure == nil {
|
if allocator.procedure == nil {
|
||||||
return nil;
|
return nil, nil;
|
||||||
}
|
}
|
||||||
data, err := allocator.procedure(allocator.data, .Alloc, size, alignment, nil, 0, loc);
|
data, err := allocator.procedure(allocator.data, .Alloc, size, alignment, nil, 0, loc);
|
||||||
_ = err;
|
return raw_data(data), err;
|
||||||
return raw_data(data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mem_free :: #force_inline proc(ptr: rawptr, allocator := context.allocator, loc := #caller_location) -> Allocator_Error {
|
mem_free :: #force_inline proc(ptr: rawptr, allocator := context.allocator, loc := #caller_location) -> Allocator_Error {
|
||||||
|
|||||||
Reference in New Issue
Block a user