Browse Source

Update builtin procedures to support the new allocator features (without breaking other code)

gingerBill 4 years ago
parent
commit
c3b3194a00

+ 4 - 3
core/mem/alloc.odin

@@ -31,9 +31,10 @@ Allocator_Query_Info :: struct {
 Allocator_Error :: runtime.Allocator_Error;
 Allocator_Error :: runtime.Allocator_Error;
 /*
 /*
 Allocator_Error :: enum byte {
 Allocator_Error :: enum byte {
-	None            = 0,
-	Out_Of_Memory   = 1,
-	Invalid_Pointer = 2,
+	None             = 0,
+	Out_Of_Memory    = 1,
+	Invalid_Pointer  = 2,
+	Invalid_Argument = 3,
 }
 }
 */
 */
 Allocator_Proc :: runtime.Allocator_Proc;
 Allocator_Proc :: runtime.Allocator_Proc;

+ 2 - 2
core/mem/allocators.odin

@@ -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);

+ 1 - 0
core/odin/ast/ast.odin

@@ -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];
 
 

+ 4 - 6
core/odin/parser/parser.odin

@@ -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":
-			tags |= {.Bounds_Check};
-		case "no_bounds_check":
-			tags |= {.No_Bounds_Check};
-		case "optional_ok":
-			tags |= {.Optional_Ok};
+		case "bounds_check":    tags |= {.Bounds_Check};
+		case "no_bounds_check": tags |= {.No_Bounds_Check};
+		case "optional_ok":     tags |= {.Optional_Ok};
+		case "optional_second": tags |= {.Optional_Second};
 		case:
 		case:
 		}
 		}
 	}
 	}

+ 4 - 3
core/runtime/core.odin

@@ -271,9 +271,10 @@ Allocator_Query_Info :: struct {
 }
 }
 
 
 Allocator_Error :: enum byte {
 Allocator_Error :: enum byte {
-	None            = 0,
-	Out_Of_Memory   = 1,
-	Invalid_Pointer = 2,
+	None             = 0,
+	Out_Of_Memory    = 1,
+	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,

+ 35 - 33
core/runtime/core_builtin.odin

@@ -127,26 +127,30 @@ free_all :: proc{mem_free_all};
 
 
 
 
 @builtin
 @builtin
-delete_string :: proc(str: string, allocator := context.allocator, loc := #caller_location) {
-	mem_free(raw_data(str), allocator, loc);
+delete_string :: proc(str: string, allocator := context.allocator, loc := #caller_location) -> Allocator_Error {
+	return mem_free(raw_data(str), allocator, loc);
 }
 }
 @builtin
 @builtin
-delete_cstring :: proc(str: cstring, allocator := context.allocator, loc := #caller_location) {
-	mem_free((^byte)(str), allocator, loc);
+delete_cstring :: proc(str: cstring, allocator := context.allocator, loc := #caller_location) -> Allocator_Error {
+	return mem_free((^byte)(str), allocator, loc);
 }
 }
 @builtin
 @builtin
-delete_dynamic_array :: proc(array: $T/[dynamic]$E, loc := #caller_location) {
-	mem_free(raw_data(array), array.allocator, loc);
+delete_dynamic_array :: proc(array: $T/[dynamic]$E, loc := #caller_location) -> Allocator_Error {
+	return mem_free(raw_data(array), array.allocator, loc);
 }
 }
 @builtin
 @builtin
-delete_slice :: proc(array: $T/[]$E, allocator := context.allocator, loc := #caller_location) {
-	mem_free(raw_data(array), allocator, loc);
+delete_slice :: proc(array: $T/[]$E, allocator := context.allocator, loc := #caller_location) -> Allocator_Error {
+	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);
-	mem_free(raw.entries.data, raw.entries.allocator, loc);
+	err := delete_slice(raw.hashes, 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 {
-	ptr := (^T)(mem_alloc(size_of(T), align_of(T), allocator, loc));
-	if ptr != nil { ptr^ = T{}; }
-	return ptr;
+new :: proc($T: typeid, allocator := context.allocator, loc := #caller_location) -> (^T, Allocator_Error) #optional_second {
+	ptr, err := mem_alloc(size_of(T), align_of(T), allocator, loc);
+	return (^T)(ptr), err;
 }
 }
 
 
 @builtin
 @builtin
-new_clone :: proc(data: $T, allocator := context.allocator, loc := #caller_location) -> ^T {
-	ptr := (^T)(mem_alloc(size_of(T), align_of(T), allocator, loc));
-	if ptr != nil { ptr^ = data; }
-	return ptr;
+new_clone :: proc(data: $T, allocator := context.allocator, loc := #caller_location) -> (^T, Allocator_Error) #optional_second {
+	ptr, err := mem_alloc(size_of(T), align_of(T), allocator, loc);
+	res := (^T)(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 {
-	case err != nil:
-		return nil;
-	case data == nil && size_of(E) != 0:
-		return nil;
+	if data == nil && size_of(E) != 0 {
+		return nil, err;
 	}
 	}
 	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;
+	return transmute(T)s, err;
 }
 }
 
 
 @builtin
 @builtin

+ 7 - 5
core/runtime/core_builtin_soa.odin

@@ -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);
 }
 }
 
 

+ 4 - 5
core/runtime/internal.odin

@@ -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);
+	return raw_data(data), err;
 }
 }
 
 
 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 {