phasm/phasm/stdlib/alloc.py
2022-09-17 20:13:16 +02:00

87 lines
2.2 KiB
Python

"""
stdlib: Memory allocation
"""
from phasm.wasmgenerator import Generator, VarType_i32 as i32, func_wrapper
IDENTIFIER = 0xA1C0
ADR_IDENTIFIER = 0
ADR_RESERVED0 = ADR_IDENTIFIER + 4
ADR_FREE_BLOCK_PTR = ADR_RESERVED0 + 4
ADR_UNALLOC_PTR = ADR_FREE_BLOCK_PTR + 4
UNALLOC_PTR = ADR_UNALLOC_PTR + 4
# For memory initialization see phasm.compiler.module_data
@func_wrapper(exported=False)
def __find_free_block__(g: Generator, alloc_size: i32) -> i32:
# Find out if we've freed any blocks at all so far
g.i32.const(ADR_FREE_BLOCK_PTR)
g.i32.load()
g.i32.const(0)
g.i32.eq()
with g.if_():
g.i32.const(0)
g.return_()
del alloc_size # TODO: Actual implement using a previously freed block
g.unreachable()
return i32('return') # To satisfy mypy
@func_wrapper()
def __alloc__(g: Generator, alloc_size: i32) -> i32:
result = i32('result')
# Check if the memory is already initialized
g.i32.const(ADR_IDENTIFIER)
g.i32.load()
g.i32.const(IDENTIFIER)
g.i32.ne()
with g.if_():
# Not yet initialized, or memory corruption
g.unreachable()
# Try to claim a free block
g.local.get(alloc_size)
g.call(__find_free_block__)
g.local.set(result)
# Check if there was a free block
g.local.get(result)
g.i32.const(0)
g.i32.eq()
with g.if_():
# No free blocks, increase allocated memory usage
# Put the address on the stack in advance so we can store to it later
g.i32.const(ADR_UNALLOC_PTR)
# Get the current unalloc pointer value
g.i32.const(ADR_UNALLOC_PTR)
g.i32.load()
g.local.tee(result)
# Calculate new unalloc pointer value
g.i32.const(4) # Header size
g.i32.add()
g.local.get(alloc_size)
g.i32.add()
# Store new unalloc pointer value (address was set on stack in advance)
g.i32.store()
# Store block size in the header
g.local.get(result)
g.local.get(alloc_size)
g.i32.store()
# Return address of the allocated memory, skipping the allocator header
g.local.get(result)
g.i32.const(4) # Header size
g.i32.add()
return i32('return') # To satisfy mypy