From 0e076234ca3d066f695c173adf62c341e7ffafc8 Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Thu, 29 Apr 2021 03:09:37 +0200 Subject: [PATCH] Set stdlib library for testing and profit. Fix bugs when using void* to step. Make constants private linkage. Compare pointers using unsigned comparison without conversion. Use manual ptrdiff code. Fix issue returning "void!". Unify pointers when doing Foo* - void*. Allow comparing for example void* < Foo* --- resources/lib/std/mem.c3 | 109 ++++++++++++++++++ resources/lib/std/runtime.c3 | 32 +++++ src/build/build_options.c | 9 +- src/build/build_options.h | 1 + src/compiler/compiler.c | 12 +- src/compiler/compiler.h | 2 +- src/compiler/llvm_codegen_expr.c | 55 +++++++-- src/compiler/llvm_codegen_function.c | 3 +- src/compiler/llvm_codegen_internal.h | 1 + src/compiler/llvm_codegen_type.c | 7 ++ src/compiler/sema_expr.c | 19 ++- src/main.c | 5 +- src/utils/file_utils.c | 2 + test/test_suite/arrays/array_literal.c3t | 4 +- .../test_suite/arrays/complex_array_const.c3t | 8 +- .../test_suite/expressions/pointer_access.c3t | 2 +- test/test_suite/expressions/strings.c3t | 2 +- test/test_suite/functions/varargs.c3t | 12 +- test/test_suite/statements/foreach_common.c3t | 14 +-- test/test_suite/statements/while_switch.c3t | 8 +- test/test_suite/struct/struct_codegen.c3t | 2 +- test/test_suite/subarrays/slice_offset.c3t | 2 +- .../subarrays/slice_offset_neg_end.c3t | 2 +- .../subarrays/slice_offset_neg_start.c3t | 2 +- test/test_suite/subarrays/slice_start.c3t | 2 +- 25 files changed, 268 insertions(+), 49 deletions(-) create mode 100644 resources/lib/std/runtime.c3 diff --git a/resources/lib/std/mem.c3 b/resources/lib/std/mem.c3 index 3aa7c3036..eeee4e926 100644 --- a/resources/lib/std/mem.c3 +++ b/resources/lib/std/mem.c3 @@ -1,9 +1,118 @@ module std::mem; extern func void* _malloc(usize bytes) @cname("malloc"); +extern func void* _realloc(void* ptr, usize bytes) @cname("realloc"); extern func void* _calloc(usize bytes, usize elements) @cname("calloc"); extern func void _free(void* ptr) @cname("free"); +public enum AllocationKind +{ + ALLOC, + REALLOC, + FREE, +} + +public enum AllocationFailureKind +{ + OUT_OF_MEMORY +} + +public error AllocationFailure +{ + AllocationFailureKind failureKind; +} + +public typedef func void!(void *data, void** pointer, usize bytes, usize alignment, AllocationKind kind) as AllocatorFunction; + +public struct Allocator +{ + AllocatorFunction allocation_function; + void *data; +} + +public func void! system_malloc_function(void *unused, void** pointer, usize bytes, usize alignment, AllocationKind kind) @inline +{ + switch (kind) + { + case ALLOC: + void* data = _malloc(bytes); + if (!data) return AllocationFailure({ OUT_OF_MEMORY })!; + *pointer = data; + return; + case REALLOC: + void* data = _realloc(*pointer, bytes); + if (!data) return AllocationFailure({ OUT_OF_MEMORY })!; + *pointer = data; + return; + case FREE: + _free(*pointer); + *pointer = null; + return; + } + $unreachable; +} + +public struct RingAllocator +{ + char *data; + usize size; + usize offset; +} + + +public func void* RingAllocator.alloc(RingAllocator *allocator, usize size) +{ + if (size > allocator.size) return null; + // Wraparound? If so, start at the beginning. + if (allocator.offset + size > allocator.size) + { + allocator.offset = size; + return allocator.data; + } + void* data = allocator.offset + allocator.data; + allocator.offset = (allocator.offset + size) & allocator.size; + return data; +} + +public func void* RingAllocator.realloc(RingAllocator *allocator, void* ptr, usize size) +{ + if (size > allocator.size) return null; + assert(allocator.data >= ptr && ptr < allocator.data + size, "Realloc on other allocator."); + // 1. The pointer is before the allocator + if (allocator.data + allocator.offset > ptr) + { + if (allocator.data + allocator.size < ptr + size) + { + // 1a. There is not enough space, we need to copy to the start. + usize pointer_offset = ptr - allocator.data; + usize copy_len = pointer_offset + size > allocator.offset ? allocator.offset - pointer_offset : size; + //memcpy(allocator.data, ptr, copy_len); + allocator.offset = size; + return allocator.data; + } + // 1b. There is enough space, so we just change the offset: + allocator.offset = ptr - allocator.data + size; + return ptr; + } + // 2. The pointer is after the allocator + // 2a. Is there sufficient space? + if (ptr + size <= allocator.data + allocator.size) + { + // Good, if so we simply change the offset and return the pointer. + allocator.offset = ptr - allocator.data + size; + return ptr; + } + // 2b. Not sufficient space, we copy to the beginning. + usize pointer_offset = ptr - allocator.data; + usize copy_len = allocator.size - (ptr - allocator.data); + if (copy_len > size) copy_len = size; + //memcpy(allocator.data, ptr, copy_len); + allocator.offset = size; + return allocator.data; +} + +public Allocator main_allocator = { &system_malloc_function, null }; + public macro malloc($Type) { // TODO: return cast(_malloc($Type.sizeof) as $Type*); diff --git a/resources/lib/std/runtime.c3 b/resources/lib/std/runtime.c3 new file mode 100644 index 000000000..d8a053108 --- /dev/null +++ b/resources/lib/std/runtime.c3 @@ -0,0 +1,32 @@ +module std::runtime; + +struct VirtualAny +{ + void* ptr; + typeid type_id; +} + +struct VirtualContainer +{ + void* ptr; + void* impl_ptr; +} + +struct SubArrayContainer +{ + void* ptr; + usize len; +} + +struct VarArrayHeader +{ + usize size; + usize capacity; + void *allocator; + +} + +struct VarArrayContainer +{ + +} diff --git a/src/build/build_options.c b/src/build/build_options.c index 54277be95..f1d7d0d05 100644 --- a/src/build/build_options.c +++ b/src/build/build_options.c @@ -63,7 +63,8 @@ static void usage(void) OUTPUT(" headers [ ...] Analyse files and generate C headers for public methods."); OUTPUT(""); OUTPUT("Options:"); - OUTPUT(" --lib - Use this directory as the c3 library path."); + OUTPUT(" --stdlib - Use this directory as the C3 standard library path."); + OUTPUT(" --lib - Use this directory as the C3 library path."); OUTPUT(" --path - Use this as the base directory for the current command."); OUTPUT(" --template