HEAP_START = 0x00108000_u32
HEAP_SIZE = 0x00008000_u32
struct HeapState
@heap_base : UInt32 = HEAP_START
@heap_top : UInt32 = HEAP_START + HEAP_SIZE
@heap_ptr : UInt32 = HEAP_START
@inited : Bool = false
def heap_base
@heap_base
end
def heap_base=(v : UInt32)
@heap_base = v
end
def heap_top
@heap_top
end
def heap_top=(v : UInt32)
@heap_top = v
end
def heap_ptr
@heap_ptr
end
def heap_ptr=(v : UInt32)
@heap_ptr = v
end
def inited
@inited
end
def inited=(v : Bool)
@inited = v
end
end
HEAP_STATE = HeapState.new
module TinyAllocI386
def self.init
return if HEAP_STATE.inited
HEAP_STATE.heap_ptr = HEAP_STATE.heap_base
HEAP_STATE.inited = true
end
def self.align_up32(v : UInt32, align : UInt32) : UInt32
mask = align - 1_u32
(v + mask) & ~mask
end
def self.malloc32(size : UInt32, align : UInt32 = 8_u32) : Pointer(UInt8)?
init_if_needed
return nil if size == 0_u32
a = align_up32(HEAP_STATE.heap_ptr, align)
new_ptr = a + size
if new_ptr > HEAP_STATE.heap_top
return nil
end
HEAP_STATE.heap_ptr = new_ptr
Pointer(UInt8).new(a.to_u64)
end
def self.reset_heap
HEAP_STATE.heap_ptr = HEAP_STATE.heap_base
end
def self.memset_bytes(ptr : Pointer(UInt8), c : UInt8, n : UInt32) : Pointer(UInt8)
i = 0_u32
while i < n
(ptr + i).value = c
i += 1
end
ptr
end
def self.memcpy_bytes(dst : Pointer(UInt8), src : Pointer(UInt8), n : UInt32) : Pointer(UInt8)
i = 0_u32
while i < n
(dst + i).value = (src + i).value
i += 1
end
dst
end
def self.calloc32(nmemb : UInt32, size : UInt32, align : UInt32 = 8_u32) : Pointer(UInt8)?
total = nmemb * size
p = malloc32(total, align)
return nil if p.nil?
memset_bytes(p, 0_u8, total)
p
end
end
lib CExports
fun malloc(size : UInt32) : Pointer(Void)
fun free(ptr : Pointer(Void))
fun memset(ptr : Pointer(Void), c : Int32, n : UInt32) : Pointer(Void)
fun memcpy(dest : Pointer(Void), src : Pointer(Void), n : UInt32) : Pointer(Void)
fun calloc(nmemb : UInt32, size : UInt32) : Pointer(Void)
end
def malloc(size : UInt32) : Pointer(Void)
TinyAllocI386.malloc32(size).as(Pointer(Void))
end
def free(ptr : Pointer(Void))
end
def memset(ptr : Pointer(Void), c : Int32, n : UInt32) : Pointer(Void)
TinyAllocI386.memset_bytes(Pointer(UInt8).new(ptr.to_i), c.to_u8, n)
ptr
end
def memcpy(dest : Pointer(Void), src : Pointer(Void), n : UInt32) : Pointer(Void)
TinyAllocI386.memcpy_bytes(
Pointer(UInt8).new(dest.to_i),
Pointer(UInt8).new(src.to_i),
n
)
dest
end
def calloc(nmemb : UInt32, size : UInt32) : Pointer(Void)
TinyAllocI386.calloc32(nmemb, size).as(Pointer(Void))
end