Add location tracking for memory allocations.

This commit is contained in:
Christoffer Lerno
2023-11-09 11:08:36 +01:00
committed by Christoffer Lerno
parent e31f2a03ba
commit f39aa1a41e
16 changed files with 186 additions and 339 deletions

View File

@@ -86,9 +86,9 @@ struct GrowableBitSet
* @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())
fn GrowableBitSet* GrowableBitSet.init_new(&self, usz initial_capacity = 1, Allocator* allocator = mem::heap(), TrackingEnv* env = mem::get_tracking_env())
{
self.data.init_new(initial_capacity, allocator);
self.data.init_new(initial_capacity, allocator, env);
return self;
}

View File

@@ -22,14 +22,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.init_new(&self, usz initial_capacity = 16, Allocator* allocator = mem::heap())
fn List* List.init_new(&self, usz initial_capacity = 16, Allocator* allocator = mem::heap(), TrackingEnv* env = mem::get_tracking_env())
{
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.alloc_aligned(Type.sizeof * initial_capacity, .alignment = Type[1].alignof, .env = env)!!;
}
else
{

View File

@@ -26,13 +26,13 @@ struct HashMap
* @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())
fn HashMap* HashMap.init_new(&map, uint capacity = DEFAULT_INITIAL_CAPACITY, float load_factor = DEFAULT_LOAD_FACTOR, Allocator* allocator = mem::heap(), TrackingEnv* env = mem::get_tracking_env())
{
capacity = math::next_power_of_2(capacity);
map.allocator = allocator;
map.load_factor = load_factor;
map.threshold = (uint)(capacity * load_factor);
map.table = allocator.new_zero_array(Entry*, capacity);
map.table = allocator.new_zero_array(Entry*, capacity, .env = env);
return map;
}
@@ -62,9 +62,9 @@ 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.init_new_from_map(&self, HashMap* other_map, Allocator* allocator = mem::heap())
fn HashMap* HashMap.init_new_from_map(&self, HashMap* other_map, Allocator* allocator = mem::heap(), TrackingEnv* env = mem::get_tracking_env())
{
self.init_new(other_map.table.len, other_map.load_factor, allocator);
self.init_new(other_map.table.len, other_map.load_factor, allocator, env);
self.put_all_for_create(other_map);
return self;
}

View File

@@ -78,9 +78,9 @@ fn usz! Object.to_format(&self, Formatter* formatter) @dynamic
}
}
fn Object* new_obj(Allocator* allocator)
fn Object* new_obj(Allocator* allocator, TrackingEnv* env = mem::get_tracking_env())
{
Object* o = allocator.new(Object);
Object* o = allocator.new(Object, .env = env);
*o = { .allocator = allocator, .type = void.typeid };
return o;
}

View File

@@ -36,9 +36,9 @@ struct PrivatePriorityQueue (Printable)
Heap heap;
}
fn void PrivatePriorityQueue.init_new(&self, usz initial_capacity = 16, Allocator* allocator = mem::heap()) @inline
fn void PrivatePriorityQueue.init_new(&self, usz initial_capacity = 16, Allocator* allocator = mem::heap(), TrackingEnv* env = mem::get_tracking_env()) @inline
{
self.heap.init_new(initial_capacity, allocator);
self.heap.init_new(initial_capacity, allocator, .env = env);
}
fn void PrivatePriorityQueue.init_temp(&self, usz initial_capacity = 16) @inline

View File

@@ -8,10 +8,10 @@ const usz MIN_CAPACITY @private = 16;
/**
* @require !self.data() "String already initialized"
**/
fn DString DString.init_new(&self, usz capacity = MIN_CAPACITY, Allocator* allocator = mem::heap())
fn DString DString.init_new(&self, usz capacity = MIN_CAPACITY, Allocator* allocator = mem::heap(), TrackingEnv* env = mem::get_tracking_env())
{
if (capacity < MIN_CAPACITY) capacity = MIN_CAPACITY;
StringData* data = allocator.new(StringData, .end_padding = capacity);
StringData* data = allocator.new(StringData, .end_padding = capacity, .env = env);
data.allocator = allocator;
data.len = 0;
data.capacity = capacity;
@@ -27,17 +27,17 @@ fn DString DString.init_temp(&self, usz capacity = MIN_CAPACITY)
return *self;
}
fn DString new_with_capacity(usz capacity, Allocator* allocator = mem::heap())
fn DString new_with_capacity(usz capacity, Allocator* allocator = mem::heap(), TrackingEnv* env = mem::get_tracking_env())
{
return DString{}.init_new(capacity, allocator);
return DString{}.init_new(capacity, allocator, .env = env);
}
fn DString temp_with_capacity(usz capacity) => new_with_capacity(capacity, mem::temp()) @inline;
fn DString new(String c = "", Allocator* allocator = mem::heap())
fn DString new(String c = "", Allocator* allocator = mem::heap(), TrackingEnv* env = mem::get_tracking_env())
{
usz len = c.len;
StringData* data = (StringData*)new_with_capacity(len, allocator);
StringData* data = (StringData*)new_with_capacity(len, allocator, env);
if (len)
{
data.len = len;
@@ -48,10 +48,10 @@ fn DString new(String c = "", Allocator* allocator = mem::heap())
fn DString temp_new(String s = "") => new(s, mem::temp()) @inline;
fn DString DString.new_concat(self, DString b, Allocator* allocator = mem::heap())
fn DString DString.new_concat(self, DString b, Allocator* allocator = mem::heap(), TrackingEnv* env = mem::get_tracking_env())
{
DString string;
string.init_new(self.len() + b.len(), allocator);
string.init_new(self.len() + b.len(), allocator, env);
string.append(self);
string.append(b);
return string;
@@ -148,37 +148,37 @@ fn void DString.append_char32(&self, Char32 c)
fn DString DString.tcopy(&self) => self.copy(mem::temp());
fn DString DString.copy(self, Allocator* allocator = null)
fn DString DString.copy(self, Allocator* allocator = null, TrackingEnv* env = mem::get_tracking_env())
{
if (!self)
{
if (allocator) return new_with_capacity(0, allocator);
if (allocator) return new_with_capacity(0, allocator, env);
return (DString)null;
}
StringData* data = self.data();
if (!allocator) allocator = mem::heap();
DString new_string = new_with_capacity(data.capacity, allocator);
DString new_string = new_with_capacity(data.capacity, allocator, env);
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 = mem::heap(), TrackingEnv* env = mem::get_tracking_env())
{
usz str_len = self.len();
if (!str_len)
{
return (ZString)allocator.calloc(1);
return (ZString)allocator.calloc(1, env);
}
char* zstr = allocator.alloc(str_len + 1);
char* zstr = allocator.alloc(str_len + 1, env);
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 = mem::heap(), TrackingEnv* env = mem::get_tracking_env())
{
return (String)self.copy_zstr(allocator)[:self.len()];
return (String)self.copy_zstr(allocator, env)[:self.len()];
}
fn String DString.tcopy_str(self) => self.copy_str(mem::temp()) @inline;
@@ -240,9 +240,9 @@ 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 = mem::heap(), TrackingEnv* env = mem::get_tracking_env())
{
return self.str_view().to_new_utf32(allocator) @inline!!;
return self.str_view().to_new_utf32(allocator, env) @inline!!;
}
fn void DString.append_string(&self, DString str)
@@ -354,7 +354,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 = mem::heap(), TrackingEnv* env = mem::get_tracking_env())
{
if (!s.len) return (DString)null;
usz total_size = joiner.len * s.len;
@@ -362,7 +362,7 @@ fn DString new_join(String[] s, String joiner, Allocator* allocator = mem::heap(
{
total_size += str.len;
}
DString res = new_with_capacity(total_size, allocator);
DString res = new_with_capacity(total_size, allocator, env);
res.append(s[0]);
foreach (String* &str : s[1..])
{
@@ -384,12 +384,12 @@ fn StringData* DString.data(self) @inline @private
return (StringData*)self;
}
fn void DString.reserve(&self, usz addition)
fn void DString.reserve(&self, usz addition, TrackingEnv* env = mem::get_tracking_env())
{
StringData* data = self.data();
if (!data)
{
*self = dstring::new_with_capacity(addition);
*self = dstring::new_with_capacity(addition, .env = env);
return;
}
usz len = data.len + addition;
@@ -398,7 +398,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)data.allocator.realloc(data, StringData.sizeof + new_capacity, env);
}
fn usz! DString.read_from_stream(&self, InStream* reader)

View File

@@ -385,6 +385,20 @@ macro void @scoped(Allocator* allocator; @body())
@body();
}
macro void @report_heap_allocs_in_scope(;@body())
{
TrackingAllocator tracker;
tracker.init(thread_allocator);
Allocator* old_allocator = thread_allocator;
thread_allocator = &tracker;
defer
{
thread_allocator = old_allocator;
tracker.print_report();
tracker.free();
}
@body();
}
macro void @stack_mem(usz $size; @body(Allocator* mem)) @builtin
{
@@ -494,11 +508,21 @@ fn void initialize_wasm_mem() @init(1) @private
thread_allocator = &wasm_allocator;
}
module std::core::mem @if(!env::TRACK_MEMORY);
module std::core::mem;
macro @clone(value) @builtin
macro TrackingEnv* get_tracking_env()
{
return mem::heap().clone(value);
$if env::TRACK_MEMORY:
return &&TrackingEnv { $$FILE, $$FUNC, $$LINE };
$else
return null;
$endif
}
macro @clone(value, TrackingEnv* env = mem::get_tracking_env()) @builtin
{
return mem::heap().clone(value, env);
}
macro @tclone(value) @builtin
@@ -506,24 +530,24 @@ macro @tclone(value) @builtin
return mem::temp().clone(value);
}
fn void* malloc(usz size) @builtin @inline
fn void* malloc(usz size, TrackingEnv* env = mem::get_tracking_env()) @builtin @inline
{
return mem::heap().alloc(size);
return mem::heap().alloc(size, env);
}
fn void* tmalloc(usz size, usz alignment = 0, usz offset = 0) @builtin @inline
fn void* tmalloc(usz size, usz alignment = 0, usz offset = 0, TrackingEnv* env = mem::get_tracking_env()) @builtin @inline
{
return temp().acquire(size, false, alignment, offset, null)!!;
return temp().acquire(size, false, alignment, offset, env)!!;
}
macro new($Type)
macro new($Type, TrackingEnv* env = mem::get_tracking_env())
{
return heap().new($Type);
return heap().new($Type, .env = env);
}
macro new_clear($Type)
macro new_clear($Type, TrackingEnv* env = mem::get_tracking_env())
{
return heap().new_clear($Type);
return heap().new_clear($Type, env);
}
macro new_temp($Type)
@@ -536,9 +560,9 @@ macro new_temp_clear($Type)
return tcalloc($Type.sizeof);
}
macro new_array($Type, usz elements)
macro new_array($Type, usz elements, TrackingEnv* env = mem::get_tracking_env())
{
return heap().new_array($Type, elements);
return heap().new_array($Type, elements, .env = env);
}
macro temp_array($Type, usz elements)
@@ -546,9 +570,9 @@ macro temp_array($Type, usz elements)
return (($Type*)tmalloc($Type.sizeof * elements, $Type.alignof))[:elements];
}
macro new_zero_array($Type, usz elements)
macro new_zero_array($Type, usz elements, TrackingEnv* env = mem::get_tracking_env())
{
return heap().new_zero_array($Type, elements);
return heap().new_zero_array($Type, elements, env);
}
macro temp_zero_array($Type, usz elements)
@@ -556,9 +580,9 @@ macro temp_zero_array($Type, usz elements)
return (($Type*)tcalloc($Type.sizeof * elements, $Type.alignof))[:elements];
}
fn void* calloc(usz size) @builtin @inline
fn void* calloc(usz size, TrackingEnv* env = mem::get_tracking_env()) @builtin @inline
{
return heap().calloc(size);
return heap().calloc(size, env);
}
fn void* tcalloc(usz size, usz alignment = 0, usz offset = 0) @builtin @inline
@@ -566,14 +590,14 @@ fn void* tcalloc(usz size, usz alignment = 0, usz offset = 0) @builtin @inline
return temp().acquire(size, false, alignment, offset, null)!!;
}
fn void* realloc(void *ptr, usz new_size) @builtin @inline
fn void* realloc(void *ptr, usz new_size, TrackingEnv* env = mem::get_tracking_env()) @builtin @inline
{
return heap().realloc(ptr, new_size);
return heap().realloc(ptr, new_size, env);
}
fn void free(void* ptr) @builtin @inline
fn void free(void* ptr, TrackingEnv* env = mem::get_tracking_env()) @builtin @inline
{
heap().free(ptr);
heap().free(ptr, env);
}
fn void* trealloc(void* ptr, usz size, usz alignment = mem::DEFAULT_MEM_ALIGNMENT) @builtin @inline

View File

@@ -9,6 +9,8 @@ struct TrackingEnv
String function;
uint line;
}
interface Allocator
{
fn void reset(usz mark) @optional;
@@ -103,116 +105,120 @@ fn usz alignment_for_allocation(usz alignment) @inline @private
return alignment < mem::DEFAULT_MEM_ALIGNMENT ? alignment = mem::DEFAULT_MEM_ALIGNMENT : alignment;
}
module std::core::mem::allocator @if(!env::TRACK_MEMORY);
// Allocator "functions"
macro void*! Allocator.alloc_checked(&self, usz size)
macro void*! Allocator.alloc_checked(&self, usz size, TrackingEnv* env = mem::get_tracking_env())
{
$if env::TESTING:
char* data = self.acquire(size, false, 0, 0, null)!;
char* data = self.acquire(size, false, 0, 0, env)!;
mem::set(data, 0xAA, size, mem::DEFAULT_MEM_ALIGNMENT);
return data;
$else
return self.acquire(size, false, 0, 0, null);
return self.acquire(size, false, 0, 0, env);
$endif
}
macro void*! Allocator.calloc_checked(&self, usz size) => self.acquire(size, true, 0, 0, null);
macro void*! Allocator.realloc_checked(&self, void* ptr, usz new_size) => self.resize(ptr, new_size, 0, 0, null);
macro Allocator.new_array(&self, $Type, usz size, usz end_padding = 0)
macro void*! Allocator.calloc_checked(&self, usz size, TrackingEnv* env = mem::get_tracking_env())
{
return (($Type*)self.alloc_checked($Type.sizeof * size + end_padding))[:size]!!;
return self.acquire(size, true, 0, 0, env);
}
macro void*! Allocator.realloc_checked(&self, void* ptr, usz new_size, TrackingEnv* env = mem::get_tracking_env())
{
return self.resize(ptr, new_size, 0, 0, env);
}
macro Allocator.new_array_checked(&self, $Type, usz size, usz end_padding = 0)
macro Allocator.new_array(&self, $Type, usz size, usz end_padding = 0, TrackingEnv* env = mem::get_tracking_env())
{
return (($Type*)self.alloc_checked($Type.sizeof * size + end_padding))[:size];
return (($Type*)self.alloc_checked($Type.sizeof * size + end_padding, env))[:size]!!;
}
macro Allocator.new_zero_array(&self, $Type, usz size, usz end_padding = 0)
macro Allocator.new_array_checked(&self, $Type, usz size, usz end_padding = 0, TrackingEnv* env = mem::get_tracking_env())
{
return (($Type*)self.calloc_checked($Type.sizeof * size + end_padding))[:size]!!;
return (($Type*)self.alloc_checked($Type.sizeof * size + end_padding, env))[:size];
}
macro Allocator.new_zero_array_checked(&self, $Type, usz size, usz end_padding = 0)
macro Allocator.new_zero_array(&self, $Type, usz size, usz end_padding = 0, TrackingEnv* env = mem::get_tracking_env())
{
return (($Type*)self.calloc_checked($Type.sizeof * size + end_padding))[:size];
return (($Type*)self.calloc_checked($Type.sizeof * size + end_padding, env))[:size]!!;
}
macro Allocator.new(&self, $Type, usz end_padding = 0) @nodiscard
macro Allocator.new_zero_array_checked(&self, $Type, usz size, usz end_padding = 0, TrackingEnv* env = mem::get_tracking_env())
{
return ($Type*)self.alloc_checked($Type.sizeof + end_padding)!!;
return (($Type*)self.calloc_checked($Type.sizeof * size + end_padding, env))[:size];
}
macro Allocator.new_checked(&self, $Type, usz end_padding = 0) @nodiscard
macro Allocator.new(&self, $Type, usz end_padding = 0, TrackingEnv* env = mem::get_tracking_env()) @nodiscard
{
return ($Type*)self.alloc_checked($Type.sizeof + end_padding);
return ($Type*)self.alloc_checked($Type.sizeof + end_padding, env)!!;
}
macro Allocator.new_clear(&self, $Type, usz end_padding = 0) @nodiscard
macro Allocator.new_checked(&self, $Type, usz end_padding = 0, TrackingEnv* env = mem::get_tracking_env()) @nodiscard
{
return ($Type*)self.calloc_checked($Type.sizeof + end_padding)!!;
return ($Type*)self.alloc_checked($Type.sizeof + end_padding, env);
}
macro Allocator.new_clear_checked(&self, $Type, usz end_padding = 0) @nodiscard
macro Allocator.new_clear(&self, $Type, usz end_padding = 0, TrackingEnv* env = mem::get_tracking_env()) @nodiscard
{
return ($Type*)self.calloc_checked($Type.sizeof + end_padding);
return ($Type*)self.calloc_checked($Type.sizeof + end_padding, env)!!;
}
macro Allocator.clone(&self, value)
macro Allocator.new_clear_checked(&self, $Type, usz end_padding = 0, TrackingEnv* env = mem::get_tracking_env()) @nodiscard
{
var x = self.alloc($typeof(value));
return ($Type*)self.calloc_checked($Type.sizeof + end_padding, env);
}
macro Allocator.clone(&self, value, TrackingEnv* env = mem::get_tracking_env())
{
var x = self.alloc($typeof(value), env);
*x = value;
return x;
}
macro void* Allocator.alloc(&self, usz size) @nodiscard
macro void* Allocator.alloc(&self, usz size, TrackingEnv* env = mem::get_tracking_env()) @nodiscard
{
return self.alloc_checked(size)!!;
return self.alloc_checked(size, env)!!;
}
macro void* Allocator.calloc(&self, usz size) @nodiscard
macro void* Allocator.calloc(&self, usz size, TrackingEnv* env = mem::get_tracking_env()) @nodiscard
{
return self.acquire(size, true, 0, 0, null)!!;
return self.acquire(size, true, 0, 0, env)!!;
}
macro void* Allocator.realloc(&self, void* ptr, usz new_size) @nodiscard
macro void* Allocator.realloc(&self, void* ptr, usz new_size, TrackingEnv* env = mem::get_tracking_env()) @nodiscard
{
return self.resize(ptr, new_size, 0, 0, null)!!;
return self.resize(ptr, new_size, 0, 0, env)!!;
}
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, TrackingEnv* env = mem::get_tracking_env())
{
$if env::TESTING:
char* data = self.acquire(size, false, alignment, offset, null)!;
char* data = self.acquire(size, false, alignment, offset, env)!;
mem::set(data, 0xAA, size, mem::DEFAULT_MEM_ALIGNMENT);
return data;
$else
return self.acquire(size, false, alignment, offset, null);
return self.acquire(size, false, alignment, offset, env);
$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, TrackingEnv* env = mem::get_tracking_env())
{
return self.acquire(size, true, alignment, offset, null);
return self.acquire(size, true, alignment, offset, env);
}
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, TrackingEnv* env = mem::get_tracking_env())
{
return self.resize(ptr, new_size, alignment, offset, null);
return self.resize(ptr, new_size, alignment, offset, env);
}
macro void Allocator.free(&self, void* ptr)
macro void Allocator.free(&self, void* ptr, TrackingEnv* env = mem::get_tracking_env())
{
$if env::TESTING:
if (ptr) ((char*)ptr)[0] = 0xBA;
$endif
self.release(ptr, false, null);
self.release(ptr, false, env);
}
macro void Allocator.free_aligned(&self, void* ptr)
macro void Allocator.free_aligned(&self, void* ptr, TrackingEnv* env = mem::get_tracking_env())
{
$if env::TESTING:
if (ptr) ((char*)ptr)[0] = 0xBA;
$endif
self.release(ptr, true, null);
self.release(ptr, true, env);
}

View File

@@ -1,194 +0,0 @@
module std::core::mem @if(env::TRACK_MEMORY);
macro @clone(value, String file = $$FILE, String func = $$FUNC, uint line = $$LINE) @builtin
{
return mem::heap().clone(value, .file = file, .func = func, .line = line);
}
macro @tclone(value, String file = $$FILE, String func = $$FUNC, uint line = $$LINE) @builtin
{
return mem::temp().clone(value, .file = file, .func = func, .line = line);
}
fn void* malloc(usz size, String file = $$FILE, String func = $$FUNC, uint line = $$LINE) @builtin @inline
{
return mem::heap().alloc(size, .file = file, .func = func, .line = line);
}
fn void* tmalloc(usz size, usz alignment = 0, usz offset = 0, String file = $$FILE, String func = $$FUNC, uint line = $$LINE) @builtin @inline
{
return temp().acquire(size, false, alignment, offset, .env = &&TrackingEnv{ file, func, line})!!;
}
macro new($Type, String file = $$FILE, String func = $$FUNC, uint line = $$LINE)
{
return heap().new($Type, .file = file, .func = func, .line = line);
}
macro new_clear($Type, String file = $$FILE, String func = $$FUNC, uint line = $$LINE)
{
return heap().new_clear($Type, .file = file, .func = func, .line = line);
}
macro new_temp($Type, String file = $$FILE, String func = $$FUNC, uint line = $$LINE)
{
return tmalloc($Type.sizeof, .file = file, .func = func, .line = line);
}
macro new_temp_clear($Type, String file = $$FILE, String func = $$FUNC, uint line = $$LINE)
{
return tcalloc($Type.sizeof, .file = file, .func = func, .line = line);
}
macro new_array($Type, usz elements, String file = $$FILE, String func = $$FUNC, uint line = $$LINE)
{
return heap().new_array($Type, elements, .file = file, .func = func, .line = line);
}
macro temp_array($Type, usz elements, String file = $$FILE, String func = $$FUNC, uint line = $$LINE)
{
return (($Type*)tmalloc($Type.sizeof * elements, $Type.alignof, .file = file, .func = func, .line = line))[:elements];
}
macro new_zero_array($Type, usz elements, String file = $$FILE, String func = $$FUNC, uint line = $$LINE)
{
return heap().new_zero_array($Type, elements, .file = file, .func = func, .line = line);
}
macro temp_zero_array($Type, usz elements, String file = $$FILE, String func = $$FUNC, uint line = $$LINE)
{
return (($Type*)tcalloc($Type.sizeof * elements, $Type.alignof, .file = file, .func = func, .line = line))[:elements];
}
fn void* calloc(usz size, String file = $$FILE, String func = $$FUNC, uint line = $$LINE) @builtin @inline
{
return heap().calloc(size, .file = file, .func = func, .line = line);
}
fn void* tcalloc(usz size, usz alignment = 0, usz offset = 0, String file = $$FILE, String func = $$FUNC, uint line = $$LINE) @builtin @inline
{
return temp().acquire(size, false, alignment, offset, .env = &&TrackingEnv{ file, func, line})!!;
}
fn void* realloc(void *ptr, usz new_size, String file = $$FILE, String func = $$FUNC, uint line = $$LINE) @builtin @inline
{
return heap().realloc(ptr, new_size, .file = file, .func = func, .line = line);
}
fn void free(void* ptr, String file = $$FILE, String func = $$FUNC, uint line = $$LINE) @builtin @inline
{
heap().free(ptr, .file = file, .func = func, .line = line);
}
fn void* trealloc(void* ptr, usz size, usz alignment = mem::DEFAULT_MEM_ALIGNMENT, String file = $$FILE, String func = $$FUNC, uint line = $$LINE) @builtin @inline
{
return temp().resize(ptr, size, alignment, 0, .env = &&TrackingEnv{ file, func, line})!!;
}
module std::core::mem::allocator @if(env::TRACK_MEMORY);
macro void*! Allocator.alloc_checked(&self, usz size, String file = $$FILE, String func = $$FUNC, uint line = $$LINE)
{
char* data = self.acquire(size, false, 0, 0, .env = &&TrackingEnv{ file, func, line})!;
mem::set(data, 0xAA, size, mem::DEFAULT_MEM_ALIGNMENT);
return data;
}
macro void*! Allocator.calloc_checked(&self, usz size, String file = $$FILE, String func = $$FUNC, uint line = $$LINE)
{
return self.acquire(size, true, 0, 0, .env = &&TrackingEnv{ file, func, line});
}
macro void*! Allocator.realloc_checked(&self, void* ptr, usz new_size, String file = $$FILE, String func = $$FUNC, uint line = $$LINE)
{
return self.resize(ptr, new_size, 0, 0, .env = &&TrackingEnv{ file, func, line});
}
macro Allocator.new_array(&self, $Type, usz size, usz end_padding = 0, String file = $$FILE, String func = $$FUNC, uint line = $$LINE)
{
return (($Type*)self.alloc_checked($Type.sizeof * size + end_padding, .file = file, .func = func, .line = line))[:size]!!;
}
macro Allocator.new_array_checked(&self, $Type, usz size, usz end_padding = 0, String file = $$FILE, String func = $$FUNC, uint line = $$LINE)
{
return (($Type*)self.alloc_checked($Type.sizeof * size + end_padding, .file = file, .func = func, .line = line))[:size];
}
macro Allocator.new_zero_array(&self, $Type, usz size, usz end_padding = 0, String file = $$FILE, String func = $$FUNC, uint line = $$LINE)
{
return (($Type*)self.calloc_checked($Type.sizeof * size + end_padding, .file = file, .func = func, .line = line))[:size]!!;
}
macro Allocator.new_zero_array_checked(&self, $Type, usz size, usz end_padding = 0, String file = $$FILE, String func = $$FUNC, uint line = $$LINE)
{
return (($Type*)self.calloc_checked($Type.sizeof * size + end_padding, .file = file, .func = func, .line = line))[:size];
}
macro Allocator.new(&self, $Type, usz end_padding = 0, String file = $$FILE, String func = $$FUNC, uint line = $$LINE) @nodiscard
{
return ($Type*)self.alloc_checked($Type.sizeof + end_padding, .file = file, .func = func, .line = line)!!;
}
macro Allocator.new_checked(&self, $Type, usz end_padding = 0, String file = $$FILE, String func = $$FUNC, uint line = $$LINE) @nodiscard
{
return ($Type*)self.alloc_checked($Type.sizeof + end_padding, .file = file, .func = func, .line = line);
}
macro Allocator.new_clear(&self, $Type, usz end_padding = 0, String file = $$FILE, String func = $$FUNC, uint line = $$LINE) @nodiscard
{
return ($Type*)self.calloc_checked($Type.sizeof + end_padding, .file = file, .func = func, .line = line)!!;
}
macro Allocator.new_clear_checked(&self, $Type, usz end_padding = 0, String file = $$FILE, String func = $$FUNC, uint line = $$LINE) @nodiscard
{
return ($Type*)self.calloc_checked($Type.sizeof + end_padding, .file = file, .func = func, .line = line);
}
macro Allocator.clone(&self, value, String file = $$FILE, String func = $$FUNC, uint line = $$LINE)
{
var x = self.alloc($typeof(value), .file = file, .func = func, .line = line);
*x = value;
return x;
}
macro void* Allocator.alloc(&self, usz size, String file = $$FILE, String func = $$FUNC, uint line = $$LINE) @nodiscard
{
return self.alloc_checked(size, .file = file, .func = func, .line = line)!!;
}
macro void* Allocator.calloc(&self, usz size, String file = $$FILE, String func = $$FUNC, uint line = $$LINE) @nodiscard
{
return self.acquire(size, true, 0, 0, .env = &&TrackingEnv{ file, func, line})!!;
}
macro void* Allocator.realloc(&self, void* ptr, usz new_size, String file = $$FILE, String func = $$FUNC, uint line = $$LINE) @nodiscard
{
return self.resize(ptr, new_size, 0, 0, .env = &&TrackingEnv{ file, func, line})!!;
}
macro void*! Allocator.alloc_aligned(&self, usz size, usz alignment, usz offset = 0, String file = $$FILE, String func = $$FUNC, uint line = $$LINE)
{
$if env::TESTING:
char* data = self.acquire(size, false, alignment, offset, .env = &&TrackingEnv{ file, func, line})!;
mem::set(data, 0xAA, size, mem::DEFAULT_MEM_ALIGNMENT);
return data;
$else
return self.acquire(size, false, alignment, offset, .env = &&TrackingEnv{ file, func, line});
$endif
}
macro void*! Allocator.calloc_aligned(&self, usz size, usz alignment, usz offset = 0, String file = $$FILE, String func = $$FUNC, uint line = $$LINE)
{
return self.acquire(size, true, alignment, offset, .env = &&TrackingEnv{ file, func, line});
}
macro void*! Allocator.realloc_aligned(&self, void* ptr, usz new_size, usz alignment = 0, usz offset = 0, String file = $$FILE, String func = $$FUNC, uint line = $$LINE)
{
return self.resize(ptr, new_size, alignment, offset, .env = &&TrackingEnv{ file, func, line});
}
macro void Allocator.free(&self, void* ptr, String file = $$FILE, String func = $$FUNC, uint line = $$LINE)
{
if (ptr) ((char*)ptr)[0] = 0xBA;
self.release(ptr, false, .env = &&TrackingEnv{ file, func, line});
}
macro void Allocator.free_aligned(&self, void* ptr, String file = $$FILE, String func = $$FUNC, uint line = $$LINE)
{
if (ptr) ((char*)ptr)[0] = 0xBA;
self.release(ptr, true, .env = &&TrackingEnv{ file, func, line});
}

View File

@@ -38,13 +38,13 @@ 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 = mem::heap(), TrackingEnv* env = mem::get_tracking_env())
{
@pool(allocator)
{
DString str = dstring::temp_with_capacity(fmt.len + $vacount * 8);
str.appendf(fmt, $vasplat());
return str.copy_str(allocator);
return str.copy_str(allocator, env);
};
}
@@ -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 = mem::heap(), TrackingEnv* env = mem::get_tracking_env())
{
if (!s)
{
return (String)allocator.new_zero_array(char, 2)[:0];
return (String)allocator.new_zero_array(char, 2, .env = env)[:0];
}
usz total_size = joiner.len * s.len;
@@ -76,7 +76,7 @@ fn String join_new(String[] s, String joiner, Allocator* allocator = mem::heap()
res.append(joiner);
res.append(*str);
}
return res.copy_str(allocator);
return res.copy_str(allocator, env);
};
}
@@ -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 = mem::heap(), TrackingEnv* env = mem::get_tracking_env())
{
usz capacity = 16;
usz i = 0;
String* holder = allocator.new_array(String, capacity);
String* holder = allocator.new_array(String, capacity, .env = env);
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(holder, String.sizeof * capacity, env);
}
holder[i++] = res;
}
@@ -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 = mem::heap(), TrackingEnv* env = mem::get_tracking_env())
{
usz len = s.len;
char* str = allocator.alloc(len + 1);
char* str = allocator.alloc(len + 1, env);
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 = mem::heap(), TrackingEnv* env = mem::get_tracking_env())
{
usz full_len = s1.len + s2.len;
char* str = allocator.alloc(full_len + 1);
char* str = allocator.alloc(full_len + 1, env);
usz s1_len = s1.len;
mem::copy(str, s1.ptr, s1_len);
mem::copy(str + s1_len, s2.ptr, s2.len);
@@ -337,27 +337,27 @@ fn String String.tconcat(s1, String s2) => s1.concat(s2, mem::temp());
fn ZString String.zstr_tcopy(s) => s.zstr_copy(mem::temp()) @inline;
fn String String.copy(s, Allocator* allocator = mem::heap())
fn String String.copy(s, Allocator* allocator = mem::heap(), TrackingEnv* env = mem::get_tracking_env())
{
usz len = s.len;
char* str = allocator.alloc(len + 1);
char* str = allocator.alloc(len + 1, env);
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 = mem::heap(), TrackingEnv* env = mem::get_tracking_env())
{
if (!s.len) return;
allocator.free(s.ptr);
allocator.free(s.ptr, env);
*s = "";
}
fn String String.tcopy(s) => s.copy(mem::temp()) @inline;
fn String ZString.copy(z, Allocator* allocator = mem::temp())
fn String ZString.copy(z, Allocator* allocator = mem::temp(), TrackingEnv* env = mem::get_tracking_env())
{
return z.str_view().copy(allocator) @inline;
return z.str_view().copy(allocator, env) @inline;
}
fn String ZString.tcopy(z)
@@ -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 = mem::heap(), TrackingEnv* env = mem::get_tracking_env())
{
usz len16 = conv::utf16len_for_utf8(s);
Char16* data = allocator.new_array_checked(Char16, len16 + 1)!;
Char16* data = allocator.new_array_checked(Char16, len16 + 1, .env = env)!;
conv::utf8to16_unsafe(s, data)!;
data[len16] = 0;
return data[:len16];
@@ -391,9 +391,9 @@ fn Char16[]! String.to_temp_utf16(s)
return s.to_new_utf16(mem::temp());
}
fn WString! String.to_new_wstring(s, Allocator* allocator = mem::heap())
fn WString! String.to_new_wstring(s, Allocator* allocator = mem::heap(), TrackingEnv* env = mem::get_tracking_env())
{
return (WString)s.to_new_utf16(allocator).ptr;
return (WString)s.to_new_utf16(allocator, env).ptr;
}
fn WString! String.to_temp_wstring(s)
@@ -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 = mem::heap(), TrackingEnv* env = mem::get_tracking_env())
{
usz codepoints = conv::utf8_codepoints(s);
Char32* data = allocator.new_array(Char32, codepoints + 1);
Char32* data = allocator.new_array(Char32, codepoints + 1, .env = env);
conv::utf8to32_unsafe(s, data)!;
data[codepoints] = 0;
return data[:codepoints];
@@ -449,32 +449,32 @@ fn String String.temp_ascii_to_upper(s)
return s.new_ascii_to_upper(mem::temp());
}
fn String! new_from_utf32(Char32[] utf32, Allocator* allocator = mem::heap())
fn String! new_from_utf32(Char32[] utf32, Allocator* allocator = mem::heap(), TrackingEnv* env = mem::get_tracking_env())
{
usz len = conv::utf8len_for_utf32(utf32);
char* data = allocator.alloc_checked(len + 1)!;
char* data = allocator.alloc_checked(len + 1, env)!;
defer catch allocator.free(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 = mem::heap(), TrackingEnv* env = mem::get_tracking_env())
{
usz len = conv::utf8len_for_utf16(utf16);
char* data = allocator.alloc_checked(len + 1)!;
char* data = allocator.alloc_checked(len + 1, env)!;
defer catch allocator.free(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 = mem::heap(), TrackingEnv* env = mem::get_tracking_env())
{
usz utf16_len;
while (wstring[utf16_len] != 0) utf16_len++;
Char16[] utf16 = wstring[:utf16_len];
return new_from_utf16(utf16, allocator);
return new_from_utf16(utf16, allocator, env);
}
fn String! temp_from_wstring(WString wstring) => new_from_wstring(wstring, mem::temp()) @inline;

View File

@@ -16,11 +16,11 @@ 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())
fn ByteBuffer*! ByteBuffer.init_new(&self, usz max_read, usz initial_capacity = 16, Allocator* allocator = mem::heap(), TrackingEnv* env = mem::get_tracking_env())
{
*self = { .allocator = allocator, .max_read = max_read };
initial_capacity = max(initial_capacity, 16);
self.grow(initial_capacity)!;
self.grow(initial_capacity, env)!;
return self;
}
@@ -128,10 +128,10 @@ fn usz! ByteBuffer.available(&self) @inline @dynamic
return self.write_idx - self.read_idx;
}
fn void! ByteBuffer.grow(&self, usz n)
fn void! ByteBuffer.grow(&self, usz n, TrackingEnv* env = mem::get_tracking_env())
{
n = math::next_power_of_2(n);
char* p = self.allocator.realloc_aligned(self.bytes, n, .alignment = char.alignof)!;
char* p = self.allocator.realloc_aligned(self.bytes, n, .alignment = char.alignof, .env = env)!;
self.bytes = p[:n];
}

View File

@@ -1305,7 +1305,7 @@ INLINE bool sema_call_expand_arguments(SemaContext *context, CalledDecl *callee,
SemaContext *new_context = context_transform_for_eval(context, &default_context, param->unit);
bool success;
SCOPE_START
new_context->original_inline_line = context->original_inline_line ? context->original_inline_line : init_expr->span.row;
new_context->original_inline_line = context->original_inline_line ? context->original_inline_line : call->span.row;
success = sema_analyse_expr_rhs(new_context, param->type, arg, true, no_match_ref);
SCOPE_END;
sema_context_destroy(&default_context);
@@ -6783,9 +6783,19 @@ static inline bool sema_expr_analyse_compiler_const(SemaContext *context, Expr *
expr_rewrite_to_string(expr, date_get());
return true;
case BUILTIN_DEF_FILE:
if (context->call_env.current_function)
{
expr_rewrite_to_string(expr, context->call_env.current_function->unit->file->name);
return true;
}
expr_rewrite_to_string(expr, context->compilation_unit->file->name);
return true;
case BUILTIN_DEF_FILEPATH:
if (context->call_env.current_function)
{
expr_rewrite_to_string(expr, context->call_env.current_function->unit->file->full_path);
return true;
}
expr_rewrite_to_string(expr, context->compilation_unit->file->full_path);
return true;
case BUILTIN_DEF_MODULE:

View File

@@ -3028,6 +3028,7 @@ bool sema_analyse_function_body(SemaContext *context, Decl *func)
Signature *signature = &func->func_decl.signature;
FunctionPrototype *prototype = func->type->function.prototype;
assert(prototype);
context->original_inline_line = 0;
context->call_env = (CallEnv) {
.current_function = func,
.kind = CALL_ENV_FUNCTION,

View File

@@ -1 +1 @@
#define COMPILER_VERSION "0.4.698"
#define COMPILER_VERSION "0.4.699"

View File

@@ -332,7 +332,7 @@ if.then7: ; preds = %if.exit4
%15 = getelementptr inbounds %Doc, ptr %literal9, i32 0, i32 0
call void @llvm.memcpy.p0.p0.i32(ptr align 8 %literal10, ptr align 8 @.__const.5, i32 8, i1 false)
call void @llvm.memcpy.p0.p0.i32(ptr align 8 %value, ptr align 8 %literal10, i32 8, i1 false)
%16 = call ptr @std.core.mem.malloc(i64 8) #3
%16 = call ptr @std.core.mem.malloc(i64 8, ptr null) #3
store ptr %16, ptr %temp, align 8
%17 = load ptr, ptr %temp, align 8
%not = icmp eq ptr %17, null
@@ -371,7 +371,7 @@ if.then16: ; preds = %if.exit13
store ptr null, ptr %literal20, align 8
%26 = getelementptr inbounds %Head, ptr %literal20, i32 0, i32 0
store %"char[]" zeroinitializer, ptr %value22, align 8
%27 = call ptr @std.core.mem.malloc(i64 16) #3
%27 = call ptr @std.core.mem.malloc(i64 16, ptr null) #3
store ptr %27, ptr %temp23, align 8
%28 = load ptr, ptr %temp23, align 8
%not24 = icmp eq ptr %28, null
@@ -394,7 +394,7 @@ noerr_block28: ; preds = %if.exit26
%31 = load ptr, ptr %temp23, align 8
store ptr %31, ptr %26, align 8
call void @llvm.memcpy.p0.p0.i32(ptr align 8 %value29, ptr align 8 %literal20, i32 8, i1 false)
%32 = call ptr @std.core.mem.malloc(i64 8) #3
%32 = call ptr @std.core.mem.malloc(i64 8, ptr null) #3
store ptr %32, ptr %temp30, align 8
%33 = load ptr, ptr %temp30, align 8
%not31 = icmp eq ptr %33, null
@@ -430,7 +430,7 @@ if.exit36: ; preds = %if.exit13
store i64 %sext, ptr %len, align 8
%42 = load i64, ptr %len, align 8
%add = add i64 %42, 1
%43 = call ptr @std.core.mem.malloc(i64 %add) #3
%43 = call ptr @std.core.mem.malloc(i64 %add, ptr null) #3
store ptr %43, ptr %str, align 8
%44 = load ptr, ptr %str, align 8
%not37 = icmp eq ptr %44, null
@@ -461,7 +461,7 @@ if.exit39: ; preds = %if.exit36
%57 = insertvalue %"char[]" undef, ptr %ptroffset47, 0
%58 = insertvalue %"char[]" %57, i64 %size, 1
store %"char[]" %58, ptr %value48, align 8
%59 = call ptr @std.core.mem.malloc(i64 16) #3
%59 = call ptr @std.core.mem.malloc(i64 16, ptr null) #3
store ptr %59, ptr %temp49, align 8
%60 = load ptr, ptr %temp49, align 8
%not50 = icmp eq ptr %60, null
@@ -484,7 +484,7 @@ noerr_block54: ; preds = %if.exit52
%63 = load ptr, ptr %temp49, align 8
store ptr %63, ptr %53, align 8
call void @llvm.memcpy.p0.p0.i32(ptr align 8 %value55, ptr align 8 %literal45, i32 8, i1 false)
%64 = call ptr @std.core.mem.malloc(i64 8) #3
%64 = call ptr @std.core.mem.malloc(i64 8, ptr null) #3
store ptr %64, ptr %temp56, align 8
%65 = load ptr, ptr %temp56, align 8
%not57 = icmp eq ptr %65, null

View File

@@ -66,7 +66,7 @@ entry:
%lo = load i64, ptr %3, align 8
%4 = getelementptr inbounds { i64, ptr }, ptr %allocator, i32 0, i32 1
%hi = load ptr, ptr %4, align 8
%5 = call ptr @std.core.dstring.new_with_capacity(i64 128, i64 %lo, ptr %hi)
%5 = call ptr @std.core.dstring.new_with_capacity(i64 128, i64 %lo, ptr %hi, ptr null)
store ptr %5, ptr %s, align 8
%6 = getelementptr inbounds %Foo, ptr %0, i32 0, i32 0
%7 = insertvalue %"any*" undef, ptr %6, 0
@@ -133,7 +133,7 @@ entry:
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 ({ i64, ptr }, ptr @std.core.mem.thread_allocator, i32 0, i32 1), align 8
%0 = call ptr @"std.collections.map$int$test.Foo$.HashMap.init_new"(ptr %map, i32 16, float 7.500000e-01, i64 %lo, ptr %hi)
%0 = call ptr @"std.collections.map$int$test.Foo$.HashMap.init_new"(ptr %map, i32 16, float 7.500000e-01, i64 %lo, ptr %hi, ptr null)
%1 = getelementptr inbounds %HashMap, ptr %map, i32 0, i32 2
%2 = insertvalue %"any*" undef, ptr %1, 0
%3 = insertvalue %"any*" %2, i64 ptrtoint (ptr @"$ct.uint" to i64), 1
@@ -213,7 +213,7 @@ after_check14: ; preds = %entry, %after_check
call void @llvm.memset.p0.i64(ptr align 8 %map2, i8 0, i64 48, i1 false)
%lo33 = load i64, ptr @std.core.mem.thread_allocator, align 8
%hi34 = load ptr, ptr getelementptr inbounds ({ i64, ptr }, ptr @std.core.mem.thread_allocator, i32 0, i32 1), align 8
%48 = call ptr @"std.collections.map$int$double$.HashMap.init_new"(ptr %map2, i32 16, float 7.500000e-01, i64 %lo33, ptr %hi34)
%48 = call ptr @"std.collections.map$int$double$.HashMap.init_new"(ptr %map2, i32 16, float 7.500000e-01, i64 %lo33, ptr %hi34, ptr null)
%49 = call i8 @"std.collections.map$int$double$.HashMap.set"(ptr %map2, i32 4, double 1.300000e+00)
%50 = call i8 @"std.collections.map$int$double$.HashMap.has_value"(ptr %map2, double 1.300000e+00)
store i8 %50, ptr %taddr36, align 1
@@ -266,7 +266,7 @@ if.exit: ; preds = %if.then, %after_che
call void @llvm.memset.p0.i64(ptr align 8 %map3, i8 0, i64 48, i1 false)
%lo59 = load i64, ptr @std.core.mem.thread_allocator, align 8
%hi60 = load ptr, ptr getelementptr inbounds ({ i64, ptr }, ptr @std.core.mem.thread_allocator, i32 0, i32 1), align 8
%76 = call ptr @"std.collections.map$int$double$.HashMap.init_new"(ptr %map3, i32 16, float 7.500000e-01, i64 %lo59, ptr %hi60)
%76 = call ptr @"std.collections.map$int$double$.HashMap.init_new"(ptr %map3, i32 16, float 7.500000e-01, i64 %lo59, ptr %hi60, ptr null)
%77 = call i8 @"std.collections.map$int$double$.HashMap.set"(ptr %map3, i32 5, double 3.200000e+00)
%78 = call i8 @"std.collections.map$int$double$.HashMap.set"(ptr %map3, i32 7, double 5.200000e+00)
%lo62 = load i64, ptr @std.core.mem.thread_allocator, align 8