From 104766edf486771fcdd8b922b8a7aa16660eb2e3 Mon Sep 17 00:00:00 2001 From: Christoffer Lerno Date: Tue, 16 Jan 2024 00:16:29 +0100 Subject: [PATCH] 0.5.4: Hash variables accept designated initializers. @safemacro overrides the need for `@` in macro names. Fixes to macro context evaluation. Updated allocator api. Removed install_win_reqs.bat. --- install_win_reqs.bat | 17 - lib/std/collections/bitset.c3 | 6 +- lib/std/collections/enummap.c3 | 2 +- lib/std/collections/enumset.c3 | 2 +- lib/std/collections/linkedlist.c3 | 13 +- lib/std/collections/list.c3 | 24 +- lib/std/collections/map.c3 | 39 +- lib/std/collections/object.c3 | 28 +- lib/std/collections/priorityqueue.c3 | 8 +- lib/std/collections/range.c3 | 8 +- lib/std/core/allocators/dynamic_arena.c3 | 10 +- lib/std/core/allocators/on_stack_allocator.c3 | 12 +- lib/std/core/allocators/temp_allocator.c3 | 25 +- lib/std/core/allocators/tracking_allocator.c3 | 4 +- lib/std/core/array.c3 | 6 +- lib/std/core/builtin.c3 | 2 +- lib/std/core/dstring.c3 | 44 +-- lib/std/core/mem.c3 | 183 +++++----- lib/std/core/mem_allocator.c3 | 345 ++++++++++++++---- lib/std/core/private/main_stub.c3 | 4 +- lib/std/core/runtime.c3 | 12 +- lib/std/core/string.c3 | 82 ++--- lib/std/encoding/csv.c3 | 8 +- lib/std/encoding/json.c3 | 2 +- lib/std/io/file.c3 | 8 +- lib/std/io/formatter.c3 | 2 +- lib/std/io/io.c3 | 4 +- lib/std/io/os/getcwd.c3 | 2 +- lib/std/io/os/rmtree.c3 | 2 +- lib/std/io/os/temp_directory.c3 | 8 +- lib/std/io/path.c3 | 32 +- lib/std/io/stream.c3 | 4 +- lib/std/io/stream/bytebuffer.c3 | 10 +- lib/std/io/stream/bytewriter.c3 | 10 +- lib/std/math/random/math.seeder.c3 | 4 +- lib/std/net/inetaddr.c3 | 2 +- lib/std/net/net.c3 | 4 +- lib/std/os/backtrace.c3 | 6 +- lib/std/os/env.c3 | 10 +- lib/std/os/linux/linux.c3 | 6 +- lib/std/os/macos/darwin.c3 | 6 +- lib/std/os/macos/objc.c3 | 2 +- lib/std/os/subprocess.c3 | 4 +- lib/std/threads/os/thread_posix.c3 | 3 +- releasenotes.md | 21 +- resources/examples/contextfree/boolerr.c3 | 2 +- resources/examples/fannkuch-redux.c3 | 6 +- resources/examples/fannkuch-redux2.c3 | 6 +- resources/examples/spectralnorm.c3 | 8 +- resources/testfragments/allocators_testing.c3 | 12 +- resources/testfragments/toposort.c3 | 9 +- src/build/project.c | 2 +- src/compiler/compiler.c | 4 +- src/compiler/compiler_internal.h | 16 +- src/compiler/copying.c | 3 + src/compiler/enums.h | 2 + src/compiler/expr.c | 7 + src/compiler/linker.c | 22 +- src/compiler/llvm_codegen_expr.c | 1 + src/compiler/sema_decls.c | 9 +- src/compiler/sema_expr.c | 110 ++++-- src/compiler/sema_liveness.c | 1 + src/compiler/sema_types.c | 6 +- src/compiler/symtab.c | 1 + src/compiler/target.c | 16 +- src/utils/file_utils.c | 18 +- src/version.h | 2 +- .../concurrency/atomic_load_store_debug.c3t | 16 +- test/test_suite/dynamic/inherit.c3t | 227 ++++-------- .../dynamic/overlapping_function.c3t | 222 ++++------- test/test_suite/errors/rethrow_macro.c3 | 4 +- .../generic/generic_lambda_complex.c3t | 12 +- test/test_suite/macros/hash_initializer.c3t | 23 ++ test/test_suite/stdlib/map.c3t | 36 +- .../switch/switch_in_defer_macro.c3t | 14 +- test/unit/regression/liveness_any.c3 | 2 +- test/unit/stdlib/collections/copy_map.c3 | 2 +- test/unit/stdlib/collections/object.c3 | 4 +- test/unit/stdlib/io/path.c3 | 2 +- test/unit/stdlib/mem/temp_mem.c3 | 18 +- 80 files changed, 982 insertions(+), 899 deletions(-) delete mode 100644 install_win_reqs.bat create mode 100644 test/test_suite/macros/hash_initializer.c3t diff --git a/install_win_reqs.bat b/install_win_reqs.bat deleted file mode 100644 index acbc4e273..000000000 --- a/install_win_reqs.bat +++ /dev/null @@ -1,17 +0,0 @@ -@echo off - -set DOWNLOAD_URL=https://aka.ms/vs/17/release - -mkdir tmp 2> NUL - -if not exist "tmp\vs_buildtools.exe" ( - bitsadmin /transfer /download /priority foreground %DOWNLOAD_URL%/vs_buildtools.exe %CD%\tmp\vs_buildtools.exe -) - -echo Preparing Build Tools, please wait... -tmp\vs_BuildTools.exe --quiet --wait --layout tmp\ --add Microsoft.VisualStudio.Component.Windows10SDK.19041 - -echo Installing Build Tools, please wait... -tmp\vs_BuildTools.exe --quiet --wait --noweb --add Microsoft.VisualStudio.Component.Windows10SDK.19041 - -REM rmdir tmp /s /q diff --git a/lib/std/collections/bitset.c3 b/lib/std/collections/bitset.c3 index 1d26146b1..76af33693 100644 --- a/lib/std/collections/bitset.c3 +++ b/lib/std/collections/bitset.c3 @@ -86,7 +86,7 @@ struct GrowableBitSet * @param initial_capacity * @param [&inout] allocator "The allocator to use, defaults to the heap allocator" **/ -fn GrowableBitSet* GrowableBitSet.new_init(&self, usz initial_capacity = 1, Allocator* allocator = mem::heap()) +fn GrowableBitSet* GrowableBitSet.new_init(&self, usz initial_capacity = 1, Allocator* allocator = allocator::heap()) { self.data.new_init(initial_capacity, allocator); return self; @@ -96,14 +96,14 @@ fn GrowableBitSet* GrowableBitSet.new_init(&self, usz initial_capacity = 1, Allo * @param initial_capacity * @param [&inout] allocator "The allocator to use, defaults to the heap allocator" **/ -fn GrowableBitSet* GrowableBitSet.init_new(&self, usz initial_capacity = 1, Allocator* allocator = mem::heap()) @deprecated("Replaced by new_init") +fn GrowableBitSet* GrowableBitSet.init_new(&self, usz initial_capacity = 1, Allocator* allocator = allocator::heap()) @deprecated("Replaced by new_init") { return self.new_init(initial_capacity, allocator) @inline; } fn GrowableBitSet* GrowableBitSet.temp_init(&self, usz initial_capacity = 1) { - return self.new_init(initial_capacity, mem::temp()) @inline; + return self.new_init(initial_capacity, allocator::temp()) @inline; } fn GrowableBitSet* GrowableBitSet.init_temp(&self, usz initial_capacity = 1) @deprecated("Replaced by temp_init") diff --git a/lib/std/collections/enummap.c3 b/lib/std/collections/enummap.c3 index 9291c3469..7d8fb9649 100644 --- a/lib/std/collections/enummap.c3 +++ b/lib/std/collections/enummap.c3 @@ -25,7 +25,7 @@ fn usz! EnumMap.to_format(&self, Formatter* formatter) @dynamic return n; } -fn String EnumMap.to_new_string(&self, Allocator* allocator = mem::heap()) @dynamic +fn String EnumMap.to_new_string(&self, Allocator* allocator = allocator::heap()) @dynamic { return string::new_format("%s", *self, .allocator = allocator); } diff --git a/lib/std/collections/enumset.c3 b/lib/std/collections/enumset.c3 index 623aae2ec..746e2b6b2 100644 --- a/lib/std/collections/enumset.c3 +++ b/lib/std/collections/enumset.c3 @@ -140,7 +140,7 @@ fn usz! EnumSet.to_format(&set, Formatter* formatter) @dynamic return n; } -fn String EnumSet.to_new_string(&set, Allocator* allocator = mem::heap()) @dynamic +fn String EnumSet.to_new_string(&set, Allocator* allocator = allocator::heap()) @dynamic { return string::new_format("%s", *set, .allocator = allocator); } diff --git a/lib/std/collections/linkedlist.c3 b/lib/std/collections/linkedlist.c3 index 1748f67d2..4e0d4b217 100644 --- a/lib/std/collections/linkedlist.c3 +++ b/lib/std/collections/linkedlist.c3 @@ -32,7 +32,7 @@ fn void LinkedList.push_last(&self, Type value) * @param [&inout] allocator "The allocator to use, defaults to the heap allocator" * @return "the initialized list" **/ -fn LinkedList* LinkedList.new_init(&self, Allocator* allocator = mem::heap()) +fn LinkedList* LinkedList.new_init(&self, Allocator* allocator = allocator::heap()) { *self = { .allocator = allocator }; return self; @@ -42,14 +42,14 @@ fn LinkedList* LinkedList.new_init(&self, Allocator* allocator = mem::heap()) * @param [&inout] allocator "The allocator to use, defaults to the heap allocator" * @return "the initialized list" **/ -fn LinkedList* LinkedList.init_new(&self, Allocator* allocator = mem::heap()) @deprecated("Replaced by new_init") +fn LinkedList* LinkedList.init_new(&self, Allocator* allocator = allocator::heap()) @deprecated("Replaced by new_init") { return self.new_init(allocator); } fn LinkedList* LinkedList.temp_init(&self) { - return self.new_init(mem::temp()) @inline; + return self.new_init(allocator::temp()) @inline; } fn LinkedList* LinkedList.init_temp(&self) @deprecated("Replaced by temp_init") @@ -62,12 +62,13 @@ fn LinkedList* LinkedList.init_temp(&self) @deprecated("Replaced by temp_init") **/ macro void LinkedList.free_node(&self, Node* node) @private { - self.allocator.free(node); + allocator::free(self.allocator, node); } + macro Node* LinkedList.alloc_node(&self) @private { - if (!self.allocator) self.allocator = mem::heap(); - return self.allocator.new(Node); + if (!self.allocator) self.allocator = allocator::heap(); + return allocator::alloc(self.allocator, Node); } fn void LinkedList.link_first(&self, Type value) @private diff --git a/lib/std/collections/list.c3 b/lib/std/collections/list.c3 index ac7761e8c..61a18dfcc 100644 --- a/lib/std/collections/list.c3 +++ b/lib/std/collections/list.c3 @@ -23,14 +23,14 @@ struct List (Printable) * @param initial_capacity "The initial capacity to reserve" * @param [&inout] allocator "The allocator to use, defaults to the heap allocator" **/ -fn List* List.new_init(&self, usz initial_capacity = 16, Allocator* allocator = mem::heap()) +fn List* List.new_init(&self, usz initial_capacity = 16, Allocator* allocator = allocator::heap()) { self.allocator = allocator; self.size = 0; if (initial_capacity > 0) { initial_capacity = math::next_power_of_2(initial_capacity); - self.entries = allocator.alloc_aligned(Type.sizeof * initial_capacity, .alignment = Type[1].alignof)!!; + self.entries = allocator::malloc_aligned(allocator, Type.sizeof * initial_capacity, .alignment = Type[1].alignof)!!; } else { @@ -44,7 +44,7 @@ fn List* List.new_init(&self, usz initial_capacity = 16, Allocator* allocator = * @param initial_capacity "The initial capacity to reserve" * @param [&inout] allocator "The allocator to use, defaults to the heap allocator" **/ -fn List* List.init_new(&self, usz initial_capacity = 16, Allocator* allocator = mem::heap()) @deprecated("Replaced by new_init") +fn List* List.init_new(&self, usz initial_capacity = 16, Allocator* allocator = allocator::heap()) @deprecated("Replaced by new_init") { return self.new_init(initial_capacity, allocator) @inline; } @@ -56,7 +56,7 @@ fn List* List.init_new(&self, usz initial_capacity = 16, Allocator* allocator = **/ fn List* List.temp_init(&self, usz initial_capacity = 16) { - return self.new_init(initial_capacity, mem::temp()) @inline; + return self.new_init(initial_capacity, allocator::temp()) @inline; } /** @@ -72,7 +72,7 @@ fn List* List.init_temp(&self, usz initial_capacity = 16) @deprecated("Replaced /** * @require self.size == 0 "The List must be empty" **/ -fn void List.init_wrapping_array(&self, Type[] types, Allocator* allocator = mem::heap()) +fn void List.init_wrapping_array(&self, Type[] types, Allocator* allocator = allocator::heap()) { self.allocator = allocator; self.size = types.len; @@ -100,7 +100,7 @@ fn usz! List.to_format(&self, Formatter* formatter) @dynamic } } -fn String List.to_new_string(&self, Allocator* allocator = mem::heap()) @dynamic +fn String List.to_new_string(&self, Allocator* allocator = allocator::heap()) @dynamic { return string::new_format("%s", *self, .allocator = allocator); } @@ -164,17 +164,17 @@ fn void List.add_all(&self, List* other_list) } -fn Type[] List.to_new_array(&self, Allocator* allocator = mem::heap()) +fn Type[] List.to_new_array(&self, Allocator* allocator = allocator::heap()) { if (!self.size) return Type[] {}; - Type[] result = allocator.new_array(Type, self.size); + Type[] result = allocator::alloc_array(allocator, Type, self.size); result[..] = self.entries[:self.size]; return result; } fn Type[] List.to_tarray(&self) { - return self.to_new_array(mem::temp()); + return self.to_new_array(allocator::temp()); } /** @@ -277,7 +277,7 @@ fn Type List.get(&self, usz index) @inline fn void List.free(&self) { if (!self.allocator) return; - self.allocator.free_aligned(self.entries); + allocator::free_aligned(self.allocator, self.entries); self.capacity = 0; self.size = 0; self.entries = null; @@ -373,9 +373,9 @@ fn void List.reserve(&self, usz min_capacity) { if (!min_capacity) return; if (self.capacity >= min_capacity) return; - if (!self.allocator) self.allocator = mem::heap(); + if (!self.allocator) self.allocator = allocator::heap(); min_capacity = math::next_power_of_2(min_capacity); - self.entries = self.allocator.realloc_aligned(self.entries, Type.sizeof * min_capacity, .alignment = Type[1].alignof) ?? null; + self.entries = allocator::realloc_aligned(self.allocator, self.entries, Type.sizeof * min_capacity, .alignment = Type[1].alignof) ?? null; self.capacity = min_capacity; } diff --git a/lib/std/collections/map.c3 b/lib/std/collections/map.c3 index 5b0d877ec..6877e85ab 100644 --- a/lib/std/collections/map.c3 +++ b/lib/std/collections/map.c3 @@ -26,13 +26,13 @@ struct HashMap * @require !self.allocator "Map was already initialized" * @require capacity < MAXIMUM_CAPACITY "Capacity cannot exceed maximum" **/ -fn HashMap* HashMap.new_init(&self, uint capacity = DEFAULT_INITIAL_CAPACITY, float load_factor = DEFAULT_LOAD_FACTOR, Allocator* allocator = mem::heap()) +fn HashMap* HashMap.new_init(&self, uint capacity = DEFAULT_INITIAL_CAPACITY, float load_factor = DEFAULT_LOAD_FACTOR, Allocator* allocator = allocator::heap()) { capacity = math::next_power_of_2(capacity); self.allocator = allocator; self.load_factor = load_factor; self.threshold = (uint)(capacity * load_factor); - self.table = allocator.new_zero_array(Entry*, capacity); + self.table = allocator::new_array(allocator, Entry*, capacity); return self; } @@ -43,7 +43,7 @@ fn HashMap* HashMap.new_init(&self, uint capacity = DEFAULT_INITIAL_CAPACITY, fl * @require !map.allocator "Map was already initialized" * @require capacity < MAXIMUM_CAPACITY "Capacity cannot exceed maximum" **/ -fn HashMap* HashMap.init_new(&map, uint capacity = DEFAULT_INITIAL_CAPACITY, float load_factor = DEFAULT_LOAD_FACTOR, Allocator* allocator = mem::heap()) @deprecated("Replaced by new_init") +fn HashMap* HashMap.init_new(&map, uint capacity = DEFAULT_INITIAL_CAPACITY, float load_factor = DEFAULT_LOAD_FACTOR, Allocator* allocator = allocator::heap()) @deprecated("Replaced by new_init") { return map.new_init(capacity, load_factor, allocator); } @@ -56,7 +56,7 @@ fn HashMap* HashMap.init_new(&map, uint capacity = DEFAULT_INITIAL_CAPACITY, flo **/ fn HashMap* HashMap.temp_init(&self, uint capacity = DEFAULT_INITIAL_CAPACITY, float load_factor = DEFAULT_LOAD_FACTOR) { - return self.new_init(capacity, load_factor, mem::temp()) @inline; + return self.new_init(capacity, load_factor, allocator::temp()) @inline; } /** @@ -85,7 +85,7 @@ fn bool HashMap.is_initialized(&map) * @param [&inout] allocator "The allocator to use" * @param [&in] other_map "The map to copy from." **/ -fn HashMap* HashMap.new_init_from_map(&self, HashMap* other_map, Allocator* allocator = mem::heap()) +fn HashMap* HashMap.new_init_from_map(&self, HashMap* other_map, Allocator* allocator = allocator::heap()) { self.new_init(other_map.table.len, other_map.load_factor, allocator); self.put_all_for_create(other_map); @@ -96,7 +96,7 @@ fn HashMap* HashMap.new_init_from_map(&self, HashMap* other_map, Allocator* allo * @param [&inout] allocator "The allocator to use" * @param [&in] other_map "The map to copy from." **/ -fn HashMap* HashMap.init_new_from_map(&self, HashMap* other_map, Allocator* allocator = mem::heap()) @deprecated("Replaced by new_init_from_map") +fn HashMap* HashMap.init_new_from_map(&self, HashMap* other_map, Allocator* allocator = allocator::heap()) @deprecated("Replaced by new_init_from_map") { return self.new_init_from_map(other_map, allocator) @inline; @@ -107,7 +107,7 @@ fn HashMap* HashMap.init_new_from_map(&self, HashMap* other_map, Allocator* allo **/ fn HashMap* HashMap.temp_init_from_map(&map, HashMap* other_map) { - return map.new_init_from_map(other_map, mem::temp()) @inline; + return map.new_init_from_map(other_map, allocator::temp()) @inline; } /** @@ -153,6 +153,7 @@ fn Entry*! HashMap.get_entry(&map, Key key) /** * Get the value or update and + * @require $assignable(#expr, Value) **/ macro Value HashMap.@get_or_set(&map, Key key, Value #expr) { @@ -239,14 +240,14 @@ fn void HashMap.free(&map) fn Key[] HashMap.key_tlist(&map) { - return map.key_new_list(mem::temp()) @inline; + return map.key_new_list(allocator::temp()) @inline; } -fn Key[] HashMap.key_new_list(&map, Allocator* allocator = mem::heap()) +fn Key[] HashMap.key_new_list(&map, Allocator* allocator = allocator::heap()) { if (!map.count) return {}; - Key[] list = allocator.new_array(Key, map.count); + Key[] list = allocator::alloc_array(allocator, Key, map.count); usz index = 0; foreach (Entry* entry : map.table) { @@ -283,13 +284,13 @@ macro HashMap.@each_entry(map; @body(entry)) fn Value[] HashMap.value_tlist(&map) { - return map.value_new_list(mem::temp()) @inline; + return map.value_new_list(allocator::temp()) @inline; } -fn Value[] HashMap.value_new_list(&map, Allocator* allocator = mem::heap()) +fn Value[] HashMap.value_new_list(&map, Allocator* allocator = allocator::heap()) { if (!map.count) return {}; - Value[] list = allocator.new_array(Value, map.count); + Value[] list = allocator::alloc_array(allocator, Value, map.count); usz index = 0; foreach (Entry* entry : map.table) { @@ -320,11 +321,10 @@ fn bool HashMap.has_value(&map, Value v) @if(VALUE_IS_EQUATABLE) fn void HashMap.add_entry(&map, uint hash, Key key, Value value, uint bucket_index) @private { - Entry* entry = map.allocator.new(Entry); $if COPY_KEYS: key = key.copy(map.allocator); $endif - *entry = { .hash = hash, .key = key, .value = value, .next = map.table[bucket_index] }; + Entry* entry = allocator::new(map.allocator, Entry, { .hash = hash, .key = key, .value = value, .next = map.table[bucket_index] }); map.table[bucket_index] = entry; if (map.count++ >= map.threshold) { @@ -341,7 +341,7 @@ fn void HashMap.resize(&map, uint new_capacity) @private map.threshold = uint.max; return; } - Entry*[] new_table = map.allocator.new_zero_array(Entry*, new_capacity); + Entry*[] new_table = allocator::new_array(map.allocator, Entry*, new_capacity); map.transfer(new_table); map.table = new_table; map.free_internal(old_table.ptr); @@ -405,7 +405,7 @@ fn void HashMap.put_for_create(&map, Key key, Value value) @private fn void HashMap.free_internal(&map, void* ptr) @inline @private { - map.allocator.free(ptr); + allocator::free(map.allocator, ptr); } fn bool HashMap.remove_entry_for_key(&map, Key key) @private @@ -440,11 +440,10 @@ fn bool HashMap.remove_entry_for_key(&map, Key key) @private fn void HashMap.create_entry(&map, uint hash, Key key, Value value, int bucket_index) @private { Entry *e = map.table[bucket_index]; - Entry* entry = map.allocator.new(Entry); $if COPY_KEYS: key = key.copy(map.allocator); $endif - *entry = { .hash = hash, .key = key, .value = value, .next = map.table[bucket_index] }; + Entry* entry = allocator::new(map.allocator, Entry, { .hash = hash, .key = key, .value = value, .next = map.table[bucket_index] }); map.table[bucket_index] = entry; map.count++; } @@ -452,7 +451,7 @@ fn void HashMap.create_entry(&map, uint hash, Key key, Value value, int bucket_i fn void HashMap.free_entry(&self, Entry *entry) @local { $if COPY_KEYS: - self.allocator.free(entry.key); + allocator::free(self.allocator, entry.key); $endif self.free_internal(entry); } diff --git a/lib/std/collections/object.c3 b/lib/std/collections/object.c3 index 350c2ae86..77cfc6add 100644 --- a/lib/std/collections/object.c3 +++ b/lib/std/collections/object.c3 @@ -80,9 +80,7 @@ fn usz! Object.to_format(&self, Formatter* formatter) @dynamic fn Object* new_obj(Allocator* allocator) { - Object* o = allocator.new(Object); - *o = { .allocator = allocator, .type = void.typeid }; - return o; + return allocator::new(allocator, Object, { .allocator = allocator, .type = void.typeid }); } fn Object* new_null() @@ -92,30 +90,22 @@ fn Object* new_null() fn Object* new_int(int128 i, Allocator* allocator) { - Object* o = allocator.new(Object); - *o = { .i = i, .allocator = allocator, .type = int128.typeid }; - return o; + return allocator::new(allocator, Object, { .i = i, .allocator = allocator, .type = int128.typeid }); } macro Object* new_enum(e, Allocator* allocator) { - Object* o = allocator.new(Object); - *o = { .i = (int128)e, .allocator = allocator, .type = @typeid(e) }; - return o; + return allocator::new(allocator, Object, { .i = (int128)e, .allocator = allocator, .type = @typeid(e) }); } fn Object* new_float(double f, Allocator* allocator) { - Object* o = allocator.new(Object); - *o = { .f = f, .allocator = allocator, .type = double.typeid }; - return o; + return allocator::new(allocator, Object, { .f = f, .allocator = allocator, .type = double.typeid }); } fn Object* new_string(String s, Allocator* allocator) { - Object* o = allocator.new(Object); - *o = { .s = s.copy(allocator), .allocator = allocator, .type = String.typeid }; - return o; + return allocator::new(allocator, Object, { .s = s.copy(allocator), .allocator = allocator, .type = String.typeid }); } @@ -131,7 +121,7 @@ fn void Object.free(&self) case void: break; case String: - self.allocator.free(self.s); + allocator::free(self.allocator, self.s); case ObjectInternalList: foreach (ol : self.array) { @@ -140,13 +130,13 @@ fn void Object.free(&self) self.array.free(); case ObjectInternalMap: self.map.@each_entry(; ObjectInternalMapEntry* entry) { - self.allocator.free(entry.key); + allocator::free(self.allocator, entry.key); entry.value.free(); }; default: break; } - if (self.allocator) self.allocator.free(self); + if (self.allocator) allocator::free(self.allocator, self); } fn bool Object.is_null(&self) @inline => self == &NULL_OBJECT; @@ -193,7 +183,7 @@ fn void Object.set_object(&self, String key, Object* new_object) @private ObjectInternalMapEntry*! entry = self.map.get_entry(key); defer { - (void)self.allocator.free(entry.key); + (void)allocator::free(self.allocator, entry.key); (void)entry.value.free(); } self.map.set(key.copy(self.map.allocator), new_object); diff --git a/lib/std/collections/priorityqueue.c3 b/lib/std/collections/priorityqueue.c3 index 90b68ca1c..bc0a378e1 100644 --- a/lib/std/collections/priorityqueue.c3 +++ b/lib/std/collections/priorityqueue.c3 @@ -36,19 +36,19 @@ struct PrivatePriorityQueue (Printable) Heap heap; } -fn void PrivatePriorityQueue.init_new(&self, usz initial_capacity = 16, Allocator* allocator = mem::heap()) @inline @deprecated("Replaced by new_init") +fn void PrivatePriorityQueue.init_new(&self, usz initial_capacity = 16, Allocator* allocator = allocator::heap()) @inline @deprecated("Replaced by new_init") { return self.new_init(initial_capacity, allocator); } -fn void PrivatePriorityQueue.new_init(&self, usz initial_capacity = 16, Allocator* allocator = mem::heap()) @inline +fn void PrivatePriorityQueue.new_init(&self, usz initial_capacity = 16, Allocator* allocator = allocator::heap()) @inline { self.heap.new_init(initial_capacity, allocator); } fn void PrivatePriorityQueue.temp_init(&self, usz initial_capacity = 16) @inline { - self.heap.new_init(initial_capacity, mem::temp()) @inline; + self.heap.new_init(initial_capacity, allocator::temp()) @inline; } fn void PrivatePriorityQueue.init_temp(&self, usz initial_capacity = 16) @inline @deprecated("Replaced by temp_init") @@ -151,7 +151,7 @@ fn usz! PrivatePriorityQueue.to_format(&self, Formatter* formatter) @dynamic return self.heap.to_format(formatter); } -fn String PrivatePriorityQueue.to_new_string(&self, Allocator* allocator = mem::heap()) @dynamic +fn String PrivatePriorityQueue.to_new_string(&self, Allocator* allocator = allocator::heap()) @dynamic { return self.heap.to_new_string(allocator); } diff --git a/lib/std/collections/range.c3 b/lib/std/collections/range.c3 index b6cc5680c..13d0db773 100644 --- a/lib/std/collections/range.c3 +++ b/lib/std/collections/range.c3 @@ -28,14 +28,14 @@ fn Type Range.get(&self, usz index) @operator([]) return (Type)(self.start + (usz)index); } -fn String Range.to_new_string(&self, Allocator* allocator = mem::heap()) @dynamic +fn String Range.to_new_string(&self, Allocator* allocator = allocator::heap()) @dynamic { return string::new_format("[%s..%s]", self.start, self.end, .allocator = allocator); } fn String Range.to_tstring(&self) { - return self.to_new_string(mem::temp()); + return self.to_new_string(allocator::temp()); } fn usz! Range.to_format(&self, Formatter* formatter) @dynamic @@ -65,14 +65,14 @@ fn usz! ExclusiveRange.to_format(&self, Formatter* formatter) @dynamic return formatter.printf("[%s..<%s]", self.start, self.end)!; } -fn String ExclusiveRange.to_new_string(&self, Allocator* allocator = mem::heap()) @dynamic +fn String ExclusiveRange.to_new_string(&self, Allocator* allocator = allocator::heap()) @dynamic { return string::new_format("[%s..<%s]", self.start, self.end, .allocator = allocator); } fn String ExclusiveRange.to_tstring(&self) { - return self.to_new_string(mem::temp()); + return self.to_new_string(allocator::temp()); } /** diff --git a/lib/std/core/allocators/dynamic_arena.c3 b/lib/std/core/allocators/dynamic_arena.c3 index eb3aba50a..6eda0c860 100644 --- a/lib/std/core/allocators/dynamic_arena.c3 +++ b/lib/std/core/allocators/dynamic_arena.c3 @@ -29,14 +29,14 @@ fn void DynamicArenaAllocator.free(&self) while (page) { DynamicArenaPage* next_page = page.prev_arena; - self.backing_allocator.free(page); + allocator::free(self.backing_allocator, page); page = next_page; } page = self.unused_page; while (page) { DynamicArenaPage* next_page = page.prev_arena; - self.backing_allocator.free(page); + allocator::free(self.backing_allocator, page); page = next_page; } self.page = null; @@ -140,11 +140,11 @@ fn void*! DynamicArenaAllocator._alloc_new(&self, usz size, usz alignment, usz o usz page_size = max(self.page_size, mem::aligned_offset(size + DynamicArenaChunk.sizeof + offset, alignment) - offset); // Grab the page without alignment (we do it ourselves) - void* mem = self.backing_allocator.alloc_checked(page_size)!; - DynamicArenaPage*! page = self.backing_allocator.new(DynamicArenaPage); + void* mem = allocator::malloc_try(self.backing_allocator, page_size)!; + DynamicArenaPage*! page = allocator::new_try(self.backing_allocator, DynamicArenaPage); if (catch err = page) { - self.backing_allocator.free(mem); + allocator::free(self.backing_allocator, mem); return err?; } page.memory = mem; diff --git a/lib/std/core/allocators/on_stack_allocator.c3 b/lib/std/core/allocators/on_stack_allocator.c3 index 6434a32d2..6d5b1610b 100644 --- a/lib/std/core/allocators/on_stack_allocator.c3 +++ b/lib/std/core/allocators/on_stack_allocator.c3 @@ -34,15 +34,15 @@ fn void OnStackAllocator.free(&self) { if (chunk.is_aligned) { - self.backing_allocator.free_aligned(chunk.data); + allocator::free_aligned(self.backing_allocator, chunk.data); } else { - self.backing_allocator.free(chunk.data); + allocator::free(self.backing_allocator, chunk.data); } void* old = chunk; chunk = chunk.prev; - self.backing_allocator.free(old); + allocator::free(self.backing_allocator, old); } self.chunk = null; self.used = 0; @@ -76,7 +76,7 @@ fn void on_stack_allocator_remove_chunk(OnStackAllocator* a, void* ptr) @local if (chunk.data == ptr) { *addr = chunk.prev; - a.backing_allocator.free(chunk); + allocator::free(a.backing_allocator, chunk); return; } addr = &chunk.prev; @@ -140,8 +140,8 @@ fn void*! OnStackAllocator.acquire(&self, usz size, bool clear, usz alignment, u if (end > total_len) { - OnStackAllocatorExtraChunk* chunk = backing_allocator.alloc_checked(OnStackAllocatorExtraChunk.sizeof)!; - defer catch backing_allocator.free(chunk); + OnStackAllocatorExtraChunk* chunk = allocator::alloc_try(backing_allocator, OnStackAllocatorExtraChunk)!; + defer catch allocator::free(backing_allocator, chunk); defer try self.chunk = chunk; *chunk = { .prev = self.chunk, .is_aligned = aligned }; return chunk.data = backing_allocator.acquire(size, clear, aligned ? alignment : 0, offset)!; diff --git a/lib/std/core/allocators/temp_allocator.c3 b/lib/std/core/allocators/temp_allocator.c3 index d46927d7b..147a1cec3 100644 --- a/lib/std/core/allocators/temp_allocator.c3 +++ b/lib/std/core/allocators/temp_allocator.c3 @@ -35,9 +35,9 @@ macro bool TempAllocatorPage.is_aligned(&self) => self.size & PAGE_IS_ALIGNED == /** * @require size >= 16 **/ -fn TempAllocator*! new_temp(usz size, Allocator* allocator) +fn TempAllocator*! new_temp_allocator(usz size, Allocator* allocator) { - TempAllocator* temp = allocator.alloc_checked(TempAllocator.sizeof + size)!; + TempAllocator* temp = allocator::alloc_with_padding(allocator, TempAllocator, size)!; temp.last_page = null; temp.backing_allocator = allocator; temp.used = 0; @@ -45,6 +45,11 @@ fn TempAllocator*! new_temp(usz size, Allocator* allocator) return temp; } +fn TempAllocator*! new_temp(usz size, Allocator* allocator) @deprecated("Use new_temp_allocator") +{ + return new_temp_allocator(size, allocator); +} + fn usz TempAllocator.mark(&self) @dynamic => self.used; fn void TempAllocator.release(&self, void* old_pointer, bool) @dynamic @@ -71,8 +76,7 @@ fn void TempAllocator.reset(&self, usz mark) @dynamic fn void! TempAllocator._free_page(&self, TempAllocatorPage* page) @inline @local { void* mem = page.start; - if (page.is_aligned()) return self.backing_allocator.free_aligned(mem); - return self.backing_allocator.free(mem); + return self.backing_allocator.release(mem, page.is_aligned()); } fn void*! TempAllocator._realloc_page(&self, TempAllocatorPage* page, usz size, usz alignment, usz offset) @inline @local @@ -92,14 +96,7 @@ fn void*! TempAllocator._realloc_page(&self, TempAllocatorPage* page, usz size, // Clear on size > original size. void* data = self.acquire(size, size > page_size, alignment, offset)!; mem::copy(data, &page.data[0], page_size, mem::DEFAULT_MEM_ALIGNMENT, mem::DEFAULT_MEM_ALIGNMENT); - if (page.is_aligned()) - { - self.backing_allocator.free_aligned(real_pointer); - } - else - { - self.backing_allocator.free(real_pointer); - } + self.backing_allocator.release(real_pointer, page.is_aligned()); return data; } @@ -168,11 +165,11 @@ fn void*! TempAllocator.acquire(&self, usz size, bool clear, usz alignment, usz usz total_alloc_size = TempAllocatorPage.sizeof + size; if (clear) { - page = self.backing_allocator.calloc_aligned(total_alloc_size, alignment, TempAllocatorPage.sizeof + offset)!; + page = allocator::calloc_aligned(self.backing_allocator, total_alloc_size, alignment, TempAllocatorPage.sizeof + offset)!; } else { - page = self.backing_allocator.alloc_aligned(total_alloc_size, alignment, TempAllocatorPage.sizeof + offset)!; + page = allocator::malloc_aligned(self.backing_allocator, total_alloc_size, alignment, TempAllocatorPage.sizeof + offset)!; } page.start = page; page.size = size | PAGE_IS_ALIGNED; diff --git a/lib/std/core/allocators/tracking_allocator.c3 b/lib/std/core/allocators/tracking_allocator.c3 index c2dab3411..28f4dd9ce 100644 --- a/lib/std/core/allocators/tracking_allocator.c3 +++ b/lib/std/core/allocators/tracking_allocator.c3 @@ -168,7 +168,7 @@ fn void! TrackingAllocator.fprint_report(&self, OutStream* out) Backtrace trace = backtrace::BACKTRACE_UNKNOWN; if (allocation.backtrace[3]) { - trace = backtrace::symbolize_backtrace(allocation.backtrace[3:1], mem::temp()).get(0) ?? backtrace::BACKTRACE_UNKNOWN; + trace = backtrace::symbolize_backtrace(allocation.backtrace[3:1], allocator::temp()).get(0) ?? backtrace::BACKTRACE_UNKNOWN; } if (trace.function.len) leaks = true; io::fprintfn(out, "%13s %p %s:%d", allocation.size, @@ -207,7 +207,7 @@ fn void! TrackingAllocator.fprint_report(&self, OutStream* out) break; } } - BacktraceList list = backtrace::symbolize_backtrace(allocation.backtrace[3..(end - 1)], mem::temp())!; + BacktraceList list = backtrace::symbolize_backtrace(allocation.backtrace[3..(end - 1)], allocator::temp())!; io::fprintfn(out, "Allocation %d (%d bytes): ", i + 1, allocation.size)!; foreach (trace : list) { diff --git a/lib/std/core/array.c3 b/lib/std/core/array.c3 index 6f1021e5b..60151d169 100644 --- a/lib/std/core/array.c3 +++ b/lib/std/core/array.c3 @@ -55,10 +55,10 @@ macro rindex_of(array, element) * @require @typeis(arr1[0], $typeof(arr2[0])) "Arrays must have the same type" * @ensure result.len == arr1.len + arr2.len **/ -macro concat_new(arr1, arr2, Allocator* allocator = mem::heap()) +macro concat_new(arr1, arr2, Allocator* allocator = allocator::heap()) { var $Type = $typeof(arr1[0]); - $Type[] result = allocator.new_array($Type, arr1.len + arr2.len); + $Type[] result = allocator::alloc_array(allocator, $Type, arr1.len + arr2.len); if (arr1.len > 0) { mem::copy(result.ptr, &arr1[0], arr1.len * $Type.sizeof, $Type.alignof, $Type.alignof); @@ -81,7 +81,7 @@ macro concat_new(arr1, arr2, Allocator* allocator = mem::heap()) * @require @typeis(arr1[0], $typeof(arr2[0])) "Arrays must have the same type" * @ensure result.len == arr1.len + arr2.len **/ -macro tconcat(arr1, arr2) => concat(arr1, arr2, mem::temp()); +macro tconcat(arr1, arr2) => concat(arr1, arr2, allocator::temp()); module std::core::array::slice(); diff --git a/lib/std/core/builtin.c3 b/lib/std/core/builtin.c3 index 95c6e346c..713f23649 100644 --- a/lib/std/core/builtin.c3 +++ b/lib/std/core/builtin.c3 @@ -75,7 +75,7 @@ fn bool print_backtrace(String message, int backtraces_to_ignore) @if(env::NATIV void*[256] buffer; void*[] backtraces = backtrace::capture_current(&buffer); backtraces_to_ignore++; - BacktraceList! backtrace = backtrace::symbolize_backtrace(backtraces, mem::temp()); + BacktraceList! backtrace = backtrace::symbolize_backtrace(backtraces, allocator::temp()); if (catch backtrace) return false; if (backtrace.len() <= backtraces_to_ignore) return false; io::eprint("\nERROR: '"); diff --git a/lib/std/core/dstring.c3 b/lib/std/core/dstring.c3 index 757f27d21..c4a1d289f 100644 --- a/lib/std/core/dstring.c3 +++ b/lib/std/core/dstring.c3 @@ -8,10 +8,10 @@ const usz MIN_CAPACITY @private = 16; /** * @require !self.data() "String already initialized" **/ -fn DString DString.new_init(&self, usz capacity = MIN_CAPACITY, Allocator* allocator = mem::heap()) +fn DString DString.new_init(&self, usz capacity = MIN_CAPACITY, Allocator* allocator = allocator::heap()) { if (capacity < MIN_CAPACITY) capacity = MIN_CAPACITY; - StringData* data = allocator.new(StringData, .end_padding = capacity); + StringData* data = allocator::alloc_with_padding(allocator, StringData, capacity)!!; data.allocator = allocator; data.len = 0; data.capacity = capacity; @@ -21,7 +21,7 @@ fn DString DString.new_init(&self, usz capacity = MIN_CAPACITY, Allocator* alloc /** * @require !self.data() "String already initialized" **/ -fn DString DString.init_new(&self, usz capacity = MIN_CAPACITY, Allocator* allocator = mem::heap()) @deprecated("Replaced by new_init") +fn DString DString.init_new(&self, usz capacity = MIN_CAPACITY, Allocator* allocator = allocator::heap()) @deprecated("Replaced by new_init") { return self.new_init(capacity, allocator) @inline; } @@ -31,7 +31,7 @@ fn DString DString.init_new(&self, usz capacity = MIN_CAPACITY, Allocator* alloc **/ fn DString DString.temp_init(&self, usz capacity = MIN_CAPACITY) { - self.new_init(capacity, mem::temp()) @inline; + self.new_init(capacity, allocator::temp()) @inline; return *self; } @@ -43,14 +43,14 @@ fn DString DString.init_temp(&self, usz capacity = MIN_CAPACITY) @deprecated("Re return self.temp_init(capacity) @inline; } -fn DString new_with_capacity(usz capacity, Allocator* allocator = mem::heap()) +fn DString new_with_capacity(usz capacity, Allocator* allocator = allocator::heap()) { return DString{}.new_init(capacity, allocator); } -fn DString temp_with_capacity(usz capacity) => new_with_capacity(capacity, mem::temp()) @inline; +fn DString temp_with_capacity(usz capacity) => new_with_capacity(capacity, allocator::temp()) @inline; -fn DString new(String c = "", Allocator* allocator = mem::heap()) +fn DString new(String c = "", Allocator* allocator = allocator::heap()) { usz len = c.len; StringData* data = (StringData*)new_with_capacity(len, allocator); @@ -62,9 +62,9 @@ fn DString new(String c = "", Allocator* allocator = mem::heap()) return (DString)data; } -fn DString temp_new(String s = "") => new(s, mem::temp()) @inline; +fn DString temp_new(String s = "") => new(s, allocator::temp()) @inline; -fn DString DString.new_concat(self, DString b, Allocator* allocator = mem::heap()) +fn DString DString.new_concat(self, DString b, Allocator* allocator = allocator::heap()) { DString string; string.new_init(self.len() + b.len(), allocator); @@ -73,9 +73,9 @@ fn DString DString.new_concat(self, DString b, Allocator* allocator = mem::heap( return string; } -fn DString DString.temp_concat(self, DString b) => self.new_concat(b, mem::temp()); +fn DString DString.temp_concat(self, DString b) => self.new_concat(b, allocator::temp()); -fn DString DString.new_tconcat(self, DString b) @deprecated("Replaced by temp_concat") => self.new_concat(b, mem::temp()); +fn DString DString.new_tconcat(self, DString b) @deprecated("Replaced by temp_concat") => self.new_concat(b, allocator::temp()); fn ZString DString.zstr_view(&self) { @@ -164,7 +164,7 @@ fn void DString.append_char32(&self, Char32 c) data.len += n; } -fn DString DString.tcopy(&self) => self.copy(mem::temp()); +fn DString DString.tcopy(&self) => self.copy(allocator::temp()); fn DString DString.copy(self, Allocator* allocator = null) { @@ -174,32 +174,32 @@ fn DString DString.copy(self, Allocator* allocator = null) return (DString)null; } StringData* data = self.data(); - if (!allocator) allocator = mem::heap(); + if (!allocator) allocator = allocator::heap(); DString new_string = new_with_capacity(data.capacity, allocator); mem::copy((char*)new_string.data(), (char*)data, StringData.sizeof + data.len); return new_string; } -fn ZString DString.copy_zstr(self, Allocator* allocator = mem::heap()) +fn ZString DString.copy_zstr(self, Allocator* allocator = allocator::heap()) { usz str_len = self.len(); if (!str_len) { - return (ZString)allocator.calloc(1); + return (ZString)allocator::calloc(allocator, 1); } - char* zstr = allocator.alloc(str_len + 1); + char* zstr = allocator::malloc(allocator, str_len + 1); StringData* data = self.data(); mem::copy(zstr, &data.chars, str_len); zstr[str_len] = 0; return (ZString)zstr; } -fn String DString.copy_str(self, Allocator* allocator = mem::heap()) +fn String DString.copy_str(self, Allocator* allocator = allocator::heap()) { return (String)self.copy_zstr(allocator)[:self.len()]; } -fn String DString.tcopy_str(self) => self.copy_str(mem::temp()) @inline; +fn String DString.tcopy_str(self) => self.copy_str(allocator::temp()) @inline; fn bool DString.equals(self, DString other_string) { @@ -222,7 +222,7 @@ fn void DString.free(&self) if (!*self) return; StringData* data = self.data(); if (!data) return; - data.allocator.free(data); + allocator::free(data.allocator, data); *self = (DString)null; } @@ -258,7 +258,7 @@ fn void DString.append_chars(&self, String str) data.len += other_len; } -fn Char32[] DString.copy_utf32(&self, Allocator* allocator = mem::heap()) +fn Char32[] DString.copy_utf32(&self, Allocator* allocator = allocator::heap()) { return self.str_view().to_new_utf32(allocator) @inline!!; } @@ -403,7 +403,7 @@ fn usz! DString.appendfn(&self, String format, args...) @maydiscard return len + 1; } -fn DString new_join(String[] s, String joiner, Allocator* allocator = mem::heap()) +fn DString new_join(String[] s, String joiner, Allocator* allocator = allocator::heap()) { if (!s.len) return (DString)null; usz total_size = joiner.len * s.len; @@ -447,7 +447,7 @@ fn void DString.reserve(&self, usz addition) if (new_capacity < MIN_CAPACITY) new_capacity = MIN_CAPACITY; while (new_capacity < len) new_capacity *= 2; data.capacity = new_capacity; - *self = (DString)data.allocator.realloc(data, StringData.sizeof + new_capacity); + *self = (DString)allocator::realloc(data.allocator, data, StringData.sizeof + new_capacity); } fn usz! DString.read_from_stream(&self, InStream* reader) diff --git a/lib/std/core/mem.c3 b/lib/std/core/mem.c3 index 3055a7f7a..0118a28f4 100644 --- a/lib/std/core/mem.c3 +++ b/lib/std/core/mem.c3 @@ -2,6 +2,7 @@ // 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::core::mem; +import std::core::mem::allocator @public; const MAX_MEMORY_ALIGNMENT = 0x1000_0000; const DEFAULT_MEM_ALIGNMENT = (void*.alignof) * 2; @@ -379,9 +380,9 @@ macro type_alloc_must_be_aligned($Type) **/ macro void @scoped(Allocator* allocator; @body()) { - Allocator* old_allocator = thread_allocator; - thread_allocator = allocator; - defer thread_allocator = old_allocator; + Allocator* old_allocator = allocator::thread_allocator; + allocator::thread_allocator = allocator; + defer allocator::thread_allocator = old_allocator; @body(); } @@ -389,11 +390,11 @@ macro void @report_heap_allocs_in_scope(;@body()) { TrackingAllocator tracker; tracker.init(thread_allocator); - Allocator* old_allocator = thread_allocator; - thread_allocator = &tracker; + Allocator* old_allocator = allocator::thread_allocator; + allocator::thread_allocator = &tracker; defer { - thread_allocator = old_allocator; + allocator::thread_allocator = old_allocator; tracker.print_report(); tracker.free(); } @@ -404,7 +405,7 @@ macro void @stack_mem(usz $size; @body(Allocator* mem)) @builtin { char[$size] buffer; OnStackAllocator allocator; - allocator.init(&buffer, mem::heap()); + allocator.init(&buffer, allocator::heap()); defer allocator.free(); @body(&allocator); } @@ -413,7 +414,7 @@ macro void @stack_pool(usz $size; @body) @builtin { char[$size] buffer; OnStackAllocator allocator; - allocator.init(&buffer, mem::heap()); + allocator.init(&buffer, allocator::heap()); defer allocator.free(); mem::@scoped(&allocator) { @@ -423,74 +424,33 @@ macro void @stack_pool(usz $size; @body) @builtin macro void @pool(TempAllocator* #other_temp = null; @body) @builtin { - TempAllocator* current = temp(); + TempAllocator* current = allocator::temp(); var $has_arg = !$is_const(#other_temp); $if $has_arg: TempAllocator* original = current; - if (current == (void*)#other_temp) current = temp_allocator_next(); + if (current == (void*)#other_temp) current = allocator::temp_allocator_next(); $endif usz mark = current.used; defer { current.reset(mark); $if $has_arg: - thread_temp_allocator = original; + allocator::thread_temp_allocator = original; $endif; } @body(); } -tlocal Allocator* thread_allocator @private = &allocator::LIBC_ALLOCATOR; -tlocal TempAllocator* thread_temp_allocator @private = null; -tlocal TempAllocator*[2] temp_allocator_pair @private; -Allocator* temp_base_allocator @private = &allocator::LIBC_ALLOCATOR; -macro TempAllocator* create_default_sized_temp_allocator(Allocator* allocator) @local -{ - $switch (env::MEMORY_ENV) - $case NORMAL: - return allocator::new_temp(1024 * 256, allocator)!!; - $case SMALL: - return allocator::new_temp(1024 * 16, allocator)!!; - $case TINY: - return allocator::new_temp(1024 * 2, allocator)!!; - $case NONE: - unreachable("Temp allocator must explicitly created when memory-env is set to 'none'."); - $endswitch -} -fn TempAllocator *temp_allocator_next() @private -{ - if (!thread_temp_allocator) - { - init_default_temp_allocators(); - return thread_temp_allocator; - } - usz index = thread_temp_allocator == temp_allocator_pair[0] ? 1 : 0; - return thread_temp_allocator = temp_allocator_pair[index]; -} import libc; -fn void init_default_temp_allocators() @private -{ - temp_allocator_pair[0] = create_default_sized_temp_allocator(temp_base_allocator); - temp_allocator_pair[1] = create_default_sized_temp_allocator(temp_base_allocator); - thread_temp_allocator = temp_allocator_pair[0]; -} - -macro TempAllocator* temp() -{ - if (!thread_temp_allocator) - { - init_default_temp_allocators(); - } - return thread_temp_allocator; -} -macro Allocator* current_allocator() => thread_allocator; -macro Allocator* heap() => thread_allocator; +macro TempAllocator* temp() @deprecated("Use allocator::temp()") => allocator::temp(); +macro Allocator* current_allocator() @deprecated("Use allocator::heap()") => allocator::heap(); +macro Allocator* heap() @deprecated("Use allocator::heap()") => allocator::heap(); module std::core::mem @if(WASM_NOLIBC); @@ -520,88 +480,143 @@ macro TrackingEnv* get_tracking_env() $endif } -macro @clone(value) @builtin +macro @clone(value) @builtin @nodiscard +{ + return allocator::clone(allocator::heap(), value); +} + +macro @tclone(value) @builtin @nodiscard +{ + return temp_new($typeof(value), value); +} + +fn void* malloc(usz size) @builtin @inline @nodiscard +{ + return allocator::malloc(allocator::heap(), size); +} + +fn void* tmalloc(usz size, usz alignment = 0, usz offset = 0) @builtin @inline @nodiscard { - return mem::heap().clone(value); + return allocator::temp().acquire(size, false, alignment, offset)!!; } -macro @tclone(value) @builtin +/** + * @require $vacount < 2 : "Too many arguments." + * @require $or($vacount == 0, $assignable($vaexpr(0), $Type)) : "The second argument must be an initializer for the type" + **/ +macro new($Type, ...) @nodiscard { - return mem::temp().clone(value); + $if $vacount == 0: + return ($Type*)calloc($Type.sizeof); + $else + $Type* val = malloc($Type.sizeof); + *val = $vaexpr(0); + return val; + $endif } -fn void* malloc(usz size) @builtin @inline +macro alloc($Type) @nodiscard { - return mem::heap().alloc(size); + return ($Type*)malloc($Type.sizeof); } -fn void* tmalloc(usz size, usz alignment = 0, usz offset = 0) @builtin @inline +macro new_clear($Type) @deprecated("Use mem::new") { - return temp().acquire(size, false, alignment, offset)!!; + return new($Type); } -macro new($Type) +macro new_temp($Type) @deprecated("Use mem::temp_alloc or mem::temp_new") { - return heap().new($Type); + return tmalloc($Type.sizeof); } -macro new_clear($Type) +/** + * @require $vacount < 2 : "Too many arguments." + * @require $or($vacount == 0, $assignable($vaexpr(0), $Type)) : "The second argument must be an initializer for the type" + **/ +macro temp_new($Type, ...) @nodiscard { - return heap().new_clear($Type); + $if $vacount == 0: + return ($Type*)tcalloc($Type.sizeof) @inline; + $else + $Type* val = tmalloc($Type.sizeof) @inline; + *val = $vaexpr(0); + return val; + $endif } -macro new_temp($Type) +macro temp_alloc($Type) @nodiscard { return tmalloc($Type.sizeof); } -macro new_temp_clear($Type) +macro new_temp_clear($Type) @deprecated("use mem::temp_new") { return tcalloc($Type.sizeof); } -macro new_array($Type, usz elements) +macro new_array($Type, usz elements) @nodiscard +{ + return allocator::new_array(heap(), $Type, elements); +} + +macro alloc_array($Type, usz elements) @nodiscard +{ + return allocator::alloc_array(heap(), $Type, elements); +} + +macro talloc_array($Type, usz elements) @nodiscard @deprecated("use mem::temp_alloc_array") { - return heap().new_array($Type, elements); + return temp_alloc_array($Type, elements); } -macro temp_array($Type, usz elements) +macro temp_alloc_array($Type, usz elements) @nodiscard { return (($Type*)tmalloc($Type.sizeof * elements, $Type.alignof))[:elements]; } -macro new_zero_array($Type, usz elements) +macro temp_array($Type, usz elements) @nodiscard @deprecated("use mem::temp_alloc_array") { - return heap().new_zero_array($Type, elements); + return temp_alloc_array($Type, elements); } -macro temp_zero_array($Type, usz elements) +macro temp_new_array($Type, usz elements) @nodiscard { return (($Type*)tcalloc($Type.sizeof * elements, $Type.alignof))[:elements]; } -fn void* calloc(usz size) @builtin @inline +macro new_zero_array($Type, usz elements) @deprecated("Use new_array") +{ + return new_array($Type, elements); +} + +macro temp_zero_array($Type, usz elements) @deprecated("Use temp_new_array") +{ + return temp_new_array($Type, elements); +} + +fn void* calloc(usz size) @builtin @inline @nodiscard { - return heap().calloc(size); + return allocator::calloc(allocator::heap(), size); } -fn void* tcalloc(usz size, usz alignment = 0, usz offset = 0) @builtin @inline +fn void* tcalloc(usz size, usz alignment = 0, usz offset = 0) @builtin @inline @nodiscard { - return temp().acquire(size, false, alignment, offset)!!; + return allocator::temp().acquire(size, false, alignment, offset)!!; } -fn void* realloc(void *ptr, usz new_size) @builtin @inline +fn void* realloc(void *ptr, usz new_size) @builtin @inline @nodiscard { - return heap().realloc(ptr, new_size); + return allocator::realloc(allocator::heap(), ptr, new_size); } fn void free(void* ptr) @builtin @inline { - heap().free(ptr); + return allocator::free(allocator::heap(), ptr); } -fn void* trealloc(void* ptr, usz size, usz alignment = mem::DEFAULT_MEM_ALIGNMENT) @builtin @inline +fn void* trealloc(void* ptr, usz size, usz alignment = mem::DEFAULT_MEM_ALIGNMENT) @builtin @inline @nodiscard { - return temp().resize(ptr, size, alignment, 0)!!; + return allocator::temp().resize(ptr, size, alignment, 0)!!; } diff --git a/lib/std/core/mem_allocator.c3 b/lib/std/core/mem_allocator.c3 index ca40d2fdb..214d9bf70 100644 --- a/lib/std/core/mem_allocator.c3 +++ b/lib/std/core/mem_allocator.c3 @@ -20,94 +20,170 @@ interface Allocator fn void release(void* ptr, bool aligned); } -struct AlignedBlock +def MemoryAllocFn = fn char[]!(usz); + +fault AllocationFailure { - usz len; - void* start; + OUT_OF_MEMORY, + CHUNK_TOO_LARGE, } -/** - * @require bytes > 0 - * @require alignment > 0 - **/ -macro void*! @aligned_alloc(#alloc_fn, usz bytes, usz alignment, usz offset) +fn usz alignment_for_allocation(usz alignment) @inline @private { - usz header = mem::aligned_offset(AlignedBlock.sizeof + offset, alignment) - offset; - $if @typekind(#alloc_fn(bytes)) == OPTIONAL: - void* data = #alloc_fn(header + bytes)!; + return alignment < mem::DEFAULT_MEM_ALIGNMENT ? alignment = mem::DEFAULT_MEM_ALIGNMENT : alignment; +} + +macro void* malloc(Allocator* allocator, usz size) @nodiscard +{ + return malloc_try(allocator, size)!!; +} + +macro void*! malloc_try(Allocator* allocator, usz size) @nodiscard +{ + $if env::TESTING: + char* data = allocator.acquire(size, false, 0, 0)!; + mem::set(data, 0xAA, size, mem::DEFAULT_MEM_ALIGNMENT); + return data; $else - void* data = #alloc_fn(header + bytes); + return allocator.acquire(size, false, 0, 0); $endif - void* mem = mem::aligned_pointer(data + header + offset, alignment) - offset; - assert(mem > data); - AlignedBlock* desc = (AlignedBlock*)mem - 1; - *desc = { bytes, data }; - return mem; } -/** - * @require bytes > 0 - * @require alignment > 0 - **/ -macro void*! @aligned_calloc(#calloc_fn, usz bytes, usz alignment, usz offset) +macro void* calloc(Allocator* allocator, usz size) @nodiscard { - usz header = mem::aligned_offset(AlignedBlock.sizeof + offset, alignment) - offset; - $if @typekind(#calloc_fn(bytes)) == OPTIONAL: - void* data = #calloc_fn(header + bytes)!; + return calloc_try(allocator, size)!!; +} + +macro void*! calloc_try(Allocator* allocator, usz size) @nodiscard +{ + return allocator.acquire(size, true, 0, 0); +} + +macro void* realloc(Allocator* allocator, void* ptr, usz new_size) @nodiscard +{ + return realloc_try(allocator, ptr, new_size)!!; +} +macro void*! realloc_try(Allocator* allocator, void* ptr, usz new_size) @nodiscard +{ + return allocator.resize(ptr, new_size, 0, 0); +} + +macro void free(Allocator* allocator, void* ptr) +{ + $if env::TESTING: + if (ptr) ((char*)ptr)[0] = 0xBA; + $endif + allocator.release(ptr, false); +} + +macro void*! malloc_aligned(Allocator* allocator, usz size, usz alignment, usz offset = 0) @nodiscard +{ + $if env::TESTING: + char* data = allocator.acquire(size, false, alignment, offset)!; + mem::set(data, 0xAA, size, mem::DEFAULT_MEM_ALIGNMENT); + return data; $else - void* data = #calloc_fn(header + bytes); + return allocator.acquire(size, false, alignment, offset); $endif - void* mem = mem::aligned_pointer(data + header + offset, alignment) - offset; - AlignedBlock* desc = (AlignedBlock*)mem - 1; - assert(mem > data); - *desc = { bytes, data }; - return mem; +} + +macro void*! calloc_aligned(Allocator* allocator, usz size, usz alignment, usz offset = 0) @nodiscard +{ + return allocator.acquire(size, true, alignment, offset); +} + +macro void*! realloc_aligned(Allocator* allocator, void* ptr, usz new_size, usz alignment, usz offset = 0) @nodiscard +{ + return allocator.resize(ptr, new_size, alignment, offset); +} + +macro void free_aligned(Allocator* allocator, void* ptr) +{ + $if env::TESTING: + if (ptr) ((char*)ptr)[0] = 0xBA; + $endif + allocator.release(ptr, true); } /** - * @require bytes > 0 - * @require alignment > 0 + * @require $vacount < 2 : "Too many arguments." + * @require $or($vacount == 1, $assignable($vaexpr(0), $Type)) : "The second argument must be an initializer for the type" **/ -macro void*! @aligned_realloc(#calloc_fn, #free_fn, void* old_pointer, usz bytes, usz alignment, usz offset) +macro new(Allocator* allocator, $Type, ...) @nodiscard { - AlignedBlock* desc = (AlignedBlock*)old_pointer - 1; - void* data_start = desc.start; - void* new_data = @aligned_calloc(#calloc_fn, bytes, alignment, offset)!; - mem::copy(new_data, old_pointer, desc.len < bytes ? desc.len : bytes, mem::DEFAULT_MEM_ALIGNMENT, mem::DEFAULT_MEM_ALIGNMENT); - $if @typekind(#free_fn(data_start)) == OPTIONAL: - #free_fn(data_start)!; + $if $vacount == 0: + return ($Type*)calloc(allocator, $Type.sizeof); $else - #free_fn(data_start); + $Type* val = malloc(allocator, $Type.sizeof); + *val = $vaexpr(0); + return val; $endif - return new_data; } -macro void! @aligned_free(#free_fn, void* old_pointer) +/** + * @require $vacount < 2 : "Too many arguments." + * @require $or($vacount == 0, $assignable($vaexpr(0), $Type)) : "The second argument must be an initializer for the type" + **/ +macro new_try(Allocator* allocator, $Type, ...) @nodiscard { - AlignedBlock* desc = (AlignedBlock*)old_pointer - 1; - $if @typekind(#free_fn(desc.start)) == OPTIONAL: - #free_fn(desc.start)!; + $if $vacount == 0: + return ($Type*)calloc_try(allocator, $Type.sizeof); $else - #free_fn(desc.start); + $Type* val = malloc_try(allocator, $Type.sizeof)!; + *val = $vaexpr(0); + return val; $endif } -def MemoryAllocFn = fn char[]!(usz); +macro new_with_padding(Allocator* allocator, $Type, usz padding) @nodiscard +{ + return ($Type*)calloc_try(allocator, $Type.sizeof + padding); +} -fault AllocationFailure +macro alloc(Allocator* allocator, $Type) @nodiscard { - OUT_OF_MEMORY, - CHUNK_TOO_LARGE, + return ($Type*)malloc(allocator, $Type.sizeof); } -fn usz alignment_for_allocation(usz alignment) @inline @private +macro alloc_try(Allocator* allocator, $Type) @nodiscard { - return alignment < mem::DEFAULT_MEM_ALIGNMENT ? alignment = mem::DEFAULT_MEM_ALIGNMENT : alignment; + return ($Type*)malloc_try(allocator, $Type.sizeof); } +macro alloc_with_padding(Allocator* allocator, $Type, usz padding) @nodiscard +{ + return ($Type*)malloc_try(allocator, $Type.sizeof + padding); +} + +macro new_array(Allocator* allocator, $Type, usz elements) @nodiscard +{ + return new_array_try(allocator, $Type, elements)!!; +} + +macro new_array_try(Allocator* allocator, $Type, usz elements) @nodiscard +{ + return (($Type*)calloc_try(allocator, $Type.sizeof * elements))[:elements]; +} + +macro alloc_array(Allocator* allocator, $Type, usz elements) @nodiscard +{ + return alloc_array_try(allocator, $Type, elements)!!; +} + +macro alloc_array_try(Allocator* allocator, $Type, usz elements) @nodiscard +{ + return (($Type*)malloc_try(allocator, $Type.sizeof * elements))[:elements]; +} + +macro clone(Allocator* allocator, value) @nodiscard +{ + return new($typeof(value), value); +} + + // Allocator "functions" -macro void*! Allocator.alloc_checked(&self, usz size) +macro void*! Allocator.alloc_checked(&self, usz size) @deprecated("Use allocator::malloc_try") { $if env::TESTING: char* data = self.acquire(size, false, 0, 0)!; @@ -118,76 +194,76 @@ macro void*! Allocator.alloc_checked(&self, usz size) $endif } -macro void*! Allocator.calloc_checked(&self, usz size) +macro void*! Allocator.calloc_checked(&self, usz size) @deprecated("Use allocator::calloc_try") { return self.acquire(size, true, 0, 0); } -macro void*! Allocator.realloc_checked(&self, void* ptr, usz new_size) + +macro void*! Allocator.realloc_checked(&self, void* ptr, usz new_size) @deprecated("Use allocator::realloc_try") { return self.resize(ptr, new_size, 0, 0); } -macro Allocator.new_array(&self, $Type, usz size, usz end_padding = 0) +macro Allocator.new_array(&self, $Type, usz size, usz end_padding = 0) @deprecated("Use allocator::alloc_array") { return (($Type*)self.alloc_checked($Type.sizeof * size + end_padding))[:size]!!; } -macro Allocator.new_array_checked(&self, $Type, usz size, usz end_padding = 0) +macro Allocator.new_array_checked(&self, $Type, usz size, usz end_padding = 0) @deprecated("Use allocator::alloc_array_try") { return (($Type*)self.alloc_checked($Type.sizeof * size + end_padding))[:size]; } -macro Allocator.new_zero_array(&self, $Type, usz size, usz end_padding = 0) +macro Allocator.new_zero_array(&self, $Type, usz size, usz end_padding = 0) @deprecated("Use allocator::new_array") { return (($Type*)self.calloc_checked($Type.sizeof * size + end_padding))[:size]!!; } -macro Allocator.new_zero_array_checked(&self, $Type, usz size, usz end_padding = 0) +macro Allocator.new_zero_array_checked(&self, $Type, usz size, usz end_padding = 0) @deprecated("Use allocator::new_array_try") { return (($Type*)self.calloc_checked($Type.sizeof * size + end_padding))[:size]; } -macro Allocator.new(&self, $Type, usz end_padding = 0) @nodiscard +macro Allocator.new(&self, $Type, usz end_padding = 0) @nodiscard @deprecated("Use allocator::alloc") { return ($Type*)self.alloc_checked($Type.sizeof + end_padding)!!; } -macro Allocator.new_checked(&self, $Type, usz end_padding = 0) @nodiscard +macro Allocator.new_checked(&self, $Type, usz end_padding = 0) @nodiscard @deprecated("Use allocator::alloc_try") { return ($Type*)self.alloc_checked($Type.sizeof + end_padding); } -macro Allocator.new_clear(&self, $Type, usz end_padding = 0) @nodiscard +macro Allocator.new_clear(&self, $Type, usz end_padding = 0) @nodiscard @deprecated("Use allocator::new") { return ($Type*)self.calloc_checked($Type.sizeof + end_padding)!!; } -macro Allocator.new_clear_checked(&self, $Type, usz end_padding = 0) @nodiscard +macro Allocator.new_clear_checked(&self, $Type, usz end_padding = 0) @nodiscard @deprecated("Use allocator::new_try") { return ($Type*)self.calloc_checked($Type.sizeof + end_padding); } - -macro Allocator.clone(&self, value) +macro Allocator.clone(&self, value) @deprecated("Use allocator::clone") { var x = self.alloc($typeof(value)); *x = value; return x; } -macro void* Allocator.alloc(&self, usz size) @nodiscard +macro void* Allocator.alloc(&self, usz size) @nodiscard @deprecated("Use allocator::malloc") { return self.alloc_checked(size)!!; } -macro void* Allocator.calloc(&self, usz size) @nodiscard +macro void* Allocator.calloc(&self, usz size) @nodiscard @deprecated("Use allocator::calloc") { return self.acquire(size, true, 0, 0)!!; } -macro void* Allocator.realloc(&self, void* ptr, usz new_size) @nodiscard +macro void* Allocator.realloc(&self, void* ptr, usz new_size) @nodiscard @deprecated("Use allocator::realloc") { return self.resize(ptr, new_size, 0, 0)!!; } -macro void*! Allocator.alloc_aligned(&self, usz size, usz alignment, usz offset = 0) +macro void*! Allocator.alloc_aligned(&self, usz size, usz alignment, usz offset = 0) @deprecated("Use allocator::alloc_aligned") { $if env::TESTING: char* data = self.acquire(size, false, alignment, offset)!; @@ -197,23 +273,23 @@ macro void*! Allocator.alloc_aligned(&self, usz size, usz alignment, usz offset return self.acquire(size, false, alignment, offset); $endif } -macro void*! Allocator.calloc_aligned(&self, usz size, usz alignment, usz offset = 0) +macro void*! Allocator.calloc_aligned(&self, usz size, usz alignment, usz offset = 0) @deprecated("Use allocator::calloc_aligned") { return self.acquire(size, true, alignment, offset); } -macro void*! Allocator.realloc_aligned(&self, void* ptr, usz new_size, usz alignment = 0, usz offset = 0) +macro void*! Allocator.realloc_aligned(&self, void* ptr, usz new_size, usz alignment = 0, usz offset = 0) @deprecated("Use allocator::realloc_aligned") { return self.resize(ptr, new_size, alignment, offset); } -macro void Allocator.free(&self, void* ptr) +macro void Allocator.free(&self, void* ptr) @deprecated("Use allocator::free") { $if env::TESTING: if (ptr) ((char*)ptr)[0] = 0xBA; $endif self.release(ptr, false); } -macro void Allocator.free_aligned(&self, void* ptr) +macro void Allocator.free_aligned(&self, void* ptr) @deprecated("Use allocator::free_aligned") { $if env::TESTING: if (ptr) ((char*)ptr)[0] = 0xBA; @@ -222,3 +298,124 @@ macro void Allocator.free_aligned(&self, void* ptr) } +/** + * @require bytes > 0 + * @require alignment > 0 + **/ +macro void*! @aligned_alloc(#alloc_fn, usz bytes, usz alignment, usz offset) +{ + usz header = mem::aligned_offset(AlignedBlock.sizeof + offset, alignment) - offset; + $if @typekind(#alloc_fn(bytes)) == OPTIONAL: + void* data = #alloc_fn(header + bytes)!; + $else + void* data = #alloc_fn(header + bytes); + $endif + void* mem = mem::aligned_pointer(data + header + offset, alignment) - offset; + assert(mem > data); + AlignedBlock* desc = (AlignedBlock*)mem - 1; + *desc = { bytes, data }; + return mem; +} + +/** + * @require bytes > 0 + * @require alignment > 0 + **/ +macro void*! @aligned_calloc(#calloc_fn, usz bytes, usz alignment, usz offset) +{ + usz header = mem::aligned_offset(AlignedBlock.sizeof + offset, alignment) - offset; + $if @typekind(#calloc_fn(bytes)) == OPTIONAL: + void* data = #calloc_fn(header + bytes)!; + $else + void* data = #calloc_fn(header + bytes); + $endif + void* mem = mem::aligned_pointer(data + header + offset, alignment) - offset; + AlignedBlock* desc = (AlignedBlock*)mem - 1; + assert(mem > data); + *desc = { bytes, data }; + return mem; +} + +struct AlignedBlock +{ + usz len; + void* start; +} + +macro void! @aligned_free(#free_fn, void* old_pointer) +{ + AlignedBlock* desc = (AlignedBlock*)old_pointer - 1; + $if @typekind(#free_fn(desc.start)) == OPTIONAL: + #free_fn(desc.start)!; + $else + #free_fn(desc.start); + $endif +} + +/** + * @require bytes > 0 + * @require alignment > 0 + **/ +macro void*! @aligned_realloc(#calloc_fn, #free_fn, void* old_pointer, usz bytes, usz alignment, usz offset) +{ + AlignedBlock* desc = (AlignedBlock*)old_pointer - 1; + void* data_start = desc.start; + void* new_data = @aligned_calloc(#calloc_fn, bytes, alignment, offset)!; + mem::copy(new_data, old_pointer, desc.len < bytes ? desc.len : bytes, mem::DEFAULT_MEM_ALIGNMENT, mem::DEFAULT_MEM_ALIGNMENT); + $if @typekind(#free_fn(data_start)) == OPTIONAL: + #free_fn(data_start)!; + $else + #free_fn(data_start); + $endif + return new_data; +} + + +// All allocators +tlocal Allocator* thread_allocator @private = &allocator::LIBC_ALLOCATOR; +tlocal TempAllocator* thread_temp_allocator @private = null; +tlocal TempAllocator*[2] temp_allocator_pair @private; +Allocator* temp_base_allocator @private = &allocator::LIBC_ALLOCATOR; + +macro TempAllocator* create_default_sized_temp_allocator(Allocator* allocator) @local +{ + $switch (env::MEMORY_ENV) + $case NORMAL: + return new_temp_allocator(1024 * 256, allocator)!!; + $case SMALL: + return new_temp_allocator(1024 * 16, allocator)!!; + $case TINY: + return new_temp_allocator(1024 * 2, allocator)!!; + $case NONE: + unreachable("Temp allocator must explicitly created when memory-env is set to 'none'."); + $endswitch +} + +macro Allocator* heap() => thread_allocator; + +macro TempAllocator* temp() +{ + if (!thread_temp_allocator) + { + init_default_temp_allocators(); + } + return thread_temp_allocator; +} + +fn void init_default_temp_allocators() @private +{ + temp_allocator_pair[0] = create_default_sized_temp_allocator(temp_base_allocator); + temp_allocator_pair[1] = create_default_sized_temp_allocator(temp_base_allocator); + thread_temp_allocator = temp_allocator_pair[0]; +} + +fn TempAllocator *temp_allocator_next() @private +{ + if (!thread_temp_allocator) + { + init_default_temp_allocators(); + return thread_temp_allocator; + } + usz index = thread_temp_allocator == temp_allocator_pair[0] ? 1 : 0; + return thread_temp_allocator = temp_allocator_pair[index]; +} \ No newline at end of file diff --git a/lib/std/core/private/main_stub.c3 b/lib/std/core/private/main_stub.c3 index 8b6777d34..26c2befbc 100644 --- a/lib/std/core/private/main_stub.c3 +++ b/lib/std/core/private/main_stub.c3 @@ -21,7 +21,7 @@ macro int @main_to_void_main(#m, int, char**) macro String[] args_to_strings(int argc, char** argv) @private { - String[] list = mem::new_array(String, argc); + String[] list = mem::alloc_array(String, argc); for (int i = 0; i < argc; i++) { char* arg = argv[i]; @@ -68,7 +68,7 @@ macro String[] win_command_line_to_strings(ushort* cmd_line) @private macro String[] wargs_strings(int argc, Char16** argv) @private { - String[] list = mem::new_array(String, argc); + String[] list = mem::alloc_array(String, argc); for (int i = 0; i < argc; i++) { Char16* arg = argv[i]; diff --git a/lib/std/core/runtime.c3 b/lib/std/core/runtime.c3 index f45836bf0..1ce8d64bb 100644 --- a/lib/std/core/runtime.c3 +++ b/lib/std/core/runtime.c3 @@ -24,11 +24,11 @@ struct BenchmarkUnit BenchmarkFn func; } -fn BenchmarkUnit[] benchmark_collection_create(Allocator* allocator = mem::heap()) +fn BenchmarkUnit[] benchmark_collection_create(Allocator* allocator = allocator::heap()) { BenchmarkFn[] fns = $$BENCHMARK_FNS; String[] names = $$BENCHMARK_NAMES; - BenchmarkUnit[] benchmarks = allocator.new_array(BenchmarkUnit, names.len); + BenchmarkUnit[] benchmarks = allocator::alloc_array(allocator, BenchmarkUnit, names.len); foreach (i, benchmark : fns) { benchmarks[i] = { names[i], fns[i] }; @@ -130,7 +130,7 @@ fn bool default_benchmark_runner() { @pool() { - return run_benchmarks(benchmark_collection_create(mem::temp())); + return run_benchmarks(benchmark_collection_create(allocator::temp())); }; } @@ -142,11 +142,11 @@ struct TestUnit TestFn func; } -fn TestUnit[] test_collection_create(Allocator* allocator = mem::heap()) +fn TestUnit[] test_collection_create(Allocator* allocator = allocator::heap()) { TestFn[] fns = $$TEST_FNS; String[] names = $$TEST_NAMES; - TestUnit[] tests = allocator.new_array(TestUnit, names.len); + TestUnit[] tests = allocator::alloc_array(allocator, TestUnit, names.len); foreach (i, test : fns) { tests[i] = { names[i], fns[i] }; @@ -236,7 +236,7 @@ fn bool default_test_runner() { @pool() { - return run_tests(test_collection_create(mem::temp())); + return run_tests(test_collection_create(allocator::temp())); }; } diff --git a/lib/std/core/string.c3 b/lib/std/core/string.c3 index 2525b1013..54e553e6f 100644 --- a/lib/std/core/string.c3 +++ b/lib/std/core/string.c3 @@ -38,7 +38,7 @@ macro String tformat(String fmt, ...) return str.str_view(); } -macro String new_format(String fmt, ..., Allocator* allocator = mem::heap()) +macro String new_format(String fmt, ..., Allocator* allocator = allocator::heap()) { @pool(allocator) { @@ -55,11 +55,11 @@ macro bool char_in_set(char c, String set) return false; } -fn String join_new(String[] s, String joiner, Allocator* allocator = mem::heap()) +fn String join_new(String[] s, String joiner, Allocator* allocator = allocator::heap()) { if (!s) { - return (String)allocator.new_zero_array(char, 2)[:0]; + return (String)allocator::new_array(allocator, char, 2)[:0]; } usz total_size = joiner.len * s.len; @@ -153,11 +153,11 @@ fn String String.strip_end(string, String needle) * @require needle.len > 0 "The needle must be at least 1 character long" * @ensure return.len > 0 **/ -fn String[] String.split(s, String needle, usz max = 0, Allocator* allocator = mem::heap()) +fn String[] String.split(s, String needle, usz max = 0, Allocator* allocator = allocator::heap()) { usz capacity = 16; usz i = 0; - String* holder = allocator.new_array(String, capacity); + String* holder = allocator::alloc_array(allocator, String, capacity); bool no_more = false; while (!no_more) { @@ -176,7 +176,7 @@ fn String[] String.split(s, String needle, usz max = 0, Allocator* allocator = m if (i == capacity) { capacity *= 2; - holder = allocator.realloc(holder, String.sizeof * capacity); + holder = allocator::realloc(allocator, holder, String.sizeof * capacity); } holder[i++] = res; } @@ -193,7 +193,7 @@ fn String[] String.split(s, String needle, usz max = 0, Allocator* allocator = m **/ fn String[] String.tsplit(s, String needle, usz max = 0) { - return s.split(needle, max, mem::temp()) @inline; + return s.split(needle, max, allocator::temp()) @inline; } fn bool String.contains(s, String needle) @@ -312,19 +312,19 @@ fn usz ZString.len(str) } -fn ZString String.zstr_copy(s, Allocator* allocator = mem::heap()) +fn ZString String.zstr_copy(s, Allocator* allocator = allocator::heap()) { usz len = s.len; - char* str = allocator.alloc(len + 1); + char* str = allocator::malloc(allocator, len + 1); mem::copy(str, s.ptr, len); str[len] = 0; return (ZString)str; } -fn String String.concat(s1, String s2, Allocator* allocator = mem::heap()) +fn String String.concat(s1, String s2, Allocator* allocator = allocator::heap()) { usz full_len = s1.len + s2.len; - char* str = allocator.alloc(full_len + 1); + char* str = allocator::malloc(allocator, full_len + 1); usz s1_len = s1.len; mem::copy(str, s1.ptr, s1_len); mem::copy(str + s1_len, s2.ptr, s2.len); @@ -332,37 +332,37 @@ fn String String.concat(s1, String s2, Allocator* allocator = mem::heap()) return (String)str[:full_len]; } -fn String String.tconcat(s1, String s2) => s1.concat(s2, mem::temp()); +fn String String.tconcat(s1, String s2) => s1.concat(s2, allocator::temp()); -fn ZString String.zstr_tcopy(s) => s.zstr_copy(mem::temp()) @inline; +fn ZString String.zstr_tcopy(s) => s.zstr_copy(allocator::temp()) @inline; -fn String String.copy(s, Allocator* allocator = mem::heap()) +fn String String.copy(s, Allocator* allocator = allocator::heap()) { usz len = s.len; - char* str = allocator.alloc(len + 1); + char* str = allocator::malloc(allocator, len + 1); mem::copy(str, s.ptr, len); str[len] = 0; return (String)str[:len]; } -fn void String.free(&s, Allocator* allocator = mem::heap()) +fn void String.free(&s, Allocator* allocator = allocator::heap()) { if (!s.len) return; - allocator.free(s.ptr); + allocator::free(allocator, s.ptr); *s = ""; } -fn String String.tcopy(s) => s.copy(mem::temp()) @inline; +fn String String.tcopy(s) => s.copy(allocator::temp()) @inline; -fn String ZString.copy(z, Allocator* allocator = mem::temp()) +fn String ZString.copy(z, Allocator* allocator = allocator::temp()) { return z.str_view().copy(allocator) @inline; } fn String ZString.tcopy(z) { - return z.str_view().copy(mem::temp()) @inline; + return z.str_view().copy(allocator::temp()) @inline; } /** @@ -371,10 +371,10 @@ fn String ZString.tcopy(z) * @return! UnicodeResult.INVALID_UTF8 "If the string contained an invalid UTF-8 sequence" * @return! AllocationFailure "If allocation of the string fails" **/ -fn Char16[]! String.to_new_utf16(s, Allocator* allocator = mem::heap()) +fn Char16[]! String.to_new_utf16(s, Allocator* allocator = allocator::heap()) { usz len16 = conv::utf16len_for_utf8(s); - Char16* data = allocator.new_array_checked(Char16, len16 + 1)!; + Char16* data = allocator::alloc_array_try(allocator, Char16, len16 + 1)!; conv::utf8to16_unsafe(s, data)!; data[len16] = 0; return data[:len16]; @@ -388,10 +388,10 @@ fn Char16[]! String.to_new_utf16(s, Allocator* allocator = mem::heap()) **/ fn Char16[]! String.to_temp_utf16(s) { - return s.to_new_utf16(mem::temp()); + return s.to_new_utf16(allocator::temp()); } -fn WString! String.to_new_wstring(s, Allocator* allocator = mem::heap()) +fn WString! String.to_new_wstring(s, Allocator* allocator = allocator::heap()) { return (WString)s.to_new_utf16(allocator).ptr; } @@ -401,10 +401,10 @@ fn WString! String.to_temp_wstring(s) return (WString)s.to_temp_utf16().ptr; } -fn Char32[]! String.to_new_utf32(s, Allocator* allocator = mem::heap()) +fn Char32[]! String.to_new_utf32(s, Allocator* allocator = allocator::heap()) { usz codepoints = conv::utf8_codepoints(s); - Char32* data = allocator.new_array(Char32, codepoints + 1); + Char32* data = allocator::alloc_array_try(allocator, Char32, codepoints + 1)!; conv::utf8to32_unsafe(s, data)!; data[codepoints] = 0; return data[:codepoints]; @@ -412,7 +412,7 @@ fn Char32[]! String.to_new_utf32(s, Allocator* allocator = mem::heap()) fn Char32[]! String.to_temp_utf32(s) { - return s.to_new_utf32(mem::temp()); + return s.to_new_utf32(allocator::temp()); } fn void String.convert_ascii_to_lower(s) @@ -420,16 +420,16 @@ fn void String.convert_ascii_to_lower(s) foreach (&c : s) if (c.is_upper()) *c += 'a' - 'A'; } -fn String String.new_ascii_to_lower(s, Allocator* allocator = mem::heap()) +fn String String.new_ascii_to_lower(s, Allocator* allocator = allocator::heap()) { String copy = s.copy(allocator); copy.convert_ascii_to_lower(); return copy; } -fn String String.temp_ascii_to_lower(s, Allocator* allocator = mem::heap()) +fn String String.temp_ascii_to_lower(s, Allocator* allocator = allocator::heap()) { - return s.new_ascii_to_lower(mem::temp()); + return s.new_ascii_to_lower(allocator::temp()); } fn void String.convert_ascii_to_upper(s) @@ -437,7 +437,7 @@ fn void String.convert_ascii_to_upper(s) foreach (&c : s) if (c.is_lower()) *c -= 'a' - 'A'; } -fn String String.new_ascii_to_upper(s, Allocator* allocator = mem::heap()) +fn String String.new_ascii_to_upper(s, Allocator* allocator = allocator::heap()) { String copy = s.copy(allocator); copy.convert_ascii_to_upper(); @@ -451,30 +451,30 @@ fn StringIterator String.iterator(s) fn String String.temp_ascii_to_upper(s) { - return s.new_ascii_to_upper(mem::temp()); + return s.new_ascii_to_upper(allocator::temp()); } -fn String! new_from_utf32(Char32[] utf32, Allocator* allocator = mem::heap()) +fn String! new_from_utf32(Char32[] utf32, Allocator* allocator = allocator::heap()) { usz len = conv::utf8len_for_utf32(utf32); - char* data = allocator.alloc_checked(len + 1)!; - defer catch allocator.free(data); + char* data = allocator::malloc_try(allocator, len + 1)!; + defer catch allocator::free(allocator, data); conv::utf32to8_unsafe(utf32, data); data[len] = 0; return (String)data[:len]; } -fn String! new_from_utf16(Char16[] utf16, Allocator* allocator = mem::heap()) +fn String! new_from_utf16(Char16[] utf16, Allocator* allocator = allocator::heap()) { usz len = conv::utf8len_for_utf16(utf16); - char* data = allocator.alloc_checked(len + 1)!; - defer catch allocator.free(data); + char* data = allocator::malloc_try(allocator, len + 1)!; + defer catch allocator::free(allocator, data); conv::utf16to8_unsafe(utf16, data)!; data[len] = 0; return (String)data[:len]; } -fn String! new_from_wstring(WString wstring, Allocator* allocator = mem::heap()) +fn String! new_from_wstring(WString wstring, Allocator* allocator = allocator::heap()) { usz utf16_len; while (wstring[utf16_len] != 0) utf16_len++; @@ -482,8 +482,8 @@ fn String! new_from_wstring(WString wstring, Allocator* allocator = mem::heap()) return new_from_utf16(utf16, allocator); } -fn String! temp_from_wstring(WString wstring) => new_from_wstring(wstring, mem::temp()) @inline; -fn String! temp_from_utf16(Char16[] utf16) => new_from_utf16(utf16, mem::temp()) @inline; +fn String! temp_from_wstring(WString wstring) => new_from_wstring(wstring, allocator::temp()) @inline; +fn String! temp_from_utf16(Char16[] utf16) => new_from_utf16(utf16, allocator::temp()) @inline; fn usz String.utf8_codepoints(s) { diff --git a/lib/std/encoding/csv.c3 b/lib/std/encoding/csv.c3 index e92585be5..7fc4cd1d3 100644 --- a/lib/std/encoding/csv.c3 +++ b/lib/std/encoding/csv.c3 @@ -13,12 +13,12 @@ fn void CsvReader.init(&self, InStream* stream, String separator = ",") self.separator = separator; } -fn String[]! CsvReader.read_new_row(self, Allocator* allocator = mem::heap()) +fn String[]! CsvReader.read_new_row(self, Allocator* allocator = allocator::heap()) { - return self.read_new_row_with_allocator(mem::temp()) @inline; + return self.read_new_row_with_allocator(allocator::temp()) @inline; } -fn String[]! CsvReader.read_new_row_with_allocator(self, Allocator* allocator = mem::heap()) +fn String[]! CsvReader.read_new_row_with_allocator(self, Allocator* allocator = allocator::heap()) { @pool(allocator) { @@ -28,7 +28,7 @@ fn String[]! CsvReader.read_new_row_with_allocator(self, Allocator* allocator = fn String[]! CsvReader.read_temp_row(self) { - return self.read_new_row_with_allocator(mem::temp()) @inline; + return self.read_new_row_with_allocator(allocator::temp()) @inline; } fn void! CsvReader.skip_row(self) @maydiscard diff --git a/lib/std/encoding/json.c3 b/lib/std/encoding/json.c3 index 7a2e3e03d..2c295e452 100644 --- a/lib/std/encoding/json.c3 +++ b/lib/std/encoding/json.c3 @@ -15,7 +15,7 @@ fault JsonParsingError INVALID_NUMBER, } -fn Object*! parse(InStream* s, Allocator* allocator = mem::heap()) +fn Object*! parse(InStream* s, Allocator* allocator = allocator::heap()) { JsonContext context = { .last_string = dstring::new_with_capacity(64, allocator), .stream = s, .allocator = allocator }; defer context.last_string.free(); diff --git a/lib/std/io/file.c3 b/lib/std/io/file.c3 index d2339b34f..57373f2da 100644 --- a/lib/std/io/file.c3 +++ b/lib/std/io/file.c3 @@ -161,14 +161,14 @@ fn char[]! load_buffer(String filename, char[] buffer) } -fn char[]! load_new(String filename, Allocator* allocator = mem::heap()) +fn char[]! load_new(String filename, Allocator* allocator = allocator::heap()) { File file = open(filename, "rb")!; defer (void)file.close(); usz len = file.seek(0, END)!; file.seek(0, SET)!; - char* data = allocator.alloc_checked(len)!; - defer catch allocator.free(data); + char* data = allocator::malloc_try(allocator, len)!; + defer catch allocator::free(allocator, data); usz read = 0; while (read < len) { @@ -179,7 +179,7 @@ fn char[]! load_new(String filename, Allocator* allocator = mem::heap()) fn char[]! load_temp(String filename) { - return load_new(filename, mem::temp()); + return load_new(filename, allocator::temp()); } /** diff --git a/lib/std/io/formatter.c3 b/lib/std/io/formatter.c3 index 1c0417472..d1423dcfb 100644 --- a/lib/std/io/formatter.c3 +++ b/lib/std/io/formatter.c3 @@ -100,7 +100,7 @@ fn usz! Formatter.print_with_function(&self, Printable* arg) } @pool() { - return self.out_substr(arg.to_new_string(mem::temp())); + return self.out_substr(arg.to_new_string(allocator::temp())); }; } return SearchResult.MISSING?; diff --git a/lib/std/io/io.c3 b/lib/std/io/io.c3 index 5f9260a50..927a6fba8 100644 --- a/lib/std/io/io.c3 +++ b/lib/std/io/io.c3 @@ -49,7 +49,7 @@ fault IoError * @param stream * @require @is_instream(stream) **/ -macro String! readline(stream = io::stdin(), Allocator* allocator = mem::heap()) +macro String! readline(stream = io::stdin(), Allocator* allocator = allocator::heap()) { bool $is_stream = @typeid(stream) == InStream*.typeid; $if $is_stream: @@ -84,7 +84,7 @@ macro String! readline(stream = io::stdin(), Allocator* allocator = mem::heap()) }; } -macro String! treadline(stream = io::stdin()) => readline(stream, mem::temp()) @inline; +macro String! treadline(stream = io::stdin()) => readline(stream, allocator::temp()) @inline; /** * @require @is_outstream(out) "The output must implement OutStream" diff --git a/lib/std/io/os/getcwd.c3 b/lib/std/io/os/getcwd.c3 index a89cef095..37d61fd03 100644 --- a/lib/std/io/os/getcwd.c3 +++ b/lib/std/io/os/getcwd.c3 @@ -1,7 +1,7 @@ module std::io::os; import libc; -macro String! getcwd(Allocator* allocator = mem::heap()) +macro String! getcwd(Allocator* allocator = allocator::heap()) { $switch $case env::WIN32: diff --git a/lib/std/io/os/rmtree.c3 b/lib/std/io/os/rmtree.c3 index 8eafa47a6..566aac919 100644 --- a/lib/std/io/os/rmtree.c3 +++ b/lib/std/io/os/rmtree.c3 @@ -46,7 +46,7 @@ fn void! native_rmtree(Path path) { @pool() { - String filename = string::new_from_wstring((WString)&find_data.cFileName, mem::temp())!; + String filename = string::new_from_wstring((WString)&find_data.cFileName, allocator::temp())!; if (filename == "." || filename == "..") continue; Path file_path = path.tappend(filename)!; if (find_data.dwFileAttributes & win32::FILE_ATTRIBUTE_DIRECTORY) diff --git a/lib/std/io/os/temp_directory.c3 b/lib/std/io/os/temp_directory.c3 index d52051422..e42f81729 100644 --- a/lib/std/io/os/temp_directory.c3 +++ b/lib/std/io/os/temp_directory.c3 @@ -1,6 +1,6 @@ module std::io::os @if(env::LIBC); -fn Path! native_temp_directory(Allocator* allocator = mem::heap()) @if(!env::WIN32) +fn Path! native_temp_directory(Allocator* allocator = allocator::heap()) @if(!env::WIN32) { foreach (String env : { "TMPDIR", "TMP", "TEMP", "TEMPDIR" }) { @@ -10,13 +10,13 @@ fn Path! native_temp_directory(Allocator* allocator = mem::heap()) @if(!env::WIN return path::new("/tmp", allocator); } -fn Path! native_temp_directory(Allocator* allocator = mem::heap()) @if(env::WIN32) +fn Path! native_temp_directory(Allocator* allocator = allocator::heap()) @if(env::WIN32) { @pool(allocator) { Win32_DWORD len = win32::getTempPathW(0, null); if (!len) return IoError.GENERAL_ERROR?; - Char16[] buff = mem::temp_array(Char16, len + (usz)1); + Char16[] buff = mem::temp_alloc_array(Char16, len + (usz)1); if (!win32::getTempPathW(len, buff)) return IoError.GENERAL_ERROR?; return path::new(string::temp_from_utf16(buff[:len]), allocator); }; @@ -24,7 +24,7 @@ fn Path! native_temp_directory(Allocator* allocator = mem::heap()) @if(env::WIN3 module std::io::os @if(env::NO_LIBC); -macro Path! native_temp_directory(Allocator* allocator = mem::heap()) +macro Path! native_temp_directory(Allocator* allocator = allocator::heap()) { return IoError.UNSUPPORTED_OPERATION?; } diff --git a/lib/std/io/path.c3 b/lib/std/io/path.c3 index 252c27436..4d953feb3 100644 --- a/lib/std/io/path.c3 +++ b/lib/std/io/path.c3 @@ -26,11 +26,11 @@ enum PathEnv POSIX } -fn Path! getcwd(Allocator* allocator = mem::heap()) +fn Path! getcwd(Allocator* allocator = allocator::heap()) { @pool(allocator) { - return new(os::getcwd(mem::temp()), allocator); + return new(os::getcwd(allocator::temp()), allocator); }; } @@ -38,9 +38,9 @@ fn bool is_dir(Path path) => os::native_is_dir(path.str_view()); fn bool is_file(Path path) => os::native_is_file(path.str_view()); fn usz! file_size(Path path) => os::native_file_size(path.str_view()); fn bool exists(Path path) => os::native_file_or_dir_exists(path.str_view()); -fn Path! tgetcwd() => getcwd(mem::temp()) @inline; +fn Path! tgetcwd() => getcwd(allocator::temp()) @inline; fn void! chdir(Path path) => os::native_chdir(path) @inline; -fn Path! temp_directory(Allocator* allocator = mem::heap()) => os::native_temp_directory(allocator); +fn Path! temp_directory(Allocator* allocator = allocator::heap()) => os::native_temp_directory(allocator); fn void! delete(Path path) => os::native_remove(path.str_view()) @inline; macro bool is_separator(char c, PathEnv path_env = DEFAULT_PATH_ENV) @@ -58,7 +58,7 @@ macro bool is_win32_separator(char c) return c == '/' || c == '\\'; } -fn PathList! ls(Path dir, bool no_dirs = false, bool no_symlinks = false, String mask = "", Allocator* allocator = mem::heap()) +fn PathList! ls(Path dir, bool no_dirs = false, bool no_symlinks = false, String mask = "", Allocator* allocator = allocator::heap()) { $if $defined(os::native_ls): return os::native_ls(dir, no_dirs, no_symlinks, mask, allocator); @@ -105,17 +105,17 @@ fn void! rmtree(Path path) $endif } -fn Path! new(String path, Allocator* allocator = mem::heap(), PathEnv path_env = DEFAULT_PATH_ENV) +fn Path! new(String path, Allocator* allocator = allocator::heap(), PathEnv path_env = DEFAULT_PATH_ENV) { return { normalize(path.copy(allocator), path_env), path_env }; } fn Path! temp_new(String path, PathEnv path_env = DEFAULT_PATH_ENV) { - return new(path, mem::temp(), path_env); + return new(path, allocator::temp(), path_env); } -fn Path! new_win32_wstring(WString path, Allocator* allocator = mem::heap()) +fn Path! new_win32_wstring(WString path, Allocator* allocator = allocator::heap()) { @pool(allocator) { @@ -123,12 +123,12 @@ fn Path! new_win32_wstring(WString path, Allocator* allocator = mem::heap()) }; } -fn Path! new_windows(String path, Allocator* allocator = mem::heap()) +fn Path! new_windows(String path, Allocator* allocator = allocator::heap()) { return new(path, allocator, WIN32); } -fn Path! new_posix(String path, Allocator* allocator = mem::heap()) +fn Path! new_posix(String path, Allocator* allocator = allocator::heap()) { return new(path, allocator, POSIX); } @@ -143,7 +143,7 @@ fn bool Path.equals(self, Path p2) * * @param [in] filename **/ -fn Path! Path.append(self, String filename, Allocator* allocator = mem::heap()) +fn Path! Path.append(self, String filename, Allocator* allocator = allocator::heap()) { if (!self.path_string.len) return new(filename, allocator, self.env)!; assert(!is_separator(self.path_string[^1], self.env)); @@ -158,7 +158,7 @@ fn Path! Path.append(self, String filename, Allocator* allocator = mem::heap()) }; } -fn Path! Path.tappend(self, String filename) => self.append(filename, mem::temp()); +fn Path! Path.tappend(self, String filename) => self.append(filename, allocator::temp()); fn usz Path.start_of_base_name(self) @local { @@ -179,13 +179,13 @@ fn bool! Path.is_absolute(self) return path_start < path_str.len && is_separator(path_str[path_start], self.env); } -fn Path! Path.absolute(self, Allocator* allocator = mem::heap()) +fn Path! Path.absolute(self, Allocator* allocator = allocator::heap()) { String path_str = self.str_view(); if (!path_str.len) path_str = "."; if (path_str == ".") { - String cwd = os::getcwd(mem::temp())!; + String cwd = os::getcwd(allocator::temp())!; return new(cwd, allocator, self.env); } switch (self.env) @@ -196,7 +196,7 @@ fn Path! Path.absolute(self, Allocator* allocator = mem::heap()) case POSIX: if (path_str[0] == PREFERRED_SEPARATOR_POSIX) return self; } - String cwd = os::getcwd(mem::temp())!; + String cwd = os::getcwd(allocator::temp())!; return Path{ cwd, self.env }.append(path_str, allocator)!; } @@ -459,7 +459,7 @@ fn usz! Path.to_format(&self, Formatter* formatter) @dynamic return formatter.print(self.str_view()); } -fn String Path.to_new_string(&self, Allocator* allocator = mem::heap()) @dynamic +fn String Path.to_new_string(&self, Allocator* allocator = allocator::heap()) @dynamic { return self.str_view().copy(allocator); } diff --git a/lib/std/io/stream.c3 b/lib/std/io/stream.c3 index dba16d50a..dd20267f2 100644 --- a/lib/std/io/stream.c3 +++ b/lib/std/io/stream.c3 @@ -142,12 +142,12 @@ fn usz! copy_to(InStream* in, OutStream* dst, char[] buffer = {}) $case NORMAL: @pool() { - return copy_through_buffer(in, dst, mem::temp_array(char, 4096)); + return copy_through_buffer(in, dst, mem::temp_alloc_array(char, 4096)); }; $case SMALL: @pool() { - return copy_through_buffer(in, dst, mem::temp_array(char, 1024)); + return copy_through_buffer(in, dst, mem::temp_alloc_array(char, 1024)); }; $case TINY: $case NONE: diff --git a/lib/std/io/stream/bytebuffer.c3 b/lib/std/io/stream/bytebuffer.c3 index ba8782cb0..1e2f08c8b 100644 --- a/lib/std/io/stream/bytebuffer.c3 +++ b/lib/std/io/stream/bytebuffer.c3 @@ -16,7 +16,7 @@ struct ByteBuffer (InStream, OutStream) * max_read defines how many bytes might be kept before its internal buffer is shrinked. * @require self.bytes.len == 0 "Buffer already initialized." **/ -fn ByteBuffer*! ByteBuffer.init_new(&self, usz max_read, usz initial_capacity = 16, Allocator* allocator = mem::heap()) @deprecated("Replaced by new_init") +fn ByteBuffer*! ByteBuffer.init_new(&self, usz max_read, usz initial_capacity = 16, Allocator* allocator = allocator::heap()) @deprecated("Replaced by new_init") { return self.new_init(max_read, initial_capacity, allocator) @inline; } @@ -26,7 +26,7 @@ fn ByteBuffer*! ByteBuffer.init_new(&self, usz max_read, usz initial_capacity = * max_read defines how many bytes might be kept before its internal buffer is shrinked. * @require self.bytes.len == 0 "Buffer already initialized." **/ -fn ByteBuffer*! ByteBuffer.new_init(&self, usz max_read, usz initial_capacity = 16, Allocator* allocator = mem::heap()) +fn ByteBuffer*! ByteBuffer.new_init(&self, usz max_read, usz initial_capacity = 16, Allocator* allocator = allocator::heap()) { *self = { .allocator = allocator, .max_read = max_read }; initial_capacity = max(initial_capacity, 16); @@ -41,7 +41,7 @@ fn ByteBuffer*! ByteBuffer.init_temp(&self, usz max_read, usz initial_capacity = fn ByteBuffer*! ByteBuffer.temp_init(&self, usz max_read, usz initial_capacity = 16) { - return self.new_init(max_read, initial_capacity, mem::temp()); + return self.new_init(max_read, initial_capacity, allocator::temp()); } /** @@ -56,7 +56,7 @@ fn ByteBuffer*! ByteBuffer.init_with_buffer(&self, char[] buf) fn void ByteBuffer.free(&self) { - if (self.allocator) self.allocator.free(self.bytes); + if (self.allocator) allocator::free(self.allocator, self.bytes); *self = {}; } @@ -146,7 +146,7 @@ fn usz! ByteBuffer.available(&self) @inline @dynamic fn void! ByteBuffer.grow(&self, usz n) { n = math::next_power_of_2(n); - char* p = self.allocator.realloc_aligned(self.bytes, n, .alignment = char.alignof)!; + char* p = allocator::realloc_aligned(self.allocator, self.bytes, n, .alignment = char.alignof)!; self.bytes = p[:n]; } diff --git a/lib/std/io/stream/bytewriter.c3 b/lib/std/io/stream/bytewriter.c3 index 2edea51e1..6b25f7080 100644 --- a/lib/std/io/stream/bytewriter.c3 +++ b/lib/std/io/stream/bytewriter.c3 @@ -13,7 +13,7 @@ struct ByteWriter (OutStream) * @require self.bytes.len == 0 "Init may not run on on already initialized data" * @ensure (bool)allocator, self.index == 0 **/ -fn ByteWriter* ByteWriter.new_init(&self, Allocator* allocator = mem::heap()) +fn ByteWriter* ByteWriter.new_init(&self, Allocator* allocator = allocator::heap()) { *self = { .bytes = {}, .allocator = allocator }; return self; @@ -25,7 +25,7 @@ fn ByteWriter* ByteWriter.new_init(&self, Allocator* allocator = mem::heap()) * @require self.bytes.len == 0 "Init may not run on on already initialized data" * @ensure (bool)allocator, self.index == 0 **/ -fn ByteWriter* ByteWriter.init_new(&self, Allocator* allocator = mem::heap()) @deprecated("Replaced by new_init") +fn ByteWriter* ByteWriter.init_new(&self, Allocator* allocator = allocator::heap()) @deprecated("Replaced by new_init") { return self.new_init(allocator) @inline; } @@ -37,7 +37,7 @@ fn ByteWriter* ByteWriter.init_new(&self, Allocator* allocator = mem::heap()) @d **/ fn ByteWriter* ByteWriter.temp_init(&self) { - return self.new_init(mem::temp()) @inline; + return self.new_init(allocator::temp()) @inline; } /** @@ -59,7 +59,7 @@ fn ByteWriter* ByteWriter.init_with_buffer(&self, char[] data) fn void! ByteWriter.destroy(&self) @dynamic { if (!self.allocator) return; - if (void* ptr = self.bytes.ptr) self.allocator.free(ptr); + if (void* ptr = self.bytes.ptr) allocator::free(self.allocator, ptr); *self = { }; } @@ -74,7 +74,7 @@ fn void! ByteWriter.ensure_capacity(&self, usz len) @inline if (!self.allocator) return IoError.OUT_OF_SPACE?; if (len < 16) len = 16; usz new_capacity = math::next_power_of_2(len); - char* new_ptr = self.allocator.realloc_checked(self.bytes.ptr, new_capacity)!; + char* new_ptr = allocator::realloc_try(self.allocator, self.bytes.ptr, new_capacity)!; self.bytes = new_ptr[:new_capacity]; } diff --git a/lib/std/math/random/math.seeder.c3 b/lib/std/math/random/math.seeder.c3 index e5fbd33cb..3ca87d0bc 100644 --- a/lib/std/math/random/math.seeder.c3 +++ b/lib/std/math/random/math.seeder.c3 @@ -26,7 +26,7 @@ fn void seeder(char[] input, char[] out_buffer) usz out_chars = out_buffer.len; @pool() { - ulong[] words = mem::temp_array(ulong, (out_chars + 7) / 8); + ulong[] words = mem::temp_alloc_array(ulong, (out_chars + 7) / 8); words[..] = ODD_PHI64; usz words_len_2 = words.len * 2; @@ -86,7 +86,7 @@ fn char[8 * 4] entropy() random_int, hash(clock::now()), hash(&DString.new_init), - hash(mem::heap()) + hash(allocator::heap()) }; return bitcast(entropy_data, char[8 * 4]); } \ No newline at end of file diff --git a/lib/std/net/inetaddr.c3 b/lib/std/net/inetaddr.c3 index 49bb20ee6..ee783e30e 100644 --- a/lib/std/net/inetaddr.c3 +++ b/lib/std/net/inetaddr.c3 @@ -56,7 +56,7 @@ fn usz! InetAddress.to_format(InetAddress* addr, Formatter* formatter) @dynamic return formatter.printf("%d.%d.%d.%d", addr.ipv4.a, addr.ipv4.b, addr.ipv4.c, addr.ipv4.d)!; } -fn String InetAddress.to_new_string(InetAddress* addr, Allocator* allocator = mem::heap()) @dynamic +fn String InetAddress.to_new_string(InetAddress* addr, Allocator* allocator = allocator::heap()) @dynamic { if (addr.is_ipv6) { diff --git a/lib/std/net/net.c3 b/lib/std/net/net.c3 index e68a9b79c..897da812f 100644 --- a/lib/std/net/net.c3 +++ b/lib/std/net/net.c3 @@ -56,7 +56,7 @@ fn uint! ipv4toint(String s) return out; } -fn String! int_to_new_ipv4(uint val, Allocator* allocator = mem::heap()) +fn String! int_to_new_ipv4(uint val, Allocator* allocator = allocator::heap()) { char[3 * 4 + 3 + 1] buffer; String res = (String)io::bprintf(&buffer, "%d.%d.%d.%d", val >> 24, (val >> 16) & 0xFF, (val >> 8) & 0xFF, val & 0xFF)!; @@ -65,5 +65,5 @@ fn String! int_to_new_ipv4(uint val, Allocator* allocator = mem::heap()) fn String! int_to_temp_ipv4(uint val) { - return int_to_new_ipv4(val, mem::temp()); + return int_to_new_ipv4(val, allocator::temp()); } diff --git a/lib/std/os/backtrace.c3 b/lib/std/os/backtrace.c3 index 2afc95ec8..bea5df024 100644 --- a/lib/std/os/backtrace.c3 +++ b/lib/std/os/backtrace.c3 @@ -48,9 +48,9 @@ fn usz! Backtrace.to_format(&self, Formatter* formatter) @dynamic fn void Backtrace.free(&self) { if (!self.allocator) return; - self.allocator.free(self.function); - self.allocator.free(self.object_file); - self.allocator.free(self.file); + allocator::free(self.allocator, self.function); + allocator::free(self.allocator, self.object_file); + allocator::free(self.allocator, self.file); } fn Backtrace* Backtrace.init(&self, uptr offset, String function, String object_file, String file = "", uint line = 0, Allocator* allocator) diff --git a/lib/std/os/env.c3 b/lib/std/os/env.c3 index 1f832f38b..b0ba7a0cf 100644 --- a/lib/std/os/env.c3 +++ b/lib/std/os/env.c3 @@ -9,7 +9,7 @@ import libc; * @require name.len > 0 * @return! SearchResult.MISSING **/ -fn String! get_var(String name, Allocator* allocator = mem::heap()) +fn String! get_var(String name, Allocator* allocator = allocator::heap()) { @pool(allocator) { @@ -38,7 +38,7 @@ fn String! get_var(String name, Allocator* allocator = mem::heap()) fn String! get_var_temp(String name) { - return get_var(name, mem::temp()); + return get_var(name, allocator::temp()); } /** @@ -72,7 +72,7 @@ fn bool set_var(String name, String value, bool overwrite = true) /** * Returns the current user's home directory. **/ -fn String! get_home_dir(Allocator* using = mem::heap()) +fn String! get_home_dir(Allocator* using = allocator::heap()) { String home; $if !env::WIN32: @@ -86,7 +86,7 @@ fn String! get_home_dir(Allocator* using = mem::heap()) /** * Returns the current user's config directory. **/ -fn Path! get_config_dir(Allocator* allocator = mem::heap()) +fn Path! get_config_dir(Allocator* allocator = allocator::heap()) { @pool(allocator) { @@ -126,7 +126,7 @@ fn bool clear_var(String name) }; } -fn String! executable_path(Allocator *allocator = mem::heap()) +fn String! executable_path(Allocator *allocator = allocator::heap()) { $if env::DARWIN: return darwin::executable_path(allocator); diff --git a/lib/std/os/linux/linux.c3 b/lib/std/os/linux/linux.c3 index 59f47829e..38d212a42 100644 --- a/lib/std/os/linux/linux.c3 +++ b/lib/std/os/linux/linux.c3 @@ -133,7 +133,7 @@ fn ulong! elf_module_image_base(String path) @local fn Backtrace! backtrace_load_from_exec(void* addr, Allocator* allocator) @local { - char[] buf = mem::temp_array(char, 1024); + char[] buf = mem::temp_alloc_array(char, 1024); String exec_path = process::execute_stdout_to_buffer(buf, {"realpath", "-e", string::tformat("/proc/%d/exe", posix::getpid())})!; String obj_name = exec_path.copy(allocator); @@ -143,7 +143,7 @@ fn Backtrace! backtrace_load_from_exec(void* addr, Allocator* allocator) @local fn Backtrace! backtrace_load_from_dlinfo(void* addr, Linux_Dl_info* info, Allocator* allocator) @local { - char[] buf = mem::temp_array(char, 1024); + char[] buf = mem::temp_alloc_array(char, 1024); void* obj_addr = addr - (uptr)info.dli_fbase + (uptr)elf_module_image_base(info.dli_fname.str_view())!; ZString obj_path = info.dli_fname; @@ -185,7 +185,7 @@ fn Backtrace! backtrace_from_addr2line(void* addr, String addr2line, String obj_ }; } -fn Backtrace! backtrace_load_element(void* addr, Allocator* allocator = mem::heap()) @local +fn Backtrace! backtrace_load_element(void* addr, Allocator* allocator = allocator::heap()) @local { if (!addr) return backtrace::BACKTRACE_UNKNOWN; diff --git a/lib/std/os/macos/darwin.c3 b/lib/std/os/macos/darwin.c3 index 8c836021b..154807bb9 100644 --- a/lib/std/os/macos/darwin.c3 +++ b/lib/std/os/macos/darwin.c3 @@ -80,7 +80,7 @@ fn uptr! load_address() @local { Darwin_segment_command_64* cmd = darwin::getsegbyname("__TEXT"); if (!cmd) return BacktraceFault.SEGMENT_NOT_FOUND?; - String path = env::executable_path(mem::temp()) ?? BacktraceFault.EXECUTABLE_PATH_NOT_FOUND?!; + String path = env::executable_path(allocator::temp()) ?? BacktraceFault.EXECUTABLE_PATH_NOT_FOUND?!; uint dyld_count = darwin::_dyld_image_count(); for (uint i = 0; i < dyld_count; i++) { @@ -93,7 +93,7 @@ fn uptr! load_address() @local } -fn Backtrace! backtrace_load_element(String execpath, void* buffer, void* load_address, Allocator* allocator = mem::heap()) @local +fn Backtrace! backtrace_load_element(String execpath, void* buffer, void* load_address, Allocator* allocator = allocator::heap()) @local { @pool(allocator) { @@ -147,7 +147,7 @@ fn BacktraceList! symbolize_backtrace(void*[] backtrace, Allocator* allocator) } @pool(allocator) { - String execpath = executable_path(mem::temp())!; + String execpath = executable_path(allocator::temp())!; foreach (addr : backtrace) { list.append(backtrace_load_element(execpath, addr, load_addr, allocator) ?? backtrace::BACKTRACE_UNKNOWN); diff --git a/lib/std/os/macos/objc.c3 b/lib/std/os/macos/objc.c3 index b12888359..7a25052dc 100644 --- a/lib/std/os/macos/objc.c3 +++ b/lib/std/os/macos/objc.c3 @@ -26,7 +26,7 @@ macro Class! class_by_name(char* c) return cls; } -macro Class[] class_get_list(Allocator *allocator = mem::heap()) +macro Class[] class_get_list(Allocator *allocator = allocator::heap()) { int num_classes = _macos_objc_getClassList(null, 0); if (!num_classes) return {}; diff --git a/lib/std/os/subprocess.c3 b/lib/std/os/subprocess.c3 index aac929d76..a765ba7fe 100644 --- a/lib/std/os/subprocess.c3 +++ b/lib/std/os/subprocess.c3 @@ -247,7 +247,7 @@ fn SubProcess! create(String[] command_line, SubProcessOptions options = {}, Str **/ fn ZString* tcopy_command_line(String[] command_line) @local @inline @if(env::POSIX) { - ZString* copy = mem::temp_array(ZString, command_line.len + 1); + ZString* copy = mem::temp_alloc_array(ZString, command_line.len + 1); foreach (i, str : command_line) { copy[i] = str.zstr_tcopy(); @@ -260,7 +260,7 @@ const ZString[1] EMPTY_ENVIRONMENT @if(env::POSIX) = { null }; fn ZString* tcopy_env(String[] environment) @local @inline @if(env::POSIX) { if (!environment.len) return &EMPTY_ENVIRONMENT; - ZString* copy = mem::temp_array(ZString, environment.len + 1); + ZString* copy = mem::temp_alloc_array(ZString, environment.len + 1); copy[environment.len] = null; foreach (i, str : environment) { diff --git a/lib/std/threads/os/thread_posix.c3 b/lib/std/threads/os/thread_posix.c3 index f91ff891e..12a32a61a 100644 --- a/lib/std/threads/os/thread_posix.c3 +++ b/lib/std/threads/os/thread_posix.c3 @@ -152,8 +152,7 @@ fn void* callback(void* arg) @private fn void! NativeThread.create(&thread, ThreadFn thread_fn, void* arg) { - PosixThreadData *thread_data = mem::new(PosixThreadData); - *thread_data = { .thread_fn = thread_fn, .arg = arg }; + PosixThreadData *thread_data = mem::new(PosixThreadData, { .thread_fn = thread_fn, .arg = arg }); if (posix::pthread_create(thread, null, &callback, thread_data) != 0) { *thread = null; diff --git a/releasenotes.md b/releasenotes.md index beec95150..37bf383c0 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -1,5 +1,24 @@ # C3C Release Notes +## 0.5.4 Change list + +### Changes / improvements +- Hash variables may now take a designated initializer. +- Added @safemacro to override the `@` requirement for non-function-like macros. +- More information available with debug log in non debug builds. +- Removed install_win_reqs.bat which didn't work well. +- Support `**` to mean `./**` + +### Fixes +- Fixes to macro context evaluation with macro varargs. + +### Stdlib changes +- Deprecated `Allocator` helper functions. +- Added `mem::allocator` functions corresponding to removed allocator functions. +- Changed `mem::new` / `mem::temp_new` to accept an optional initializer, and will clear by default. +- Mem `_clear` and `_zero` variants deprecated. "new_*" functions will clear by default. +- Mem "alloc_*" functions replace old "new_*" behaviour. + ## 0.5.3 Change list ### Changes / improvements @@ -229,7 +248,7 @@ - Added `saturated` math. - Added `@expect`, `@unlikely` and `@likely` macros. - Temp allocator uses memory-env to determine starting size. -- Temp allocator is now accessed using `mem::temp()`, heap allocator using `mem::heap()`. +- Temp allocator is now accessed using `mem::temp()`, heap allocator using `allocator::heap()`. - Float parsing added. - Additions to std::net, ipv4/ipv6 parsing. - Stream api. diff --git a/resources/examples/contextfree/boolerr.c3 b/resources/examples/contextfree/boolerr.c3 index 9a608748b..89015acb4 100644 --- a/resources/examples/contextfree/boolerr.c3 +++ b/resources/examples/contextfree/boolerr.c3 @@ -75,7 +75,7 @@ fn void main() { const String[] URLS = { "good", "title-empty", "title-missing", "head-missing", "fail" }; DynamicArenaAllocator dynamic_arena; - dynamic_arena.init(1024, mem::heap()); + dynamic_arena.init(1024, allocator::heap()); OutStream* out = io::stdout(); foreach (String url : URLS) { diff --git a/resources/examples/fannkuch-redux.c3 b/resources/examples/fannkuch-redux.c3 index 7ab508a50..710f78597 100644 --- a/resources/examples/fannkuch-redux.c3 +++ b/resources/examples/fannkuch-redux.c3 @@ -5,9 +5,9 @@ import libc; fn int fannkuchredux(int n) { - int* perm = mem::new_array(int, n); - int* perm1 = mem::new_array(int, n); - int* count = mem::new_array(int, n); + int* perm = mem::alloc_array(int, n); + int* perm1 = mem::alloc_array(int, n); + int* count = mem::alloc_array(int, n); int max_flips_count; int perm_count; int checksum; diff --git a/resources/examples/fannkuch-redux2.c3 b/resources/examples/fannkuch-redux2.c3 index 1d59b33fe..b561c833d 100644 --- a/resources/examples/fannkuch-redux2.c3 +++ b/resources/examples/fannkuch-redux2.c3 @@ -4,9 +4,9 @@ import std::math; fn int fannkuchredux(int n) { - int[] perm = mem::new_array(int, n); - int[] perm1 = mem::new_array(int, n); - int* count = mem::new_array(int, n); + int[] perm = mem::alloc_array(int, n); + int[] perm1 = mem::alloc_array(int, n); + int* count = mem::alloc_array(int, n); int max_flips_count; int perm_count; int checksum; diff --git a/resources/examples/spectralnorm.c3 b/resources/examples/spectralnorm.c3 index f9bb68e45..ebb91bcfb 100644 --- a/resources/examples/spectralnorm.c3 +++ b/resources/examples/spectralnorm.c3 @@ -44,10 +44,10 @@ fn void eval_AtA_times_u(double[] u, double[] atau, double[] x) fn void main(String[] args) { int n = args.len == 2 ? args[1].to_int()!! : 2000; - temparr = mem::new_array(double, n); - double[] u = mem::new_array(double, n); - double[] v = mem::new_array(double, n); - double[] x = mem::new_array(double, (usz)(n * n)); + temparr = mem::alloc_array(double, n); + double[] u = mem::alloc_array(double, n); + double[] v = mem::alloc_array(double, n); + double[] x = mem::alloc_array(double, (usz)(n * n)); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) diff --git a/resources/testfragments/allocators_testing.c3 b/resources/testfragments/allocators_testing.c3 index 067ecbe33..37b9952a9 100644 --- a/resources/testfragments/allocators_testing.c3 +++ b/resources/testfragments/allocators_testing.c3 @@ -9,7 +9,7 @@ enum Foo fn void print_pages() { - mem::temp().print_pages(io::stdout())!!; + allocator::temp().print_pages(io::stdout())!!; } fn void setstring(char* dst, String str) @@ -24,7 +24,7 @@ fn void setstring(char* dst, String str) fn void testAllocator(Allocator* a, int val) { io::printn("Test"); - void* data = a.alloc_aligned(val, 128, 16)!!; + void* data = a.malloc_aligned(val, 128, 16)!!; io::printf("Aligned with offset %p, align 16: %s offset align 128: %s\n", data, mem::ptr_is_aligned(data, 16), mem::ptr_is_aligned(data + 16, 128)); data = a.calloc_aligned(val, 128, 16)!!; io::printf("Aligned with offset %p, align 16: %s offset align 128: %s\n", data, mem::ptr_is_aligned(data, 16), mem::ptr_is_aligned(data + 16, 128)); @@ -63,7 +63,7 @@ fn void main() io::printf("First big: %p\n", first_big); print_pages(); }; - mem::@scoped(mem::temp()) + mem::@scoped(allocator::temp()) { io::printf("Malloc: %p\n", (void*)malloc(23)); io::printf("Malloc: %p\n", (void*)malloc(23)); @@ -73,14 +73,14 @@ fn void main() { io::printf("Talloc: %p\n", (void*)tmalloc(22)); }; - testAllocator(mem::temp(), 126); - testAllocator(mem::temp(), 12600); + testAllocator(allocator::temp(), 126); + testAllocator(allocator::temp(), 12600); ArenaAllocator aa; aa.init(&&char[1024] {}); testAllocator(&aa, 126); io::printn("Test dynamic arena"); DynamicArenaAllocator dynamic_arena; - dynamic_arena.init(1024, mem::heap()); + dynamic_arena.init(1024, allocator::heap()); testAllocator(&dynamic_arena, 112); testAllocator(&dynamic_arena, 712); first_big[3] = 123; diff --git a/resources/testfragments/toposort.c3 b/resources/testfragments/toposort.c3 index b77dcb7a9..dd3379dd1 100644 --- a/resources/testfragments/toposort.c3 +++ b/resources/testfragments/toposort.c3 @@ -23,16 +23,15 @@ struct TopoList fn void sort(InputPair[] pairs, uint elements) { - InputPair[] result = mem::new_array(InputPair, pairs.len); - TopoList* top = mem::new_array(TopoList, elements); + InputPair[] result = mem::alloc_array(InputPair, pairs.len); + TopoList* top = mem::alloc_array(TopoList, elements); for (int i = 0; i < pairs.len; i++) { InputPair pair = pairs[i]; assert(pair.value >= 0 && pair.value < elements); assert(pair.successor >= 0 && pair.successor < elements); top[pair.successor].count++; - Entry* successor_entry = mem::new(Entry); - *successor_entry = { pair.successor, null }; + Entry* successor_entry = mem::new(Entry, { pair.successor, null }); Entry** next_ref = &top[pair.value].next; while (*next_ref) { @@ -40,7 +39,7 @@ fn void sort(InputPair[] pairs, uint elements) } *next_ref = successor_entry; } - int[] intout = mem::new_array(int, elements); + int[] intout = mem::alloc_array(int, elements); int count = 0; while LOOP: (1) { diff --git a/src/build/project.c b/src/build/project.c index 508d8d740..63c3e4575 100644 --- a/src/build/project.c +++ b/src/build/project.c @@ -365,7 +365,7 @@ static void load_into_build_target(JSONObject *json, const char *type, BuildTarg [OPT_SETTING_OTINY] = "Oz" }; OptimizationSetting opt = (OptimizationSetting)get_valid_string_setting(json, "opt", type, opt_settings, 0, ELEMENTLEN(opt_settings), "'O0', 'O1' etc."); - if (opt != OPTIMIZATION_NOT_SET) target->optsetting = opt; + if (opt != OPT_SETTING_NOT_SET) target->optsetting = opt; // Safety level target->feature.safe_mode = (SafetyLevel)get_valid_bool(json, "safe", type, target->feature.safe_mode); diff --git a/src/compiler/compiler.c b/src/compiler/compiler.c index 5a149493c..a0fee2035 100644 --- a/src/compiler/compiler.c +++ b/src/compiler/compiler.c @@ -582,7 +582,7 @@ static const char **target_expand_source_names(const char** dirs, const char **s VECEACH(dirs, i) { const char *name = dirs[i]; - DEBUG_LOG("Searching for sources in %s", name); + INFO_LOG("Searching for sources in %s", name); size_t name_len = strlen(name); if (name_len < 1) goto INVALID_NAME; if (name[name_len - 1] == '*') @@ -594,7 +594,7 @@ static const char **target_expand_source_names(const char** dirs, const char **s continue; } if (name[name_len - 2] != '*') goto INVALID_NAME; - DEBUG_LOG("Searching for wildcard sources in %s", name); + INFO_LOG("Searching for wildcard sources in %s", name); if (name_len == 2 || name[name_len - 3] == '/') { char *path = str_copy(name, name_len - 2); diff --git a/src/compiler/compiler_internal.h b/src/compiler/compiler_internal.h index 8e0a6a48c..5eeb270bc 100644 --- a/src/compiler/compiler_internal.h +++ b/src/compiler/compiler_internal.h @@ -64,6 +64,7 @@ typedef unsigned AstId; typedef unsigned ExprId; typedef unsigned DeclId; typedef unsigned TypeInfoId; +typedef struct SemaContext_ SemaContext; typedef struct Int128_ @@ -469,7 +470,7 @@ typedef struct VarDecl_ int32_t index; struct { - struct SemaContext_ *context; + SemaContext *context; SourceSpan span; } hash_var; struct @@ -533,6 +534,7 @@ struct Signature_ CalleeAttributes attrs; bool is_macro : 1; bool is_at_macro : 1; + bool is_safemacro : 1; Variadic variadic : 3; CallABI abi : 8; unsigned vararg_index; @@ -1138,6 +1140,11 @@ typedef struct TypeInfoId type; } ExprCastable; +typedef struct +{ + Expr *inner; + SemaContext *context; +} ExprOtherContext; struct Expr_ { @@ -1159,6 +1166,7 @@ struct Expr_ ExprConst const_expr; // 32 ExprCtArg ct_arg_expr; ExprCtAndOr ct_and_or_expr; + ExprOtherContext expr_other_context; ExprCastable castable_expr; ExprCtCall ct_call_expr; // 24 ExprIdentifierRaw ct_ident_expr; // 24 @@ -1664,7 +1672,7 @@ typedef struct }; } CallEnv; -typedef struct SemaContext_ +struct SemaContext_ { Module *core_module; // Evaluated in this. @@ -1700,11 +1708,11 @@ typedef struct SemaContext_ Decl** ct_locals; }; Type *rtype; - struct SemaContext_ *yield_context; + SemaContext *yield_context; Decl** locals; DynamicScope active_scope; Expr *return_expr; -} SemaContext; +}; typedef struct diff --git a/src/compiler/copying.c b/src/compiler/copying.c index ed2b7c941..2cfcb79d6 100644 --- a/src/compiler/copying.c +++ b/src/compiler/copying.c @@ -296,6 +296,9 @@ Expr *copy_expr(CopyStruct *c, Expr *source_expr) { case EXPR_ANYSWITCH: UNREACHABLE + case EXPR_OTHER_CONTEXT: + MACRO_COPY_EXPR(expr->expr_other_context.inner); + return expr; case EXPR_EMBED: MACRO_COPY_EXPR(expr->embed_expr.len); MACRO_COPY_EXPR(expr->embed_expr.filename); diff --git a/src/compiler/enums.h b/src/compiler/enums.h index dd08064f7..86a9b8a9c 100644 --- a/src/compiler/enums.h +++ b/src/compiler/enums.h @@ -247,6 +247,7 @@ typedef enum EXPR_MACRO_BODY_EXPANSION, EXPR_NOP, EXPR_OPERATOR_CHARS, + EXPR_OTHER_CONTEXT, EXPR_POINTER_OFFSET, EXPR_POST_UNARY, EXPR_RETHROW, @@ -808,6 +809,7 @@ typedef enum ATTRIBUTE_PUBLIC, ATTRIBUTE_PURE, ATTRIBUTE_REFLECT, + ATTRIBUTE_SAFEMACRO, ATTRIBUTE_SECTION, ATTRIBUTE_TEST, ATTRIBUTE_UNUSED, diff --git a/src/compiler/expr.c b/src/compiler/expr.c index 97b59aa1c..7286c5134 100644 --- a/src/compiler/expr.c +++ b/src/compiler/expr.c @@ -43,6 +43,8 @@ bool expr_may_addr(Expr *expr) if (IS_OPTIONAL(expr)) return false; switch (expr->expr_kind) { + case EXPR_OTHER_CONTEXT: + return expr_may_addr(expr->expr_other_context.inner); case EXPR_IDENTIFIER: { Decl *decl = expr->identifier_expr.decl; @@ -148,6 +150,9 @@ bool expr_is_constant_eval(Expr *expr, ConstantEvalKind eval_kind) RETRY: switch (expr->expr_kind) { + case EXPR_OTHER_CONTEXT: + expr = expr->expr_other_context.inner; + goto RETRY; case EXPR_SWIZZLE: return false; case EXPR_POINTER_OFFSET: @@ -660,6 +665,8 @@ bool expr_is_pure(Expr *expr) case EXPR_BENCHMARK_HOOK: case EXPR_TEST_HOOK: return false; + case EXPR_OTHER_CONTEXT: + return expr_is_pure(expr->expr_other_context.inner); case EXPR_SWIZZLE: return exprid_is_pure(expr->swizzle_expr.parent); case EXPR_BUILTIN_ACCESS: diff --git a/src/compiler/linker.c b/src/compiler/linker.c index a8b7440fa..3f41e459a 100644 --- a/src/compiler/linker.c +++ b/src/compiler/linker.c @@ -358,7 +358,7 @@ static const char *find_linux_crt(void) if (!glob("/usr/lib/*/crt1.o", 0, NULL, &globbuf) && globbuf.gl_pathc) { const char *path = globbuf.gl_pathv[0]; - DEBUG_LOG("Found crt at %s", path); + INFO_LOG("Found crt at %s", path); size_t len = strlen(path); assert(len > 6); const char *res = str_copy(path, len - 6); @@ -367,7 +367,7 @@ static const char *find_linux_crt(void) } else { - DEBUG_LOG("No crt in /usr/lib/*/"); + INFO_LOG("No crt in /usr/lib/*/"); } #endif return NULL; @@ -381,7 +381,7 @@ static const char *find_linux_crt_begin(void) if (!glob("/usr/lib/gcc/*/*/crtbegin.o", 0, NULL, &globbuf) && globbuf.gl_pathc) { const char *path = globbuf.gl_pathv[0]; - DEBUG_LOG("Found crtbegin at %s", path); + INFO_LOG("Found crtbegin at %s", path); size_t len = strlen(path); assert(len > 10); const char *res = str_copy(path, len - 10); @@ -390,7 +390,7 @@ static const char *find_linux_crt_begin(void) } else { - DEBUG_LOG("No crtbegin in /usr/lib/gcc/*/*/"); + INFO_LOG("No crtbegin in /usr/lib/gcc/*/*/"); } #endif return NULL; @@ -694,7 +694,7 @@ LinkerType linker_find_linker_type(void) static bool link_exe(const char *output_file, const char **files_to_link, unsigned file_count) { - DEBUG_LOG("Using linker directly."); + INFO_LOG("Using linker directly."); const char **args = NULL; LinkerType linker_type = linker_find_linker_type(); linker_setup(&args, files_to_link, file_count, output_file, linker_type); @@ -709,7 +709,7 @@ static bool link_exe(const char *output_file, const char **files_to_link, unsign arg_list = str_cat(arg_list, " "); arg_list = str_cat(arg_list, args[i]); } - DEBUG_LOG("Linker arguments: %s to %d", arg_list, platform_target.object_format); + INFO_LOG("Linker arguments: %s to %d", arg_list, platform_target.object_format); switch (platform_target.object_format) { case OBJ_FORMAT_COFF: @@ -731,7 +731,7 @@ static bool link_exe(const char *output_file, const char **files_to_link, unsign { error_exit("Failed to create an executable: %s", error); } - DEBUG_LOG("Linking complete."); + INFO_LOG("Linking complete."); return true; } @@ -777,7 +777,7 @@ const char *concat_string_parts(const char **args) void platform_linker(const char *output_file, const char **files, unsigned file_count) { - DEBUG_LOG("Using cc linker."); + INFO_LOG("Using cc linker."); const char **parts = NULL; vec_add(parts, active_target.cc ? active_target.cc : "cc"); append_fpie_pic_options(platform_target.reloc_model, &parts); @@ -860,7 +860,7 @@ const char *platform_compiler(const char *file, const char *flags) bool dynamic_lib_linker(const char *output_file, const char **files, unsigned file_count) { - DEBUG_LOG("Using linker directly."); + INFO_LOG("Using linker directly."); const char **args = NULL; LinkerType linker_type = linker_find_linker_type(); linker_setup(&args, files, file_count, output_file, linker_type); @@ -875,7 +875,7 @@ bool dynamic_lib_linker(const char *output_file, const char **files, unsigned fi arg_list = str_cat(arg_list, " "); arg_list = str_cat(arg_list, args[i]); } - DEBUG_LOG("Linker arguments: %s to %d", arg_list, platform_target.object_format); + DEBUG_LOG("INFO_LOG arguments: %s to %d", arg_list, platform_target.object_format); switch (platform_target.object_format) { case OBJ_FORMAT_COFF: @@ -897,7 +897,7 @@ bool dynamic_lib_linker(const char *output_file, const char **files, unsigned fi { error_exit("Failed to create an executable: %s", error); } - DEBUG_LOG("Linking complete."); + INFO_LOG("Linking complete."); return true; error_exit("Apologies, dynamic libs are still not supported."); diff --git a/src/compiler/llvm_codegen_expr.c b/src/compiler/llvm_codegen_expr.c index 82b79c95f..5f31976c8 100644 --- a/src/compiler/llvm_codegen_expr.c +++ b/src/compiler/llvm_codegen_expr.c @@ -6879,6 +6879,7 @@ void llvm_emit_expr(GenContext *c, BEValue *value, Expr *expr) case EXPR_GENERIC_IDENT: case EXPR_EMBED: case EXPR_MACRO_BODY: + case EXPR_OTHER_CONTEXT: UNREACHABLE case EXPR_LAMBDA: llvm_emit_lambda(c, value, expr); diff --git a/src/compiler/sema_decls.c b/src/compiler/sema_decls.c index e8ddcfb4b..117141261 100644 --- a/src/compiler/sema_decls.c +++ b/src/compiler/sema_decls.c @@ -878,8 +878,7 @@ static inline bool sema_analyse_signature(SemaContext *context, Signature *sig, unsigned param_count = vec_size(params); unsigned vararg_index = sig->vararg_index; bool is_macro = sig->is_macro; - bool is_macro_at_name = sig->is_at_macro; - + bool is_macro_at_name = sig->is_at_macro || sig->is_safemacro; // Check return type assert(sig->rtype || sig->is_macro); Type *rtype = NULL; @@ -2018,6 +2017,7 @@ static bool sema_analyse_attribute(SemaContext *context, Decl *decl, Attr *attr, [ATTRIBUTE_PUBLIC] = ATTR_FUNC | ATTR_MACRO | ATTR_GLOBAL | ATTR_CONST | USER_DEFINED_TYPES | ATTR_DEF | ATTR_INTERFACE, [ATTRIBUTE_PURE] = ATTR_CALL, [ATTRIBUTE_REFLECT] = ATTR_FUNC | ATTR_GLOBAL | ATTR_CONST | USER_DEFINED_TYPES, + [ATTRIBUTE_SAFEMACRO] = ATTR_MACRO, [ATTRIBUTE_SECTION] = ATTR_FUNC | ATTR_CONST | ATTR_GLOBAL, [ATTRIBUTE_TEST] = ATTR_FUNC, [ATTRIBUTE_UNUSED] = (AttributeDomain)~(ATTR_CALL), @@ -2298,6 +2298,9 @@ static bool sema_analyse_attribute(SemaContext *context, Decl *decl, Attr *attr, case ATTRIBUTE_PURE: // Only used for calls. UNREACHABLE + case ATTRIBUTE_SAFEMACRO: + decl->func_decl.signature.is_safemacro = true; + break; case ATTRIBUTE_REFLECT: decl->will_reflect = true; break; @@ -2976,7 +2979,7 @@ static inline bool sema_analyse_macro(SemaContext *context, Decl *decl, bool *er if (*erase_decl) return true; if (!sema_analyse_signature(context, &decl->func_decl.signature, decl->func_decl.type_parent)) return decl_poison(decl); - if (!decl->func_decl.signature.is_at_macro && decl->func_decl.body_param) + if (!decl->func_decl.signature.is_at_macro && decl->func_decl.body_param && !decl->func_decl.signature.is_safemacro) { SEMA_ERROR(decl, "Names of macros with a trailing body must start with '@'."); return decl_poison(decl); diff --git a/src/compiler/sema_expr.c b/src/compiler/sema_expr.c index 0f82e5bde..a0c9af7da 100644 --- a/src/compiler/sema_expr.c +++ b/src/compiler/sema_expr.c @@ -40,7 +40,7 @@ static inline bool sema_expr_analyse_binary(SemaContext *context, Expr *expr); static inline bool sema_expr_analyse_ct_eval(SemaContext *context, Expr *expr); static inline bool sema_expr_analyse_identifier(SemaContext *context, Type *to, Expr *expr); static inline bool sema_expr_analyse_ct_identifier(SemaContext *context, Expr *expr); -static inline bool sema_expr_analyse_hash_identifier(SemaContext *context, Expr *expr); +static inline bool sema_expr_analyse_hash_identifier(SemaContext *context, Type *infer_type, Expr *expr); static inline bool sema_expr_analyse_ternary(SemaContext *context, Expr *expr); static inline bool sema_expr_analyse_cast(SemaContext *context, Expr *expr, bool *invalid_cast_ref); static inline bool sema_expr_analyse_or_error(SemaContext *context, Expr *expr); @@ -411,6 +411,8 @@ static bool sema_binary_is_expr_lvalue(Expr *top_expr, Expr *expr) case EXPR_SUBSCRIPT_ASSIGN: case EXPR_CT_IDENT: return true; + case EXPR_OTHER_CONTEXT: + return sema_binary_is_expr_lvalue(top_expr, expr->expr_other_context.inner); case EXPR_IDENTIFIER: { Decl *decl = expr->identifier_expr.decl; @@ -536,7 +538,6 @@ static bool sema_binary_is_expr_lvalue(Expr *top_expr, Expr *expr) static bool expr_may_ref(Expr *expr) { - switch (expr->expr_kind) { case EXPR_SWIZZLE: @@ -544,6 +545,8 @@ static bool expr_may_ref(Expr *expr) case EXPR_CT_IDENT: case EXPR_EMBED: return false; + case EXPR_OTHER_CONTEXT: + return expr_may_ref(expr->expr_other_context.inner); case EXPR_SUBSCRIPT_ASSIGN: return true; case EXPR_IDENTIFIER: @@ -1015,27 +1018,24 @@ static inline bool sema_expr_analyse_ct_identifier(SemaContext *context, Expr *e return true; } -static inline bool sema_expr_analyse_hash_identifier(SemaContext *context, Expr *expr) +static inline bool sema_expr_analyse_hash_identifier(SemaContext *context, Type *infer_type, Expr *expr) { assert(expr && expr->hash_ident_expr.identifier); DEBUG_LOG("Resolving identifier '%s'", expr->hash_ident_expr.identifier); Decl *decl = sema_resolve_symbol(context, expr->hash_ident_expr.identifier, NULL, expr->span); // Already handled - if (!decl_ok(decl)) - { - return expr_poison(expr); - } + if (!decl_ok(decl)) return expr_poison(expr); assert(decl->decl_kind == DECL_VAR); - expr_replace(expr, copy_expr_single(decl->var.init_expr)); - REMINDER("Remove analysis for hash"); - if (!sema_analyse_expr_lvalue_fold_const(decl->var.hash_var.context, expr)) + if (infer_type) { - // Poison the decl so we don't evaluate twice. - decl_poison(decl); - return false; + if (!sema_analyse_inferred_expr(decl->var.hash_var.context, infer_type, expr)) return decl_poison(decl); + } + else + { + if (!sema_analyse_expr_lvalue_fold_const(decl->var.hash_var.context, expr)) return decl_poison(decl); } return true; } @@ -1483,7 +1483,7 @@ static inline bool sema_call_analyse_invocation(SemaContext *context, Expr *call if (callee.macro) { // Just keep as lvalues - if (!sema_analyse_expr_lvalue_fold_const(context, val)) return false; +// if (!sema_analyse_expr_lvalue_fold_const(context, val)) return false; } else { @@ -1941,12 +1941,18 @@ bool sema_expr_analyse_macro_call(SemaContext *context, Expr *call_expr, Expr *s context_change_scope_with_flags(¯o_context, SCOPE_MACRO); macro_context.block_return_defer = macro_context.active_scope.defer_last; - macro_context.inlining_span = context->current_macro ? context->inlining_span : call_expr->span; macro_context.current_macro = decl; macro_context.yield_body = macro_body ? macro_body->macro_body_expr.body : NULL; macro_context.yield_params = body_params; macro_context.yield_context = context; + FOREACH_BEGIN(Expr *expr, call_expr->call_expr.varargs) + if (expr->resolve_status == RESOLVE_DONE) continue; + Expr *expr_inner = expr_copy(expr); + expr->expr_kind = EXPR_OTHER_CONTEXT; + expr->expr_other_context.inner = expr_inner; + expr->expr_other_context.context = context; + FOREACH_END(); macro_context.macro_varargs = call_expr->call_expr.varargs; macro_context.original_inline_line = context->original_inline_line ? context->original_inline_line : call_expr->span.row; macro_context.macro_params = params; @@ -6020,6 +6026,9 @@ static inline const char *sema_addr_may_take_of_ident(Expr *inner) Decl *decl = decl_raw(inner->identifier_expr.decl); switch (decl->decl_kind) { + case DECL_POISONED: + expr_poison(inner); + return NULL; case DECL_FUNC: if (decl->func_decl.attr_test) { @@ -6111,6 +6120,7 @@ static inline bool sema_expr_analyse_addr(SemaContext *context, Expr *expr, bool // 2. Take the address. const char *error = sema_addr_check_may_take(inner); + if (!expr_ok(inner)) return false; if (error) { if (failed_ref) @@ -7273,9 +7283,9 @@ static Type *sema_expr_check_type_exists(SemaContext *context, TypeInfo *type_in if (!context->current_macro) return NULL; Expr *arg_expr = sema_expr_analyse_ct_arg_index(context, type_info->unresolved_type_expr, NULL, false); if (!expr_ok(arg_expr)) return NULL; + if (!sema_analyse_expr_lvalue_fold_const(context, arg_expr)) return poisoned_type; if (arg_expr->expr_kind != EXPR_TYPEINFO) return NULL; - if (!sema_resolve_type_info(context, type_info, RESOLVE_TYPE_DEFAULT)) return poisoned_type; - return type_info->type->canonical; + return arg_expr->type_expr->type->canonical; } case TYPE_INFO_TYPEFROM: case TYPE_INFO_TYPEOF: @@ -7671,11 +7681,16 @@ static inline bool sema_expr_analyse_ct_defined(SemaContext *context, Expr *expr for (unsigned i = 0; i < list_len; i++) { Expr *main_expr = list[i]; + SemaContext *active_context = context; RETRY: switch (main_expr->expr_kind) { + case EXPR_OTHER_CONTEXT: + active_context = expr->expr_other_context.context; + main_expr = expr->expr_other_context.inner; + goto RETRY; case EXPR_ACCESS: - if (!sema_expr_analyse_access(context, main_expr, &failed)) + if (!sema_expr_analyse_access(active_context, main_expr, &failed)) { if (!failed) return false; success = false; @@ -7683,20 +7698,20 @@ static inline bool sema_expr_analyse_ct_defined(SemaContext *context, Expr *expr break; case EXPR_IDENTIFIER: { - Decl *decl = sema_find_path_symbol(context, main_expr->identifier_expr.ident, main_expr->identifier_expr.path); + Decl *decl = sema_find_path_symbol(active_context, main_expr->identifier_expr.ident, main_expr->identifier_expr.path); if (!decl_ok(decl)) return false; success = decl != NULL; break; } case EXPR_COMPILER_CONST: - success = sema_expr_analyse_compiler_const(context, main_expr, false); + success = sema_expr_analyse_compiler_const(active_context, main_expr, false); break; case EXPR_BUILTIN: - success = sema_expr_analyse_builtin(context, main_expr, false); + success = sema_expr_analyse_builtin(active_context, main_expr, false); break; case EXPR_UNARY: main_expr->resolve_status = RESOLVE_RUNNING; - if (!sema_expr_analyse_unary(context, main_expr, &failed)) + if (!sema_expr_analyse_unary(active_context, main_expr, &failed)) { if (!failed) return false; success = false; @@ -7704,17 +7719,17 @@ static inline bool sema_expr_analyse_ct_defined(SemaContext *context, Expr *expr break; case EXPR_TYPEINFO: { - Type *type = sema_expr_check_type_exists(context, main_expr->type_expr); + Type *type = sema_expr_check_type_exists(active_context, main_expr->type_expr); if (!type_ok(type)) return false; success = type != NULL; break; } case EXPR_CT_EVAL: - success = sema_ct_eval_expr(context, "$eval", main_expr->inner_expr, false); + success = sema_ct_eval_expr(active_context, "$eval", main_expr->inner_expr, false); break; case EXPR_HASH_IDENT: { - Decl *decl = sema_resolve_symbol(context, main_expr->hash_ident_expr.identifier, NULL, main_expr->span); + Decl *decl = sema_resolve_symbol(active_context, main_expr->hash_ident_expr.identifier, NULL, main_expr->span); if (!decl_ok(decl)) return false; if (!decl) RETURN_SEMA_ERROR(list[i], "No parameter '%s' found.", main_expr->hash_ident_expr.identifier); main_expr = copy_expr_single(decl->var.init_expr); @@ -7722,7 +7737,7 @@ static inline bool sema_expr_analyse_ct_defined(SemaContext *context, Expr *expr } case EXPR_SUBSCRIPT: { - if (!sema_expr_analyse_subscript(context, main_expr, SUBSCRIPT_EVAL_VALID)) + if (!sema_expr_analyse_subscript(active_context, main_expr, SUBSCRIPT_EVAL_VALID)) { return false; } @@ -7733,7 +7748,7 @@ static inline bool sema_expr_analyse_ct_defined(SemaContext *context, Expr *expr break; } case EXPR_CAST: - if (!sema_expr_analyse_cast(context, main_expr, &failed)) + if (!sema_expr_analyse_cast(active_context, main_expr, &failed)) { if (!failed) return false; success = false; @@ -7741,7 +7756,7 @@ static inline bool sema_expr_analyse_ct_defined(SemaContext *context, Expr *expr break; case EXPR_CT_IDENT: { - Decl *decl = sema_resolve_symbol(context, main_expr->ct_ident_expr.identifier, NULL, main_expr->span); + Decl *decl = sema_resolve_symbol(active_context, main_expr->ct_ident_expr.identifier, NULL, main_expr->span); if (!decl_ok(decl)) return false; success = decl != NULL; break; @@ -7749,7 +7764,7 @@ static inline bool sema_expr_analyse_ct_defined(SemaContext *context, Expr *expr case EXPR_CALL: { bool no_match; - if (!sema_expr_analyse_call(context, main_expr, &no_match)) + if (!sema_expr_analyse_call(active_context, main_expr, &no_match)) { if (!no_match) return false; success = false; @@ -7757,15 +7772,15 @@ static inline bool sema_expr_analyse_ct_defined(SemaContext *context, Expr *expr break; } case EXPR_FORCE_UNWRAP: - if (!sema_analyse_expr(context, main_expr->inner_expr)) return false; + if (!sema_analyse_expr(active_context, main_expr->inner_expr)) return false; success = IS_OPTIONAL(main_expr->inner_expr); break; case EXPR_RETHROW: - if (!sema_analyse_expr(context, main_expr->rethrow_expr.inner)) return false; + if (!sema_analyse_expr(active_context, main_expr->rethrow_expr.inner)) return false; success = IS_OPTIONAL(main_expr->rethrow_expr.inner); break; case EXPR_OPTIONAL: - if (!sema_expr_analyse_optional(context, main_expr, &failed)) + if (!sema_expr_analyse_optional(active_context, main_expr, &failed)) { if (!failed) return false; success = false; @@ -7787,6 +7802,9 @@ static inline bool sema_expr_analyse_ct_defined(SemaContext *context, Expr *expr case EXPR_BUILTIN_ACCESS: case EXPR_DECL: UNREACHABLE + case EXPR_CT_ARG: + puts("Foekf"); + FALLTHROUGH; case EXPR_BINARY: case EXPR_BITACCESS: case EXPR_BITASSIGN: @@ -7821,13 +7839,12 @@ static inline bool sema_expr_analyse_ct_defined(SemaContext *context, Expr *expr case EXPR_STRINGIFY: case EXPR_TERNARY: case EXPR_CT_CASTABLE: - case EXPR_CT_ARG: case EXPR_CT_CALL: case EXPR_EXPRESSION_LIST: case EXPR_POST_UNARY: case EXPR_TYPEID: case EXPR_TYPEID_INFO: - if (!sema_analyse_expr(context, main_expr)) return false; + if (!sema_analyse_expr(active_context, main_expr)) return false; break; } if (!success) break; @@ -7872,6 +7889,7 @@ static inline bool sema_expr_analyse_ct_arg(SemaContext *context, Type *infer_ty // Not found, so generate a new. if (!decl) { + if (!sema_analyse_inferred_expr(context, infer_type, arg_expr)) return false; if (type_is_invalid_storage_type(arg_expr->type)) { RETURN_SEMA_ERROR(expr, "The vararg doesn't have a valid runtime type."); @@ -7884,6 +7902,7 @@ static inline bool sema_expr_analyse_ct_arg(SemaContext *context, Type *infer_ty // Replace with the identifier. expr->expr_kind = EXPR_IDENTIFIER; expr_resolve_ident(expr, decl); + assert(expr->type); return true; } case TOKEN_CT_VAEXPR: @@ -7892,7 +7911,7 @@ static inline bool sema_expr_analyse_ct_arg(SemaContext *context, Type *infer_ty ASSIGN_EXPR_OR_RET(Expr *arg_expr, sema_expr_analyse_ct_arg_index(context, exprptr(expr->ct_arg_expr.arg), NULL, true), false); expr_replace(expr, copy_expr_single(arg_expr)); - return true; + return sema_analyse_inferred_expr(context, infer_type, expr); } case TOKEN_CT_VACONST: { @@ -7900,6 +7919,7 @@ static inline bool sema_expr_analyse_ct_arg(SemaContext *context, Type *infer_ty ASSIGN_EXPR_OR_RET(Expr *arg_expr, sema_expr_analyse_ct_arg_index(context, exprptr(expr->ct_arg_expr.arg), NULL, true), false); arg_expr = copy_expr_single(arg_expr); + if (!sema_analyse_inferred_expr(context, infer_type, arg_expr)) return false; if (!expr_is_constant_eval(arg_expr, CONSTANT_EVAL_CONSTANT_VALUE)) { SEMA_ERROR(arg_expr, "This argument needs to be a compile time constant."); @@ -7915,7 +7935,6 @@ static inline bool sema_expr_analyse_ct_arg(SemaContext *context, Type *infer_ty ASSIGN_EXPR_OR_RET(Expr *arg_expr, sema_expr_analyse_ct_arg_index(context, exprptr(expr->ct_arg_expr.arg), &index, true), false); - if (!sema_binary_is_expr_lvalue(arg_expr, arg_expr)) return false; index++; assert(index < 0x10000); @@ -7933,6 +7952,7 @@ static inline bool sema_expr_analyse_ct_arg(SemaContext *context, Type *infer_ty if (!decl) { arg_expr = copy_expr_single(arg_expr); + if (!sema_analyse_expr_lvalue_fold_const(context, arg_expr)) return false; expr_insert_addr(arg_expr); decl = decl_new_generated_var(arg_expr->type, VARDECL_PARAM_REF, arg_expr->span); decl->var.init_expr = arg_expr; @@ -7942,6 +7962,7 @@ static inline bool sema_expr_analyse_ct_arg(SemaContext *context, Type *infer_ty // Replace with the identifier. expr->expr_kind = EXPR_IDENTIFIER; expr_resolve_ident(expr, decl); + assert(expr->type); return true; } case TOKEN_CT_VATYPE: @@ -8177,6 +8198,13 @@ static inline bool sema_analyse_expr_dispatch(SemaContext *context, Expr *expr) case EXPR_SWIZZLE: case EXPR_MACRO_BODY: UNREACHABLE + case EXPR_OTHER_CONTEXT: + context = expr->expr_other_context.context; + expr_replace(expr, expr->expr_other_context.inner); + if (expr->resolve_status == RESOLVE_DONE) return expr_ok(expr); + assert(expr->resolve_status == RESOLVE_NOT_DONE); + expr->resolve_status = RESOLVE_RUNNING; + return sema_analyse_expr_dispatch(context, expr); case EXPR_CT_CASTABLE: return sema_expr_analyse_castable(context, expr); case EXPR_EMBED: @@ -8210,7 +8238,7 @@ static inline bool sema_analyse_expr_dispatch(SemaContext *context, Expr *expr) case EXPR_CT_CALL: return sema_expr_analyse_ct_call(context, expr); case EXPR_HASH_IDENT: - return sema_expr_analyse_hash_identifier(context, expr); + return sema_expr_analyse_hash_identifier(context, NULL, expr); case EXPR_CT_IDENT: return sema_expr_analyse_ct_identifier(context, expr); case EXPR_OPTIONAL: @@ -8648,9 +8676,12 @@ bool sema_analyse_inferred_expr(SemaContext *context, Type *infer_type, Expr *ex } expr->resolve_status = RESOLVE_RUNNING; - switch (expr->expr_kind) { + case EXPR_OTHER_CONTEXT: + context = expr->expr_other_context.context; + expr_replace(expr, expr->expr_other_context.inner); + return sema_analyse_inferred_expr(context, infer_type, expr); case EXPR_DESIGNATED_INITIALIZER_LIST: case EXPR_INITIALIZER_LIST: if (!sema_expr_analyse_initializer_list(context, infer_type, expr)) return expr_poison(expr); @@ -8664,6 +8695,9 @@ bool sema_analyse_inferred_expr(SemaContext *context, Type *infer_type, Expr *ex case EXPR_LAMBDA: if (!sema_expr_analyse_lambda(context, infer_type, expr)) return expr_poison(expr); break; + case EXPR_HASH_IDENT: + if (!sema_expr_analyse_hash_identifier(context, infer_type, expr)) return expr_poison(expr); + break; case EXPR_CT_ARG: if (!sema_expr_analyse_ct_arg(context, infer_type, expr)) return expr_poison(expr); break; diff --git a/src/compiler/sema_liveness.c b/src/compiler/sema_liveness.c index a13719bfa..a6d5325f9 100644 --- a/src/compiler/sema_liveness.c +++ b/src/compiler/sema_liveness.c @@ -280,6 +280,7 @@ static void sema_trace_expr_liveness(Expr *expr) case EXPR_CT_CASTABLE: case EXPR_CT_AND_OR: case EXPR_MACRO_BODY: + case EXPR_OTHER_CONTEXT: UNREACHABLE case EXPR_DESIGNATOR: sema_trace_expr_liveness(expr->designator_expr.value); diff --git a/src/compiler/sema_types.c b/src/compiler/sema_types.c index c89dd1acf..67eeccee6 100644 --- a/src/compiler/sema_types.c +++ b/src/compiler/sema_types.c @@ -349,11 +349,9 @@ INLINE bool sema_resolve_vatype(SemaContext *context, TypeInfo *type_info) RETURN_SEMA_ERROR(type_info, "'%s' can only be used inside of a macro.", token_type_to_string(TOKEN_CT_VATYPE)); } ASSIGN_EXPR_OR_RET(Expr *arg_expr, sema_expr_analyse_ct_arg_index(context, type_info->unresolved_type_expr, NULL, - true), - false); + true), false); + if (!sema_analyse_expr_lvalue(context, arg_expr)) return false; if (arg_expr->expr_kind != EXPR_TYPEINFO) RETURN_SEMA_ERROR(arg_expr, "The argument was not a type."); - - assert(arg_expr->resolve_status == RESOLVE_DONE); type_info->type = arg_expr->type_expr->type; return true; } diff --git a/src/compiler/symtab.c b/src/compiler/symtab.c index ac83475e9..d5556d1e2 100644 --- a/src/compiler/symtab.c +++ b/src/compiler/symtab.c @@ -351,6 +351,7 @@ void symtab_init(uint32_t capacity) attribute_list[ATTRIBUTE_PURE] = kw_at_pure; attribute_list[ATTRIBUTE_PUBLIC] = KW_DEF("@public"); attribute_list[ATTRIBUTE_REFLECT] = KW_DEF("@reflect"); + attribute_list[ATTRIBUTE_SAFEMACRO] = KW_DEF("@safemacro"); attribute_list[ATTRIBUTE_SECTION] = KW_DEF("@section"); attribute_list[ATTRIBUTE_TEST] = KW_DEF("@test"); attribute_list[ATTRIBUTE_UNUSED] = KW_DEF("@unused"); diff --git a/src/compiler/target.c b/src/compiler/target.c index b505e87d5..fde8531cd 100644 --- a/src/compiler/target.c +++ b/src/compiler/target.c @@ -766,8 +766,8 @@ static const char *x86_cpu_from_set(X86CpuSet set) static void x86_features_from_host(X86Features *cpu_features) { char *features = LLVMGetHostCPUFeatures(); - DEBUG_LOG("Detected the following host features: %s", features); - DEBUG_LOG("For %s", LLVMGetHostCPUName()); + INFO_LOG("Detected the following host features: %s", features); + INFO_LOG("For %s", LLVMGetHostCPUName()); char *tok = strtok(features, ","); *cpu_features = x86_feature_zero; while (tok != NULL) @@ -915,7 +915,7 @@ static inline void target_setup_x64_abi(BuildTarget *target) else { cpu_set = x64_cpu_default(); - DEBUG_LOG("Set default CPU as %s\n", x86_cpu_set[cpu_set]); + INFO_LOG("Set default CPU as %s\n", x86_cpu_set[cpu_set]); } platform_target.cpu = x86_cpu_from_set(cpu_set); @@ -1737,8 +1737,8 @@ void *llvm_target_machine_create(void) default: UNREACHABLE } - DEBUG_LOG("CPU: %s", platform_target.cpu); - DEBUG_LOG("Features: %s", platform_target.features); + INFO_LOG("CPU: %s", platform_target.cpu); + INFO_LOG("Features: %s", platform_target.features); void *result = LLVMCreateTargetMachine(target, platform_target.target_triple, platform_target.cpu ? platform_target.cpu : "", platform_target.features ? platform_target.features : "", (LLVMCodeGenOptLevel)platform_target.llvm_opt_level, @@ -1789,8 +1789,8 @@ void target_setup(BuildTarget *target) } platform_target.llvm_opt_level = (int)level; - DEBUG_LOG("Triple picked was %s.", platform_target.target_triple); - DEBUG_LOG("Default was %s.", LLVM_DEFAULT_TARGET_TRIPLE); + INFO_LOG("Triple picked was %s.", platform_target.target_triple); + INFO_LOG("Default was %s.", LLVM_DEFAULT_TARGET_TRIPLE); StringSlice target_triple_string = slice_from_string(platform_target.target_triple); platform_target.arch = arch_from_llvm_string(slice_next_token(&target_triple_string, '-')); @@ -1946,7 +1946,7 @@ void target_setup(BuildTarget *target) active_target.macos.sdk = NULL; if (sysroot) { - DEBUG_LOG("Macos SDK: %s", sysroot); + INFO_LOG("Macos SDK: %s", sysroot); active_target.macos.sdk = macos_sysroot_sdk_information(sysroot); if (platform_target.arch == ARCH_TYPE_AARCH64) { diff --git a/src/utils/file_utils.c b/src/utils/file_utils.c index e2d9fd506..75869e48e 100644 --- a/src/utils/file_utils.c +++ b/src/utils/file_utils.c @@ -334,14 +334,14 @@ static inline const char *lib_find(const char *exe_path, const char *rel_path) if (err || !S_ISREG(info.st_mode)) return NULL; const char *lib_path = str_printf("%s%s", exe_path, rel_path); - DEBUG_LOG("Library path found at %s", lib_path); + INFO_LOG("Library path found at %s", lib_path); return lib_path; } const char *find_rel_exe_dir(const char *dir) { char *path = find_executable_path(); - DEBUG_LOG("Detected executable path at %s", path); + INFO_LOG("Detected executable path at %s", path); size_t strlen_path = strlen(path); // Remove any last path slash if (strlen_path > 1 && (path[strlen_path - 1] == '/' || path[strlen_path - 1] == '\\')) @@ -372,7 +372,7 @@ const char *find_lib_dir(void) char *path = find_executable_path(); - DEBUG_LOG("Detected executable path at %s", path); + INFO_LOG("Detected executable path at %s", path); size_t strlen_path = strlen(path); // Remove any last path slash @@ -392,7 +392,7 @@ const char *find_lib_dir(void) if ((lib_path = lib_find(path, "/../../lib/c3/"))) goto DONE; if ((lib_path = lib_find(path, "/../../lib/"))) goto DONE; - DEBUG_LOG("Could not find the standard library /lib/std/"); + INFO_LOG("Could not find the standard library /lib/std/"); DONE:; free(path); return lib_path; @@ -536,8 +536,14 @@ void file_add_wildcard_files(const char ***files, const char *path, bool recursi void file_add_wildcard_files(const char ***files, const char *path, bool recursive, const char **suffix_list, int suffix_count) { + size_t len = strlen(path); + if (len == 0) + { + path = "./"; + len = 2; + } DIR *dir = opendir(path); - bool path_ends_with_slash = is_path_separator(path[strlen(path) - 1]); + bool path_ends_with_slash = is_path_separator(path[len - 1]); if (!dir) { error_exit("Can't open the directory '%s'. Please check the paths. %s", path, strerror(errno)); @@ -568,7 +574,7 @@ void file_add_wildcard_files(const char ***files, const char *path, bool recursi continue; } char *format = path_ends_with_slash ? "%s%s" : "%s/%s"; - DEBUG_LOG("Added file %s", ent->d_name); + INFO_LOG("Added file %s", ent->d_name); vec_add(*files, str_printf(format, path, ent->d_name)); } closedir(dir); diff --git a/src/version.h b/src/version.h index 76c9b1134..d67a62d42 100644 --- a/src/version.h +++ b/src/version.h @@ -1 +1 @@ -#define COMPILER_VERSION "0.5.3" +#define COMPILER_VERSION "0.5.4" diff --git a/test/test_suite/concurrency/atomic_load_store_debug.c3t b/test/test_suite/concurrency/atomic_load_store_debug.c3t index 01859f393..50134e96c 100644 --- a/test/test_suite/concurrency/atomic_load_store_debug.c3t +++ b/test/test_suite/concurrency/atomic_load_store_debug.c3t @@ -89,21 +89,21 @@ declare i1 @llvm.expect.i1(i1, i1) #2 !13 = !DILocation(line: 12, column: 10, scope: !6) !14 = !DILocalVariable(name: "x", scope: !6, file: !5, line: 13, type: !11, align: 4) !15 = !DILocation(line: 13, column: 6, scope: !6) -!16 = !DILocation(line: 195, column: 23, scope: !17) -!17 = distinct !DILexicalBlock(scope: !6, file: !18, line: 195, column: 9) +!16 = !DILocation(line: +!17 = distinct !DILexicalBlock(scope: !6, file: !18, !18 = !DIFile(filename: "mem.c3" !19 = !DILocalVariable(name: "y", scope: !6, file: !5, line: 14, type: !11, align: 4) !20 = !DILocation(line: 14, column: 6, scope: !6) -!21 = !DILocation(line: 195, column: 23, scope: !22) -!22 = distinct !DILexicalBlock(scope: !6, file: !18, line: 195, column: 9) +!21 = !DILocation(line: +!22 = distinct !DILexicalBlock(scope: !6, file: !18 !23 = !DILocation(line: 15, column: 25, scope: !6) !24 = !DILocation(line: 15, column: 19, scope: !6) -!25 = !DILocation(line: 210, column: 20, scope: !26) -!26 = distinct !DILexicalBlock(scope: !6, file: !18, line: 210, column: 2) +!25 = !DILocation(line: +!26 = distinct !DILexicalBlock(scope: !6, file: !18, line: !27 = !DILocation(line: 16, column: 24, scope: !6) !28 = !DILocation(line: 16, column: 19, scope: !6) -!29 = !DILocation(line: 210, column: 20, scope: !30) -!30 = distinct !DILexicalBlock(scope: !6, file: !18, line: 210, column: 2) +!29 = !DILocation(line: +!30 = distinct !DILexicalBlock(scope: !6, file: !18, line: !31 = !DILocation(line: 17, column: 20, scope: !6) !32 = !DILocation(line: 17, column: 6, scope: !6) !33 = distinct !DISubprogram(name: "_$main", linkageName: "main" diff --git a/test/test_suite/dynamic/inherit.c3t b/test/test_suite/dynamic/inherit.c3t index 4968dbdf1..75895c538 100644 --- a/test/test_suite/dynamic/inherit.c3t +++ b/test/test_suite/dynamic/inherit.c3t @@ -31,7 +31,7 @@ struct Test (TestProto, TestProto2) fn void main() { - TestProto* z = mem::new(Test); + TestProto* z = mem::alloc(Test); z.tesT(); Base* w = z; w.tesT(); @@ -41,20 +41,12 @@ fn void main() %.introspect = type { i8, i64, ptr, i64, i64, i64, [0 x i64] } %"any*" = type { ptr, i64 } -%"any*[]" = type { ptr, i64 } - @"$ct.inherit.Test" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 8, i64 0, i64 1, [0 x i64] zeroinitializer }, align 8 -@std.core.mem.thread_allocator = external thread_local global %"any*", align 8 -@"$sel.acquire" = linkonce_odr constant [8 x i8] c"acquire\00", align 1 -@.panic_msg = internal constant [45 x i8] c"No method 'acquire' could be found on target\00", align 1 -@.file = internal constant [17 x i8] c"mem_allocator.c3\00", align 1 +@"$sel.tesT" = linkonce_odr constant [5 x i8] c"tesT\00", align 1 +@.panic_msg = internal constant [42 x i8] c"No method 'tesT' could be found on target\00", align 1 +@.file = internal constant [11 x i8] c"inherit.c3\00", align 1 @.func = internal constant [5 x i8] c"main\00", align 1 @std.core.builtin.panic = external global ptr, align 8 -@"$ct.anyfault" = linkonce global %.introspect { i8 6, i64 0, ptr null, i64 8, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8 -@.panic_msg.1 = internal constant [37 x i8] c"Unexpected fault '%s' was unwrapped!\00", align 1 -@"$sel.tesT" = linkonce_odr constant [5 x i8] c"tesT\00", align 1 -@.panic_msg.2 = internal constant [42 x i8] c"No method 'tesT' could be found on target\00", align 1 -@.file.3 = internal constant [11 x i8] c"inherit.c3\00", align 1 @"$ct.dyn.inherit.Test.tesT" = global { ptr, ptr, ptr } { ptr @inherit.Test.tesT, ptr @"$sel.tesT", ptr null }, align 8 @"$ct.dyn.inherit.Test.hello" = global { ptr, ptr, ptr } { ptr @inherit.Test.hello, ptr @"$sel.hello", ptr null }, align 8 @"$sel.hello" = linkonce_odr constant [6 x i8] c"hello\00", align 1 @@ -76,221 +68,126 @@ entry: define void @inherit.main() #0 { entry: %z = alloca %"any*", align 8 - %self = alloca %"any*", align 8 - %error_var = alloca i64, align 8 - %self1 = alloca %"any*", align 8 %.inlinecache = alloca ptr, align 8 %.cachedtype = alloca ptr, align 8 - %retparam = alloca ptr, align 8 - %varargslots = alloca [1 x %"any*"], align 16 - %indirectarg = alloca %"any*[]", align 8 - %.inlinecache4 = alloca ptr, align 8 - %.cachedtype5 = alloca ptr, align 8 %w = alloca %"any*", align 8 - %.inlinecache15 = alloca ptr, align 8 - %.cachedtype16 = alloca ptr, align 8 - store ptr null, ptr %.cachedtype16, align 8 - store ptr null, ptr %.cachedtype5, align 8 + %.inlinecache3 = alloca ptr, align 8 + %.cachedtype4 = alloca ptr, align 8 + store ptr null, ptr %.cachedtype4, align 8 store ptr null, ptr %.cachedtype, align 8 - call void @llvm.memcpy.p0.p0.i32(ptr align 8 %self, ptr align 8 @std.core.mem.thread_allocator, i32 16, i1 false) - call void @llvm.memcpy.p0.p0.i32(ptr align 8 %self1, ptr align 8 %self, i32 16, i1 false) - %ptradd = getelementptr inbounds i8, ptr %self1, i64 8 - %0 = load i64, ptr %ptradd, align 8 - %1 = inttoptr i64 %0 to ptr + %0 = call ptr @std.core.mem.malloc(i64 8) #1 + %1 = insertvalue %"any*" undef, ptr %0, 0 + %2 = insertvalue %"any*" %1, i64 ptrtoint (ptr @"$ct.inherit.Test" to i64), 1 + store %"any*" %2, ptr %z, align 8 + %ptradd = getelementptr inbounds i8, ptr %z, i64 8 + %3 = load i64, ptr %ptradd, align 8 + %4 = inttoptr i64 %3 to ptr %type = load ptr, ptr %.cachedtype, align 8 - %2 = icmp eq ptr %1, %type - br i1 %2, label %cache_hit, label %cache_miss - + %5 = icmp eq ptr %4, %type + br i1 %5, label %cache_hit, label %cache_miss cache_miss: ; preds = %entry - %ptradd2 = getelementptr inbounds i8, ptr %1, i64 16 - %3 = load ptr, ptr %ptradd2, align 8 - %4 = call ptr @.dyn_search(ptr %3, ptr @"$sel.acquire") - store ptr %4, ptr %.inlinecache, align 8 - store ptr %1, ptr %.cachedtype, align 8 - br label %5 - + %ptradd1 = getelementptr inbounds i8, ptr %4, i64 16 + %6 = load ptr, ptr %ptradd1, align 8 + %7 = call ptr @.dyn_search(ptr %6, ptr @"$sel.tesT") + store ptr %7, ptr %.inlinecache, align 8 + store ptr %4, ptr %.cachedtype, align 8 + br label %8 cache_hit: ; preds = %entry %cache_hit_fn = load ptr, ptr %.inlinecache, align 8 - br label %5 - -5: ; preds = %cache_hit, %cache_miss - %fn_phi = phi ptr [ %cache_hit_fn, %cache_hit ], [ %4, %cache_miss ] - %6 = icmp eq ptr %fn_phi, null - br i1 %6, label %missing_function, label %match - -missing_function: ; preds = %5 - %7 = load ptr, ptr @std.core.builtin.panic, align 8 - call void %7(ptr @.panic_msg, i64 44, ptr @.file, i64 16, ptr @.func, i64 4, i32 117) - unreachable - -match: ; preds = %5 - %8 = load ptr, ptr %self1, align 8 - %9 = call i64 %fn_phi(ptr %retparam, ptr %8, i64 8, i8 zeroext 0, i64 0, i64 0) - %not_err = icmp eq i64 %9, 0 - %10 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) - br i1 %10, label %after_check, label %assign_optional - -assign_optional: ; preds = %match - store i64 %9, ptr %error_var, align 8 - br label %panic_block - -after_check: ; preds = %match - %11 = load ptr, ptr %retparam, align 8 - br label %noerr_block - -panic_block: ; preds = %assign_optional - %12 = insertvalue %"any*" undef, ptr %error_var, 0 - %13 = insertvalue %"any*" %12, i64 ptrtoint (ptr @"$ct.anyfault" to i64), 1 - store %"any*" %13, ptr %varargslots, align 16 - %14 = insertvalue %"any*[]" undef, ptr %varargslots, 0 - %"$$temp" = insertvalue %"any*[]" %14, i64 1, 1 - store %"any*[]" %"$$temp", ptr %indirectarg, align 8 - call void @std.core.builtin.panicf(ptr @.panic_msg.1, i64 36, ptr @.file, i64 16, ptr @.func, i64 4, i32 152, ptr byval(%"any*[]") align 8 %indirectarg) + br label %8 +8: ; preds = %cache_hit, %cache_miss + %fn_phi = phi ptr [ %cache_hit_fn, %cache_hit ], [ %7, %cache_miss ] + %9 = icmp eq ptr %fn_phi, null + br i1 %9, label %missing_function, label %match +missing_function: ; preds = %8 + %10 = load ptr, ptr @std.core.builtin.panic, align 8 + call void %10(ptr @.panic_msg, i64 41, ptr @.file, i64 10, ptr @.func, i64 4, i32 34) unreachable - -noerr_block: ; preds = %after_check - %15 = insertvalue %"any*" undef, ptr %11, 0 - %16 = insertvalue %"any*" %15, i64 ptrtoint (ptr @"$ct.inherit.Test" to i64), 1 - store %"any*" %16, ptr %z, align 8 - %ptradd3 = getelementptr inbounds i8, ptr %z, i64 8 - %17 = load i64, ptr %ptradd3, align 8 - %18 = inttoptr i64 %17 to ptr - %type6 = load ptr, ptr %.cachedtype5, align 8 - %19 = icmp eq ptr %18, %type6 - br i1 %19, label %cache_hit9, label %cache_miss7 - -cache_miss7: ; preds = %noerr_block - %ptradd8 = getelementptr inbounds i8, ptr %18, i64 16 - %20 = load ptr, ptr %ptradd8, align 8 - %21 = call ptr @.dyn_search(ptr %20, ptr @"$sel.tesT") - store ptr %21, ptr %.inlinecache4, align 8 - store ptr %18, ptr %.cachedtype5, align 8 - br label %22 - -cache_hit9: ; preds = %noerr_block - %cache_hit_fn10 = load ptr, ptr %.inlinecache4, align 8 - br label %22 - -22: ; preds = %cache_hit9, %cache_miss7 - %fn_phi11 = phi ptr [ %cache_hit_fn10, %cache_hit9 ], [ %21, %cache_miss7 ] - %23 = icmp eq ptr %fn_phi11, null - br i1 %23, label %missing_function12, label %match13 - -missing_function12: ; preds = %22 - %24 = load ptr, ptr @std.core.builtin.panic, align 8 - call void %24(ptr @.panic_msg.2, i64 41, ptr @.file.3, i64 10, ptr @.func, i64 4, i32 34) - unreachable - -match13: ; preds = %22 - %25 = load ptr, ptr %z, align 8 - call void %fn_phi11(ptr %25) - %26 = load %"any*", ptr %z, align 8 - store %"any*" %26, ptr %w, align 8 - %ptradd14 = getelementptr inbounds i8, ptr %w, i64 8 - %27 = load i64, ptr %ptradd14, align 8 - %28 = inttoptr i64 %27 to ptr - %type17 = load ptr, ptr %.cachedtype16, align 8 - %29 = icmp eq ptr %28, %type17 - br i1 %29, label %cache_hit20, label %cache_miss18 - -cache_miss18: ; preds = %match13 - %ptradd19 = getelementptr inbounds i8, ptr %28, i64 16 - %30 = load ptr, ptr %ptradd19, align 8 - %31 = call ptr @.dyn_search(ptr %30, ptr @"$sel.tesT") - store ptr %31, ptr %.inlinecache15, align 8 - store ptr %28, ptr %.cachedtype16, align 8 - br label %32 - -cache_hit20: ; preds = %match13 - %cache_hit_fn21 = load ptr, ptr %.inlinecache15, align 8 - br label %32 - -32: ; preds = %cache_hit20, %cache_miss18 - %fn_phi22 = phi ptr [ %cache_hit_fn21, %cache_hit20 ], [ %31, %cache_miss18 ] - %33 = icmp eq ptr %fn_phi22, null - br i1 %33, label %missing_function23, label %match24 - -missing_function23: ; preds = %32 - %34 = load ptr, ptr @std.core.builtin.panic, align 8 - call void %34(ptr @.panic_msg.2, i64 41, ptr @.file.3, i64 10, ptr @.func, i64 4, i32 36) +match: ; preds = %8 + %11 = load ptr, ptr %z, align 8 + call void %fn_phi(ptr %11) + %12 = load %"any*", ptr %z, align 8 + store %"any*" %12, ptr %w, align 8 + %ptradd2 = getelementptr inbounds i8, ptr %w, i64 8 + %13 = load i64, ptr %ptradd2, align 8 + %14 = inttoptr i64 %13 to ptr + %type5 = load ptr, ptr %.cachedtype4, align 8 + %15 = icmp eq ptr %14, %type5 + br i1 %15, label %cache_hit8, label %cache_miss6 +cache_miss6: ; preds = %match + %ptradd7 = getelementptr inbounds i8, ptr %14, i64 16 + %16 = load ptr, ptr %ptradd7, align 8 + %17 = call ptr @.dyn_search(ptr %16, ptr @"$sel.tesT") + store ptr %17, ptr %.inlinecache3, align 8 + store ptr %14, ptr %.cachedtype4, align 8 + br label %18 +cache_hit8: ; preds = %match + %cache_hit_fn9 = load ptr, ptr %.inlinecache3, align 8 + br label %18 +18: ; preds = %cache_hit8, %cache_miss6 + %fn_phi10 = phi ptr [ %cache_hit_fn9, %cache_hit8 ], [ %17, %cache_miss6 ] + %19 = icmp eq ptr %fn_phi10, null + br i1 %19, label %missing_function11, label %match12 +missing_function11: ; preds = %18 + %20 = load ptr, ptr @std.core.builtin.panic, align 8 + call void %20(ptr @.panic_msg, i64 41, ptr @.file, i64 10, ptr @.func, i64 4, i32 36) unreachable - -match24: ; preds = %32 - %35 = load ptr, ptr %w, align 8 - call void %fn_phi22(ptr %35) +match12: ; preds = %18 + %21 = load ptr, ptr %w, align 8 + call void %fn_phi10(ptr %21) ret void } - -; Function Attrs: define i32 @main(i32 %0, ptr %1) #0 { entry: call void @inherit.main() ret i32 0 } - -; Function Attrs: -declare void @llvm.memcpy.p0.p0.i32(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i32, i1 immarg) #1 - define weak_odr ptr @.dyn_search(ptr %0, ptr %1) unnamed_addr { entry: br label %check - check: ; preds = %no_match, %entry %2 = phi ptr [ %0, %entry ], [ %9, %no_match ] %3 = icmp eq ptr %2, null br i1 %3, label %missing_function, label %compare - missing_function: ; preds = %check ret ptr null - compare: ; preds = %check %4 = getelementptr inbounds { ptr, ptr, ptr }, ptr %2, i32 0, i32 1 %5 = load ptr, ptr %4, align 8 %6 = icmp eq ptr %5, %1 br i1 %6, label %match, label %no_match - match: ; preds = %compare %7 = load ptr, ptr %2, align 8 ret ptr %7 - no_match: ; preds = %compare %8 = getelementptr inbounds { ptr, ptr, ptr }, ptr %2, i32 0, i32 2 %9 = load ptr, ptr %8, align 8 br label %check } - -; Function Attrs: -declare void @std.core.builtin.panicf(ptr, i64, ptr, i64, ptr, i64, i32, ptr byval(%"any*[]") align 8) #0 - define internal void @.static_initialize.0() { entry: br label %dtable_check - dtable_check: ; preds = %dtable_next, %entry %dtable_ref = phi ptr [ getelementptr inbounds (%.introspect, ptr @"$ct.inherit.Test", i32 0, i32 2), %entry ], [ %next_dtable_ref, %dtable_next ] %dtable_ptr = load ptr, ptr %dtable_ref, align 8 %0 = icmp eq ptr %dtable_ptr, null br i1 %0, label %dtable_found, label %dtable_next - dtable_next: ; preds = %dtable_check %next_dtable_ref = getelementptr inbounds { ptr, ptr, ptr }, ptr %dtable_ptr, i32 0, i32 2 br label %dtable_check - dtable_found: ; preds = %dtable_check store ptr @"$ct.dyn.inherit.Test.tesT", ptr %dtable_ref, align 8 br label %dtable_check1 - dtable_check1: ; preds = %dtable_next4, %dtable_found %dtable_ref2 = phi ptr [ getelementptr inbounds (%.introspect, ptr @"$ct.inherit.Test", i32 0, i32 2), %dtable_found ], [ %next_dtable_ref5, %dtable_next4 ] %dtable_ptr3 = load ptr, ptr %dtable_ref2, align 8 %1 = icmp eq ptr %dtable_ptr3, null br i1 %1, label %dtable_found6, label %dtable_next4 - dtable_next4: ; preds = %dtable_check1 %next_dtable_ref5 = getelementptr inbounds { ptr, ptr, ptr }, ptr %dtable_ptr3, i32 0, i32 2 br label %dtable_check1 - dtable_found6: ; preds = %dtable_check1 store ptr @"$ct.dyn.inherit.Test.hello", ptr %dtable_ref2, align 8 ret void +} } \ No newline at end of file diff --git a/test/test_suite/dynamic/overlapping_function.c3t b/test/test_suite/dynamic/overlapping_function.c3t index fa49c2887..4e0bb7a41 100644 --- a/test/test_suite/dynamic/overlapping_function.c3t +++ b/test/test_suite/dynamic/overlapping_function.c3t @@ -25,7 +25,7 @@ struct Test (TestProto, TestProto2) fn void main() { - TestProto* z = mem::new(Test); + TestProto* z = mem::alloc(Test); z.tesT(); TestProto2* w = (TestProto2*)z; w.tesT(); @@ -35,25 +35,16 @@ fn void main() %.introspect = type { i8, i64, ptr, i64, i64, i64, [0 x i64] } %"any*" = type { ptr, i64 } -%"any*[]" = type { ptr, i64 } - @"$ct.overlap.Test" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 8, i64 0, i64 1, [0 x i64] zeroinitializer }, align 8 -@std.core.mem.thread_allocator = external thread_local global %"any*", align 8 -@"$sel.acquire" = linkonce_odr constant [8 x i8] c"acquire\00", align 1 -@.panic_msg = internal constant [45 x i8] c"No method 'acquire' could be found on target\00", align 1 -@.file = internal constant [17 x i8] c"mem_allocator.c3\00", align 1 +@"$sel.tesT" = linkonce_odr constant [5 x i8] c"tesT\00", align 1 +@.panic_msg = internal constant [42 x i8] c"No method 'tesT' could be found on target\00", align 1 +@.file = internal constant [24 x i8] c"overlapping_function.c3\00", align 1 @.func = internal constant [5 x i8] c"main\00", align 1 @std.core.builtin.panic = external global ptr, align 8 -@"$ct.anyfault" = linkonce global %.introspect { i8 6, i64 0, ptr null, i64 8, i64 0, i64 0, [0 x i64] zeroinitializer }, align 8 -@.panic_msg.1 = internal constant [37 x i8] c"Unexpected fault '%s' was unwrapped!\00", align 1 -@"$sel.tesT" = linkonce_odr constant [5 x i8] c"tesT\00", align 1 -@.panic_msg.2 = internal constant [42 x i8] c"No method 'tesT' could be found on target\00", align 1 -@.file.3 = internal constant [24 x i8] c"overlapping_function.c3\00", align 1 @"$ct.dyn.overlap.Test.tesT" = global { ptr, ptr, ptr } { ptr @overlap.Test.tesT, ptr @"$sel.tesT", ptr null }, align 8 @"$ct.dyn.overlap.Test.foo" = global { ptr, ptr, ptr } { ptr @overlap.Test.foo, ptr @"$sel.foo", ptr null }, align 8 @"$sel.foo" = linkonce_odr constant [4 x i8] c"foo\00", align 1 @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 1, ptr @.static_initialize.0, ptr null }] - ; Function Attrs: nounwind uwtable define void @overlap.Test.tesT(ptr %0) #0 { entry: @@ -70,148 +61,73 @@ entry: define void @overlap.main() #0 { entry: %z = alloca %"any*", align 8 - %self = alloca %"any*", align 8 - %error_var = alloca i64, align 8 - %self1 = alloca %"any*", align 8 %.inlinecache = alloca ptr, align 8 %.cachedtype = alloca ptr, align 8 - %retparam = alloca ptr, align 8 - %varargslots = alloca [1 x %"any*"], align 16 - %indirectarg = alloca %"any*[]", align 8 - %.inlinecache4 = alloca ptr, align 8 - %.cachedtype5 = alloca ptr, align 8 %w = alloca %"any*", align 8 - %.inlinecache15 = alloca ptr, align 8 - %.cachedtype16 = alloca ptr, align 8 - store ptr null, ptr %.cachedtype16, align 8 - store ptr null, ptr %.cachedtype5, align 8 + %.inlinecache3 = alloca ptr, align 8 + %.cachedtype4 = alloca ptr, align 8 + store ptr null, ptr %.cachedtype4, align 8 store ptr null, ptr %.cachedtype, align 8 - call void @llvm.memcpy.p0.p0.i32(ptr align 8 %self, ptr align 8 @std.core.mem.thread_allocator, i32 16, i1 false) - call void @llvm.memcpy.p0.p0.i32(ptr align 8 %self1, ptr align 8 %self, i32 16, i1 false) - %ptradd = getelementptr inbounds i8, ptr %self1, i64 8 - %0 = load i64, ptr %ptradd, align 8 - %1 = inttoptr i64 %0 to ptr + %0 = call ptr @std.core.mem.malloc(i64 8) #1 + %1 = insertvalue %"any*" undef, ptr %0, 0 + %2 = insertvalue %"any*" %1, i64 ptrtoint (ptr @"$ct.overlap.Test" to i64), 1 + store %"any*" %2, ptr %z, align 8 + %ptradd = getelementptr inbounds i8, ptr %z, i64 8 + %3 = load i64, ptr %ptradd, align 8 + %4 = inttoptr i64 %3 to ptr %type = load ptr, ptr %.cachedtype, align 8 - %2 = icmp eq ptr %1, %type - br i1 %2, label %cache_hit, label %cache_miss - + %5 = icmp eq ptr %4, %type + br i1 %5, label %cache_hit, label %cache_miss cache_miss: ; preds = %entry - %ptradd2 = getelementptr inbounds i8, ptr %1, i64 16 - %3 = load ptr, ptr %ptradd2, align 8 - %4 = call ptr @.dyn_search(ptr %3, ptr @"$sel.acquire") - store ptr %4, ptr %.inlinecache, align 8 - store ptr %1, ptr %.cachedtype, align 8 - br label %5 - + %ptradd1 = getelementptr inbounds i8, ptr %4, i64 16 + %6 = load ptr, ptr %ptradd1, align 8 + %7 = call ptr @.dyn_search(ptr %6, ptr @"$sel.tesT") + store ptr %7, ptr %.inlinecache, align 8 + store ptr %4, ptr %.cachedtype, align 8 + br label %8 cache_hit: ; preds = %entry %cache_hit_fn = load ptr, ptr %.inlinecache, align 8 - br label %5 - -5: ; preds = %cache_hit, %cache_miss - %fn_phi = phi ptr [ %cache_hit_fn, %cache_hit ], [ %4, %cache_miss ] - %6 = icmp eq ptr %fn_phi, null - br i1 %6, label %missing_function, label %match - -missing_function: ; preds = %5 - %7 = load ptr, ptr @std.core.builtin.panic, align 8 - call void %7(ptr @.panic_msg, i64 44, ptr @.file, i64 16, ptr @.func, i64 4, i32 117) - unreachable - -match: ; preds = %5 - %8 = load ptr, ptr %self1, align 8 - %9 = call i64 %fn_phi(ptr %retparam, ptr %8, i64 8, i8 zeroext 0, i64 0, i64 0) - %not_err = icmp eq i64 %9, 0 - %10 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) - br i1 %10, label %after_check, label %assign_optional - -assign_optional: ; preds = %match - store i64 %9, ptr %error_var, align 8 - br label %panic_block - -after_check: ; preds = %match - %11 = load ptr, ptr %retparam, align 8 - br label %noerr_block - -panic_block: ; preds = %assign_optional - %12 = insertvalue %"any*" undef, ptr %error_var, 0 - %13 = insertvalue %"any*" %12, i64 ptrtoint (ptr @"$ct.anyfault" to i64), 1 - store %"any*" %13, ptr %varargslots, align 16 - %14 = insertvalue %"any*[]" undef, ptr %varargslots, 0 - %"$$temp" = insertvalue %"any*[]" %14, i64 1, 1 - store %"any*[]" %"$$temp", ptr %indirectarg, align 8 - call void @std.core.builtin.panicf(ptr @.panic_msg.1, i64 36, ptr @.file, i64 16, ptr @.func, i64 4, i32 152, ptr byval(%"any*[]") align 8 %indirectarg) - unreachable - -noerr_block: ; preds = %after_check - %15 = insertvalue %"any*" undef, ptr %11, 0 - %16 = insertvalue %"any*" %15, i64 ptrtoint (ptr @"$ct.overlap.Test" to i64), 1 - store %"any*" %16, ptr %z, align 8 - %ptradd3 = getelementptr inbounds i8, ptr %z, i64 8 - %17 = load i64, ptr %ptradd3, align 8 - %18 = inttoptr i64 %17 to ptr - %type6 = load ptr, ptr %.cachedtype5, align 8 - %19 = icmp eq ptr %18, %type6 - br i1 %19, label %cache_hit9, label %cache_miss7 - -cache_miss7: ; preds = %noerr_block - %ptradd8 = getelementptr inbounds i8, ptr %18, i64 16 - %20 = load ptr, ptr %ptradd8, align 8 - %21 = call ptr @.dyn_search(ptr %20, ptr @"$sel.tesT") - store ptr %21, ptr %.inlinecache4, align 8 - store ptr %18, ptr %.cachedtype5, align 8 - br label %22 - -cache_hit9: ; preds = %noerr_block - %cache_hit_fn10 = load ptr, ptr %.inlinecache4, align 8 - br label %22 - -22: ; preds = %cache_hit9, %cache_miss7 - %fn_phi11 = phi ptr [ %cache_hit_fn10, %cache_hit9 ], [ %21, %cache_miss7 ] - %23 = icmp eq ptr %fn_phi11, null - br i1 %23, label %missing_function12, label %match13 - -missing_function12: ; preds = %22 - %24 = load ptr, ptr @std.core.builtin.panic, align 8 - call void %24(ptr @.panic_msg.2, i64 41, ptr @.file.3, i64 23, ptr @.func, i64 4, i32 28) + br label %8 +8: ; preds = %cache_hit, %cache_miss + %fn_phi = phi ptr [ %cache_hit_fn, %cache_hit ], [ %7, %cache_miss ] + %9 = icmp eq ptr %fn_phi, null + br i1 %9, label %missing_function, label %match +missing_function: ; preds = %8 + %10 = load ptr, ptr @std.core.builtin.panic, align 8 + call void %10(ptr @.panic_msg, i64 41, ptr @.file, i64 23, ptr @.func, i64 4, i32 28) unreachable - -match13: ; preds = %22 - %25 = load ptr, ptr %z, align 8 - call void %fn_phi11(ptr %25) - %26 = load %"any*", ptr %z, align 8 - store %"any*" %26, ptr %w, align 8 - %ptradd14 = getelementptr inbounds i8, ptr %w, i64 8 - %27 = load i64, ptr %ptradd14, align 8 - %28 = inttoptr i64 %27 to ptr - %type17 = load ptr, ptr %.cachedtype16, align 8 - %29 = icmp eq ptr %28, %type17 - br i1 %29, label %cache_hit20, label %cache_miss18 - -cache_miss18: ; preds = %match13 - %ptradd19 = getelementptr inbounds i8, ptr %28, i64 16 - %30 = load ptr, ptr %ptradd19, align 8 - %31 = call ptr @.dyn_search(ptr %30, ptr @"$sel.tesT") - store ptr %31, ptr %.inlinecache15, align 8 - store ptr %28, ptr %.cachedtype16, align 8 - br label %32 - -cache_hit20: ; preds = %match13 - %cache_hit_fn21 = load ptr, ptr %.inlinecache15, align 8 - br label %32 - -32: ; preds = %cache_hit20, %cache_miss18 - %fn_phi22 = phi ptr [ %cache_hit_fn21, %cache_hit20 ], [ %31, %cache_miss18 ] - %33 = icmp eq ptr %fn_phi22, null - br i1 %33, label %missing_function23, label %match24 - -missing_function23: ; preds = %32 - %34 = load ptr, ptr @std.core.builtin.panic, align 8 - call void %34(ptr @.panic_msg.2, i64 41, ptr @.file.3, i64 23, ptr @.func, i64 4, i32 30) +match: ; preds = %8 + %11 = load ptr, ptr %z, align 8 + call void %fn_phi(ptr %11) + %12 = load %"any*", ptr %z, align 8 + store %"any*" %12, ptr %w, align 8 + %ptradd2 = getelementptr inbounds i8, ptr %w, i64 8 + %13 = load i64, ptr %ptradd2, align 8 + %14 = inttoptr i64 %13 to ptr + %type5 = load ptr, ptr %.cachedtype4, align 8 + %15 = icmp eq ptr %14, %type5 + br i1 %15, label %cache_hit8, label %cache_miss6 +cache_miss6: ; preds = %match + %ptradd7 = getelementptr inbounds i8, ptr %14, i64 16 + %16 = load ptr, ptr %ptradd7, align 8 + %17 = call ptr @.dyn_search(ptr %16, ptr @"$sel.tesT") + store ptr %17, ptr %.inlinecache3, align 8 + store ptr %14, ptr %.cachedtype4, align 8 + br label %18 +cache_hit8: ; preds = %match + %cache_hit_fn9 = load ptr, ptr %.inlinecache3, align 8 + br label %18 +18: ; preds = %cache_hit8, %cache_miss6 + %fn_phi10 = phi ptr [ %cache_hit_fn9, %cache_hit8 ], [ %17, %cache_miss6 ] + %19 = icmp eq ptr %fn_phi10, null + br i1 %19, label %missing_function11, label %match12 +missing_function11: ; preds = %18 + %20 = load ptr, ptr @std.core.builtin.panic, align 8 + call void %20(ptr @.panic_msg, i64 41, ptr @.file, i64 23, ptr @.func, i64 4, i32 30) unreachable - -match24: ; preds = %32 - %35 = load ptr, ptr %w, align 8 - call void %fn_phi22(ptr %35) +match12: ; preds = %18 + %21 = load ptr, ptr %w, align 8 + call void %fn_phi10(ptr %21) ret void } @@ -225,63 +141,47 @@ entry: define weak_odr ptr @.dyn_search(ptr %0, ptr %1) unnamed_addr { entry: br label %check - check: ; preds = %no_match, %entry %2 = phi ptr [ %0, %entry ], [ %9, %no_match ] %3 = icmp eq ptr %2, null br i1 %3, label %missing_function, label %compare - missing_function: ; preds = %check ret ptr null - compare: ; preds = %check %4 = getelementptr inbounds { ptr, ptr, ptr }, ptr %2, i32 0, i32 1 %5 = load ptr, ptr %4, align 8 %6 = icmp eq ptr %5, %1 br i1 %6, label %match, label %no_match - match: ; preds = %compare %7 = load ptr, ptr %2, align 8 ret ptr %7 - no_match: ; preds = %compare %8 = getelementptr inbounds { ptr, ptr, ptr }, ptr %2, i32 0, i32 2 %9 = load ptr, ptr %8, align 8 br label %check } - - -; Function Attrs: -declare void @std.core.builtin.panicf(ptr, i64, ptr, i64, ptr, i64, i32, ptr byval(%"any*[]") align 8) #0 - define internal void @.static_initialize.0() { entry: br label %dtable_check - dtable_check: ; preds = %dtable_next, %entry %dtable_ref = phi ptr [ getelementptr inbounds (%.introspect, ptr @"$ct.overlap.Test", i32 0, i32 2), %entry ], [ %next_dtable_ref, %dtable_next ] %dtable_ptr = load ptr, ptr %dtable_ref, align 8 %0 = icmp eq ptr %dtable_ptr, null br i1 %0, label %dtable_found, label %dtable_next - dtable_next: ; preds = %dtable_check %next_dtable_ref = getelementptr inbounds { ptr, ptr, ptr }, ptr %dtable_ptr, i32 0, i32 2 br label %dtable_check - dtable_found: ; preds = %dtable_check store ptr @"$ct.dyn.overlap.Test.tesT", ptr %dtable_ref, align 8 br label %dtable_check1 - dtable_check1: ; preds = %dtable_next4, %dtable_found %dtable_ref2 = phi ptr [ getelementptr inbounds (%.introspect, ptr @"$ct.overlap.Test", i32 0, i32 2), %dtable_found ], [ %next_dtable_ref5, %dtable_next4 ] %dtable_ptr3 = load ptr, ptr %dtable_ref2, align 8 %1 = icmp eq ptr %dtable_ptr3, null br i1 %1, label %dtable_found6, label %dtable_next4 - dtable_next4: ; preds = %dtable_check1 %next_dtable_ref5 = getelementptr inbounds { ptr, ptr, ptr }, ptr %dtable_ptr3, i32 0, i32 2 br label %dtable_check1 - dtable_found6: ; preds = %dtable_check1 store ptr @"$ct.dyn.overlap.Test.foo", ptr %dtable_ref2, align 8 ret void diff --git a/test/test_suite/errors/rethrow_macro.c3 b/test/test_suite/errors/rethrow_macro.c3 index 00225e552..02a0a8f09 100644 --- a/test/test_suite/errors/rethrow_macro.c3 +++ b/test/test_suite/errors/rethrow_macro.c3 @@ -3,12 +3,12 @@ import std::io; macro char[] read(src, Allocator* allocator, n) { - char* data = allocator.alloc_checked(n)!; // #error: Rethrow is only allowed in macros + char* data = allocator::malloc_try(allocator, n)!; // #error: Rethrow is only allowed in macros io::read_all(src, data[:n])!; } fn void main() { ByteReader br; - read(&br, mem::temp(), 10); + read(&br, allocator::temp(), 10); } \ No newline at end of file diff --git a/test/test_suite/generic/generic_lambda_complex.c3t b/test/test_suite/generic/generic_lambda_complex.c3t index 781f4363c..aa90376cb 100644 --- a/test/test_suite/generic/generic_lambda_complex.c3t +++ b/test/test_suite/generic/generic_lambda_complex.c3t @@ -46,7 +46,7 @@ struct TextTag * @require self.tags.len == 0 "template already initialized" * @require tag_start != tag_end **/ -fn void! TextTemplate.init(&self, String template, String tag_start = "{{", String tag_end = "}}", Allocator* using = mem::heap()) +fn void! TextTemplate.init(&self, String template, String tag_start = "{{", String tag_end = "}}", Allocator* using = allocator::heap()) { TextTagList tags; @@ -98,7 +98,7 @@ fn void! TextTemplate.init(&self, String template, String tag_start = "{{", Stri fn void! TextTemplate.free(&self) { - self.allocator.free(self.tags); + allocator::free(self.allocator, self.tags); *self = {}; } @@ -161,7 +161,7 @@ fn void! main() String foo_tmpl = "<<{{foo}} | {{bar}}>>"; FooTmpl ft; - ft.init(foo_tmpl, .using = mem::temp())!; + ft.init(foo_tmpl, .using = allocator::temp())!; defer ft.free()!!; @@ -183,16 +183,16 @@ entry: %indirectarg6 = alloca %"any*[]", align 8 store %"char[]" { ptr @.str, i64 21 }, ptr %foo_tmpl, align 8 call void @llvm.memset.p0.i64(ptr align 8 %ft, i8 0, i64 72, i1 false) - %0 = load ptr, ptr @std.core.mem.thread_temp_allocator, align 8 + %0 = load ptr, ptr @std.core.mem.allocator.thread_temp_allocator, align 8 %not = icmp eq ptr %0, null br i1 %not, label %if.then, label %if.exit if.then: ; preds = %entry - call void @std.core.mem.init_default_temp_allocators() + call void @std.core.mem.allocator.init_default_temp_allocators() br label %if.exit if.exit: ; preds = %if.then, %entry - %1 = load ptr, ptr @std.core.mem.thread_temp_allocator, align 8 + %1 = load ptr, ptr @std.core.mem.allocator.thread_temp_allocator, align 8 %2 = insertvalue %"any*" undef, ptr %1, 0 %3 = insertvalue %"any*" %2, i64 ptrtoint (ptr @"$ct.std.core.mem.allocator.TempAllocator" to i64), 1 %lo = load ptr, ptr %foo_tmpl, align 8 diff --git a/test/test_suite/macros/hash_initializer.c3t b/test/test_suite/macros/hash_initializer.c3t new file mode 100644 index 000000000..6dbf2d3ea --- /dev/null +++ b/test/test_suite/macros/hash_initializer.c3t @@ -0,0 +1,23 @@ +module test; + +macro int[2] test(#abc) @safemacro +{ + return #abc; +} + +fn void main() +{ + int[2] x = int[2] { 1, 2 }; + int[2] y = test({ 2, 3 }); + int[2] z = test({ [0] = 1 }); +} + +/* #expect: test.ll + +@.__const = private unnamed_addr constant [2 x i32] [i32 1, i32 2], align 4 +@.__const.1 = private unnamed_addr constant [2 x i32] [i32 2, i32 3], align 4 +@.__const.2 = private unnamed_addr constant [2 x i32] [i32 1, i32 0], align 4 + + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %x, ptr align 4 @.__const, i32 8, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %y, ptr align 4 @.__const.1, i32 8, i1 false) + call void @llvm.memcpy.p0.p0.i32(ptr align 4 %z, ptr align 4 @.__const.2, i32 8, i1 false) diff --git a/test/test_suite/stdlib/map.c3t b/test/test_suite/stdlib/map.c3t index 3dd5ad8d5..daa30e1ad 100644 --- a/test/test_suite/stdlib/map.c3t +++ b/test/test_suite/stdlib/map.c3t @@ -9,7 +9,7 @@ struct Foo (Printable) { int x; void* bar; } def IntFooMap = HashMap(); def IntDoubleMap = HashMap(); -fn String Foo.to_new_string(Foo* foo, Allocator* allocator = mem::heap()) @dynamic +fn String Foo.to_new_string(Foo* foo, Allocator* allocator = allocator::heap()) @dynamic { DString s = dstring::new_with_capacity(128, allocator); s.appendf("{%s, %p}", foo.x, foo.bar); @@ -128,8 +128,8 @@ entry: %result70 = alloca %"int[]", align 8 %retparam71 = alloca i64, align 8 call void @llvm.memset.p0.i64(ptr align 8 %map, i8 0, i64 48, i1 false) - %lo = load i64, ptr @std.core.mem.thread_allocator, align 8 - %hi = load ptr, ptr getelementptr inbounds (i8, ptr @std.core.mem.thread_allocator, i64 8), align 8 + %lo = load i64, ptr @std.core.mem.allocator.thread_allocator, align 8 + %hi = load ptr, ptr getelementptr inbounds (i8, ptr @std.core.mem.allocator.thread_allocator, i64 8), align 8 %0 = call ptr @"std.collections.map$int$test.Foo$.HashMap.new_init"(ptr %map, i32 16, float 7.500000e-01, i64 %lo, ptr %hi) %ptradd = getelementptr inbounds i8, ptr %map, i64 32 %1 = insertvalue %"any*" undef, ptr %ptradd, 0 @@ -188,8 +188,8 @@ after_check18: ; preds = %entry, %after_check %ptradd30 = getelementptr inbounds i8, ptr %literal28, i64 8 %hi31 = load ptr, ptr %ptradd30, align 8 %26 = call i8 @"std.collections.map$int$test.Foo$.HashMap.set"(ptr %map, i32 7, i64 %lo29, ptr %hi31) - %lo33 = load i64, ptr @std.core.mem.thread_allocator, align 8 - %hi34 = load ptr, ptr getelementptr inbounds (i8, ptr @std.core.mem.thread_allocator, i64 8), align 8 + %lo33 = load i64, ptr @std.core.mem.allocator.thread_allocator, align 8 + %hi34 = load ptr, ptr getelementptr inbounds (i8, ptr @std.core.mem.allocator.thread_allocator, i64 8), align 8 %27 = call { ptr, i64 } @"std.collections.map$int$test.Foo$.HashMap.value_new_list"(ptr %map, i64 %lo33, ptr %hi34) store { ptr, i64 } %27, ptr %result, align 8 %28 = insertvalue %"any*" undef, ptr %result, 0 @@ -197,8 +197,8 @@ after_check18: ; preds = %entry, %after_check store %"any*" %29, ptr %varargslots32, align 16 %30 = call i64 @std.io.printfn(ptr %retparam35, ptr @.str.8, i64 10, ptr %varargslots32, i64 1) call void @llvm.memset.p0.i64(ptr align 8 %map2, i8 0, i64 48, i1 false) - %lo38 = load i64, ptr @std.core.mem.thread_allocator, align 8 - %hi39 = load ptr, ptr getelementptr inbounds (i8, ptr @std.core.mem.thread_allocator, i64 8), align 8 + %lo38 = load i64, ptr @std.core.mem.allocator.thread_allocator, align 8 + %hi39 = load ptr, ptr getelementptr inbounds (i8, ptr @std.core.mem.allocator.thread_allocator, i64 8), align 8 %31 = call ptr @"std.collections.map$int$double$.HashMap.new_init"(ptr %map2, i32 16, float 7.500000e-01, i64 %lo38, ptr %hi39) %32 = call i8 @"std.collections.map$int$double$.HashMap.set"(ptr %map2, i32 4, double 1.300000e+00) %33 = call i8 @"std.collections.map$int$double$.HashMap.has_value"(ptr %map2, double 1.300000e+00) @@ -214,45 +214,45 @@ after_check18: ; preds = %entry, %after_check store %"any*" %39, ptr %varargslots45, align 16 %40 = call i64 @std.io.printfn(ptr %retparam47, ptr @.str.10, i64 12, ptr %varargslots45, i64 1) %41 = call i8 @"std.collections.map$int$double$.HashMap.set"(ptr %map2, i32 100, double 3.400000e+00) - %lo51 = load i64, ptr @std.core.mem.thread_allocator, align 8 - %hi52 = load ptr, ptr getelementptr inbounds (i8, ptr @std.core.mem.thread_allocator, i64 8), align 8 + %lo51 = load i64, ptr @std.core.mem.allocator.thread_allocator, align 8 + %hi52 = load ptr, ptr getelementptr inbounds (i8, ptr @std.core.mem.allocator.thread_allocator, i64 8), align 8 %42 = call { ptr, i64 } @"std.collections.map$int$double$.HashMap.key_new_list"(ptr %map2, i64 %lo51, ptr %hi52) store { ptr, i64 } %42, ptr %result53, align 8 %43 = insertvalue %"any*" undef, ptr %result53, 0 %44 = insertvalue %"any*" %43, i64 ptrtoint (ptr @"$ct.sa$int" to i64), 1 store %"any*" %44, ptr %varargslots50, align 16 %45 = call i64 @std.io.printfn(ptr %retparam54, ptr @.str.11, i64 2, ptr %varargslots50, i64 1) - %lo58 = load i64, ptr @std.core.mem.thread_allocator, align 8 - %hi59 = load ptr, ptr getelementptr inbounds (i8, ptr @std.core.mem.thread_allocator, i64 8), align 8 + %lo58 = load i64, ptr @std.core.mem.allocator.thread_allocator, align 8 + %hi59 = load ptr, ptr getelementptr inbounds (i8, ptr @std.core.mem.allocator.thread_allocator, i64 8), align 8 %46 = call { ptr, i64 } @"std.collections.map$int$double$.HashMap.value_new_list"(ptr %map2, i64 %lo58, ptr %hi59) store { ptr, i64 } %46, ptr %result60, align 8 %47 = insertvalue %"any*" undef, ptr %result60, 0 %48 = insertvalue %"any*" %47, i64 ptrtoint (ptr @"$ct.sa$double" to i64), 1 store %"any*" %48, ptr %varargslots57, align 16 %49 = call i64 @std.io.printfn(ptr %retparam61, ptr @.str.12, i64 2, ptr %varargslots57, i64 1) - %50 = load ptr, ptr @std.core.mem.thread_temp_allocator, align 8 + %50 = load ptr, ptr @std.core.mem.allocator.thread_temp_allocator, align 8 %not = icmp eq ptr %50, null br i1 %not, label %if.then, label %if.exit if.then: ; preds = %after_check18 - call void @std.core.mem.init_default_temp_allocators() + call void @std.core.mem.allocator.init_default_temp_allocators() br label %if.exit if.exit: ; preds = %if.then, %after_check18 - %51 = load ptr, ptr @std.core.mem.thread_temp_allocator, align 8 + %51 = load ptr, ptr @std.core.mem.allocator.thread_temp_allocator, align 8 store ptr %51, ptr %current, align 8 %52 = load ptr, ptr %current, align 8 %ptradd64 = getelementptr inbounds i8, ptr %52, i64 24 %53 = load i64, ptr %ptradd64, align 8 store i64 %53, ptr %mark, align 8 call void @llvm.memset.p0.i64(ptr align 8 %map3, i8 0, i64 48, i1 false) - %lo65 = load i64, ptr @std.core.mem.thread_allocator, align 8 - %hi66 = load ptr, ptr getelementptr inbounds (i8, ptr @std.core.mem.thread_allocator, i64 8), align 8 + %lo65 = load i64, ptr @std.core.mem.allocator.thread_allocator, align 8 + %hi66 = load ptr, ptr getelementptr inbounds (i8, ptr @std.core.mem.allocator.thread_allocator, i64 8), align 8 %54 = call ptr @"std.collections.map$int$double$.HashMap.new_init"(ptr %map3, i32 16, float 7.500000e-01, i64 %lo65, ptr %hi66) %55 = call i8 @"std.collections.map$int$double$.HashMap.set"(ptr %map3, i32 5, double 3.200000e+00) %56 = call i8 @"std.collections.map$int$double$.HashMap.set"(ptr %map3, i32 7, double 5.200000e+00) - %lo68 = load i64, ptr @std.core.mem.thread_allocator, align 8 - %hi69 = load ptr, ptr getelementptr inbounds (i8, ptr @std.core.mem.thread_allocator, i64 8), align 8 + %lo68 = load i64, ptr @std.core.mem.allocator.thread_allocator, align 8 + %hi69 = load ptr, ptr getelementptr inbounds (i8, ptr @std.core.mem.allocator.thread_allocator, i64 8), align 8 %57 = call { ptr, i64 } @"std.collections.map$int$double$.HashMap.key_new_list"(ptr %map3, i64 %lo68, ptr %hi69) store { ptr, i64 } %57, ptr %result70, align 8 %58 = insertvalue %"any*" undef, ptr %result70, 0 diff --git a/test/test_suite/switch/switch_in_defer_macro.c3t b/test/test_suite/switch/switch_in_defer_macro.c3t index db6e3cab4..4dcd33131 100644 --- a/test/test_suite/switch/switch_in_defer_macro.c3t +++ b/test/test_suite/switch/switch_in_defer_macro.c3t @@ -50,7 +50,7 @@ struct Lexer } } -fn void! Lexer.init(&self, InStream* reader, Ident ident, Allocator* using = mem::heap()) +fn void! Lexer.init(&self, InStream* reader, Ident ident, Allocator* using = allocator::heap()) { TokenTrie trie; ushort max_token; @@ -67,13 +67,13 @@ fn void! Lexer.init(&self, InStream* reader, Ident ident, Allocator* using = mem assert(end.len > 0 && end.len <= ushort.max); max_token = max(max_token, (ushort)end.len); } - char* buf = using.alloc_checked(max_token)!; + char* buf = allocator::malloc_try(using, max_token)!; *self = { .allocator = using, .reader = reader, .buf = buf[:max_token], .tokens = trie }; } fn void! Lexer.free(&self) { - self.allocator.free(self.buf); + allocator::free(self.allocator, self.buf); *self = {}; } @@ -489,7 +489,7 @@ struct TrieNode bool valid; } -fn void Trie.init(&self, usz initial_capacity = 8, Allocator* using = mem::heap()) +fn void Trie.init(&self, usz initial_capacity = 8, Allocator* using = allocator::heap()) { *self = {}; self.nodes.new_init(initial_capacity, .allocator = using); @@ -709,7 +709,7 @@ fn void test() @.str.5 = private unnamed_addr constant [3 x i8] c"*/\00", align 1 @"lexer_test.Comment$end" = linkonce constant [2 x %"char[]"] [%"char[]" { ptr @.str.4, i64 1 }, %"char[]" { ptr @.str.5, i64 2 }], align 8 @"$ct.std.io.ByteReader" = linkonce global %.introspect { i8 10, i64 0, ptr null, i64 24, i64 0, i64 2, [0 x i64] zeroinitializer }, align 8 -@std.core.mem.thread_allocator = external thread_local global %"any*", align 8 +@std.core.mem.allocator.thread_allocator = external thread_local global %"any*", align 8 ; Function Attrs: define zeroext i8 @lexer_test.is_ident_char(i64 %0, i8 zeroext %1) #0 { @@ -789,8 +789,8 @@ loop.body: ; preds = %loop.cond %lo3 = load i64, ptr %taddr, align 8 %ptradd4 = getelementptr inbounds i8, ptr %taddr, i64 8 %hi5 = load ptr, ptr %ptradd4, align 8 - %lo6 = load i64, ptr @std.core.mem.thread_allocator, align 8 - %hi7 = load ptr, ptr getelementptr inbounds (i8, ptr @std.core.mem.thread_allocator, i64 8), align 8 + %lo6 = load i64, ptr @std.core.mem.allocator.thread_allocator, align 8 + %hi7 = load ptr, ptr getelementptr inbounds (i8, ptr @std.core.mem.allocator.thread_allocator, i64 8), align 8 %8 = call i64 @"lexer$lexer_test.Token$lexer_test.Comment$.Lexer.init"(ptr %lex, i64 %lo3, ptr %hi5, ptr @lexer_test.is_ident_char, i64 %lo6, ptr %hi7) %not_err = icmp eq i64 %8, 0 %9 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) diff --git a/test/unit/regression/liveness_any.c3 b/test/unit/regression/liveness_any.c3 index a8bcc1d05..e9c6baf5a 100644 --- a/test/unit/regression/liveness_any.c3 +++ b/test/unit/regression/liveness_any.c3 @@ -15,6 +15,6 @@ struct Test (TestProto) fn void reflect_test() @test { - TestProto* b = mem::new(Test); + TestProto* b = mem::alloc(Test); b.tesT(); } \ No newline at end of file diff --git a/test/unit/stdlib/collections/copy_map.c3 b/test/unit/stdlib/collections/copy_map.c3 index 610948571..913ff07ef 100644 --- a/test/unit/stdlib/collections/copy_map.c3 +++ b/test/unit/stdlib/collections/copy_map.c3 @@ -5,7 +5,7 @@ import std::collections::map; fn void! copy_map() @test { TrackingAllocator alloc; - alloc.init(mem::heap()); + alloc.init(allocator::heap()); assert(alloc.allocated() == 0); mem::@scoped(&alloc) { diff --git a/test/unit/stdlib/collections/object.c3 b/test/unit/stdlib/collections/object.c3 index f4259e824..ed01ca5f1 100644 --- a/test/unit/stdlib/collections/object.c3 +++ b/test/unit/stdlib/collections/object.c3 @@ -3,12 +3,12 @@ import std::collections::object; fn void test_general() { - Object* root = object::new_obj(mem::heap()); + Object* root = object::new_obj(allocator::heap()); root.set("foo", 1); root.set("bar", "baz"); assert(root.get_int("foo")! == 1); assert(root.get_string("bar")! == "baz"); - Object* goo = root.set("goo", object::new_obj(mem::heap())); + Object* goo = root.set("goo", object::new_obj(allocator::heap())); goo.append("hello"); goo.append(132); assert(root.get("goo").get_int_at(1)! == 132); diff --git a/test/unit/stdlib/io/path.c3 b/test/unit/stdlib/io/path.c3 index ff8ad6be6..8ac294fa4 100644 --- a/test/unit/stdlib/io/path.c3 +++ b/test/unit/stdlib/io/path.c3 @@ -306,7 +306,7 @@ fn void! test_path_is_absolute() fn void! test_path_absolute() { assert(path::new_posix("/").absolute()!.str_view() == "/"); - assert(path::new_posix(".").absolute()!.str_view() == path::getcwd(mem::temp())!!.str_view()); + assert(path::new_posix(".").absolute()!.str_view() == path::getcwd(allocator::temp())!!.str_view()); assert(path::new_windows(`C:\abs`).absolute()!.str_view() == `C:\abs`); } \ No newline at end of file diff --git a/test/unit/stdlib/mem/temp_mem.c3 b/test/unit/stdlib/mem/temp_mem.c3 index b6ad2f603..2b6437402 100644 --- a/test/unit/stdlib/mem/temp_mem.c3 +++ b/test/unit/stdlib/mem/temp_mem.c3 @@ -9,7 +9,7 @@ fn String add(String s, Allocator* a, int x) tmp = "foo".tconcat(s); tmp = add(tmp, a, x - 1); }; - ulong* y = mem::new_temp(ulong); + ulong* y = mem::temp_alloc(ulong); *y = 0xAAAA_AAAA_AAAA_AAAA; return tmp.concat("a", .allocator = a); } @@ -18,7 +18,7 @@ fn String breakit(String s, Allocator* a) { @pool(a) { - return inner2("foo".concat(s, mem::temp()), a); + return inner2("foo".concat(s, allocator::temp()), a); }; } @@ -26,10 +26,10 @@ fn String inner2(String s, Allocator* a) { @pool(a) { - ulong* z1 = mem::new_temp(ulong); + ulong* z1 = mem::temp_alloc(ulong); *z1 = 0xAAAA_AAAA_AAAA_AAAA; String y = inner3(s, a); - ulong* z = mem::new_temp(ulong); + ulong* z = mem::temp_alloc(ulong); *z = 0xAAAA_AAAA_AAAA_AAAA; return y; }; @@ -39,10 +39,10 @@ fn String inner3(String s, Allocator* a) { @pool(a) { - ulong* z1 = mem::new_temp(ulong); + ulong* z1 = mem::temp_alloc(ulong); *z1 = 0xAAAA_AAAA_AAAA_AAAA; String y = inner4(s, a); - ulong* z = mem::new_temp(ulong); + ulong* z = mem::temp_alloc(ulong); *z = 0xAAAA_AAAA_AAAA_AAAA; return y; }; @@ -52,17 +52,17 @@ fn String inner4(String s, Allocator* a) { @pool(a) { - String y = s.concat("xy**********", mem::temp()).copy(a); + String y = s.concat("xy**********", allocator::temp()).copy(a); return y; }; } fn void! test_temp_allocator() @test { - assert("foofoofoofoofoofooabcaaaaaa" == add("abc", mem::temp(), 5), "was %s", add("abc", mem::temp(), 5)); + assert("foofoofoofoofoofooabcaaaaaa" == add("abc", allocator::temp(), 5), "was %s", add("abc", allocator::temp(), 5)); } fn void! test_temp_allocator2() @test { - assert("fooxyz0123456789xy**********" == breakit("xyz0123456789", mem::temp())); + assert("fooxyz0123456789xy**********" == breakit("xyz0123456789", allocator::temp())); }