Skip to content

Commit

Permalink
Rename variables to ensure uniqueness when inlining
Browse files Browse the repository at this point in the history
  • Loading branch information
alexcere committed Oct 30, 2024
1 parent 20a7bd4 commit 7deca00
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 1 deletion.
9 changes: 8 additions & 1 deletion src/cfg_methods/preprocessing_methods.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,17 @@
from cfg_methods.function_inlining import inline_functions
from cfg_methods.sub_block_generation import combine_remove_blocks_cfg, split_blocks_cfg
from cfg_methods.jump_insertion import insert_jumps_tags_cfg
from cfg_methods.variable_renaming import rename_variables_cfg


def preprocess_cfg(cfg: CFG, dot_file_dir: Path) -> Dict[str, Dict[str, int]]:
# First we inline the functions
# Assign distinct names for all the variables in the CFG among different functions and blocks
# TODO: in the future, we could do the renaming just in the inliner when two block lists are merged
rename_variables_cfg(cfg)
dot_file_dir.joinpath("renamed").mkdir(exist_ok=True, parents=True)
liveness_info = dot_from_analysis(cfg, dot_file_dir.joinpath("renamed"))

# We inline the functions
inline_functions(cfg)
dot_file_dir.joinpath("inlined").mkdir(exist_ok=True, parents=True)
liveness_info = dot_from_analysis(cfg, dot_file_dir.joinpath("inlined"))
Expand Down
75 changes: 75 additions & 0 deletions src/cfg_methods/variable_renaming.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
"""
Methods for renaming the variables in the CFG. This is needed because different functions might share
the same variables name, and it interferes the liveness analysis
"""
from typing import Dict, List, Tuple, Set
from global_params.types import var_id_T
from parser.cfg import CFG
from parser.cfg_instruction import CFGInstruction
from parser.cfg_block_list import CFGBlockList


def rename_variables_cfg(cfg: CFG) -> None:
# Store which variable names have been already assigned
already_assigned = set()
free_index = 0
for object_id, cfg_object in cfg.objectCFG.items():
free_index = rename_variables_block_list(cfg_object.blocks, already_assigned, free_index)

# We also consider the information per function
for cfg_function in cfg_object.functions.values():
free_index = rename_variables_block_list(cfg_function.blocks, already_assigned, free_index)

sub_object = cfg.get_subobject()

if sub_object is not None:
rename_variables_cfg(sub_object)


def rename_variables_block_list(block_list: CFGBlockList, variables_assigned: Set[var_id_T], free_index: int) -> int:
# The renaming dict keeps track of the changes in this block to maintain the coherence
renaming_dict = dict()
for block_name, block in block_list.blocks.items():
for instruction in block.get_instructions():
free_index = modify_vars_in_instr(instruction, variables_assigned, renaming_dict, free_index)
return free_index


def modify_vars_in_instr(instruction: CFGInstruction, variables_assigned: Set[var_id_T],
renaming_dict: Dict[var_id_T, var_id_T], free_index: int) -> int:
instruction.in_args, free_index = modified_var_list(instruction.in_args, variables_assigned,
renaming_dict, free_index)
instruction.out_args, free_index = modified_var_list(instruction.out_args, variables_assigned,
renaming_dict, free_index)
return free_index


def modified_var_list(var_list: List[var_id_T], variables_assigned: Set[var_id_T], renaming_dict: Dict[var_id_T, var_id_T],
free_index: int) -> Tuple[List[var_id_T], int]:
updated_var_list = []
for variable in var_list:
new_variable_name = renaming_dict.get(variable, None)

# We ignore constants in the renaming
if variable.startswith("0x"):
updated_var_list.append(variable)

# If it is not None, it means we have already assigned a new name to this variable
elif new_variable_name is not None:
updated_var_list.append(new_variable_name)

# Repeated name from another variable. We have to assign a new name
elif variable in variables_assigned:
new_variable_name = f"v{free_index}"
renaming_dict[variable] = new_variable_name
variables_assigned.add(variable)
updated_var_list.append(new_variable_name)
free_index += 1

# The variable name is available. We just update the free index to ensure no overlapping is possible
else:
free_index = max(free_index, int(variable[1:]) + 1)
variables_assigned.add(variable)
updated_var_list.append(variable)

return updated_var_list, free_index

0 comments on commit 7deca00

Please sign in to comment.