From 7c34a364271f973c1435e609112801958cc17532 Mon Sep 17 00:00:00 2001 From: alexcere <48130030+alexcere@users.noreply.github.com> Date: Mon, 21 Oct 2024 15:30:08 +0200 Subject: [PATCH] Split block by index instead of instruction --- src/parser/cfg_block_actions/split_block.py | 17 ++++++++--------- tests/test_split_block.py | 11 +++++++++-- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/src/parser/cfg_block_actions/split_block.py b/src/parser/cfg_block_actions/split_block.py index 1591b049..56b59e99 100644 --- a/src/parser/cfg_block_actions/split_block.py +++ b/src/parser/cfg_block_actions/split_block.py @@ -24,8 +24,9 @@ class SplitBlock(BlockAction): It needs the corresponding blocklist to update the fields correspondingly """ - def __init__(self, cfg_instruction: CFGInstruction, cfg_block: CFGBlock, cfg_blocklist: CFGBlockList): - self._cfg_instruction: CFGInstruction = cfg_instruction + def __init__(self, instr_idx: int, cfg_block: CFGBlock, cfg_blocklist: CFGBlockList): + # We add one to the index so that it points to the initial instruction of the second half + self._instr_idx: int = instr_idx + 1 self._cfg_block: Optional[CFGBlock] = cfg_block self._cfg_block_list: CFGBlockList = cfg_blocklist self._initial_id = self._cfg_block.block_id @@ -33,20 +34,17 @@ def __init__(self, cfg_instruction: CFGInstruction, cfg_block: CFGBlock, cfg_blo self._second_half: Optional[CFGBlock] = None def perform_action(self): - # First we find the index of the instruction. It is included as part of the first split block - instr_idx = self._cfg_block.get_instructions().index(self._cfg_instruction) + 1 - # first_half_id = new_node_name(self._initial_id) second_half_id = new_node_name(first_half_id) # We reuse the block name, so we don't need to modify the previous blocks - first_half = CFGBlock(first_half_id, self._cfg_block.get_instructions()[:instr_idx], "sub_block", + first_half = CFGBlock(first_half_id, self._cfg_block.get_instructions()[:self._instr_idx], "sub_block", self._cfg_block.assignment_dict) self._first_half = first_half # Then we generate the second half - second_half = CFGBlock(second_half_id, self._cfg_block.get_instructions()[instr_idx:], + second_half = CFGBlock(second_half_id, self._cfg_block.get_instructions()[self._instr_idx:], self._cfg_block.get_jump_type(), self._cfg_block.assignment_dict) self._second_half = second_half @@ -69,8 +67,9 @@ def _update_first_half(self): self._first_half.set_comes_from(self._cfg_block.get_comes_from()) self._first_half.set_falls_to(self._second_half.block_id) self._first_half.set_jump_to(None) + # We need to force the input arguments of the instruction we have use to split - self._first_half.final_stack_elements = self._cfg_instruction.get_in_args() + self._first_half.final_stack_elements = self._cfg_block.get_instructions()[self._instr_idx].get_in_args() # Finally, we update the information from the blocks that jumped (or fell) to the first one for pred_block_id in self._cfg_block.get_comes_from(): @@ -117,4 +116,4 @@ def _modify_comes_from(self, block_id: block_id_T, new_pred_block_id: block_id_T assert found_previous, f"Comes from list {comes_from} of {block_id} does not contain {self._initial_id}" def __str__(self): - return f"SplitBlock {self._initial_id} at instruction {self._cfg_instruction}" + return f"SplitBlock {self._initial_id} at instruction with index {self._instr_idx}" diff --git a/tests/test_split_block.py b/tests/test_split_block.py index ad7d6f4b..dfe2900f 100644 --- a/tests/test_split_block.py +++ b/tests/test_split_block.py @@ -14,6 +14,13 @@ def test_split_block_simple(self, n, instructions): # We don't want to select the last index selected_index = (n % (len(instructions) - 1)) - split_object = SplitBlock(instructions[selected_index], cfg_block, cfg_block_list) + split_object = SplitBlock(selected_index, cfg_block, cfg_block_list) split_object.perform_action() - assert True + assert len(cfg_block_list.blocks) == 2, "There must be two sub blocks" + assert "block_1" in cfg_block_list.blocks, "Block block_1 must appear in the block list" + assert "block_2" in cfg_block_list.blocks, "Block block_2 must appear in the block list" + assert len(cfg_block_list.blocks["block_1"].get_instructions()) == selected_index + 1, \ + f"First block must contain {selected_index} instructions" + n_remaining_instrs = len(cfg_block.get_instructions()) - selected_index - 1 + assert len(cfg_block_list.blocks["block_2"].get_instructions()) == n_remaining_instrs, \ + f"Second block must contain {n_remaining_instrs} instructions"