Skip to content

Commit

Permalink
selftest: recursively determine register inputs
Browse files Browse the repository at this point in the history
Previously the selftest would determine which registers
are supposed to contain addresses  (and allocate memory
accordingly) by going through all memory operations and
assuming that address registers used in those are the
inputs holding the addresses initially.

This assumption does not hold as
(1) addresses may be moved around
(2) addresses may actually be a result of a previous computation.

One example where this did not work was

vmov rX, sY
ldr tZ, [rX]

here the selftest would assume that rX needs to be
an address. However, sY is the register holding the
address on entry of the code.

This commit refines the code determining the address
registers by recursively going through the DFG
and determining the _input_ registers that affect
values being used as addresses.
Note that in the above examples rX would not be
marked as an address, at it is not an input.

Hopefully this approach is more robust.
  • Loading branch information
mkannwischer committed Dec 16, 2024
1 parent c0100ae commit 0c8c873
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 1 deletion.
2 changes: 1 addition & 1 deletion slothy/core/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -866,7 +866,7 @@ def selftest(self, log):
addr = getattr(t.inst, "addr", None)
if addr is None:
continue
addresses.add(addr)
addresses = addresses.union(tree.find_all_predecessors_input_registers(t, addr))

# For now, we don't look into increments and immedate offsets
# to gauge the amount of memory we actually need. Instaed, we
Expand Down
20 changes: 20 additions & 0 deletions slothy/core/dataflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -780,6 +780,26 @@ def has_symbolic_registers(self):
return True
return False

def find_all_predecessors_input_registers(self, consumer, register_name):
""" recursively finds the set of input registers registers that a certain value depends on."""
producer = consumer.reg_state[register_name].src
# if this is a virtual input instruction this is an actual input
# otherwise this is computed from other inputs
if isinstance(producer.inst, VirtualInputInstruction):
return set(producer.inst.args_out)
else:
# go through all predecessors and recursively call this function
# Note that we only care about inputs (i.e., produced by a VirtualInputInstruction)
regs = []
if hasattr(producer.inst, "args_in"):
regs += producer.inst.args_in
if hasattr(producer.inst, "args_in_out"):
regs += producer.inst.args_in_out
predecessors = set()
for reg in regs:
predecessors = predecessors.union(self.find_all_predecessors_input_registers(producer, reg))
return set(predecessors)

def ssa(self, filter_func=None):
"""Transform data flow graph into single static assignment (SSA) form."""
# Go through non-virtual instruction nodes and assign unique names to
Expand Down

0 comments on commit 0c8c873

Please sign in to comment.