From 5e184f04e79266adf57d94f4ba3427fdb02ac83b Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Wed, 12 Oct 2022 18:29:42 +0200 Subject: [PATCH] List now has correct alignment and takes memory allocator initializer. Bugfix of aligned allocations. --- lib/std/core/allocators/mem_allocator_fn.c3 | 8 ++- lib/std/core/allocators/temp_allocator.c3 | 1 - lib/std/list.c3 | 49 ++++++++++++++++--- src/version.h | 2 +- test/test_suite/functions/test_regression.c3t | 8 +-- .../functions/test_regression_mingw.c3t | 4 +- .../test_suite2/functions/test_regression.c3t | 4 +- .../functions/test_regression_mingw.c3t | 4 +- 8 files changed, 57 insertions(+), 23 deletions(-) diff --git a/lib/std/core/allocators/mem_allocator_fn.c3 b/lib/std/core/allocators/mem_allocator_fn.c3 index 52830af81..52df46551 100644 --- a/lib/std/core/allocators/mem_allocator_fn.c3 +++ b/lib/std/core/allocators/mem_allocator_fn.c3 @@ -35,7 +35,7 @@ private fn void* _libc_aligned_alloc(usz bytes, usz alignment, usz offset) @inli { usz header = mem::aligned_offset(AlignedBlock.sizeof + offset, alignment) - offset; void* data = libc::malloc(header + bytes); - void* mem = mem::aligned_pointer(data + offset, alignment) - offset; + void* mem = mem::aligned_pointer(data + header + offset, alignment) - offset; assert(mem > data); AlignedBlock* desc = (AlignedBlock*)mem - 1; *desc = { bytes, data }; @@ -50,7 +50,7 @@ private fn void* _libc_aligned_calloc(usz bytes, usz alignment, usz offset) @inl { usz header = mem::aligned_offset(AlignedBlock.sizeof + offset, alignment) - offset; void* data = libc::calloc(header + bytes, 1); - void* mem = mem::aligned_pointer(data + offset, alignment) - offset; + void* mem = mem::aligned_pointer(data + header + offset, alignment) - offset; AlignedBlock* desc = (AlignedBlock*)mem - 1; assert(mem > data); *desc = { bytes, data }; @@ -64,7 +64,7 @@ private fn void* _libc_aligned_calloc(usz bytes, usz alignment, usz offset) @inl private fn void* _libc_aligned_realloc(void* old_pointer, usz bytes, usz alignment, usz offset) @inline { AlignedBlock* desc = (AlignedBlock*)old_pointer - 1; - void* data_start = desc.start; + void* data_start = desc.start; void* new_data = _libc_aligned_calloc(bytes, alignment, offset); mem::copy(new_data, old_pointer, desc.len > bytes ? desc.len : bytes, DEFAULT_MEM_ALIGNMENT, DEFAULT_MEM_ALIGNMENT); libc::free(data_start); @@ -86,12 +86,10 @@ fn void*! libc_allocator_fn(Allocator* unused, usz bytes, usz alignment, usz off switch (kind) { case ALIGNED_ALLOC: - if (alignment <= DEFAULT_MEM_ALIGNMENT) nextcase ALLOC; data = _libc_aligned_alloc(bytes, alignment, offset); case ALLOC: data = libc::malloc(bytes); case ALIGNED_CALLOC: - if (alignment <= DEFAULT_MEM_ALIGNMENT) nextcase CALLOC; data = _libc_aligned_calloc(bytes, alignment, offset); case CALLOC: data = libc::calloc(bytes, 1); diff --git a/lib/std/core/allocators/temp_allocator.c3 b/lib/std/core/allocators/temp_allocator.c3 index bb7a863a2..949105fb3 100644 --- a/lib/std/core/allocators/temp_allocator.c3 +++ b/lib/std/core/allocators/temp_allocator.c3 @@ -75,7 +75,6 @@ private fn void*! temp_allocator_function(Allocator* data, usz size, usz alignme case FREE: case ALIGNED_FREE: if (!old_pointer) return null; - io::println("Freeing stuff\n"); arena._free(old_pointer)?; return null; case MARK: diff --git a/lib/std/list.c3 b/lib/std/list.c3 index 8f53f9ac8..2d4766fe2 100644 --- a/lib/std/list.c3 +++ b/lib/std/list.c3 @@ -2,21 +2,33 @@ // Use of this source code is governed by the MIT license // a copy of which can be found in the LICENSE_STDLIB file. module std::array::list; +import std::math; struct List { usz size; usz capacity; + Allocator *allocator; Type *entries; } -private fn void List.ensure_capacity(List *list) @inline +/** + * @require allocator != null "A valid allocator must be provided" + **/ +fn void List.init(List* list, usz initial_capacity = 16, Allocator* allocator = mem::temp_allocator()) { - if (list.capacity == list.size) - { - list.capacity = list.capacity ? 2 * list.capacity : 16; - list.entries = realloc(list.entries, Type.sizeof * list.capacity); - } + list.allocator = allocator; + list.size = 0; + if (initial_capacity > 0) + { + initial_capacity = math::next_power_of_2(initial_capacity); + list.entries = allocator.alloc_aligned(Type.sizeof * initial_capacity, Type[1].alignof)!!; + } + else + { + list.entries = null; + } + list.capacity = initial_capacity; } @@ -111,7 +123,8 @@ fn Type List.get(List *list, usz index) fn void List.free(List *list) { - free(list.entries); + if (!list.allocator) return; + list.allocator.free_aligned(list.entries)!!; list.capacity = 0; list.size = 0; list.entries = null; @@ -122,6 +135,19 @@ fn void List.swap(List *list, usz i, usz j) @swap(list.entries[i], list.entries[j]); } +/** + * Reserve at least min_capacity + **/ +fn void List.reserve(List *list, usz min_capacity) +{ + if (!min_capacity) return; + if (list.capacity >= min_capacity) return; + if (!list.allocator) list.allocator = mem::temp_allocator(); + min_capacity = math::next_power_of_2(min_capacity); + list.entries = list.allocator.realloc_aligned(list.entries, Type.sizeof * min_capacity, Type[1].alignof) ?? null; + list.capacity = min_capacity; +} + macro Type List.@item_at(List &list, usz index) @operator([]) { return list.entries[index]; @@ -131,3 +157,12 @@ macro Type* List.@item_ref(List &list, usz index) @operator(&[]) { return &list.entries[index]; } + + +private fn void List.ensure_capacity(List *list) @inline +{ + if (list.capacity == list.size) + { + list.reserve(list.capacity ? 2 * list.capacity : 16); + } +} diff --git a/src/version.h b/src/version.h index e26afee2a..bc36943ac 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1 @@ -#define COMPILER_VERSION "0.3.81" \ No newline at end of file +#define COMPILER_VERSION "0.3.82" \ No newline at end of file diff --git a/test/test_suite/functions/test_regression.c3t b/test/test_suite/functions/test_regression.c3t index ad5341fbe..6bb559101 100644 --- a/test/test_suite/functions/test_regression.c3t +++ b/test/test_suite/functions/test_regression.c3t @@ -241,7 +241,8 @@ fn Type getValue(Blob blob) %"int[]" = type { i32*, i64 } %LinkedList = type { i64, %Node*, %Node* } %Node = type { %Node*, %Node*, i32 } -%List = type { i64, i64, i32* } +%List = type { i64, i64, %Allocator*, i32* } +%Allocator = type { i64 (i8**, %Allocator*, i64, i64, i64, i8*, i32)* } %Foo = type { i32, i32 } @"ct$test_Bobo" = linkonce constant %.introspect { i8 10, i64 20, i64 0, i64 6, [0 x i64] zeroinitializer }, align 8 @@ -250,7 +251,8 @@ fn Type getValue(Blob blob) @"ct$test_Foo2" = linkonce constant %.introspect { i8 10, i64 4, i64 0, i64 1, [0 x i64] zeroinitializer }, align 8 @"ct$test_Foo" = linkonce constant %.introspect { i8 10, i64 8, i64 0, i64 2, [0 x i64] zeroinitializer }, align 8 @"ct$int" = linkonce constant %.introspect { i8 2, i64 4, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8 -@"ct$test_MyEnum" = linkonce constant { i8, i64, i64, i64, [3 x %"char[]"] } { i8 8, i64 4, i64 ptrtoint (%.introspect* @"ct$int" to i64), i64 3, [3 x %"char[]"] [%"char[]" { i8* getelementptr +@"ct$test_MyEnum" = linkonce constant { i8, i64, i64, i64, [3 x %"char[]"] } { i8 8, i64 4, i64 ptrtoint (%.introspect* @"ct$int" to i64), i64 3, [3 x %"char[]"] [%"char[]" { i8* getelementptr inbounds ([5 x i8], [5 x i8]* @.enum.0, i64 0, i64 0), i64 4 }, %"char[]" { i8* getelementptr inbounds ([6 x i8], [6 x i8]* @.enum.1, i64 0, i64 0), i64 5 }, %"char[]" { i8* getelementptr inbounds ([4 x i8], [4 x i8]* @.enum.2, i64 0, i64 0), i64 3 }] }, align 8 + define void @test_Foo2_printme(%Foo2* %0) #0 { entry: %1 = getelementptr inbounds %Foo2, %Foo2* %0, i32 0, i32 0 @@ -493,7 +495,7 @@ loop.exit: ; preds = %loop.cond store i32 3, i32* %elements, align 4 %12 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str.4, i32 0, i32 0)) %13 = bitcast %List* %array to i8* - call void @llvm.memset.p0i8.i64(i8* align 8 %13, i8 0, i64 24, i1 false) + call void @llvm.memset.p0i8.i64(i8* align 8 %13, i8 0, i64 32, i1 false) call void @"std_array_list$$int_List_append"(%List* %array, i32 100) call void @"std_array_list$$int_List_append"(%List* %array, i32 200) call void @"std_array_list$$int_List_append"(%List* %array, i32 400) diff --git a/test/test_suite/functions/test_regression_mingw.c3t b/test/test_suite/functions/test_regression_mingw.c3t index d09250f0f..dbcd45bf9 100644 --- a/test/test_suite/functions/test_regression_mingw.c3t +++ b/test/test_suite/functions/test_regression_mingw.c3t @@ -243,7 +243,7 @@ fn Type getValue(Blob blob) %"int[]" = type { i32*, i64 } %LinkedList = type { i64, %Node*, %Node* } %Node = type { %Node*, %Node*, i32 } -%List = type { i64, i64, i32* } +%List = type { i64, i64, %Allocator*, i32* } %Foo = type { i32, i32 } $"ct$test_Bobo" = comdat any @@ -533,7 +533,7 @@ loop.exit: ; preds = %loop.cond store i32 3, i32* %elements, align 4 %12 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([7 x i8], [7 x i8]* @.str.4, i32 0, i32 0)) %13 = bitcast %List* %array to i8* - call void @llvm.memset.p0i8.i64(i8* align 8 %13, i8 0, i64 24, i1 false) + call void @llvm.memset.p0i8.i64(i8* align 8 %13, i8 0, i64 32, i1 false) call void @"std_array_list$$int_List_append"(%List* %array, i32 100) call void @"std_array_list$$int_List_append"(%List* %array, i32 200) call void @"std_array_list$$int_List_append"(%List* %array, i32 400) diff --git a/test/test_suite2/functions/test_regression.c3t b/test/test_suite2/functions/test_regression.c3t index 7681ad6ee..dd593f75e 100644 --- a/test/test_suite2/functions/test_regression.c3t +++ b/test/test_suite2/functions/test_regression.c3t @@ -240,7 +240,7 @@ fn Type getValue(Blob blob) %Bobo = type { i16, float, i16, i16, float, i16 } %"int[]" = type { ptr, i64 } %LinkedList = type { i64, ptr, ptr } -%List = type { i64, i64, ptr } +%List = type { i64, i64, ptr, ptr } %Foo = type { i32, i32 } @"ct$test_Bobo" = linkonce constant %.introspect { i8 10, i64 20, i64 0, i64 6, [0 x i64] zeroinitializer }, align 8 @@ -482,7 +482,7 @@ loop.exit: ; preds = %loop.cond %10 = call i32 (ptr, ...) @printf(ptr @.str.3, i32 3) store i32 3, ptr %elements, align 4 %11 = call i32 (ptr, ...) @printf(ptr @.str.4) - call void @llvm.memset.p0.i64(ptr align 8 %array, i8 0, i64 24, i1 false) + call void @llvm.memset.p0.i64(ptr align 8 %array, i8 0, i64 32, i1 false) call void @"std_array_list$$int_List_append"(ptr %array, i32 100) call void @"std_array_list$$int_List_append"(ptr %array, i32 200) call void @"std_array_list$$int_List_append"(ptr %array, i32 400) diff --git a/test/test_suite2/functions/test_regression_mingw.c3t b/test/test_suite2/functions/test_regression_mingw.c3t index d8bebbc7e..48f098836 100644 --- a/test/test_suite2/functions/test_regression_mingw.c3t +++ b/test/test_suite2/functions/test_regression_mingw.c3t @@ -242,7 +242,7 @@ fn Type getValue(Blob blob) %Bobo = type { i16, float, i16, i16, float, i16 } %"int[]" = type { ptr, i64 } %LinkedList = type { i64, ptr, ptr } -%List = type { i64, i64, ptr } +%List = type { i64, i64, ptr, ptr } %Foo = type { i32, i32 } $"ct$test_Bobo" = comdat any @@ -519,7 +519,7 @@ loop.exit: ; preds = %loop.cond %10 = call i32 (ptr, ...) @printf(ptr @.str.3, i32 3) store i32 3, ptr %elements, align 4 %11 = call i32 (ptr, ...) @printf(ptr @.str.4) - call void @llvm.memset.p0.i64(ptr align 8 %array, i8 0, i64 24, i1 false) + call void @llvm.memset.p0.i64(ptr align 8 %array, i8 0, i64 32, i1 false) call void @"std_array_list$$int_List_append"(ptr %array, i32 100) call void @"std_array_list$$int_List_append"(ptr %array, i32 200) call void @"std_array_list$$int_List_append"(ptr %array, i32 400)