-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Devise preprocessing methods, yet to be tested
- Loading branch information
Showing
4 changed files
with
133 additions
and
0 deletions.
There are no files selected for viewing
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
""" | ||
Module to perform function inlining. | ||
""" | ||
from typing import Set, Dict, Tuple, List | ||
from collections import defaultdict | ||
from parser.cfg_block import CFGBlock | ||
from parser.cfg_block_list import CFGBlockList | ||
from parser.cfg import CFG | ||
from parser.cfg_block_actions.inline_function import InlineFunction | ||
|
||
|
||
def generate_function2blocks(cfg: CFG) -> Dict[str, List[Tuple[int, CFGBlock, CFGBlockList]]]: | ||
""" | ||
Links each function to the block and block list in which it is used | ||
""" | ||
function2blocks = dict() | ||
for object_id, cfg_object in cfg.objectCFG.items(): | ||
function_names = set(cfg_object.functions.keys()) | ||
function2blocks.update(generate_function2blocks_block_list(cfg_object.blocks, function_names)) | ||
|
||
# We also consider the information per function | ||
for cfg_function in cfg_object.functions.values(): | ||
function2blocks.update(generate_function2blocks_block_list(cfg_function.blocks, function_names)) | ||
|
||
sub_object = cfg.get_subobject() | ||
|
||
if sub_object is not None: | ||
function2blocks.update(generate_function2blocks_block_list(cfg_object.blocks, function_names)) | ||
|
||
return function2blocks | ||
|
||
|
||
def generate_function2blocks_block_list(cfg_block_list: CFGBlockList, function_names: Set[str]) -> \ | ||
Dict[str, List[Tuple[int, CFGBlock, CFGBlockList]]]: | ||
""" | ||
Links the function calls that appear in the block list to the exact block and the block list | ||
""" | ||
function2blocks = defaultdict(lambda: []) | ||
for block_name, block in cfg_block_list.blocks.items(): | ||
for i, instruction in enumerate(block.get_instructions()): | ||
if instruction.get_op_name() in function_names: | ||
function2blocks[instruction.get_op_name()].append((i, block, cfg_block_list)) | ||
return function2blocks | ||
|
||
|
||
def inline_functions(cfg: CFG, function2blocks: Dict[str, List[Tuple[int, CFGBlock, CFGBlockList]]]) -> None: | ||
""" | ||
Inlines the functions that are invoked just in one place | ||
""" | ||
for object_id, cfg_object in cfg.objectCFG.items(): | ||
|
||
# We also consider the information per function | ||
for function_name, cfg_function in cfg_object.functions.items(): | ||
invocation_list = function2blocks[function_name] | ||
if len(invocation_list) == 1: | ||
pos, cfg_block, cfg_block_list = invocation_list[0] | ||
inline_action = InlineFunction(pos, cfg_block, cfg_block_list, function_name, cfg_object) | ||
inline_action.perform_action() | ||
|
||
sub_object = cfg.get_subobject() | ||
|
||
if sub_object is not None: | ||
inline_functions(sub_object, function2blocks) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
""" | ||
Module to insert the JUMP, JUMPI and PUSH [tag] instructions before performing the liveness analysis | ||
""" | ||
from parser.cfg import CFG | ||
|
||
|
||
def insert_jump_instructions(cfg: CFG): | ||
""" | ||
Introduces the JUMP, JUMPI and PUSH [tag] instructions in the blocks according to the CFG structure | ||
""" | ||
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
""" | ||
Module used to generate the sub blocks and count how many times each function is invoked. | ||
Same idea as optimizable_block_list but using the cfg actions and simplifying the process | ||
""" | ||
from parser.cfg_block_list import CFGBlockList | ||
from parser.cfg import CFG | ||
import parser.constants as constants | ||
from parser.cfg_block_actions.split_block import SplitBlock | ||
|
||
|
||
def split_blocks_cfg(cfg: CFG) -> None: | ||
""" | ||
Splits the blocks in the cfg | ||
""" | ||
for object_id, cfg_object in cfg.objectCFG.items(): | ||
modify_block_list_split(cfg_object.blocks) | ||
|
||
# We also consider the information per function | ||
for function_name, cfg_function in cfg_object.functions.items(): | ||
modify_block_list_split(cfg_function.blocks) | ||
|
||
sub_object = cfg.get_subobject() | ||
|
||
if sub_object is not None: | ||
split_blocks_cfg(sub_object) | ||
|
||
|
||
def modify_block_list_split(block_list: CFGBlockList) -> None: | ||
""" | ||
Modifies a CFGBlockList by splitting blocks when function calls and split instructions are found | ||
""" | ||
blocks_to_traverse = list(block_list.blocks.items()) | ||
new_start_block = None | ||
for block_name, cfg_block in blocks_to_traverse: | ||
|
||
# It can be reassigned if the block is split multiple times | ||
current_block = cfg_block | ||
instr_idx = 0 | ||
|
||
while instr_idx < len(current_block.get_instructions()): | ||
instr = current_block.get_instructions()[instr_idx] | ||
|
||
is_split_instr = instr.get_op_name() in constants.split_block | ||
is_function_call = instr.get_op_name() in cfg_block.function_calls | ||
is_jump = instr.get_op_name() in ["JUMP", "JUMPI"] | ||
|
||
if is_split_instr or is_function_call or is_jump: | ||
# Sub blocks contain a split instruction or a function call as the last instruction | ||
split_block_action = SplitBlock(instr_idx, current_block, block_list) | ||
split_block_action.perform_action() | ||
|
||
# If the current block corresponds to the initial block and we modify it | ||
if new_start_block is None and current_block.block_id == block_list.start_block: | ||
new_start_block = split_block_action.first_half | ||
|
||
current_block = split_block_action.second_half | ||
instr_idx = 0 | ||
else: | ||
instr_idx += 1 |