diff --git a/lib/std/collections/anylist.c3 b/lib/std/collections/anylist.c3 index ae263be0f..6c6254c76 100644 --- a/lib/std/collections/anylist.c3 +++ b/lib/std/collections/anylist.c3 @@ -44,7 +44,7 @@ fn AnyList* AnyList.init(&self, Allocator allocator, usz initial_capacity = 16) *> fn AnyList* AnyList.tinit(&self, usz initial_capacity = 16) { - return self.init(tmem(), initial_capacity) @inline; + return self.init(tmem, initial_capacity) @inline; } fn bool AnyList.is_initialized(&self) @inline => self.allocator != null; @@ -74,7 +74,7 @@ fn usz? AnyList.to_format(&self, Formatter* formatter) @dynamic *> macro void AnyList.push(&self, element) { - if (!self.allocator) self.allocator = tmem(); + if (!self.allocator) self.allocator = tmem; self.append_internal(allocator::clone(self.allocator, element)); } @@ -121,7 +121,7 @@ fn any? AnyList.copy_pop(&self, Allocator allocator) Pop the last value and allocate the copy using the temp allocator @return? NO_MORE_ELEMENT *> -fn any? AnyList.tcopy_pop(&self) => self.copy_pop(tmem()); +fn any? AnyList.tcopy_pop(&self) => self.copy_pop(tmem); <* Pop the last value. It must later be released using list.free_element() @@ -177,7 +177,7 @@ fn any? AnyList.copy_pop_first(&self, Allocator allocator) <* Same as temp_pop() but pops the first value instead. *> -fn any? AnyList.tcopy_pop_first(&self) => self.copy_pop_first(tmem()); +fn any? AnyList.tcopy_pop_first(&self) => self.copy_pop_first(tmem); <* @require index < self.size @@ -415,7 +415,7 @@ fn void AnyList.reserve(&self, usz min_capacity) { if (!min_capacity) return; if (self.capacity >= min_capacity) return; - if (!self.allocator) self.allocator = tmem(); + if (!self.allocator) self.allocator = tmem; min_capacity = math::next_power_of_2(min_capacity); self.entries = allocator::realloc(self.allocator, self.entries, any.sizeof * min_capacity); self.capacity = min_capacity; diff --git a/lib/std/collections/bitset.c3 b/lib/std/collections/bitset.c3 index 3681efed4..0ef405010 100644 --- a/lib/std/collections/bitset.c3 +++ b/lib/std/collections/bitset.c3 @@ -94,7 +94,7 @@ fn GrowableBitSet* GrowableBitSet.init(&self, Allocator allocator, usz initial_c fn GrowableBitSet* GrowableBitSet.tinit(&self, usz initial_capacity = 1) { - return self.init(tmem(), initial_capacity) @inline; + return self.init(tmem, initial_capacity) @inline; } fn void GrowableBitSet.free(&self) diff --git a/lib/std/collections/elastic_array.c3 b/lib/std/collections/elastic_array.c3 index cd8f36eb4..297dd049a 100644 --- a/lib/std/collections/elastic_array.c3 +++ b/lib/std/collections/elastic_array.c3 @@ -169,9 +169,9 @@ macro Type[] ElasticArray.to_array(&self, Allocator allocator) fn Type[] ElasticArray.to_tarray(&self) { $if type_is_overaligned(): - return self.to_aligned_array(tmem()); + return self.to_aligned_array(tmem); $else - return self.to_array(tmem()); + return self.to_array(tmem); $endif; } diff --git a/lib/std/collections/hashmap.c3 b/lib/std/collections/hashmap.c3 index 94943c02c..4809e1175 100644 --- a/lib/std/collections/hashmap.c3 +++ b/lib/std/collections/hashmap.c3 @@ -61,7 +61,7 @@ fn HashMap* HashMap.init(&self, Allocator allocator, uint capacity = DEFAULT_INI *> fn HashMap* HashMap.tinit(&self, uint capacity = DEFAULT_INITIAL_CAPACITY, float load_factor = DEFAULT_LOAD_FACTOR) { - return self.init(tmem(), capacity, load_factor) @inline; + return self.init(tmem, capacity, load_factor) @inline; } <* @@ -90,7 +90,7 @@ macro HashMap* HashMap.init_with_key_values(&self, Allocator allocator, ..., uin *> macro HashMap* HashMap.tinit_with_key_values(&self, ..., uint capacity = DEFAULT_INITIAL_CAPACITY, float load_factor = DEFAULT_LOAD_FACTOR) { - return self.tinit_with_key_values(tmem(), capacity, load_factor); + return self.tinit_with_key_values(tmem, capacity, load_factor); } <* @@ -126,7 +126,7 @@ fn HashMap* HashMap.init_from_keys_and_values(&self, Allocator allocator, Key[] *> fn HashMap* HashMap.tinit_from_keys_and_values(&self, Key[] keys, Value[] values, uint capacity = DEFAULT_INITIAL_CAPACITY, float load_factor = DEFAULT_LOAD_FACTOR) { - return self.init_from_keys_and_values(tmem(), keys, values, capacity, load_factor); + return self.init_from_keys_and_values(tmem, keys, values, capacity, load_factor); } <* @@ -158,7 +158,7 @@ fn HashMap* HashMap.init_from_map(&self, Allocator allocator, HashMap* other_map *> fn HashMap* HashMap.tinit_from_map(&map, HashMap* other_map) { - return map.init_from_map(tmem(), other_map) @inline; + return map.init_from_map(tmem, other_map) @inline; } fn bool HashMap.is_empty(&map) @inline @@ -287,7 +287,7 @@ fn void HashMap.free(&map) fn Key[] HashMap.tkeys(&self) { - return self.keys(tmem()) @inline; + return self.keys(tmem) @inline; } fn Key[] HashMap.keys(&self, Allocator allocator) @@ -334,7 +334,7 @@ macro HashMap.@each_entry(map; @body(entry)) fn Value[] HashMap.tvalues(&map) { - return map.values(tmem()) @inline; + return map.values(tmem) @inline; } fn Value[] HashMap.values(&self, Allocator allocator) diff --git a/lib/std/collections/linkedlist.c3 b/lib/std/collections/linkedlist.c3 index 9d5fce0f0..b27c45cbc 100644 --- a/lib/std/collections/linkedlist.c3 +++ b/lib/std/collections/linkedlist.c3 @@ -32,7 +32,7 @@ fn LinkedList* LinkedList.init(&self, Allocator allocator) fn LinkedList* LinkedList.tinit(&self) { - return self.init(tmem()) @inline; + return self.init(tmem) @inline; } fn bool LinkedList.is_initialized(&self) @inline => self.allocator != null; @@ -47,7 +47,7 @@ macro void LinkedList.free_node(&self, Node* node) @private macro Node* LinkedList.alloc_node(&self) @private { - if (!self.allocator) self.allocator = tmem(); + if (!self.allocator) self.allocator = tmem; return allocator::alloc(self.allocator, Node); } diff --git a/lib/std/collections/list.c3 b/lib/std/collections/list.c3 index 585435288..65369642b 100644 --- a/lib/std/collections/list.c3 +++ b/lib/std/collections/list.c3 @@ -45,7 +45,7 @@ fn List* List.init(&self, Allocator allocator, usz initial_capacity = 16) *> fn List* List.tinit(&self, usz initial_capacity = 16) { - return self.init(tmem(), initial_capacity) @inline; + return self.init(tmem, initial_capacity) @inline; } <* @@ -173,9 +173,9 @@ macro Type[] List.to_array(&self, Allocator allocator) fn Type[] List.to_tarray(&self) { $if type_is_overaligned(): - return self.to_aligned_array(tmem()); + return self.to_aligned_array(tmem); $else - return self.to_array(tmem()); + return self.to_array(tmem); $endif; } @@ -354,7 +354,7 @@ fn void List.ensure_capacity(&self, usz min_capacity) @local case &dummy: self.allocator = mem; case null: - self.allocator = tmem(); + self.allocator = tmem; default: break; } diff --git a/lib/std/collections/priorityqueue.c3 b/lib/std/collections/priorityqueue.c3 index 64d9a595d..253a050cc 100644 --- a/lib/std/collections/priorityqueue.c3 +++ b/lib/std/collections/priorityqueue.c3 @@ -42,7 +42,7 @@ fn PrivatePriorityQueue* PrivatePriorityQueue.init(&self, Allocator allocator, u fn PrivatePriorityQueue* PrivatePriorityQueue.tinit(&self, usz initial_capacity = 16) @inline { - self.init(tmem(), initial_capacity); + self.init(tmem, initial_capacity); return self; } diff --git a/lib/std/compression/qoi.c3 b/lib/std/compression/qoi.c3 index eecfa4dd9..cf95907bb 100644 --- a/lib/std/compression/qoi.c3 +++ b/lib/std/compression/qoi.c3 @@ -66,7 +66,7 @@ import std::io; fn usz? write(String filename, char[] input, QOIDesc* desc) => @pool() { // encode data - char[] output = encode(tmem(), input, desc)!; + char[] output = encode(tmem, input, desc)!; file::save(filename, output)!; return output.len; diff --git a/lib/std/core/allocators/tracking_allocator.c3 b/lib/std/core/allocators/tracking_allocator.c3 index 2591ec02a..b026df40f 100644 --- a/lib/std/core/allocators/tracking_allocator.c3 +++ b/lib/std/core/allocators/tracking_allocator.c3 @@ -155,7 +155,7 @@ fn void? TrackingAllocator.fprint_report(&self, OutStream out) => @pool() Backtrace trace = backtrace::BACKTRACE_UNKNOWN; if (allocation.backtrace[3]) { - trace = backtrace::symbolize_backtrace(tmem(), allocation.backtrace[3:1]).get(0) ?? backtrace::BACKTRACE_UNKNOWN; + trace = backtrace::symbolize_backtrace(tmem, allocation.backtrace[3:1]).get(0) ?? backtrace::BACKTRACE_UNKNOWN; } if (trace.function.len) leaks = true; io::fprintfn(out, "%13s %p %s:%d", allocation.size, @@ -194,7 +194,7 @@ fn void? TrackingAllocator.fprint_report(&self, OutStream out) => @pool() break; } } - BacktraceList list = backtrace::symbolize_backtrace(tmem(), allocation.backtrace[3..(end - 1)])!; + BacktraceList list = backtrace::symbolize_backtrace(tmem, allocation.backtrace[3..(end - 1)])!; 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 f22c957c6..dca56a592 100644 --- a/lib/std/core/array.c3 +++ b/lib/std/core/array.c3 @@ -81,7 +81,7 @@ macro concat(Allocator allocator, arr1, arr2) @nodiscard @require @typeis(arr1[0], $typeof(arr2[0])) : "Arrays must have the same type" @ensure return.len == arr1.len + arr2.len *> -macro tconcat(arr1, arr2) @nodiscard => concat(tmem(), arr1, arr2); +macro tconcat(arr1, arr2) @nodiscard => concat(tmem, arr1, arr2); module std::core::array::slice{Type}; diff --git a/lib/std/core/builtin.c3 b/lib/std/core/builtin.c3 index dd19c7698..c2267dad3 100644 --- a/lib/std/core/builtin.c3 +++ b/lib/std/core/builtin.c3 @@ -90,7 +90,7 @@ macro anycast(any v, $Type) @builtin fn bool print_backtrace(String message, int backtraces_to_ignore) @if(env::NATIVE_STACKTRACE) => @stack_mem(0x1100; Allocator smem) { - TempAllocator* t = allocator::current_temp; + Allocator t = allocator::current_temp; TempAllocator* new_t = allocator::new_temp_allocator(smem, 0x1000)!!; allocator::current_temp = new_t; defer @@ -101,7 +101,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(tmem(), backtraces); + BacktraceList? backtrace = backtrace::symbolize_backtrace(tmem, backtraces); 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 712b051fd..cedb31e1c 100644 --- a/lib/std/core/dstring.c3 +++ b/lib/std/core/dstring.c3 @@ -24,7 +24,7 @@ fn DString DString.init(&self, Allocator allocator, usz capacity = MIN_CAPACITY) *> fn DString DString.tinit(&self, usz capacity = MIN_CAPACITY) { - return self.init(tmem(), capacity) @inline; + return self.init(tmem, capacity) @inline; } fn DString new_with_capacity(Allocator allocator, usz capacity) @@ -32,7 +32,7 @@ fn DString new_with_capacity(Allocator allocator, usz capacity) return (DString){}.init(allocator, capacity); } -fn DString temp_with_capacity(usz capacity) => new_with_capacity(tmem(), capacity) @inline; +fn DString temp_with_capacity(usz capacity) => new_with_capacity(tmem, capacity) @inline; fn DString new(Allocator allocator, String c = "") { @@ -46,7 +46,7 @@ fn DString new(Allocator allocator, String c = "") return (DString)data; } -fn DString temp(String s = "") => new(tmem(), s) @inline; +fn DString temp(String s = "") => new(tmem, s) @inline; fn void DString.replace_char(self, char ch, char replacement) @@ -108,7 +108,7 @@ fn DString DString.concat(self, Allocator allocator, DString b) return string; } -fn DString DString.tconcat(self, DString b) => self.concat(tmem(), b); +fn DString DString.tconcat(self, DString b) => self.concat(tmem, b); fn ZString DString.zstr_view(&self) { @@ -218,7 +218,7 @@ fn usz DString.append_char32(&self, Char32 c) return n; } -fn DString DString.tcopy(&self) => self.copy(tmem()); +fn DString DString.tcopy(&self) => self.copy(tmem); fn DString DString.copy(self, Allocator allocator) { @@ -248,7 +248,7 @@ fn String DString.copy_str(self, Allocator allocator) return (String)self.copy_zstr(allocator)[:self.len()]; } -fn String DString.tcopy_str(self) => self.copy_str(tmem()) @inline; +fn String DString.tcopy_str(self) => self.copy_str(tmem) @inline; fn bool DString.equals(self, DString other_string) { @@ -536,15 +536,13 @@ macro void DString.insert_at(&self, usz index, value) $endswitch } +import libc; fn usz? DString.appendf(&self, String format, args...) @maydiscard { if (!self.data()) self.tinit(format.len + 20); - @pool() - { - Formatter formatter; - formatter.init(&out_string_append_fn, self); - return formatter.vprintf(format, args); - }; + Formatter formatter; + formatter.init(&out_string_append_fn, self); + return formatter.vprintf(format, args); } fn usz? DString.appendfn(&self, String format, args...) @maydiscard diff --git a/lib/std/core/mem.c3 b/lib/std/core/mem.c3 index 94b84fd1f..e4eccd22b 100644 --- a/lib/std/core/mem.c3 +++ b/lib/std/core/mem.c3 @@ -571,6 +571,19 @@ fn void temp_pop(PoolState old_state) allocator::pop_pool(old_state) @inline; } +macro void @pool_init(Allocator allocator, usz pool_size, usz buffer_size; @body) @builtin +{ + Allocator current = allocator::current_temp; + TempAllocator* top = allocator::top_temp; + allocator::create_temp_allocator(allocator, pool_size, buffer_size); + defer + { + allocator::destroy_temp_allocators(); + allocator::top_temp = top; + allocator::current_temp = current; + } + @body(); +} macro void @pool(;@body) @builtin { PoolState state = allocator::push_pool() @inline; @@ -636,7 +649,7 @@ fn void* malloc_aligned(usz size, usz alignment) @builtin @inline @nodiscard fn void* tmalloc(usz size, usz alignment = 0) @builtin @inline @nodiscard { if (!size) return null; - return tmem().acquire(size, NO_ZERO, alignment)!!; + return tmem.acquire(size, NO_ZERO, alignment)!!; } <* @@ -814,7 +827,7 @@ fn void* calloc_aligned(usz size, usz alignment) @builtin @inline @nodiscard fn void* tcalloc(usz size, usz alignment = 0) @builtin @inline @nodiscard { if (!size) return null; - return tmem().acquire(size, ZERO, alignment)!!; + return tmem.acquire(size, ZERO, alignment)!!; } fn void* realloc(void *ptr, usz new_size) @builtin @inline @nodiscard @@ -841,7 +854,7 @@ fn void* trealloc(void* ptr, usz size, usz alignment = mem::DEFAULT_MEM_ALIGNMEN { if (!size) return null; if (!ptr) return tmalloc(size, alignment); - return tmem().resize(ptr, size, alignment)!!; + return tmem.resize(ptr, size, alignment)!!; } module std::core::mem @if(env::NO_LIBC); diff --git a/lib/std/core/mem_allocator.c3 b/lib/std/core/mem_allocator.c3 index 93fee8087..72ab37e26 100644 --- a/lib/std/core/mem_allocator.c3 +++ b/lib/std/core/mem_allocator.c3 @@ -359,10 +359,12 @@ alias mem @builtin = thread_allocator ; tlocal Allocator thread_allocator @private = base_allocator(); Allocator temp_base_allocator @private = base_allocator(); -typedef PoolState = void*; +typedef PoolState = TempAllocator*; -tlocal TempAllocator* current_temp; +const LazyTempAllocator LAZY_TEMP @private = {}; +tlocal Allocator current_temp = &LAZY_TEMP; tlocal TempAllocator* top_temp; +tlocal bool auto_create_temp = false; usz temp_allocator_min_size = temp_allocator_default_min_size(); usz temp_allocator_buffer_size = temp_allocator_default_buffer_size(); @@ -370,16 +372,16 @@ usz temp_allocator_new_mult = 4; fn PoolState push_pool() { - TempAllocator* old = current_temp ?: create_temp_allocator(); - current_temp = current_temp.derive_allocator(temp_allocator_min_size, temp_allocator_buffer_size, temp_allocator_new_mult)!!; - return (PoolState)old; + Allocator old = top_temp ? current_temp : create_temp_allocator_on_demand(); + current_temp = ((TempAllocator*)old).derive_allocator(temp_allocator_min_size, temp_allocator_buffer_size, temp_allocator_new_mult)!!; + return (PoolState)old.ptr; } fn void pop_pool(PoolState old) { - current_temp = (TempAllocator*)old; - current_temp.reset(); - + TempAllocator* temp = (TempAllocator*)old; + current_temp = temp; + temp.reset(); } macro Allocator base_allocator() @private @@ -424,18 +426,36 @@ macro usz temp_allocator_default_buffer_size() @local macro Allocator heap() => thread_allocator; <* - @require !current_temp : "This should never be called when temp already exists" + @require !top_temp : "This should never be called when temp already exists" *> -fn TempAllocator* create_temp_allocator() @private +fn Allocator create_temp_allocator_on_demand() @private { - return top_temp = current_temp = allocator::new_temp_allocator(base_allocator(), temp_allocator_size())!!; + if (!auto_create_temp) + { + auto_create_temp = true; + abort("Only the main thread pool is implicitly created. Use '@pool_init()' to enable the temp allocator on other threads."); + } + return create_temp_allocator(base_allocator(), temp_allocator_size()); } -macro Allocator temp() +<* + @require !top_temp : "This should never be called when temp already exists" +*> +fn Allocator create_temp_allocator(Allocator allocator, usz size, usz buffer = temp_allocator_default_buffer_size()) @private { - return current_temp ?: create_temp_allocator(); + return current_temp = top_temp = allocator::new_temp_allocator(allocator, size)!!; } -alias tmem @builtin = temp; +macro Allocator temp() +{ + return current_temp; +} + +alias tmem @builtin = current_temp; + +fn void allow_implicit_temp_allocator_on_load_thread() @init(1) @local @if(env::LIBC) +{ + auto_create_temp = true; +} fn void destroy_temp_allocators_after_exit() @finalizer(65535) @local @if(env::LIBC) { @@ -449,6 +469,27 @@ fn void destroy_temp_allocators() { if (!top_temp) return; top_temp.free(); + top_temp = null; + current_temp = &LAZY_TEMP; +} + +import libc; +typedef LazyTempAllocator (Allocator) @private = uptr; + +fn void*? LazyTempAllocator.acquire(&self, usz bytes, AllocInitType init_type, usz alignment) @dynamic +{ + if (!top_temp) create_temp_allocator_on_demand(); + return top_temp.acquire(bytes, init_type, alignment); +} + +fn void*? LazyTempAllocator.resize(&self, void* old_ptr, usz new_bytes, usz alignment) @dynamic +{ + if (!top_temp) create_temp_allocator_on_demand(); + return top_temp.resize(old_ptr, new_bytes, alignment); +} + +fn void LazyTempAllocator.release(&self, void* old_ptr, bool aligned) @dynamic +{ } const NullAllocator NULL_ALLOCATOR = {}; diff --git a/lib/std/core/runtime_benchmark.c3 b/lib/std/core/runtime_benchmark.c3 index c0f4e582a..0cb98d1f8 100644 --- a/lib/std/core/runtime_benchmark.c3 +++ b/lib/std/core/runtime_benchmark.c3 @@ -96,5 +96,5 @@ fn bool run_benchmarks(BenchmarkUnit[] benchmarks) fn bool default_benchmark_runner(String[] args) => @pool() { - return run_benchmarks(benchmark_collection_create(tmem())); + return run_benchmarks(benchmark_collection_create(tmem)); } diff --git a/lib/std/core/runtime_test.c3 b/lib/std/core/runtime_test.c3 index 6c41e1ec4..a0adce33e 100644 --- a/lib/std/core/runtime_test.c3 +++ b/lib/std/core/runtime_test.c3 @@ -329,6 +329,6 @@ fn bool run_tests(String[] args, TestUnit[] tests) @private fn bool default_test_runner(String[] args) => @pool() { assert(test_context == null, "test suite is already running"); - return run_tests(args, test_collection_create(tmem())); + return run_tests(args, test_collection_create(tmem)); } diff --git a/lib/std/core/string.c3 b/lib/std/core/string.c3 index 938cb284e..bec71f2f0 100644 --- a/lib/std/core/string.c3 +++ b/lib/std/core/string.c3 @@ -278,7 +278,7 @@ fn String[] String.split(s, Allocator allocator, String needle, usz max = 0, boo @param max : "Max number of elements, 0 means no limit, defaults to 0" @param skip_empty : "True to skip empty elements" *> -fn String[] String.tsplit(s, String needle, usz max = 0, bool skip_empty = false) => s.split(tmem(), needle, max, skip_empty) @inline; +fn String[] String.tsplit(s, String needle, usz max = 0, bool skip_empty = false) => s.split(tmem, needle, max, skip_empty) @inline; faultdef BUFFER_EXCEEDED; @@ -516,10 +516,10 @@ fn String String.concat(s1, Allocator allocator, String s2) return (String)str[:full_len]; } -fn String String.tconcat(s1, String s2) => s1.concat(tmem(), s2); +fn String String.tconcat(s1, String s2) => s1.concat(tmem, s2); -fn ZString String.zstr_tcopy(s) => s.zstr_copy(tmem()) @inline; +fn ZString String.zstr_tcopy(s) => s.zstr_copy(tmem) @inline; <* Copy this string, by duplicating the string, always adding a zero byte @@ -542,7 +542,7 @@ fn void String.free(&s, Allocator allocator) *s = ""; } -fn String String.tcopy(s) => s.copy(tmem()) @inline; +fn String String.tcopy(s) => s.copy(tmem) @inline; fn String ZString.copy(z, Allocator allocator) { @@ -551,7 +551,7 @@ fn String ZString.copy(z, Allocator allocator) fn String ZString.tcopy(z) { - return z.str_view().copy(tmem()) @inline; + return z.str_view().copy(tmem) @inline; } <* @@ -568,14 +568,14 @@ fn Char16[]? String.to_utf16(s, Allocator allocator) return data[:len16]; } -fn Char16[]? String.to_temp_utf16(s) => s.to_utf16(tmem()); +fn Char16[]? String.to_temp_utf16(s) => s.to_utf16(tmem); fn WString? String.to_wstring(s, Allocator allocator) { return (WString)s.to_utf16(allocator).ptr; } -fn WString? String.to_temp_wstring(s) => s.to_wstring(tmem()); +fn WString? String.to_temp_wstring(s) => s.to_wstring(tmem); fn Char32[]? String.to_utf32(s, Allocator allocator) { @@ -586,7 +586,7 @@ fn Char32[]? String.to_utf32(s, Allocator allocator) return data[:codepoints]; } -fn Char32[]? String.to_temp_utf32(s) => s.to_utf32(tmem()); +fn Char32[]? String.to_temp_utf32(s) => s.to_utf32(tmem); <* Convert a string to ASCII lower case in place. @@ -608,7 +608,7 @@ fn String String.to_lower_copy(s, Allocator allocator) fn String String.to_lower_tcopy(s) { - return s.to_lower_copy(tmem()); + return s.to_lower_copy(tmem); } <* @@ -648,7 +648,7 @@ fn StringIterator String.iterator(s) *> fn String String.to_upper_tcopy(s) { - return s.to_upper_copy(tmem()); + return s.to_upper_copy(tmem); } fn String? from_utf32(Allocator allocator, Char32[] utf32) @@ -679,8 +679,8 @@ fn String? from_wstring(Allocator allocator, WString wstring) return from_utf16(allocator, utf16); } -fn String? tfrom_wstring(WString wstring) => from_wstring(tmem(), wstring) @inline; -fn String? tfrom_utf16(Char16[] utf16) => from_utf16(tmem(), utf16) @inline; +fn String? tfrom_wstring(WString wstring) => from_wstring(tmem, wstring) @inline; +fn String? tfrom_utf16(Char16[] utf16) => from_utf16(tmem, utf16) @inline; fn usz String.utf8_codepoints(s) { @@ -839,4 +839,4 @@ macro String from_struct(Allocator allocator, x) }; } -macro String tfrom_struct(x) => from_struct(tmem(), x); +macro String tfrom_struct(x) => from_struct(tmem, x); diff --git a/lib/std/encoding/base32.c3 b/lib/std/encoding/base32.c3 index 1fb5a6d5a..efc346d83 100644 --- a/lib/std/encoding/base32.c3 +++ b/lib/std/encoding/base32.c3 @@ -40,8 +40,8 @@ fn char[]? decode(Allocator allocator, char[] src, char padding = DEFAULT_PAD, B return decode_buffer(src, dst, padding, alphabet); } -fn String? tencode(char[] code, char padding = DEFAULT_PAD, Base32Alphabet* alphabet = &STANDARD) @inline => encode(tmem(), code, padding, alphabet); -fn char[]? tdecode(char[] code, char padding = DEFAULT_PAD, Base32Alphabet* alphabet = &STANDARD) @inline => decode(tmem(), code, padding, alphabet); +fn String? tencode(char[] code, char padding = DEFAULT_PAD, Base32Alphabet* alphabet = &STANDARD) @inline => encode(tmem, code, padding, alphabet); +fn char[]? tdecode(char[] code, char padding = DEFAULT_PAD, Base32Alphabet* alphabet = &STANDARD) @inline => decode(tmem, code, padding, alphabet); <* Calculate the length in bytes of the decoded data. diff --git a/lib/std/encoding/base64.c3 b/lib/std/encoding/base64.c3 index 4bb6ef92a..d01574415 100644 --- a/lib/std/encoding/base64.c3 +++ b/lib/std/encoding/base64.c3 @@ -55,8 +55,8 @@ fn char[]? decode(Allocator allocator, char[] src, char padding = DEFAULT_PAD, B return decode_buffer(src, dst, padding, alphabet); } -fn String tencode(char[] code, char padding = DEFAULT_PAD, Base64Alphabet* alphabet = &STANDARD) @inline => encode(tmem(), code, padding, alphabet); -fn char[]? tdecode(char[] code, char padding = DEFAULT_PAD, Base64Alphabet* alphabet = &STANDARD) @inline => decode(tmem(), code, padding, alphabet); +fn String tencode(char[] code, char padding = DEFAULT_PAD, Base64Alphabet* alphabet = &STANDARD) @inline => encode(tmem, code, padding, alphabet); +fn char[]? tdecode(char[] code, char padding = DEFAULT_PAD, Base64Alphabet* alphabet = &STANDARD) @inline => decode(tmem, code, padding, alphabet); <* diff --git a/lib/std/encoding/csv.c3 b/lib/std/encoding/csv.c3 index c60ef8179..7a7273968 100644 --- a/lib/std/encoding/csv.c3 +++ b/lib/std/encoding/csv.c3 @@ -51,7 +51,7 @@ fn CsvRow? CsvReader.read_row(self, Allocator allocator) fn CsvRow? CsvReader.tread_row(self) { - return self.read_row(tmem()) @inline; + return self.read_row(tmem) @inline; } <* diff --git a/lib/std/encoding/hex.c3 b/lib/std/encoding/hex.c3 index 6e528ed3e..c2f28ad5d 100644 --- a/lib/std/encoding/hex.c3 +++ b/lib/std/encoding/hex.c3 @@ -25,8 +25,8 @@ fn char[]? decode(Allocator allocator, char[] code) return data[:decode_bytes(code, data)!]; } -fn String tencode(char[] code) @inline => encode(tmem(), code); -fn char[]? tdecode(char[] code) @inline => decode(tmem(), code); +fn String tencode(char[] code) @inline => encode(tmem, code); +fn char[]? tdecode(char[] code) @inline => decode(tmem, code); <* diff --git a/lib/std/encoding/json.c3 b/lib/std/encoding/json.c3 index 65f9676db..461f12929 100644 --- a/lib/std/encoding/json.c3 +++ b/lib/std/encoding/json.c3 @@ -15,7 +15,7 @@ fn Object*? parse_string(Allocator allocator, String s) fn Object*? tparse_string(String s) { - return parse(tmem(), (ByteReader){}.init(s)); + return parse(tmem, (ByteReader){}.init(s)); } fn Object*? parse(Allocator allocator, InStream s) @@ -32,7 +32,7 @@ fn Object*? parse(Allocator allocator, InStream s) fn Object*? tparse(InStream s) { - return parse(tmem(), s); + return parse(tmem, s); } // -- Implementation follows -- diff --git a/lib/std/io/file.c3 b/lib/std/io/file.c3 index 52b75b645..f06336a8b 100644 --- a/lib/std/io/file.c3 +++ b/lib/std/io/file.c3 @@ -201,7 +201,7 @@ fn char[]? load(Allocator allocator, String filename) fn char[]? load_path(Allocator allocator, Path path) => load(allocator, path.str_view()); -fn char[]? load_temp(String filename) => load(tmem(), filename); +fn char[]? load_temp(String filename) => load(tmem, filename); fn char[]? load_path_temp(Path path) => load_temp(path.str_view()); diff --git a/lib/std/io/io.c3 b/lib/std/io/io.c3 index 9f24434f5..8bfe75985 100644 --- a/lib/std/io/io.c3 +++ b/lib/std/io/io.c3 @@ -98,7 +98,7 @@ macro String? readline(Allocator allocator, stream = io::stdin()) *> macro String? treadline(stream = io::stdin()) { - return readline(tmem(), stream) @inline; + return readline(tmem, stream) @inline; } <* diff --git a/lib/std/io/path.c3 b/lib/std/io/path.c3 index 09ca26ea2..d98854c55 100644 --- a/lib/std/io/path.c3 +++ b/lib/std/io/path.c3 @@ -30,7 +30,7 @@ fn Path? cwd(Allocator allocator) { @pool() { - return new(allocator, os::getcwd(tmem())); + return new(allocator, os::getcwd(tmem)); }; } @@ -38,7 +38,7 @@ 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? tcwd() => cwd(tmem()) @inline; +fn Path? tcwd() => cwd(tmem) @inline; <* @require @is_pathlike(path) : "Expected a Path or String to chdir" @@ -150,7 +150,7 @@ fn Path? new(Allocator allocator, String path, PathEnv path_env = DEFAULT_ENV) *> fn Path? temp(String path, PathEnv path_env = DEFAULT_ENV) { - return new(tmem(), path, path_env); + return new(tmem, path, path_env); } fn Path? from_win32_wstring(Allocator allocator, WString path) => @pool() @@ -193,7 +193,7 @@ fn Path? Path.append(self, Allocator allocator, String filename) }; } -fn Path? Path.tappend(self, String filename) => self.append(tmem(), filename); +fn Path? Path.tappend(self, String filename) => self.append(tmem, filename); fn usz? start_of_base_name(String str, PathEnv path_env) @local { @@ -249,7 +249,7 @@ fn Path? Path.absolute(self, Allocator allocator) { @pool() { - String cwd = os::getcwd(tmem())!; + String cwd = os::getcwd(tmem)!; return new(allocator, cwd, self.env); }; } @@ -263,8 +263,8 @@ fn Path? Path.absolute(self, Allocator allocator) return { string::from_wstring(allocator, buffer), WIN32, allocator }; }; $else - String cwd = os::getcwd(tmem())!; - return (Path){ cwd, self.env, tmem() }.append(allocator, path_str)!; + String cwd = os::getcwd(tmem)!; + return (Path){ cwd, self.env, tmem }.append(allocator, path_str)!; $endif } @@ -273,7 +273,7 @@ fn String? String.file_basename(self, Allocator allocator) => @pool() return temp(self).basename().copy(allocator); } -fn String? String.file_tbasename(self) => self.file_basename(tmem()); +fn String? String.file_tbasename(self) => self.file_basename(tmem); fn String Path.basename(self) { @@ -283,7 +283,7 @@ fn String Path.basename(self) return path_str[basename_start..]; } -fn String? String.path_tdirname(self) => self.path_dirname(tmem()); +fn String? String.path_tdirname(self) => self.path_dirname(tmem); fn String? String.path_dirname(self, Allocator allocator) => @pool() { @@ -347,7 +347,7 @@ fn Path? String.to_path(self, Allocator allocator) fn Path? String.to_tpath(self) { - return new(tmem(), self); + return new(tmem, self); } fn usz? volume_name_len(String path, PathEnv path_env) @local diff --git a/lib/std/io/stream/bytebuffer.c3 b/lib/std/io/stream/bytebuffer.c3 index 3e4c9b6e8..3e086314d 100644 --- a/lib/std/io/stream/bytebuffer.c3 +++ b/lib/std/io/stream/bytebuffer.c3 @@ -26,7 +26,7 @@ fn ByteBuffer* ByteBuffer.init(&self, Allocator allocator, usz max_read, usz ini fn ByteBuffer* ByteBuffer.tinit(&self, usz max_read, usz initial_capacity = 16) { - return self.init(tmem(), max_read, initial_capacity); + return self.init(tmem, max_read, initial_capacity); } <* diff --git a/lib/std/io/stream/bytewriter.c3 b/lib/std/io/stream/bytewriter.c3 index a6a4c73a7..8a87e506c 100644 --- a/lib/std/io/stream/bytewriter.c3 +++ b/lib/std/io/stream/bytewriter.c3 @@ -27,7 +27,7 @@ fn ByteWriter* ByteWriter.init(&self, Allocator allocator) *> fn ByteWriter* ByteWriter.tinit(&self) { - return self.init(tmem()) @inline; + return self.init(tmem) @inline; } fn ByteWriter* ByteWriter.init_with_buffer(&self, char[] data) diff --git a/lib/std/io/stream/multireader.c3 b/lib/std/io/stream/multireader.c3 index 3aaf5b855..e1d00a3a3 100644 --- a/lib/std/io/stream/multireader.c3 +++ b/lib/std/io/stream/multireader.c3 @@ -33,7 +33,7 @@ fn MultiReader* MultiReader.init(&self, Allocator allocator, InStream... readers *> fn MultiReader* MultiReader.tinit(&self, InStream... readers) { - return self.init(tmem(), ...readers); + return self.init(tmem, ...readers); } fn void MultiReader.free(&self) diff --git a/lib/std/io/stream/multiwriter.c3 b/lib/std/io/stream/multiwriter.c3 index 793f4a26d..22c35c4bf 100644 --- a/lib/std/io/stream/multiwriter.c3 +++ b/lib/std/io/stream/multiwriter.c3 @@ -30,7 +30,7 @@ fn MultiWriter* MultiWriter.init(&self, Allocator allocator, OutStream... writer *> fn MultiWriter* MultiWriter.tinit(&self, OutStream... writers) { - return self.init(tmem(), ...writers); + return self.init(tmem, ...writers); } fn void MultiWriter.free(&self) diff --git a/lib/std/net/inetaddr.c3 b/lib/std/net/inetaddr.c3 index f2cf5bce0..96f7c2977 100644 --- a/lib/std/net/inetaddr.c3 +++ b/lib/std/net/inetaddr.c3 @@ -63,7 +63,7 @@ fn String InetAddress.to_string(&self, Allocator allocator) fn String InetAddress.to_tstring(&self) { - return string::format(tmem(), "%s", *self); + return string::format(tmem, "%s", *self); } fn InetAddress? ipv6_from_str(String s) diff --git a/lib/std/net/url.c3 b/lib/std/net/url.c3 index a3419df5e..365db081d 100644 --- a/lib/std/net/url.c3 +++ b/lib/std/net/url.c3 @@ -47,7 +47,7 @@ struct Url(Printable) @require url_string.len > 0 : "the url_string must be len 1 or more" @return "the parsed Url" *> -fn Url? tparse(String url_string) => parse(tmem(), url_string); +fn Url? tparse(String url_string) => parse(tmem, url_string); <* Parse a URL string into a Url struct. @@ -252,7 +252,7 @@ struct UrlQueryValues @param [in] query @return "a UrlQueryValues HashMap" *> -fn UrlQueryValues parse_query_to_temp(String query) => parse_query(tmem(), query); +fn UrlQueryValues parse_query_to_temp(String query) => parse_query(tmem, query); <* Parse the query parameters of the Url into a UrlQueryValues map. diff --git a/lib/std/net/url_encoding.c3 b/lib/std/net/url_encoding.c3 index 90c6156fa..815ea1299 100644 --- a/lib/std/net/url_encoding.c3 +++ b/lib/std/net/url_encoding.c3 @@ -100,7 +100,7 @@ fn String encode(Allocator allocator, String s, UrlEncodingMode mode) => @pool() @param mode : "Url encoding mode" @return "Percent-encoded String" *> -fn String tencode(String s, UrlEncodingMode mode) => encode(tmem(), s, mode); +fn String tencode(String s, UrlEncodingMode mode) => encode(tmem, s, mode); <* Calculate the length of the percent-decoded string. @@ -167,4 +167,4 @@ fn String? decode(Allocator allocator, String s, UrlEncodingMode mode) => @pool @param mode : "Url encoding mode" @return "Percent-decoded String" *> -fn String? tdecode(String s, UrlEncodingMode mode) => decode(tmem(), s, mode); +fn String? tdecode(String s, UrlEncodingMode mode) => decode(tmem, s, mode); diff --git a/lib/std/os/env.c3 b/lib/std/os/env.c3 index 4a40d6b49..525d09049 100644 --- a/lib/std/os/env.c3 +++ b/lib/std/os/env.c3 @@ -36,7 +36,7 @@ fn String? get_var(Allocator allocator, String name) => @pool() fn String? tget_var(String name) { - return get_var(tmem(), name); + return get_var(tmem, name); } <* diff --git a/lib/std/os/macos/darwin.c3 b/lib/std/os/macos/darwin.c3 index 59e081843..3c136662f 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 backtrace::SEGMENT_NOT_FOUND?; - String path = env::executable_path(tmem()) ?? backtrace::EXECUTABLE_PATH_NOT_FOUND?!; + String path = env::executable_path(tmem) ?? backtrace::EXECUTABLE_PATH_NOT_FOUND?!; uint dyld_count = darwin::_dyld_image_count(); for (uint i = 0; i < dyld_count; i++) { @@ -147,7 +147,7 @@ fn BacktraceList? symbolize_backtrace(Allocator allocator, void*[] backtrace) } @pool() { - String execpath = executable_path(tmem())!; + String execpath = executable_path(tmem)!; foreach (addr : backtrace) { list.push(backtrace_load_element(allocator, execpath, addr, load_addr) ?? backtrace::BACKTRACE_UNKNOWN); diff --git a/lib/std/threads/thread.c3 b/lib/std/threads/thread.c3 index a030da9f6..47e673de7 100644 --- a/lib/std/threads/thread.c3 +++ b/lib/std/threads/thread.c3 @@ -72,7 +72,11 @@ macro void OnceFlag.call(&flag, OnceFn func) => NativeOnceFlag.call_once((Native macro void yield() => os::native_thread_yield(); macro Thread current() => (Thread)os::native_thread_current(); -macro void exit(int result) => os::native_thread_exit(result); +macro void exit(int result) +{ + allocator::destroy_temp_allocators(); + os::native_thread_exit(result); +} macro void? sleep(Duration d) @maydiscard => os::native_sleep_nano(d.to_nano()); macro void? sleep_ms(ulong ms) @maydiscard => sleep(time::ms(ms)); macro void? sleep_ns(NanoDuration ns) @maydiscard => os::native_sleep_nano(ns); diff --git a/lib/std/time/format.c3 b/lib/std/time/format.c3 index 41ec56b6f..31a05af70 100644 --- a/lib/std/time/format.c3 +++ b/lib/std/time/format.c3 @@ -62,7 +62,7 @@ fn String format(Allocator allocator, DateTimeFormat type, TzDateTime dt) } } -fn String tformat(DateTimeFormat dt_format, TzDateTime dt) => format(tmem(), dt_format, dt); +fn String tformat(DateTimeFormat dt_format, TzDateTime dt) => format(tmem, dt_format, dt); fn String TzDateTime.format(self, Allocator allocator, DateTimeFormat dt_format) => format(allocator, dt_format, self); diff --git a/releasenotes.md b/releasenotes.md index 96210899f..054569744 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -40,6 +40,8 @@ - Temp allocator now supports more than 2 in-flight stacks. - Printing stacktrace uses its own temp allocator. - Allow inferred type on body parameters. E.g. `@stack_mem(1024; alloc) { ... };` +- Use `@pool_init()` to set up a temp pool on a thread. Only the main thread has implicit temp pool setup. +- `tmem` is now a variable. ### Fixes - Fix address sanitizer to work on MachO targets (e.g. MacOS). diff --git a/resources/testfragments/allocators_testing.c3 b/resources/testfragments/allocators_testing.c3 index bb33fd161..60fc088f8 100644 --- a/resources/testfragments/allocators_testing.c3 +++ b/resources/testfragments/allocators_testing.c3 @@ -9,7 +9,7 @@ enum Foo fn void print_pages() { - tmem().print_pages(io::stdout())!!; + tmem.print_pages(io::stdout())!!; } fn void setstring(char* dst, String str) @@ -63,7 +63,7 @@ fn void main() io::printf("First big: %p\n", first_big); print_pages(); }; - mem::@scoped(tmem()) + mem::@scoped(tmem) { io::printf("Malloc: %p\n", (void*)malloc(23)); io::printf("Malloc: %p\n", (void*)malloc(23)); @@ -73,8 +73,8 @@ fn void main() { io::printf("Talloc: %p\n", (void*)tmalloc(22)); }; - testAllocator(tmem(), 126); - testAllocator(tmem(), 12600); + testAllocator(tmem, 126); + testAllocator(tmem, 12600); ArenaAllocator aa; aa.init(&&char[1024] {}); testAllocator(&aa, 126); diff --git a/test/src/test_suite_runner.c3 b/test/src/test_suite_runner.c3 index 96437346d..23acb7167 100644 --- a/test/src/test_suite_runner.c3 +++ b/test/src/test_suite_runner.c3 @@ -476,7 +476,7 @@ fn void test_file(Path file_path) io::printfn(`FAILED - %s did not contain: "%s"`, file.name, next); io::printfn("\n\n\n---------------------------------------------------> %s\n\n", file.name); (void)file_ll.seek(0); - (void)io::printn((String)io::read_fully(tmem(), &file_ll)); + (void)io::printn((String)io::read_fully(tmem, &file_ll)); io::printfn("<---------------------------------------------------- %s\n", file_path); return; } @@ -496,7 +496,7 @@ fn void test_file(Path file_path) fn void? test_path(Path file_path) { (void)path::chdir(start_cwd); - foreach (file : path::ls(tmem(), file_path)!!) + foreach (file : path::ls(tmem, file_path)!!) { @pool() { diff --git a/test/test_suite/generic/generic_lambda_complex.c3t b/test/test_suite/generic/generic_lambda_complex.c3t index a08951b7d..760c6e37a 100644 --- a/test/test_suite/generic/generic_lambda_complex.c3t +++ b/test/test_suite/generic/generic_lambda_complex.c3t @@ -171,79 +171,62 @@ entry: %ft = alloca %TextTemplate, align 8 %error_var = alloca i64, align 8 %indirectarg = alloca %"char[]", align 8 - %indirectarg1 = alloca %any, align 8 %varargslots = alloca [1 x %any], align 16 - %indirectarg2 = alloca %"any[]", align 8 - %error_var3 = alloca i64, align 8 - %varargslots8 = alloca [1 x %any], align 16 - %indirectarg10 = alloca %"any[]", align 8 + %indirectarg1 = alloca %"any[]", align 8 + %error_var2 = alloca i64, align 8 + %varargslots7 = alloca [1 x %any], align 16 + %indirectarg9 = 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.allocator.current_temp, align 8 - %i2b = icmp ne ptr %0, null - br i1 %i2b, label %cond.lhs, label %cond.rhs - -cond.lhs: ; preds = %entry - br label %cond.phi - -cond.rhs: ; preds = %entry - %1 = call ptr @std.core.mem.allocator.create_temp_allocator() - br label %cond.phi - -cond.phi: ; preds = %cond.rhs, %cond.lhs - %val = phi ptr [ %0, %cond.lhs ], [ %1, %cond.rhs ] - %2 = insertvalue %any undef, ptr %val, 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 %ptradd = getelementptr inbounds i8, ptr %foo_tmpl, i64 8 %hi = load i64, ptr %ptradd, align 8 store %"char[]" { ptr @.str.2, i64 2 }, ptr %indirectarg, align 8 - store %any %3, ptr %indirectarg1, align 8 - %4 = call i64 @"abc$text_test.Foo$.TextTemplate.init"(ptr %ft, ptr %lo, i64 %hi, ptr @.str.1, i64 2, ptr byval(%"char[]") align 8 %indirectarg, ptr byval(%any) align 8 %indirectarg1) - %not_err = icmp eq i64 %4, 0 - %5 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) - br i1 %5, label %after_check, label %assign_optional + %0 = call i64 @"abc$text_test.Foo$.TextTemplate.init"(ptr %ft, ptr %lo, i64 %hi, ptr @.str.1, i64 2, ptr byval(%"char[]") align 8 %indirectarg, ptr byval(%any) align 8 @std.core.mem.allocator.current_temp) + %not_err = icmp eq i64 %0, 0 + %1 = call i1 @llvm.expect.i1(i1 %not_err, i1 true) + br i1 %1, label %after_check, label %assign_optional -assign_optional: ; preds = %cond.phi - store i64 %4, ptr %error_var, align 8 +assign_optional: ; preds = %entry + store i64 %0, ptr %error_var, align 8 br label %panic_block -after_check: ; preds = %cond.phi +after_check: ; preds = %entry br label %noerr_block panic_block: ; preds = %assign_optional - %6 = insertvalue %any undef, ptr %error_var, 0 - %7 = insertvalue %any %6, i64 ptrtoint (ptr @"$ct.fault" to i64), 1 - store %any %7, ptr %varargslots, align 16 - %8 = insertvalue %"any[]" undef, ptr %varargslots, 0 - %"$$temp" = insertvalue %"any[]" %8, i64 1, 1 - store %"any[]" %"$$temp", ptr %indirectarg2, align 8 - call void @std.core.builtin.panicf(ptr @.panic_msg, i64 36, ptr @.file + %2 = insertvalue %any undef, ptr %error_var, 0 + %3 = insertvalue %any %2, i64 ptrtoint (ptr @"$ct.fault" to i64), 1 + store %any %3, ptr %varargslots, align 16 + %4 = insertvalue %"any[]" undef, ptr %varargslots, 0 + %"$$temp" = insertvalue %"any[]" %4, i64 1, 1 + store %"any[]" %"$$temp", ptr %indirectarg1, align 8 + call void @std.core.builtin.panicf(ptr @.panic_msg, i64 36, ptr @.file, i64 25, ptr @.func, i64 4, i32 159, ptr byval(%"any[]") align 8 %indirectarg1) #3 unreachable noerr_block: ; preds = %after_check - %9 = call i64 @"abc$text_test.Foo$.TextTemplate.free"(ptr %ft) - %not_err4 = icmp eq i64 %9, 0 - %10 = call i1 @llvm.expect.i1(i1 %not_err4, i1 true) - br i1 %10, label %after_check6, label %assign_optional5 + %5 = call i64 @"abc$text_test.Foo$.TextTemplate.free"(ptr %ft) + %not_err3 = icmp eq i64 %5, 0 + %6 = call i1 @llvm.expect.i1(i1 %not_err3, i1 true) + br i1 %6, label %after_check5, label %assign_optional4 -assign_optional5: ; preds = %noerr_block - store i64 %9, ptr %error_var3, align 8 - br label %panic_block7 +assign_optional4: ; preds = %noerr_block + store i64 %5, ptr %error_var2, align 8 + br label %panic_block6 -after_check6: ; preds = %noerr_block - br label %noerr_block11 +after_check5: ; preds = %noerr_block + br label %noerr_block10 -panic_block7: ; preds = %assign_optional5 - %11 = insertvalue %any undef, ptr %error_var3, 0 - %12 = insertvalue %any %11, i64 ptrtoint (ptr @"$ct.fault" to i64), 1 - store %any %12, ptr %varargslots8, align 16 - %13 = insertvalue %"any[]" undef, ptr %varargslots8, 0 - %"$$temp9" = insertvalue %"any[]" %13, i64 1, 1 - store %"any[]" %"$$temp9", ptr %indirectarg10, align 8 - call void @std.core.builtin.panicf(ptr @.panic_msg, i64 36, ptr @.file, i64 25, ptr @.func, +panic_block6: ; preds = %assign_optional4 + %7 = insertvalue %any undef, ptr %error_var2, 0 + %8 = insertvalue %any %7, i64 ptrtoint (ptr @"$ct.fault" to i64), 1 + store %any %8, ptr %varargslots7, align 16 + %9 = insertvalue %"any[]" undef, ptr %varargslots7, 0 + %"$$temp8" = insertvalue %"any[]" %9, i64 1, 1 + store %"any[]" %"$$temp8", ptr %indirectarg9, align 8 + call void @std.core.builtin.panicf(ptr @.panic_msg, i64 36, ptr @.file, i64 25, ptr @.func, i64 4, i32 160, ptr byval(%"any[]") align 8 %indirectarg9) #3 unreachable -noerr_block11: ; preds = %after_check6 +noerr_block10: ; preds = %after_check5 ret void } diff --git a/test/unit/stdlib/mem/temp_mem.c3 b/test/unit/stdlib/mem/temp_mem.c3 index 69d58a211..d6a2d840f 100644 --- a/test/unit/stdlib/mem/temp_mem.c3 +++ b/test/unit/stdlib/mem/temp_mem.c3 @@ -18,7 +18,7 @@ fn String breakit(String s, Allocator a) { @pool() { - return inner2("foo".concat(tmem(), s), a); + return inner2("foo".concat(tmem, s), a); }; } @@ -52,7 +52,7 @@ fn String inner4(String s, Allocator a) { @pool() { - String y = s.concat(tmem(), "xy**********").copy(a); + String y = s.concat(tmem, "xy**********").copy(a); return y; }; }