hare

The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

commit ad59f1354e785679a7833aea8c47410653231c23
parent ae071fd6c0afd5fb052e20d618be2a2deddc2d75
Author: Drew DeVault <sir@cmpwn.com>
Date:   Thu,  8 Jul 2021 22:05:43 -0400

rt: add basic +debug allocator

Signed-off-by: Drew DeVault <sir@cmpwn.com>

Diffstat:
Art/malloc+debug.ha | 87+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 87 insertions(+), 0 deletions(-)

diff --git a/rt/malloc+debug.ha b/rt/malloc+debug.ha @@ -0,0 +1,87 @@ +// This is a very simple "debug" allocator which works by allocating only via +// mmap and returning pointers to the end of the segment such that any writes +// beyond the end will cause an immediate segfault to occur. +// +// Ultimately, this should be replaced with a much more sophisticated debugging +// allocator. +let pagesz: size = 4096; + +def AUXV_PAGESZ: u64 = 6; + +type auxv64 = struct { + a_type: u64, + union { + a_val: u64, + a_ptr: *void, + a_fnc: *fn() void, + } +}; + +@init fn init() void = { + let i = 0; + for (rt::envp[i] != null) { + i += 1; + }; + let auxv = &rt::envp[i + 1]: *[*]auxv64; + for (let i = 0z; auxv[i].a_type != 0; i += 1) { + if (auxv[i].a_type == AUXV_PAGESZ) { + pagesz = auxv[i].a_val: size; + break; + }; + }; +}; + +export fn malloc(n: size) nullable *void = { + if (n == 0) { + return null; + }; + let z = n + size(*void) + size(size); + if (z % pagesz != 0) { + z += pagesz - z % pagesz; + }; + let seg = match (segmalloc(z)) { + null => return null, + ptr: *void => ptr, + }; + let user = &(seg: *[*]u8)[z - n]; + let segptr = &(user: *[*]*void)[-1]; + let szptr = &(segptr: *[*]size)[-1]; + *segptr = seg; + *szptr = n; + return user; +}; + +export @symbol("rt.free") fn free_(_p: nullable *void) void = { + if (_p != null) { + let user = _p: *void; + let segptr = &(user: *[*]*void)[-1]; + let szptr = &(segptr: *[*]size)[-1]; + let z = *szptr + size(*void) + size(size); + if (z % pagesz != 0) { + z += pagesz - z % pagesz; + }; + segfree(*segptr, z); + }; +}; + +export fn realloc(user: nullable *void, n: size) nullable *void = { + if (n == 0) { + free(user); + return null; + } else if (user == null) { + return malloc(n); + }; + + let user = user: *void; + let segptr = &(user: *[*]*void)[-1]; + let szptr = &(segptr: *[*]size)[-1]; + let z = *szptr; + + let new = malloc(n); + if (new != null) { + memcpy(new: *void, user, if (z < n) z else n); + free(user); + }; + + return new; +};