diff --git a/phasm/compiler.py b/phasm/compiler.py index 0b456a2..b74b1c7 100644 --- a/phasm/compiler.py +++ b/phasm/compiler.py @@ -361,6 +361,7 @@ def module(inp: ourlang.Module) -> wasm.Module: result.functions = [ _generate____new_reference___(inp), _generate_stdlib_alloc___init__(inp), + _generate_stdlib_alloc___find_free_block__(inp), _generate_stdlib_alloc___alloc__(inp), _generate____access_bytes_index___(inp), ] + [ @@ -394,6 +395,9 @@ def _generate____new_reference___(mod: ourlang.Module) -> wasm.Function: ], ) +STDLIB_ALLOC__FREE_BLOCK = '0x08' +STDLIB_ALLOC__UNALLOC_ADDR = '0x0C' + def _generate_stdlib_alloc___init__(mod: ourlang.Module) -> wasm.Function: return wasm.Function( 'stdlib.alloc.__init__', @@ -411,15 +415,17 @@ def _generate_stdlib_alloc___init__(mod: ourlang.Module) -> wasm.Function: wasm.Statement('end'), wasm.Statement('i32.const', '0x04', comment='Reserved'), - wasm.Statement('i32.const', '0x000000'), + wasm.Statement('i32.const', '0x00000000'), wasm.Statement('i32.store'), - wasm.Statement('i32.const', '0x08', comment='Address of next free block'), - wasm.Statement('i32.const', '0x000000'), + wasm.Statement('i32.const', STDLIB_ALLOC__FREE_BLOCK, + comment='Address of next free block'), + wasm.Statement('i32.const', '0x00000000'), wasm.Statement('i32.store'), - wasm.Statement('i32.const', '0x0C', comment='Reserved'), - wasm.Statement('i32.const', '0x000000'), + wasm.Statement('i32.const', STDLIB_ALLOC__UNALLOC_ADDR, + comment='Address of first unallocated byte'), + wasm.Statement('i32.const', '0x10'), wasm.Statement('i32.store'), wasm.Statement('i32.const', '0x00', comment='Done setting up'), @@ -428,6 +434,30 @@ def _generate_stdlib_alloc___init__(mod: ourlang.Module) -> wasm.Function: ], ) +def _generate_stdlib_alloc___find_free_block__(mod: ourlang.Module) -> wasm.Function: + return wasm.Function( + 'stdlib.alloc.__find_free_block__', + 'stdlib.alloc.__find_free_block__', + [ + ('alloc_size', type_(mod.types['i32']), ), + ], + [ + ('result', type_(mod.types['i32']), ), + ], + type_(mod.types['i32']), + [ + wasm.Statement('i32.const', STDLIB_ALLOC__FREE_BLOCK), + wasm.Statement('i32.load'), + wasm.Statement('i32.const', '0x00000000'), + wasm.Statement('i32.eq'), + wasm.Statement('if'), + wasm.Statement('i32.const', '0x00000000'), + wasm.Statement('return'), + wasm.Statement('end'), + wasm.Statement('unreachable'), + ], + ) + def _generate_stdlib_alloc___alloc__(mod: ourlang.Module) -> wasm.Function: return wasm.Function( 'stdlib.alloc.__alloc__', @@ -444,15 +474,36 @@ def _generate_stdlib_alloc___alloc__(mod: ourlang.Module) -> wasm.Function: wasm.Statement('i32.load'), wasm.Statement('i32.const', '0xA1C0'), wasm.Statement('i32.ne'), - wasm.Statement('if', comment='Failed to set up'), + wasm.Statement('if', comment='Failed to set up or memory corruption'), wasm.Statement('unreachable'), wasm.Statement('end'), - # wasm.Statement('local.get', '$alloc_size'), - # wasm.Statement('call', '$stdlib.alloc.__find_space__'), - wasm.Statement('i32.const', '0x16', comment='STUB'), + wasm.Statement('local.get', '$alloc_size'), + wasm.Statement('call', '$stdlib.alloc.__find_free_block__'), wasm.Statement('local.set', '$result'), + # Check if there was a free block + wasm.Statement('local.get', '$result'), + wasm.Statement('i32.const', '0x00000000'), + wasm.Statement('i32.eq'), + wasm.Statement('if', comment='No free block found'), + + # Use unallocated space + wasm.Statement('i32.const', STDLIB_ALLOC__UNALLOC_ADDR), + + wasm.Statement('i32.const', STDLIB_ALLOC__UNALLOC_ADDR), + wasm.Statement('i32.load'), + wasm.Statement('local.tee', '$result'), + + # Updated unalloc pointer (address already set on stack) + wasm.Statement('i32.const', '0x04'), # Struct size + wasm.Statement('i32.add'), + wasm.Statement('local.get', '$alloc_size'), + wasm.Statement('i32.add'), + wasm.Statement('i32.store', 'offset=0'), + + wasm.Statement('end'), + # Store block size wasm.Statement('local.get', '$result'), wasm.Statement('local.get', '$alloc_size'), diff --git a/tests/integration/test_stdlib_alloc.py b/tests/integration/test_stdlib_alloc.py index 52ccfa4..80c3065 100644 --- a/tests/integration/test_stdlib_alloc.py +++ b/tests/integration/test_stdlib_alloc.py @@ -54,7 +54,7 @@ def testEntry() -> u8: b'\xC0\xA1\x00\x00' b'\x00\x00\x00\x00' b'\x00\x00\x00\x00' - b'\x00\x00\x00\x00' + b'\x10\x00\x00\x00' b'\x10\x11\x12\x13' # Untouched because unused ) == memory[0:20] @@ -93,8 +93,10 @@ def testEntry() -> u8: sys.stderr.write(f'{DASHES} Memory (pre run) {DASHES}\n') _dump_memory(rtime.get_memory(0)) - offset = rtime.find_function('stdlib.alloc.__init__')() - offset = rtime.find_function('stdlib.alloc.__alloc__')(32) + rtime.find_function('stdlib.alloc.__init__')() + offset0 = rtime.find_function('stdlib.alloc.__alloc__')(32) + offset1 = rtime.find_function('stdlib.alloc.__alloc__')(32) + offset2 = rtime.find_function('stdlib.alloc.__alloc__')(32) sys.stderr.write(f'{DASHES} Memory (pre run) {DASHES}\n') _dump_memory(rtime.get_memory(0)) @@ -103,4 +105,8 @@ def testEntry() -> u8: assert b'\xC0\xA1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' == memory[0:12] - assert 0 == offset + assert 0x14 == offset0 + assert 0x38 == offset1 + assert 0x5C == offset2 + + assert False