Emitted code epilogue block contains a superflous jump to the next available code address.
Port, board and/or hardware
mpy-cross built from git commit 6db29978ac8954f3686f9eb59dd71b55c3495456 (current master)
MicroPython version
MicroPython v1.25.0-preview.216.g6db29978a.dirty on 2025-01-17; mpy-cross emitting mpy v6.3
Reproduction
- Run
mpy-cross -X emit=native -march=debug tests/basics/0prelim.py - Look at the last part of the output for a jump to
label_0.
This applies to any supported architecture with a native emitter, but -march=debug is used in the command line to make the problem visible without using a disassembler.
Expected behaviour
There should be no empty jump being emitted at the end of a block.
Observed behaviour
At the end of an emitted block of code this can be seen (taken from tests/basics/0prelim.py):
...
jump(label_0)
label(label_0)
EXIT(0)
This applies also to functions that need a more involved cleanup procedure:
(tests/basics/async_for.py):
...
jump(label_0)
dead_code load(r_temp0, r_fun_table, 0)
dead_code store(r_temp0, r_local2, 5)
dead_code mov_reg_imm(r_temp0, 40=0x28)
dead_code add(r_temp0, r_local2)
dead_code store(r_temp0, r_local2, 2)
dead_code mov_reg_imm(r_temp0, 0=0x0)
dead_code mov_local_reg(local_3, r_temp0)
dead_code jump(label_0)
label(label_0)
call_ind(nlr_pop)
mov_reg_local(r_ret, local_3)
EXIT(0)
(tests/basics/array_micropython.py):
...
mov_local_reg(local_3, r_ret)
jump(label_0)
label(label_0)
mov_reg_local(r_arg1, local_6)
call_ind(native_swap_globals)
call_ind(nlr_pop)
mov_reg_local(r_ret, local_3)
EXIT(0)
Additional Information
This is not specific to mpy-cross as the same issue occurs when emitting a block of code at runtime as well.
Code of Conduct
Yes, I agree
py: fix native emitter to work with `async with` statements
This fixes the native emitter so that async with statements now work with it.
This PR also includes a new "debug native emitter" that can be used to print out pseudo instructions generated by the native emitter, to help debug issues with it. Eg with the following test.py file:
@micropython.native
def f():
return 1
mpy-cross can be used as follows to get debug output from the native emitter:
$ ./build/mpy-cross -march=debug test.py
ENTRY(num_locals=6)
load(r_fun_table, r_arg1, 1)
load(r_local3, r_fun_table, 2)
load(r_fun_table, r_fun_table, 3)
load(r_fun_table, r_fun_table, 0)
mov_local_reg(local_0, r_arg1)
mov_reg_imm(r_arg1, 1=0x1)
mov_local_reg(local_3, r_arg1)
mov_reg_local_addr(r_arg1, local_0)
call_ind(setup_code_state)
mov_reg_imm(r_ret, 3=0x3)
jump(label_0)
dead_code load(r_ret, r_fun_table, 0)
dead_code jump(label_0)
label(label_0)
EXIT(0)