mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Use backtrace on windows. Updated backtrace API
This commit is contained in:
committed by
Christoffer Lerno
parent
81c93e3488
commit
ffb0021d04
@@ -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(), TrackingEnv* env = mem::get_tracking_env())
|
||||
fn GrowableBitSet* GrowableBitSet.init_new(&self, usz initial_capacity = 1, Allocator* allocator = mem::heap())
|
||||
{
|
||||
self.data.init_new(initial_capacity, allocator, env);
|
||||
self.data.init_new(initial_capacity, allocator);
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
@@ -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(), TrackingEnv* env = mem::get_tracking_env())
|
||||
fn List* List.init_new(&self, usz initial_capacity = 16, Allocator* allocator = mem::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, .env = env)!!;
|
||||
self.entries = allocator.alloc_aligned(Type.sizeof * initial_capacity, .alignment = Type[1].alignof)!!;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -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(), TrackingEnv* env = mem::get_tracking_env())
|
||||
fn HashMap* HashMap.init_new(&map, uint capacity = DEFAULT_INITIAL_CAPACITY, float load_factor = DEFAULT_LOAD_FACTOR, Allocator* allocator = mem::heap())
|
||||
{
|
||||
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, .env = env);
|
||||
map.table = allocator.new_zero_array(Entry*, capacity);
|
||||
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(), TrackingEnv* env = mem::get_tracking_env())
|
||||
fn HashMap* HashMap.init_new_from_map(&self, HashMap* other_map, Allocator* allocator = mem::heap())
|
||||
{
|
||||
self.init_new(other_map.table.len, other_map.load_factor, allocator, env);
|
||||
self.init_new(other_map.table.len, other_map.load_factor, allocator);
|
||||
self.put_all_for_create(other_map);
|
||||
return self;
|
||||
}
|
||||
|
||||
@@ -78,9 +78,9 @@ fn usz! Object.to_format(&self, Formatter* formatter) @dynamic
|
||||
}
|
||||
}
|
||||
|
||||
fn Object* new_obj(Allocator* allocator, TrackingEnv* env = mem::get_tracking_env())
|
||||
fn Object* new_obj(Allocator* allocator)
|
||||
{
|
||||
Object* o = allocator.new(Object, .env = env);
|
||||
Object* o = allocator.new(Object);
|
||||
*o = { .allocator = allocator, .type = void.typeid };
|
||||
return o;
|
||||
}
|
||||
|
||||
@@ -36,9 +36,9 @@ struct PrivatePriorityQueue (Printable)
|
||||
Heap heap;
|
||||
}
|
||||
|
||||
fn void PrivatePriorityQueue.init_new(&self, usz initial_capacity = 16, Allocator* allocator = mem::heap(), TrackingEnv* env = mem::get_tracking_env()) @inline
|
||||
fn void PrivatePriorityQueue.init_new(&self, usz initial_capacity = 16, Allocator* allocator = mem::heap()) @inline
|
||||
{
|
||||
self.heap.init_new(initial_capacity, allocator, .env = env);
|
||||
self.heap.init_new(initial_capacity, allocator);
|
||||
}
|
||||
|
||||
fn void PrivatePriorityQueue.init_temp(&self, usz initial_capacity = 16) @inline
|
||||
|
||||
@@ -29,7 +29,7 @@ struct ArenaAllocatorHeader @local
|
||||
char[*] data;
|
||||
}
|
||||
|
||||
fn void ArenaAllocator.release(&self, void* ptr, bool, TrackingEnv* env = null) @dynamic
|
||||
fn void ArenaAllocator.release(&self, void* ptr, bool) @dynamic
|
||||
{
|
||||
if (!ptr) return;
|
||||
assert((uptr)ptr >= (uptr)self.data.ptr, "Pointer originates from a different allocator.");
|
||||
@@ -50,7 +50,7 @@ fn void ArenaAllocator.reset(&self, usz mark) @dynamic => self.used = mark;
|
||||
* @require offset <= size && offset >= 0
|
||||
* @require mem::aligned_offset(offset, ArenaAllocatorHeader.alignof) == offset
|
||||
**/
|
||||
fn void*! ArenaAllocator.acquire(&self, usz size, bool clear, usz alignment, usz offset, TrackingEnv* env = null) @dynamic
|
||||
fn void*! ArenaAllocator.acquire(&self, usz size, bool clear, usz alignment, usz offset) @dynamic
|
||||
{
|
||||
if (!size) return null;
|
||||
alignment = alignment_for_allocation(alignment);
|
||||
@@ -76,7 +76,7 @@ fn void*! ArenaAllocator.acquire(&self, usz size, bool clear, usz alignment, usz
|
||||
* @require offset <= size && offset >= 0
|
||||
* @require mem::aligned_offset(offset, ArenaAllocatorHeader.alignof) == offset
|
||||
**/
|
||||
fn void*! ArenaAllocator.resize(&self, void *old_pointer, usz size, usz alignment, usz offset, TrackingEnv* env) @dynamic
|
||||
fn void*! ArenaAllocator.resize(&self, void *old_pointer, usz size, usz alignment, usz offset) @dynamic
|
||||
{
|
||||
if (!size)
|
||||
{
|
||||
@@ -110,7 +110,7 @@ fn void*! ArenaAllocator.resize(&self, void *old_pointer, usz size, usz alignmen
|
||||
return old_pointer;
|
||||
}
|
||||
// Otherwise just allocate new memory.
|
||||
void* mem = self.acquire(size, false, alignment, offset, env)!;
|
||||
void* mem = self.acquire(size, false, alignment, offset)!;
|
||||
mem::copy(mem, old_pointer, old_size, mem::DEFAULT_MEM_ALIGNMENT, mem::DEFAULT_MEM_ALIGNMENT);
|
||||
return mem;
|
||||
}
|
||||
@@ -60,7 +60,7 @@ struct DynamicArenaChunk @local
|
||||
/**
|
||||
* @require self.page `tried to free pointer on invalid allocator`
|
||||
*/
|
||||
fn void DynamicArenaAllocator.release(&self, void* ptr, bool, TrackingEnv* env) @dynamic
|
||||
fn void DynamicArenaAllocator.release(&self, void* ptr, bool) @dynamic
|
||||
{
|
||||
if (!ptr) return;
|
||||
DynamicArenaPage* current_page = self.page;
|
||||
@@ -74,16 +74,16 @@ fn void DynamicArenaAllocator.release(&self, void* ptr, bool, TrackingEnv* env)
|
||||
/**
|
||||
* @require self.page `tried to realloc pointer on invalid allocator`
|
||||
*/
|
||||
fn void*! DynamicArenaAllocator.resize(&self, void* old_pointer, usz size, usz alignment, usz offset, TrackingEnv* env) @dynamic
|
||||
fn void*! DynamicArenaAllocator.resize(&self, void* old_pointer, usz size, usz alignment, usz offset) @dynamic
|
||||
{
|
||||
if (!size)
|
||||
{
|
||||
self.release(old_pointer, alignment > 0, env);
|
||||
self.release(old_pointer, alignment > 0);
|
||||
return null;
|
||||
}
|
||||
if (!old_pointer)
|
||||
{
|
||||
return self.acquire(size, true, alignment, offset, env);
|
||||
return self.acquire(size, true, alignment, offset);
|
||||
}
|
||||
DynamicArenaPage* current_page = self.page;
|
||||
alignment = alignment_for_allocation(alignment);
|
||||
@@ -108,7 +108,7 @@ fn void*! DynamicArenaAllocator.resize(&self, void* old_pointer, usz size, usz a
|
||||
current_page.used += add_size;
|
||||
return old_pointer;
|
||||
}
|
||||
void* new_mem = self.acquire(size, false, alignment, offset, env)!;
|
||||
void* new_mem = self.acquire(size, false, alignment, offset)!;
|
||||
mem::copy(new_mem, old_pointer, old_size, mem::DEFAULT_MEM_ALIGNMENT);
|
||||
return new_mem;
|
||||
}
|
||||
@@ -163,7 +163,7 @@ fn void*! DynamicArenaAllocator._alloc_new(&self, usz size, usz alignment, usz o
|
||||
/**
|
||||
* @require !alignment || math::is_power_of_2(alignment)
|
||||
*/
|
||||
fn void*! DynamicArenaAllocator.acquire(&self, usz size, bool clear, usz alignment, usz offset, TrackingEnv* env) @dynamic
|
||||
fn void*! DynamicArenaAllocator.acquire(&self, usz size, bool clear, usz alignment, usz offset) @dynamic
|
||||
{
|
||||
if (!size) return null;
|
||||
alignment = alignment_for_allocation(alignment);
|
||||
|
||||
@@ -21,7 +21,7 @@ fn void SimpleHeapAllocator.init(&self, MemoryAllocFn allocator)
|
||||
self.free_list = null;
|
||||
}
|
||||
|
||||
fn void*! SimpleHeapAllocator.acquire(&self, usz size, bool clear, usz alignment, usz offset, TrackingEnv* env) @dynamic
|
||||
fn void*! SimpleHeapAllocator.acquire(&self, usz size, bool clear, usz alignment, usz offset) @dynamic
|
||||
{
|
||||
if (!size) return null;
|
||||
if (clear)
|
||||
@@ -31,23 +31,23 @@ fn void*! SimpleHeapAllocator.acquire(&self, usz size, bool clear, usz alignment
|
||||
return alignment > 0 ? @aligned_alloc(self._alloc, size, alignment, offset) : self._alloc(size);
|
||||
}
|
||||
|
||||
fn void*! SimpleHeapAllocator.resize(&self, void* old_pointer, usz size, usz alignment, usz offset, TrackingEnv* env) @dynamic
|
||||
fn void*! SimpleHeapAllocator.resize(&self, void* old_pointer, usz size, usz alignment, usz offset) @dynamic
|
||||
{
|
||||
if (!size)
|
||||
{
|
||||
self.release(old_pointer, alignment > 0, env);
|
||||
self.release(old_pointer, alignment > 0);
|
||||
return null;
|
||||
}
|
||||
if (!old_pointer)
|
||||
{
|
||||
return self.acquire(size, true, alignment, offset, env);
|
||||
return self.acquire(size, true, alignment, offset);
|
||||
}
|
||||
return alignment > 0
|
||||
? @aligned_realloc(self._calloc, self._free, old_pointer, size, alignment, offset)
|
||||
: self._realloc(old_pointer, size);
|
||||
}
|
||||
|
||||
fn void SimpleHeapAllocator.release(&self, void* old_pointer, bool aligned, TrackingEnv* env) @dynamic
|
||||
fn void SimpleHeapAllocator.release(&self, void* old_pointer, bool aligned) @dynamic
|
||||
{
|
||||
if (aligned)
|
||||
{
|
||||
|
||||
@@ -10,7 +10,7 @@ const LibcAllocator LIBC_ALLOCATOR = {};
|
||||
|
||||
distinct LibcAllocator (Allocator) = uptr;
|
||||
|
||||
fn void*! LibcAllocator.acquire(&self, usz bytes, bool clear, usz alignment, usz offset, TrackingEnv* env) @dynamic
|
||||
fn void*! LibcAllocator.acquire(&self, usz bytes, bool clear, usz alignment, usz offset) @dynamic
|
||||
{
|
||||
assert(alignment != 0 || offset == 0);
|
||||
if (clear)
|
||||
@@ -29,17 +29,17 @@ fn void*! LibcAllocator.acquire(&self, usz bytes, bool clear, usz alignment, usz
|
||||
}
|
||||
}
|
||||
|
||||
fn void*! LibcAllocator.resize(&self, void* old_ptr, usz new_bytes, usz alignment, usz offset, TrackingEnv* env) @dynamic
|
||||
fn void*! LibcAllocator.resize(&self, void* old_ptr, usz new_bytes, usz alignment, usz offset) @dynamic
|
||||
{
|
||||
assert(alignment != 0 || offset == 0);
|
||||
if (!new_bytes)
|
||||
{
|
||||
self.release(old_ptr, alignment > 0, env);
|
||||
self.release(old_ptr, alignment > 0);
|
||||
return null;
|
||||
}
|
||||
if (!old_ptr)
|
||||
{
|
||||
return self.acquire(new_bytes, true, alignment, offset, env);
|
||||
return self.acquire(new_bytes, true, alignment, offset);
|
||||
}
|
||||
if (alignment)
|
||||
{
|
||||
@@ -50,7 +50,7 @@ fn void*! LibcAllocator.resize(&self, void* old_ptr, usz new_bytes, usz alignmen
|
||||
}
|
||||
|
||||
|
||||
fn void LibcAllocator.release(&self, void* old_ptr, bool aligned, TrackingEnv* env) @dynamic
|
||||
fn void LibcAllocator.release(&self, void* old_ptr, bool aligned) @dynamic
|
||||
{
|
||||
if (aligned)
|
||||
{
|
||||
|
||||
@@ -54,7 +54,7 @@ struct OnStackAllocatorHeader
|
||||
char[*] data;
|
||||
}
|
||||
|
||||
fn void OnStackAllocator.release(&self, void* old_pointer, bool aligned, TrackingEnv* env = null) @dynamic
|
||||
fn void OnStackAllocator.release(&self, void* old_pointer, bool aligned) @dynamic
|
||||
{
|
||||
if (!old_pointer) return;
|
||||
if (allocation_in_stack_mem(self, old_pointer)) return;
|
||||
@@ -103,18 +103,18 @@ fn OnStackAllocatorExtraChunk* on_stack_allocator_find_chunk(OnStackAllocator* a
|
||||
* @require offset <= size && offset >= 0
|
||||
* @require mem::aligned_offset(offset, OnStackAllocatorExtraChunk.alignof) == offset
|
||||
**/
|
||||
fn void*! OnStackAllocator.resize(&self, void* old_pointer, usz size, usz alignment, usz offset, TrackingEnv* env) @dynamic
|
||||
fn void*! OnStackAllocator.resize(&self, void* old_pointer, usz size, usz alignment, usz offset) @dynamic
|
||||
{
|
||||
if (!allocation_in_stack_mem(self, old_pointer))
|
||||
{
|
||||
OnStackAllocatorExtraChunk* chunk = on_stack_allocator_find_chunk(self, old_pointer);
|
||||
assert(chunk, "Tried to realloc pointer not belonging to the allocator");
|
||||
return chunk.data = self.backing_allocator.resize(old_pointer, size, alignment, offset, env)!;
|
||||
return chunk.data = self.backing_allocator.resize(old_pointer, size, alignment, offset)!;
|
||||
}
|
||||
|
||||
OnStackAllocatorHeader* header = old_pointer - OnStackAllocatorHeader.sizeof;
|
||||
usz old_size = header.size;
|
||||
void* mem = self.acquire(size, true, alignment, offset, env)!;
|
||||
void* mem = self.acquire(size, true, alignment, offset)!;
|
||||
mem::copy(mem, old_pointer, old_size, mem::DEFAULT_MEM_ALIGNMENT, mem::DEFAULT_MEM_ALIGNMENT);
|
||||
return mem;
|
||||
}
|
||||
@@ -126,7 +126,7 @@ fn void*! OnStackAllocator.resize(&self, void* old_pointer, usz size, usz alignm
|
||||
* @require offset == 0 || alignment > 0
|
||||
* @require mem::aligned_offset(offset, OnStackAllocatorHeader.alignof) == offset
|
||||
**/
|
||||
fn void*! OnStackAllocator.acquire(&self, usz size, bool clear, usz alignment, usz offset, TrackingEnv* env) @dynamic
|
||||
fn void*! OnStackAllocator.acquire(&self, usz size, bool clear, usz alignment, usz offset) @dynamic
|
||||
{
|
||||
if (size == 0) return null;
|
||||
bool aligned = alignment > 0;
|
||||
@@ -144,7 +144,7 @@ fn void*! OnStackAllocator.acquire(&self, usz size, bool clear, usz alignment, u
|
||||
defer catch backing_allocator.free(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, env)!;
|
||||
return chunk.data = backing_allocator.acquire(size, clear, aligned ? alignment : 0, offset)!;
|
||||
}
|
||||
self.used = end;
|
||||
void *mem = aligned_pointer_to_offset - offset;
|
||||
|
||||
@@ -47,7 +47,7 @@ fn TempAllocator*! new_temp(usz size, Allocator* allocator)
|
||||
|
||||
fn usz TempAllocator.mark(&self) @dynamic => self.used;
|
||||
|
||||
fn void TempAllocator.release(&self, void* old_pointer, bool, TrackingEnv* env) @dynamic
|
||||
fn void TempAllocator.release(&self, void* old_pointer, bool) @dynamic
|
||||
{
|
||||
usz old_size = *(usz*)(old_pointer - DEFAULT_SIZE_PREFIX);
|
||||
if (old_pointer + old_size == &self.data[self.used])
|
||||
@@ -75,7 +75,7 @@ fn void! TempAllocator._free_page(&self, TempAllocatorPage* page) @inline @local
|
||||
return self.backing_allocator.free(mem);
|
||||
}
|
||||
|
||||
fn void*! TempAllocator._realloc_page(&self, TempAllocatorPage* page, usz size, usz alignment, usz offset, TrackingEnv* env) @inline @local
|
||||
fn void*! TempAllocator._realloc_page(&self, TempAllocatorPage* page, usz size, usz alignment, usz offset) @inline @local
|
||||
{
|
||||
// Then the actual start pointer:
|
||||
void* real_pointer = page.start;
|
||||
@@ -90,7 +90,7 @@ fn void*! TempAllocator._realloc_page(&self, TempAllocatorPage* page, usz size,
|
||||
*pointer_to_prev = page.prev_page;
|
||||
usz page_size = page.pagesize();
|
||||
// Clear on size > original size.
|
||||
void* data = self.acquire(size, size > page_size, alignment, offset, env)!;
|
||||
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())
|
||||
{
|
||||
@@ -103,16 +103,16 @@ fn void*! TempAllocator._realloc_page(&self, TempAllocatorPage* page, usz size,
|
||||
return data;
|
||||
}
|
||||
|
||||
fn void*! TempAllocator.resize(&self, void* pointer, usz size, usz alignment, usz offset, TrackingEnv* env) @dynamic
|
||||
fn void*! TempAllocator.resize(&self, void* pointer, usz size, usz alignment, usz offset) @dynamic
|
||||
{
|
||||
if (!size)
|
||||
{
|
||||
self.release(pointer, alignment > 0, env);
|
||||
self.release(pointer, alignment > 0);
|
||||
return null;
|
||||
}
|
||||
if (!pointer)
|
||||
{
|
||||
return self.acquire(size, true, alignment, offset, env);
|
||||
return self.acquire(size, true, alignment, offset);
|
||||
}
|
||||
TempAllocatorChunk *chunk = pointer - TempAllocatorChunk.sizeof;
|
||||
if (chunk.size == (usz)-1)
|
||||
@@ -120,11 +120,11 @@ fn void*! TempAllocator.resize(&self, void* pointer, usz size, usz alignment, us
|
||||
assert(self.last_page, "Realloc of non temp pointer");
|
||||
// First grab the page
|
||||
TempAllocatorPage *page = pointer - TempAllocatorPage.sizeof;
|
||||
return self._realloc_page(page, size, alignment, offset, env);
|
||||
return self._realloc_page(page, size, alignment, offset);
|
||||
}
|
||||
|
||||
// TODO optimize last allocation
|
||||
TempAllocatorChunk* data = self.acquire(size, size > chunk.size, alignment, offset, env)!;
|
||||
TempAllocatorChunk* data = self.acquire(size, size > chunk.size, alignment, offset)!;
|
||||
mem::copy(data, pointer, chunk.size, mem::DEFAULT_MEM_ALIGNMENT, mem::DEFAULT_MEM_ALIGNMENT);
|
||||
|
||||
return data;
|
||||
@@ -134,7 +134,7 @@ fn void*! TempAllocator.resize(&self, void* pointer, usz size, usz alignment, us
|
||||
* @require !alignment || math::is_power_of_2(alignment)
|
||||
* @require alignment <= mem::MAX_MEMORY_ALIGNMENT `alignment too big`
|
||||
**/
|
||||
fn void*! TempAllocator.acquire(&self, usz size, bool clear, usz alignment, usz offset, TrackingEnv* env) @dynamic
|
||||
fn void*! TempAllocator.acquire(&self, usz size, bool clear, usz alignment, usz offset) @dynamic
|
||||
{
|
||||
if (!size) return null;
|
||||
alignment = alignment_for_allocation(alignment);
|
||||
@@ -182,7 +182,7 @@ fn void*! TempAllocator.acquire(&self, usz size, bool clear, usz alignment, usz
|
||||
// Here we might need to pad
|
||||
usz padded_header_size = mem::aligned_offset(TempAllocatorPage.sizeof, mem::DEFAULT_MEM_ALIGNMENT);
|
||||
usz total_alloc_size = padded_header_size + size;
|
||||
void* alloc = self.backing_allocator.acquire(total_alloc_size, clear, 0, 0, null)!;
|
||||
void* alloc = self.backing_allocator.acquire(total_alloc_size, clear, 0, 0)!;
|
||||
|
||||
// Find the page.
|
||||
page = alloc + padded_header_size - TempAllocatorPage.sizeof;
|
||||
|
||||
@@ -6,11 +6,12 @@ module std::core::mem::allocator;
|
||||
import std::collections::map;
|
||||
import std::collections::list;
|
||||
|
||||
const MAX_BACKTRACE = 8;
|
||||
struct Allocation
|
||||
{
|
||||
usz size;
|
||||
TrackingEnv tracking_env;
|
||||
void* ptr;
|
||||
usz size;
|
||||
void*[MAX_BACKTRACE] backtrace;
|
||||
}
|
||||
|
||||
def AllocMap = HashMap(<uptr, Allocation>);
|
||||
@@ -79,38 +80,42 @@ fn Allocation[] TrackingAllocator.allocations_tlist(&self, Allocator* allocator)
|
||||
**/
|
||||
fn usz TrackingAllocator.allocation_count(&self) => self.map.count;
|
||||
|
||||
fn void*! TrackingAllocator.acquire(&self, usz size, bool clear, usz alignment, usz offset, TrackingEnv* env) @dynamic
|
||||
fn void*! TrackingAllocator.acquire(&self, usz size, bool clear, usz alignment, usz offset) @dynamic
|
||||
{
|
||||
void* data = self.inner_allocator.acquire(size, clear, alignment, offset, env)!;
|
||||
void* data = self.inner_allocator.acquire(size, clear, alignment, offset)!;
|
||||
self.allocs_total++;
|
||||
if (data)
|
||||
{
|
||||
self.map.set((uptr)data, { .size = size, .ptr = data, .tracking_env = env ? *env : TrackingEnv{} });
|
||||
void*[MAX_BACKTRACE] bt;
|
||||
backtrace::capture_current(&bt);
|
||||
self.map.set((uptr)data, { data, size, bt });
|
||||
self.mem_total += size;
|
||||
self.allocs_total++;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
fn void*! TrackingAllocator.resize(&self, void* old_pointer, usz size, usz alignment, usz offset, TrackingEnv* env) @dynamic
|
||||
fn void*! TrackingAllocator.resize(&self, void* old_pointer, usz size, usz alignment, usz offset) @dynamic
|
||||
{
|
||||
void* data = self.inner_allocator.resize(old_pointer, size, alignment, offset, env)!;
|
||||
void* data = self.inner_allocator.resize(old_pointer, size, alignment, offset)!;
|
||||
if (old_pointer)
|
||||
{
|
||||
self.map.remove((uptr)old_pointer);
|
||||
}
|
||||
if (data)
|
||||
{
|
||||
self.map.set((uptr)data, { .size = size, .ptr = data, .tracking_env = env ? *env : TrackingEnv{} });
|
||||
void*[8] bt;
|
||||
backtrace::capture_current(&bt);
|
||||
self.map.set((uptr)data, { data, size, bt });
|
||||
self.mem_total += size;
|
||||
self.allocs_total++;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
fn void TrackingAllocator.release(&self, void* old_pointer, bool is_aligned, TrackingEnv* env) @dynamic
|
||||
fn void TrackingAllocator.release(&self, void* old_pointer, bool is_aligned) @dynamic
|
||||
{
|
||||
self.inner_allocator.release(old_pointer, is_aligned, env);
|
||||
self.inner_allocator.release(old_pointer, is_aligned);
|
||||
if (old_pointer) self.map.remove((uptr)old_pointer);
|
||||
}
|
||||
|
||||
@@ -126,41 +131,84 @@ fn void! TrackingAllocator.fprint_report(&self, OutStream* out)
|
||||
|
||||
usz total = 0;
|
||||
usz entries = 0;
|
||||
bool leaks = false;
|
||||
@pool()
|
||||
{
|
||||
Allocation[] allocs = self.map.value_tlist();
|
||||
if (allocs.len)
|
||||
{
|
||||
$if (!env::TRACK_MEMORY):
|
||||
io::fprintn(out, "======== Memory Report ========")!;
|
||||
io::fprintn(out, "Size in bytes Address")!;
|
||||
foreach (i, &allocation : allocs)
|
||||
if (!allocs[0].backtrace[0])
|
||||
{
|
||||
entries++;
|
||||
total += allocation.size;
|
||||
io::fprintfn(out, "%13s %p", allocation.size, allocation.ptr)!;
|
||||
io::fprintn(out, "======== Memory Report ========")!;
|
||||
io::fprintn(out, "Size in bytes Address")!;
|
||||
foreach (i, &allocation : allocs)
|
||||
{
|
||||
entries++;
|
||||
total += allocation.size;
|
||||
io::fprintfn(out, "%13s %p", allocation.size, allocation.ptr)!;
|
||||
}
|
||||
io::fprintn(out, "===============================")!;
|
||||
|
||||
}
|
||||
io::fprintn(out, "===============================")!;
|
||||
$else
|
||||
io::fprintn(out, "================================== Memory Report ==================================")!;
|
||||
io::fprintn(out, "Size in bytes Address Function File")!;
|
||||
foreach (i, &allocation : allocs)
|
||||
else
|
||||
{
|
||||
entries++;
|
||||
total += allocation.size;
|
||||
TrackingEnv *env = &allocation.tracking_env;
|
||||
io::fprintfn(out, "%13s %p %-30s %s:%d", allocation.size, allocation.ptr, env.function, env.file, env.line)!;
|
||||
io::fprintn(out, "================================== Memory Report ==================================")!;
|
||||
io::fprintn(out, "Size in bytes Address Function ")!;
|
||||
foreach (i, &allocation : allocs)
|
||||
{
|
||||
entries++;
|
||||
total += allocation.size;
|
||||
BacktraceList backtraces = {};
|
||||
Backtrace trace = backtrace::BACKTRACE_UNKNOWN;
|
||||
if (allocation.backtrace[3])
|
||||
{
|
||||
trace = backtrace::symbolize_backtrace(allocation.backtrace[3:1], mem::temp()).get(0) ?? backtrace::BACKTRACE_UNKNOWN;
|
||||
}
|
||||
if (trace.function.len) leaks = true;
|
||||
io::fprintfn(out, "%13s %p %s:%d", allocation.size,
|
||||
allocation.ptr, trace.function.len ? trace.function : "???",
|
||||
trace.line ? trace.line : 0)!;
|
||||
}
|
||||
io::fprintn(out, "===================================================================================")!;
|
||||
}
|
||||
io::fprintn(out, "===================================================================================")!;
|
||||
$endif
|
||||
}
|
||||
else
|
||||
{
|
||||
io::fprintn(out, "* NO ALLOCATIONS FOUND *")!;
|
||||
}
|
||||
io::fprintfn(out, "- Total currently allocated memory: %d", total)!;
|
||||
io::fprintfn(out, "- Total current allocations: %d", entries)!;
|
||||
io::fprintfn(out, "- Total allocations (freed and retained): %d", self.allocs_total)!;
|
||||
io::fprintfn(out, "- Total allocated memory (freed and retained): %d", self.mem_total)!;
|
||||
if (leaks)
|
||||
{
|
||||
io::fprintn(out)!;
|
||||
io::fprintn(out, "Full leak report:")!;
|
||||
foreach (i, &allocation : allocs)
|
||||
{
|
||||
if (!allocation.backtrace[3])
|
||||
{
|
||||
io::fprintfn(out, "Allocation %d (%d bytes) - no backtrace available.", i + 1, allocation.size)!;
|
||||
continue;
|
||||
}
|
||||
BacktraceList backtraces = {};
|
||||
usz end = MAX_BACKTRACE;
|
||||
foreach (j, val : allocation.backtrace)
|
||||
{
|
||||
if (!val)
|
||||
{
|
||||
end = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
BacktraceList list = backtrace::symbolize_backtrace(allocation.backtrace[3..(end - 1)], mem::temp())!;
|
||||
io::fprintfn(out, "Allocation %d (%d bytes): ", i + 1, allocation.size)!;
|
||||
foreach (trace : list)
|
||||
{
|
||||
io::fprintfn(out, " %s", trace);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
io::fprintfn(out, "- Total currently allocated memory: %d", total)!;
|
||||
io::fprintfn(out, "- Total current allocations: %d", entries)!;
|
||||
io::fprintfn(out, "- Total allocations (freed and retained): %d", self.allocs_total)!;
|
||||
io::fprintfn(out, "- Total allocated memory (freed and retained): %d", self.mem_total)!;
|
||||
|
||||
}
|
||||
@@ -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(), TrackingEnv* env = mem::get_tracking_env())
|
||||
fn DString DString.init_new(&self, usz capacity = MIN_CAPACITY, Allocator* allocator = mem::heap())
|
||||
{
|
||||
if (capacity < MIN_CAPACITY) capacity = MIN_CAPACITY;
|
||||
StringData* data = allocator.new(StringData, .end_padding = capacity, .env = env);
|
||||
StringData* data = allocator.new(StringData, .end_padding = capacity);
|
||||
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(), TrackingEnv* env = mem::get_tracking_env())
|
||||
fn DString new_with_capacity(usz capacity, Allocator* allocator = mem::heap())
|
||||
{
|
||||
return DString{}.init_new(capacity, allocator, .env = env);
|
||||
return DString{}.init_new(capacity, allocator);
|
||||
}
|
||||
|
||||
fn DString temp_with_capacity(usz capacity) => new_with_capacity(capacity, mem::temp()) @inline;
|
||||
|
||||
fn DString new(String c = "", Allocator* allocator = mem::heap(), TrackingEnv* env = mem::get_tracking_env())
|
||||
fn DString new(String c = "", Allocator* allocator = mem::heap())
|
||||
{
|
||||
usz len = c.len;
|
||||
StringData* data = (StringData*)new_with_capacity(len, allocator, env);
|
||||
StringData* data = (StringData*)new_with_capacity(len, allocator);
|
||||
if (len)
|
||||
{
|
||||
data.len = len;
|
||||
@@ -48,10 +48,10 @@ fn DString new(String c = "", Allocator* allocator = mem::heap(), TrackingEnv* e
|
||||
|
||||
fn DString temp_new(String s = "") => new(s, mem::temp()) @inline;
|
||||
|
||||
fn DString DString.new_concat(self, DString b, Allocator* allocator = mem::heap(), TrackingEnv* env = mem::get_tracking_env())
|
||||
fn DString DString.new_concat(self, DString b, Allocator* allocator = mem::heap())
|
||||
{
|
||||
DString string;
|
||||
string.init_new(self.len() + b.len(), allocator, env);
|
||||
string.init_new(self.len() + b.len(), allocator);
|
||||
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, TrackingEnv* env = mem::get_tracking_env())
|
||||
fn DString DString.copy(self, Allocator* allocator = null)
|
||||
{
|
||||
if (!self)
|
||||
{
|
||||
if (allocator) return new_with_capacity(0, allocator, env);
|
||||
if (allocator) return new_with_capacity(0, allocator);
|
||||
return (DString)null;
|
||||
}
|
||||
StringData* data = self.data();
|
||||
if (!allocator) allocator = mem::heap();
|
||||
DString new_string = new_with_capacity(data.capacity, allocator, env);
|
||||
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(), TrackingEnv* env = mem::get_tracking_env())
|
||||
fn ZString DString.copy_zstr(self, Allocator* allocator = mem::heap())
|
||||
{
|
||||
usz str_len = self.len();
|
||||
if (!str_len)
|
||||
{
|
||||
return (ZString)allocator.calloc(1, env);
|
||||
return (ZString)allocator.calloc(1);
|
||||
}
|
||||
char* zstr = allocator.alloc(str_len + 1, env);
|
||||
char* zstr = allocator.alloc(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(), TrackingEnv* env = mem::get_tracking_env())
|
||||
fn String DString.copy_str(self, Allocator* allocator = mem::heap())
|
||||
{
|
||||
return (String)self.copy_zstr(allocator, env)[:self.len()];
|
||||
return (String)self.copy_zstr(allocator)[: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(), TrackingEnv* env = mem::get_tracking_env())
|
||||
fn Char32[] DString.copy_utf32(&self, Allocator* allocator = mem::heap())
|
||||
{
|
||||
return self.str_view().to_new_utf32(allocator, env) @inline!!;
|
||||
return self.str_view().to_new_utf32(allocator) @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(), TrackingEnv* env = mem::get_tracking_env())
|
||||
fn DString new_join(String[] s, String joiner, Allocator* allocator = mem::heap())
|
||||
{
|
||||
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, env);
|
||||
DString res = new_with_capacity(total_size, allocator);
|
||||
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, TrackingEnv* env = mem::get_tracking_env())
|
||||
fn void DString.reserve(&self, usz addition)
|
||||
{
|
||||
StringData* data = self.data();
|
||||
if (!data)
|
||||
{
|
||||
*self = dstring::new_with_capacity(addition, .env = env);
|
||||
*self = dstring::new_with_capacity(addition);
|
||||
return;
|
||||
}
|
||||
usz len = data.len + addition;
|
||||
@@ -398,7 +398,7 @@ fn void DString.reserve(&self, usz addition, TrackingEnv* env = mem::get_trackin
|
||||
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, env);
|
||||
*self = (DString)data.allocator.realloc(data, StringData.sizeof + new_capacity);
|
||||
}
|
||||
|
||||
fn usz! DString.read_from_stream(&self, InStream* reader)
|
||||
|
||||
@@ -520,9 +520,9 @@ macro TrackingEnv* get_tracking_env()
|
||||
$endif
|
||||
}
|
||||
|
||||
macro @clone(value, TrackingEnv* env = mem::get_tracking_env()) @builtin
|
||||
macro @clone(value) @builtin
|
||||
{
|
||||
return mem::heap().clone(value, env);
|
||||
return mem::heap().clone(value);
|
||||
}
|
||||
|
||||
macro @tclone(value) @builtin
|
||||
@@ -530,24 +530,24 @@ macro @tclone(value) @builtin
|
||||
return mem::temp().clone(value);
|
||||
}
|
||||
|
||||
fn void* malloc(usz size, TrackingEnv* env = mem::get_tracking_env()) @builtin @inline
|
||||
fn void* malloc(usz size) @builtin @inline
|
||||
{
|
||||
return mem::heap().alloc(size, env);
|
||||
return mem::heap().alloc(size);
|
||||
}
|
||||
|
||||
fn void* tmalloc(usz size, usz alignment = 0, usz offset = 0, TrackingEnv* env = mem::get_tracking_env()) @builtin @inline
|
||||
fn void* tmalloc(usz size, usz alignment = 0, usz offset = 0) @builtin @inline
|
||||
{
|
||||
return temp().acquire(size, false, alignment, offset, env)!!;
|
||||
return temp().acquire(size, false, alignment, offset)!!;
|
||||
}
|
||||
|
||||
macro new($Type, TrackingEnv* env = mem::get_tracking_env())
|
||||
macro new($Type)
|
||||
{
|
||||
return heap().new($Type, .env = env);
|
||||
return heap().new($Type);
|
||||
}
|
||||
|
||||
macro new_clear($Type, TrackingEnv* env = mem::get_tracking_env())
|
||||
macro new_clear($Type)
|
||||
{
|
||||
return heap().new_clear($Type, env);
|
||||
return heap().new_clear($Type);
|
||||
}
|
||||
|
||||
macro new_temp($Type)
|
||||
@@ -560,9 +560,9 @@ macro new_temp_clear($Type)
|
||||
return tcalloc($Type.sizeof);
|
||||
}
|
||||
|
||||
macro new_array($Type, usz elements, TrackingEnv* env = mem::get_tracking_env())
|
||||
macro new_array($Type, usz elements)
|
||||
{
|
||||
return heap().new_array($Type, elements, .env = env);
|
||||
return heap().new_array($Type, elements);
|
||||
}
|
||||
|
||||
macro temp_array($Type, usz elements)
|
||||
@@ -570,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, TrackingEnv* env = mem::get_tracking_env())
|
||||
macro new_zero_array($Type, usz elements)
|
||||
{
|
||||
return heap().new_zero_array($Type, elements, env);
|
||||
return heap().new_zero_array($Type, elements);
|
||||
}
|
||||
|
||||
macro temp_zero_array($Type, usz elements)
|
||||
@@ -580,28 +580,28 @@ macro temp_zero_array($Type, usz elements)
|
||||
return (($Type*)tcalloc($Type.sizeof * elements, $Type.alignof))[:elements];
|
||||
}
|
||||
|
||||
fn void* calloc(usz size, TrackingEnv* env = mem::get_tracking_env()) @builtin @inline
|
||||
fn void* calloc(usz size) @builtin @inline
|
||||
{
|
||||
return heap().calloc(size, env);
|
||||
return heap().calloc(size);
|
||||
}
|
||||
|
||||
fn void* tcalloc(usz size, usz alignment = 0, usz offset = 0) @builtin @inline
|
||||
{
|
||||
return temp().acquire(size, false, alignment, offset, null)!!;
|
||||
return temp().acquire(size, false, alignment, offset)!!;
|
||||
}
|
||||
|
||||
fn void* realloc(void *ptr, usz new_size, TrackingEnv* env = mem::get_tracking_env()) @builtin @inline
|
||||
fn void* realloc(void *ptr, usz new_size) @builtin @inline
|
||||
{
|
||||
return heap().realloc(ptr, new_size, env);
|
||||
return heap().realloc(ptr, new_size);
|
||||
}
|
||||
|
||||
fn void free(void* ptr, TrackingEnv* env = mem::get_tracking_env()) @builtin @inline
|
||||
fn void free(void* ptr) @builtin @inline
|
||||
{
|
||||
heap().free(ptr, env);
|
||||
heap().free(ptr);
|
||||
}
|
||||
|
||||
fn void* trealloc(void* ptr, usz size, usz alignment = mem::DEFAULT_MEM_ALIGNMENT) @builtin @inline
|
||||
{
|
||||
return temp().resize(ptr, size, alignment, 0, null)!!;
|
||||
return temp().resize(ptr, size, alignment, 0)!!;
|
||||
}
|
||||
|
||||
|
||||
@@ -15,9 +15,9 @@ interface Allocator
|
||||
{
|
||||
fn void reset(usz mark) @optional;
|
||||
fn usz mark() @optional;
|
||||
fn void*! acquire(usz size, bool clear, usz alignment, usz offset, TrackingEnv* env);
|
||||
fn void*! resize(void* ptr, usz new_size, usz alignment, usz offset, TrackingEnv* env);
|
||||
fn void release(void* ptr, bool aligned, TrackingEnv* env);
|
||||
fn void*! acquire(usz size, bool clear, usz alignment, usz offset);
|
||||
fn void*! resize(void* ptr, usz new_size, usz alignment, usz offset);
|
||||
fn void release(void* ptr, bool aligned);
|
||||
}
|
||||
|
||||
struct AlignedBlock
|
||||
@@ -107,118 +107,118 @@ fn usz alignment_for_allocation(usz alignment) @inline @private
|
||||
|
||||
// Allocator "functions"
|
||||
|
||||
macro void*! Allocator.alloc_checked(&self, usz size, TrackingEnv* env = mem::get_tracking_env())
|
||||
macro void*! Allocator.alloc_checked(&self, usz size)
|
||||
{
|
||||
$if env::TESTING:
|
||||
char* data = self.acquire(size, false, 0, 0, env)!;
|
||||
char* data = self.acquire(size, false, 0, 0)!;
|
||||
mem::set(data, 0xAA, size, mem::DEFAULT_MEM_ALIGNMENT);
|
||||
return data;
|
||||
$else
|
||||
return self.acquire(size, false, 0, 0, env);
|
||||
return self.acquire(size, false, 0, 0);
|
||||
$endif
|
||||
}
|
||||
|
||||
macro void*! Allocator.calloc_checked(&self, usz size, TrackingEnv* env = mem::get_tracking_env())
|
||||
macro void*! Allocator.calloc_checked(&self, usz size)
|
||||
{
|
||||
return self.acquire(size, true, 0, 0, env);
|
||||
return self.acquire(size, true, 0, 0);
|
||||
}
|
||||
macro void*! Allocator.realloc_checked(&self, void* ptr, usz new_size, TrackingEnv* env = mem::get_tracking_env())
|
||||
macro void*! Allocator.realloc_checked(&self, void* ptr, usz new_size)
|
||||
{
|
||||
return self.resize(ptr, new_size, 0, 0, env);
|
||||
return self.resize(ptr, new_size, 0, 0);
|
||||
}
|
||||
|
||||
macro Allocator.new_array(&self, $Type, usz size, usz end_padding = 0, TrackingEnv* env = mem::get_tracking_env())
|
||||
macro Allocator.new_array(&self, $Type, usz size, usz end_padding = 0)
|
||||
{
|
||||
return (($Type*)self.alloc_checked($Type.sizeof * size + end_padding, env))[:size]!!;
|
||||
return (($Type*)self.alloc_checked($Type.sizeof * size + end_padding))[:size]!!;
|
||||
}
|
||||
|
||||
macro Allocator.new_array_checked(&self, $Type, usz size, usz end_padding = 0, TrackingEnv* env = mem::get_tracking_env())
|
||||
macro Allocator.new_array_checked(&self, $Type, usz size, usz end_padding = 0)
|
||||
{
|
||||
return (($Type*)self.alloc_checked($Type.sizeof * size + end_padding, env))[:size];
|
||||
return (($Type*)self.alloc_checked($Type.sizeof * size + end_padding))[:size];
|
||||
}
|
||||
|
||||
macro Allocator.new_zero_array(&self, $Type, usz size, usz end_padding = 0, TrackingEnv* env = mem::get_tracking_env())
|
||||
macro Allocator.new_zero_array(&self, $Type, usz size, usz end_padding = 0)
|
||||
{
|
||||
return (($Type*)self.calloc_checked($Type.sizeof * size + end_padding, env))[:size]!!;
|
||||
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, TrackingEnv* env = mem::get_tracking_env())
|
||||
macro Allocator.new_zero_array_checked(&self, $Type, usz size, usz end_padding = 0)
|
||||
{
|
||||
return (($Type*)self.calloc_checked($Type.sizeof * size + end_padding, env))[:size];
|
||||
return (($Type*)self.calloc_checked($Type.sizeof * size + end_padding))[:size];
|
||||
}
|
||||
|
||||
macro Allocator.new(&self, $Type, usz end_padding = 0, TrackingEnv* env = mem::get_tracking_env()) @nodiscard
|
||||
macro Allocator.new(&self, $Type, usz end_padding = 0) @nodiscard
|
||||
{
|
||||
return ($Type*)self.alloc_checked($Type.sizeof + end_padding, env)!!;
|
||||
return ($Type*)self.alloc_checked($Type.sizeof + end_padding)!!;
|
||||
}
|
||||
|
||||
macro Allocator.new_checked(&self, $Type, usz end_padding = 0, TrackingEnv* env = mem::get_tracking_env()) @nodiscard
|
||||
macro Allocator.new_checked(&self, $Type, usz end_padding = 0) @nodiscard
|
||||
{
|
||||
return ($Type*)self.alloc_checked($Type.sizeof + end_padding, env);
|
||||
return ($Type*)self.alloc_checked($Type.sizeof + end_padding);
|
||||
}
|
||||
|
||||
macro Allocator.new_clear(&self, $Type, usz end_padding = 0, TrackingEnv* env = mem::get_tracking_env()) @nodiscard
|
||||
macro Allocator.new_clear(&self, $Type, usz end_padding = 0) @nodiscard
|
||||
{
|
||||
return ($Type*)self.calloc_checked($Type.sizeof + end_padding, env)!!;
|
||||
return ($Type*)self.calloc_checked($Type.sizeof + end_padding)!!;
|
||||
}
|
||||
|
||||
macro Allocator.new_clear_checked(&self, $Type, usz end_padding = 0, TrackingEnv* env = mem::get_tracking_env()) @nodiscard
|
||||
macro Allocator.new_clear_checked(&self, $Type, usz end_padding = 0) @nodiscard
|
||||
{
|
||||
return ($Type*)self.calloc_checked($Type.sizeof + end_padding, env);
|
||||
return ($Type*)self.calloc_checked($Type.sizeof + end_padding);
|
||||
}
|
||||
|
||||
macro Allocator.clone(&self, value, TrackingEnv* env = mem::get_tracking_env())
|
||||
macro Allocator.clone(&self, value)
|
||||
{
|
||||
var x = self.alloc($typeof(value), env);
|
||||
var x = self.alloc($typeof(value));
|
||||
*x = value;
|
||||
return x;
|
||||
}
|
||||
|
||||
macro void* Allocator.alloc(&self, usz size, TrackingEnv* env = mem::get_tracking_env()) @nodiscard
|
||||
macro void* Allocator.alloc(&self, usz size) @nodiscard
|
||||
{
|
||||
return self.alloc_checked(size, env)!!;
|
||||
return self.alloc_checked(size)!!;
|
||||
}
|
||||
macro void* Allocator.calloc(&self, usz size, TrackingEnv* env = mem::get_tracking_env()) @nodiscard
|
||||
macro void* Allocator.calloc(&self, usz size) @nodiscard
|
||||
{
|
||||
return self.acquire(size, true, 0, 0, env)!!;
|
||||
return self.acquire(size, true, 0, 0)!!;
|
||||
}
|
||||
macro void* Allocator.realloc(&self, void* ptr, usz new_size, TrackingEnv* env = mem::get_tracking_env()) @nodiscard
|
||||
macro void* Allocator.realloc(&self, void* ptr, usz new_size) @nodiscard
|
||||
{
|
||||
return self.resize(ptr, new_size, 0, 0, env)!!;
|
||||
return self.resize(ptr, new_size, 0, 0)!!;
|
||||
}
|
||||
|
||||
macro void*! Allocator.alloc_aligned(&self, usz size, usz alignment, usz offset = 0, TrackingEnv* env = mem::get_tracking_env())
|
||||
macro void*! Allocator.alloc_aligned(&self, usz size, usz alignment, usz offset = 0)
|
||||
{
|
||||
$if env::TESTING:
|
||||
char* data = self.acquire(size, false, alignment, offset, env)!;
|
||||
char* data = self.acquire(size, false, alignment, offset)!;
|
||||
mem::set(data, 0xAA, size, mem::DEFAULT_MEM_ALIGNMENT);
|
||||
return data;
|
||||
$else
|
||||
return self.acquire(size, false, alignment, offset, env);
|
||||
return self.acquire(size, false, alignment, offset);
|
||||
$endif
|
||||
}
|
||||
macro void*! Allocator.calloc_aligned(&self, usz size, usz alignment, usz offset = 0, TrackingEnv* env = mem::get_tracking_env())
|
||||
macro void*! Allocator.calloc_aligned(&self, usz size, usz alignment, usz offset = 0)
|
||||
{
|
||||
return self.acquire(size, true, alignment, offset, env);
|
||||
return self.acquire(size, true, alignment, offset);
|
||||
}
|
||||
macro void*! Allocator.realloc_aligned(&self, void* ptr, usz new_size, usz alignment = 0, usz offset = 0, TrackingEnv* env = mem::get_tracking_env())
|
||||
macro void*! Allocator.realloc_aligned(&self, void* ptr, usz new_size, usz alignment = 0, usz offset = 0)
|
||||
{
|
||||
return self.resize(ptr, new_size, alignment, offset, env);
|
||||
return self.resize(ptr, new_size, alignment, offset);
|
||||
}
|
||||
|
||||
macro void Allocator.free(&self, void* ptr, TrackingEnv* env = mem::get_tracking_env())
|
||||
macro void Allocator.free(&self, void* ptr)
|
||||
{
|
||||
$if env::TESTING:
|
||||
if (ptr) ((char*)ptr)[0] = 0xBA;
|
||||
$endif
|
||||
self.release(ptr, false, env);
|
||||
self.release(ptr, false);
|
||||
}
|
||||
macro void Allocator.free_aligned(&self, void* ptr, TrackingEnv* env = mem::get_tracking_env())
|
||||
macro void Allocator.free_aligned(&self, void* ptr)
|
||||
{
|
||||
$if env::TESTING:
|
||||
if (ptr) ((char*)ptr)[0] = 0xBA;
|
||||
$endif
|
||||
self.release(ptr, true, env);
|
||||
self.release(ptr, true);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -38,13 +38,13 @@ macro String tformat(String fmt, ...)
|
||||
return str.str_view();
|
||||
}
|
||||
|
||||
macro String new_format(String fmt, ..., Allocator* allocator = mem::heap(), TrackingEnv* env = mem::get_tracking_env())
|
||||
macro String new_format(String fmt, ..., Allocator* allocator = mem::heap())
|
||||
{
|
||||
@pool(allocator)
|
||||
{
|
||||
DString str = dstring::temp_with_capacity(fmt.len + $vacount * 8);
|
||||
str.appendf(fmt, $vasplat());
|
||||
return str.copy_str(allocator, env);
|
||||
return str.copy_str(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(), TrackingEnv* env = mem::get_tracking_env())
|
||||
fn String join_new(String[] s, String joiner, Allocator* allocator = mem::heap())
|
||||
{
|
||||
if (!s)
|
||||
{
|
||||
return (String)allocator.new_zero_array(char, 2, .env = env)[:0];
|
||||
return (String)allocator.new_zero_array(char, 2)[: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, env);
|
||||
return res.copy_str(allocator);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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(), TrackingEnv* env = mem::get_tracking_env())
|
||||
fn String[] String.split(s, String needle, usz max = 0, Allocator* allocator = mem::heap())
|
||||
{
|
||||
usz capacity = 16;
|
||||
usz i = 0;
|
||||
String* holder = allocator.new_array(String, capacity, .env = env);
|
||||
String* holder = allocator.new_array(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, env);
|
||||
holder = allocator.realloc(holder, String.sizeof * capacity);
|
||||
}
|
||||
holder[i++] = res;
|
||||
}
|
||||
@@ -312,19 +312,19 @@ fn usz ZString.len(str)
|
||||
}
|
||||
|
||||
|
||||
fn ZString String.zstr_copy(s, Allocator* allocator = mem::heap(), TrackingEnv* env = mem::get_tracking_env())
|
||||
fn ZString String.zstr_copy(s, Allocator* allocator = mem::heap())
|
||||
{
|
||||
usz len = s.len;
|
||||
char* str = allocator.alloc(len + 1, env);
|
||||
char* str = allocator.alloc(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(), TrackingEnv* env = mem::get_tracking_env())
|
||||
fn String String.concat(s1, String s2, Allocator* allocator = mem::heap())
|
||||
{
|
||||
usz full_len = s1.len + s2.len;
|
||||
char* str = allocator.alloc(full_len + 1, env);
|
||||
char* str = allocator.alloc(full_len + 1);
|
||||
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(), TrackingEnv* env = mem::get_tracking_env())
|
||||
fn String String.copy(s, Allocator* allocator = mem::heap())
|
||||
{
|
||||
usz len = s.len;
|
||||
char* str = allocator.alloc(len + 1, env);
|
||||
char* str = allocator.alloc(len + 1);
|
||||
mem::copy(str, s.ptr, len);
|
||||
str[len] = 0;
|
||||
return (String)str[:len];
|
||||
}
|
||||
|
||||
fn void String.free(&s, Allocator* allocator = mem::heap(), TrackingEnv* env = mem::get_tracking_env())
|
||||
fn void String.free(&s, Allocator* allocator = mem::heap())
|
||||
{
|
||||
if (!s.len) return;
|
||||
allocator.free(s.ptr, env);
|
||||
allocator.free(s.ptr);
|
||||
*s = "";
|
||||
}
|
||||
|
||||
fn String String.tcopy(s) => s.copy(mem::temp()) @inline;
|
||||
|
||||
fn String ZString.copy(z, Allocator* allocator = mem::temp(), TrackingEnv* env = mem::get_tracking_env())
|
||||
fn String ZString.copy(z, Allocator* allocator = mem::temp())
|
||||
{
|
||||
return z.str_view().copy(allocator, env) @inline;
|
||||
return z.str_view().copy(allocator) @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(), TrackingEnv* env = mem::get_tracking_env())
|
||||
fn Char16[]! String.to_new_utf16(s, Allocator* allocator = mem::heap())
|
||||
{
|
||||
usz len16 = conv::utf16len_for_utf8(s);
|
||||
Char16* data = allocator.new_array_checked(Char16, len16 + 1, .env = env)!;
|
||||
Char16* data = allocator.new_array_checked(Char16, len16 + 1)!;
|
||||
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(), TrackingEnv* env = mem::get_tracking_env())
|
||||
fn WString! String.to_new_wstring(s, Allocator* allocator = mem::heap())
|
||||
{
|
||||
return (WString)s.to_new_utf16(allocator, env).ptr;
|
||||
return (WString)s.to_new_utf16(allocator).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(), TrackingEnv* env = mem::get_tracking_env())
|
||||
fn Char32[]! String.to_new_utf32(s, Allocator* allocator = mem::heap())
|
||||
{
|
||||
usz codepoints = conv::utf8_codepoints(s);
|
||||
Char32* data = allocator.new_array(Char32, codepoints + 1, .env = env);
|
||||
Char32* data = allocator.new_array(Char32, codepoints + 1);
|
||||
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(), TrackingEnv* env = mem::get_tracking_env())
|
||||
fn String! new_from_utf32(Char32[] utf32, Allocator* allocator = mem::heap())
|
||||
{
|
||||
usz len = conv::utf8len_for_utf32(utf32);
|
||||
char* data = allocator.alloc_checked(len + 1, env)!;
|
||||
char* data = allocator.alloc_checked(len + 1)!;
|
||||
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(), TrackingEnv* env = mem::get_tracking_env())
|
||||
fn String! new_from_utf16(Char16[] utf16, Allocator* allocator = mem::heap())
|
||||
{
|
||||
usz len = conv::utf8len_for_utf16(utf16);
|
||||
char* data = allocator.alloc_checked(len + 1, env)!;
|
||||
char* data = allocator.alloc_checked(len + 1)!;
|
||||
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(), TrackingEnv* env = mem::get_tracking_env())
|
||||
fn String! new_from_wstring(WString wstring, Allocator* allocator = mem::heap())
|
||||
{
|
||||
usz utf16_len;
|
||||
while (wstring[utf16_len] != 0) utf16_len++;
|
||||
Char16[] utf16 = wstring[:utf16_len];
|
||||
return new_from_utf16(utf16, allocator, env);
|
||||
return new_from_utf16(utf16, allocator);
|
||||
}
|
||||
|
||||
fn String! temp_from_wstring(WString wstring) => new_from_wstring(wstring, mem::temp()) @inline;
|
||||
|
||||
@@ -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(), TrackingEnv* env = mem::get_tracking_env())
|
||||
fn ByteBuffer*! ByteBuffer.init_new(&self, usz max_read, usz initial_capacity = 16, Allocator* allocator = mem::heap())
|
||||
{
|
||||
*self = { .allocator = allocator, .max_read = max_read };
|
||||
initial_capacity = max(initial_capacity, 16);
|
||||
self.grow(initial_capacity, env)!;
|
||||
self.grow(initial_capacity)!;
|
||||
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, TrackingEnv* env = mem::get_tracking_env())
|
||||
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, .env = env)!;
|
||||
char* p = self.allocator.realloc_aligned(self.bytes, n, .alignment = char.alignof)!;
|
||||
self.bytes = p[:n];
|
||||
}
|
||||
|
||||
|
||||
@@ -74,7 +74,7 @@ fn Backtrace* Backtrace.init(&self, uptr offset, String function, String object_
|
||||
return self;
|
||||
}
|
||||
|
||||
fn void*[] capture_current(void*[] buffer) @if(env::POSIX || env::WIN32)
|
||||
fn void*[] capture_current(void*[] buffer)
|
||||
{
|
||||
if (!buffer.len) return buffer[:0];
|
||||
$switch
|
||||
@@ -94,3 +94,8 @@ def BacktraceList = List(<Backtrace>);
|
||||
def symbolize_backtrace = linux::symbolize_backtrace @if(env::LINUX);
|
||||
def symbolize_backtrace = win32::symbolize_backtrace @if(env::WIN32);
|
||||
def symbolize_backtrace = darwin::symbolize_backtrace @if(env::DARWIN);
|
||||
|
||||
fn BacktraceList! symbolize_backtrace(void*[] backtrace, Allocator* allocator) @if(!env::NATIVE_STACKTRACE)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
## 0.5.0 Change List
|
||||
|
||||
### Changes / improvements
|
||||
- Trackable allocator with leak allocation backtraces.
|
||||
- `$defined` can take a list of expressions.
|
||||
- `$and` compile time "and" which does not check expressions after the first is an error.
|
||||
- `$is_const` returns true if an expression is compile time const.
|
||||
|
||||
@@ -1 +1 @@
|
||||
#define COMPILER_VERSION "0.4.704"
|
||||
#define COMPILER_VERSION "0.4.705"
|
||||
|
||||
@@ -81,7 +81,6 @@ entry:
|
||||
%type = load ptr, ptr %.cachedtype, align 8
|
||||
%4 = icmp eq ptr %3, %type
|
||||
br i1 %4, label %cache_hit, label %cache_miss
|
||||
|
||||
cache_miss: ; preds = %entry
|
||||
%5 = getelementptr inbounds %.introspect, ptr %3, i32 0, i32 2
|
||||
%6 = load ptr, ptr %5, align 8
|
||||
@@ -89,36 +88,29 @@ cache_miss: ; preds = %entry
|
||||
store ptr %7, ptr %.inlinecache, align 8
|
||||
store ptr %3, ptr %.cachedtype, align 8
|
||||
br label %8
|
||||
|
||||
cache_hit: ; preds = %entry
|
||||
%cache_hit_fn = load ptr, ptr %.inlinecache, align 8
|
||||
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 44, ptr @.file, i64 16
|
||||
unreachable
|
||||
|
||||
match: ; preds = %8
|
||||
%11 = load ptr, ptr %2, align 8
|
||||
%12 = call i64 %fn_phi(ptr %retparam, ptr %11, i64 8, i8 zeroext 0, i64 0, i64 0, ptr null)
|
||||
%12 = call i64 %fn_phi(ptr %retparam, ptr %11, i64 8, i8 zeroext 0, i64 0, i64 0)
|
||||
%not_err = icmp eq i64 %12, 0
|
||||
%13 = call i1 @llvm.expect.i1(i1 %not_err, i1 true)
|
||||
br i1 %13, label %after_check, label %assign_optional
|
||||
|
||||
assign_optional: ; preds = %match
|
||||
store i64 %12, ptr %error_var, align 8
|
||||
br label %panic_block
|
||||
|
||||
after_check: ; preds = %match
|
||||
%14 = load ptr, ptr %retparam, align 8
|
||||
br label %noerr_block
|
||||
|
||||
panic_block: ; preds = %assign_optional
|
||||
%15 = insertvalue %"any*" undef, ptr %error_var, 0
|
||||
%16 = insertvalue %"any*" %15, i64 ptrtoint (ptr @"$ct.anyfault" to i64), 1
|
||||
@@ -129,7 +121,6 @@ panic_block: ; preds = %assign_optional
|
||||
store %"any*[]" %"$$temp", ptr %indirectarg, align 8
|
||||
call void @std.core.builtin.panicf(ptr @.panic_msg.1, i64 36, ptr @.file
|
||||
unreachable
|
||||
|
||||
noerr_block: ; preds = %after_check
|
||||
%19 = insertvalue %"any*" undef, ptr %14, 0
|
||||
%20 = insertvalue %"any*" %19, i64 ptrtoint (ptr @"$ct.inherit.Test" to i64), 1
|
||||
@@ -141,7 +132,6 @@ noerr_block: ; preds = %after_check
|
||||
%type4 = load ptr, ptr %.cachedtype3, align 8
|
||||
%25 = icmp eq ptr %24, %type4
|
||||
br i1 %25, label %cache_hit6, label %cache_miss5
|
||||
|
||||
cache_miss5: ; preds = %noerr_block
|
||||
%26 = getelementptr inbounds %.introspect, ptr %24, i32 0, i32 2
|
||||
%27 = load ptr, ptr %26, align 8
|
||||
@@ -149,21 +139,17 @@ cache_miss5: ; preds = %noerr_block
|
||||
store ptr %28, ptr %.inlinecache2, align 8
|
||||
store ptr %24, ptr %.cachedtype3, align 8
|
||||
br label %29
|
||||
|
||||
cache_hit6: ; preds = %noerr_block
|
||||
%cache_hit_fn7 = load ptr, ptr %.inlinecache2, align 8
|
||||
br label %29
|
||||
|
||||
29: ; preds = %cache_hit6, %cache_miss5
|
||||
%fn_phi8 = phi ptr [ %cache_hit_fn7, %cache_hit6 ], [ %28, %cache_miss5 ]
|
||||
%30 = icmp eq ptr %fn_phi8, null
|
||||
br i1 %30, label %missing_function9, label %match10
|
||||
|
||||
missing_function9: ; preds = %29
|
||||
%31 = load ptr, ptr @std.core.builtin.panic, align 8
|
||||
call void %31(ptr @.panic_msg.2, i64 41
|
||||
unreachable
|
||||
|
||||
match10: ; preds = %29
|
||||
%32 = load ptr, ptr %23, align 8
|
||||
call void %fn_phi8(ptr %32)
|
||||
@@ -176,7 +162,6 @@ match10: ; preds = %29
|
||||
%type13 = load ptr, ptr %.cachedtype12, align 8
|
||||
%38 = icmp eq ptr %37, %type13
|
||||
br i1 %38, label %cache_hit15, label %cache_miss14
|
||||
|
||||
cache_miss14: ; preds = %match10
|
||||
%39 = getelementptr inbounds %.introspect, ptr %37, i32 0, i32 2
|
||||
%40 = load ptr, ptr %39, align 8
|
||||
@@ -184,21 +169,17 @@ cache_miss14: ; preds = %match10
|
||||
store ptr %41, ptr %.inlinecache11, align 8
|
||||
store ptr %37, ptr %.cachedtype12, align 8
|
||||
br label %42
|
||||
|
||||
cache_hit15: ; preds = %match10
|
||||
%cache_hit_fn16 = load ptr, ptr %.inlinecache11, align 8
|
||||
br label %42
|
||||
|
||||
42: ; preds = %cache_hit15, %cache_miss14
|
||||
%fn_phi17 = phi ptr [ %cache_hit_fn16, %cache_hit15 ], [ %41, %cache_miss14 ]
|
||||
%43 = icmp eq ptr %fn_phi17, null
|
||||
br i1 %43, label %missing_function18, label %match19
|
||||
|
||||
missing_function18: ; preds = %42
|
||||
%44 = load ptr, ptr @std.core.builtin.panic, align 8
|
||||
call void %44(ptr @.panic_msg.2, i64 41, ptr @.file.3, i64 10, ptr @.func, i64 4, i32 36)
|
||||
unreachable
|
||||
|
||||
match19: ; preds = %42
|
||||
%45 = load ptr, ptr %36, align 8
|
||||
call void %fn_phi17(ptr %45)
|
||||
@@ -209,25 +190,20 @@ match19: ; preds = %42
|
||||
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
|
||||
@@ -237,31 +213,25 @@ no_match: ; preds = %compare
|
||||
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
|
||||
|
||||
@@ -68,7 +68,6 @@ entry:
|
||||
%type = load ptr, ptr %.cachedtype, align 8
|
||||
%4 = icmp eq ptr %3, %type
|
||||
br i1 %4, label %cache_hit, label %cache_miss
|
||||
|
||||
cache_miss: ; preds = %entry
|
||||
%5 = getelementptr inbounds %.introspect, ptr %3, i32 0, i32 2
|
||||
%6 = load ptr, ptr %5, align 8
|
||||
@@ -76,36 +75,29 @@ cache_miss: ; preds = %entry
|
||||
store ptr %7, ptr %.inlinecache, align 8
|
||||
store ptr %3, ptr %.cachedtype, align 8
|
||||
br label %8
|
||||
|
||||
cache_hit: ; preds = %entry
|
||||
%cache_hit_fn = load ptr, ptr %.inlinecache, align 8
|
||||
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 44, ptr @.file, i64 16, ptr @.func, i64 4
|
||||
unreachable
|
||||
|
||||
match: ; preds = %8
|
||||
%11 = load ptr, ptr %2, align 8
|
||||
%12 = call i64 %fn_phi(ptr %retparam, ptr %11, i64 8, i8 zeroext 0, i64 0, i64 0, ptr null)
|
||||
%12 = call i64 %fn_phi(ptr %retparam, ptr %11, i64 8, i8 zeroext 0, i64 0, i64 0)
|
||||
%not_err = icmp eq i64 %12, 0
|
||||
%13 = call i1 @llvm.expect.i1(i1 %not_err, i1 true)
|
||||
br i1 %13, label %after_check, label %assign_optional
|
||||
|
||||
assign_optional: ; preds = %match
|
||||
store i64 %12, ptr %error_var, align 8
|
||||
br label %panic_block
|
||||
|
||||
after_check: ; preds = %match
|
||||
%14 = load ptr, ptr %retparam, align 8
|
||||
br label %noerr_block
|
||||
|
||||
panic_block: ; preds = %assign_optional
|
||||
%15 = insertvalue %"any*" undef, ptr %error_var, 0
|
||||
%16 = insertvalue %"any*" %15, i64 ptrtoint (ptr @"$ct.anyfault" to i64), 1
|
||||
@@ -116,7 +108,6 @@ panic_block: ; preds = %assign_optional
|
||||
store %"any*[]" %"$$temp", ptr %indirectarg, align 8
|
||||
call void @std.core.builtin.panicf(ptr @.panic_msg.1
|
||||
unreachable
|
||||
|
||||
noerr_block: ; preds = %after_check
|
||||
%19 = insertvalue %"any*" undef, ptr %14, 0
|
||||
%20 = insertvalue %"any*" %19, i64 ptrtoint (ptr @"$ct.overlap.Test" to i64), 1
|
||||
@@ -128,7 +119,6 @@ noerr_block: ; preds = %after_check
|
||||
%type4 = load ptr, ptr %.cachedtype3, align 8
|
||||
%25 = icmp eq ptr %24, %type4
|
||||
br i1 %25, label %cache_hit6, label %cache_miss5
|
||||
|
||||
cache_miss5: ; preds = %noerr_block
|
||||
%26 = getelementptr inbounds %.introspect, ptr %24, i32 0, i32 2
|
||||
%27 = load ptr, ptr %26, align 8
|
||||
@@ -136,21 +126,17 @@ cache_miss5: ; preds = %noerr_block
|
||||
store ptr %28, ptr %.inlinecache2, align 8
|
||||
store ptr %24, ptr %.cachedtype3, align 8
|
||||
br label %29
|
||||
|
||||
cache_hit6: ; preds = %noerr_block
|
||||
%cache_hit_fn7 = load ptr, ptr %.inlinecache2, align 8
|
||||
br label %29
|
||||
|
||||
29: ; preds = %cache_hit6, %cache_miss5
|
||||
%fn_phi8 = phi ptr [ %cache_hit_fn7, %cache_hit6 ], [ %28, %cache_miss5 ]
|
||||
%30 = icmp eq ptr %fn_phi8, null
|
||||
br i1 %30, label %missing_function9, label %match10
|
||||
|
||||
missing_function9: ; preds = %29
|
||||
%31 = load ptr, ptr @std.core.builtin.panic, align 8
|
||||
call void %31(ptr @.panic_msg.2, i64 41, ptr @.file
|
||||
unreachable
|
||||
|
||||
match10: ; preds = %29
|
||||
%32 = load ptr, ptr %23, align 8
|
||||
call void %fn_phi8(ptr %32)
|
||||
@@ -163,7 +149,6 @@ match10: ; preds = %29
|
||||
%type13 = load ptr, ptr %.cachedtype12, align 8
|
||||
%38 = icmp eq ptr %37, %type13
|
||||
br i1 %38, label %cache_hit15, label %cache_miss14
|
||||
|
||||
cache_miss14: ; preds = %match10
|
||||
%39 = getelementptr inbounds %.introspect, ptr %37, i32 0, i32 2
|
||||
%40 = load ptr, ptr %39, align 8
|
||||
@@ -171,21 +156,17 @@ cache_miss14: ; preds = %match10
|
||||
store ptr %41, ptr %.inlinecache11, align 8
|
||||
store ptr %37, ptr %.cachedtype12, align 8
|
||||
br label %42
|
||||
|
||||
cache_hit15: ; preds = %match10
|
||||
%cache_hit_fn16 = load ptr, ptr %.inlinecache11, align 8
|
||||
br label %42
|
||||
|
||||
42: ; preds = %cache_hit15, %cache_miss14
|
||||
%fn_phi17 = phi ptr [ %cache_hit_fn16, %cache_hit15 ], [ %41, %cache_miss14 ]
|
||||
%43 = icmp eq ptr %fn_phi17, null
|
||||
br i1 %43, label %missing_function18, label %match19
|
||||
|
||||
missing_function18: ; preds = %42
|
||||
%44 = load ptr, ptr @std.core.builtin.panic, align 8
|
||||
call void %44(ptr @.panic_msg.2, i64 41, ptr @.file.3, i64 23, ptr @.func, i64 4, i32 30)
|
||||
unreachable
|
||||
|
||||
match19: ; preds = %42
|
||||
%45 = load ptr, ptr %36, align 8
|
||||
call void %fn_phi17(ptr %45)
|
||||
@@ -194,31 +175,25 @@ match19: ; preds = %42
|
||||
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
|
||||
|
||||
@@ -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, ptr null) #3
|
||||
%16 = call ptr @std.core.mem.malloc(i64 8) #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, ptr null) #3
|
||||
%27 = call ptr @std.core.mem.malloc(i64 16) #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, ptr null) #3
|
||||
%32 = call ptr @std.core.mem.malloc(i64 8) #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, ptr null) #3
|
||||
%43 = call ptr @std.core.mem.malloc(i64 %add) #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, ptr null) #3
|
||||
%59 = call ptr @std.core.mem.malloc(i64 16) #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, ptr null) #3
|
||||
%64 = call ptr @std.core.mem.malloc(i64 8) #3
|
||||
store ptr %64, ptr %temp56, align 8
|
||||
%65 = load ptr, ptr %temp56, align 8
|
||||
%not57 = icmp eq ptr %65, null
|
||||
|
||||
@@ -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, ptr null)
|
||||
%5 = call ptr @std.core.dstring.new_with_capacity(i64 128, i64 %lo, ptr %hi)
|
||||
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, ptr null)
|
||||
%0 = call ptr @"std.collections.map$int$test.Foo$.HashMap.init_new"(ptr %map, i32 16, float 7.500000e-01, i64 %lo, ptr %hi)
|
||||
%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, ptr null)
|
||||
%48 = call ptr @"std.collections.map$int$double$.HashMap.init_new"(ptr %map2, i32 16, float 7.500000e-01, i64 %lo33, ptr %hi34)
|
||||
%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, ptr null)
|
||||
%76 = call ptr @"std.collections.map$int$double$.HashMap.init_new"(ptr %map3, i32 16, float 7.500000e-01, i64 %lo59, ptr %hi60)
|
||||
%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
|
||||
|
||||
Reference in New Issue
Block a user