Skip to content

Commit

Permalink
Fix variable renamign
Browse files Browse the repository at this point in the history
  • Loading branch information
alexcere committed Nov 13, 2024
1 parent b36648a commit 53c9451
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 74 deletions.
4 changes: 3 additions & 1 deletion src/cfg_methods/cfg_block_actions/inline_function.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,9 @@ def perform_action(self):
for exit_id in function_exists_ids:
exit_block = self._cfg_blocklist.get_block(exit_id)
# Finally, we remove the function return from the exit id
exit_block.remove_instruction(-1)
exit_function_return = exit_block.remove_instruction(-1)
assert exit_function_return.get_op_name() == "functionReturn", f"Last instruction of exit block " \
f"{exit_id} must be a functionReturn"

# is_correct, reason = validate_block_list_comes_from(self._cfg_blocklist)

Expand Down
14 changes: 4 additions & 10 deletions src/cfg_methods/function_inlining.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,7 @@ def inline_functions_cfg_object(cfg_object: CFGObject, function_call_info: funct
split_block_index = 0
position_index = instr_pos + _adjust_phi_function_idx_misalignment(cfg_block_list.blocks[split_blocks[split_block_index]])

function_to_inline, renaming_dict = _generate_function_to_inline(cfg_function, func_idx, call_idx,
len(call_info))
function_to_inline, renaming_dict = _generate_function_to_inline(cfg_function, func_idx, call_idx, len(call_info))

# nx.nx_agraph.write_dot(cfg_block_list.to_graph_info(), f"antes.dot")

Expand Down Expand Up @@ -201,17 +200,12 @@ def _generate_function_to_inline(original_function: CFGFunction, func_idx: int,
block_list.rename_blocks(renaming_dict)

var_ids = _var_ids_from_list(block_list)
renaming_vars = {var_: f"{var_}_f{func_idx}_{current_call_idx}" for var_ in var_ids}
renaming_vars.update((var_, f"{var_}_f{func_idx}_{current_call_idx}") for var_ in copied_function.arguments)
bef = copy(renaming_vars)
nx.nx_agraph.write_dot(copied_function.blocks.to_graph_info(), "bef.dot")
renaming_vars = {var_: f"{var_.split('_')[0]}_f{func_idx}_{current_call_idx}" for var_ in var_ids}
renaming_vars.update((var_, f"{var_.split('_')[0]}_f{func_idx}_{current_call_idx}") for var_ in copied_function.arguments)

n_renaming_vars = len(renaming_vars)
rename_function(copied_function, renaming_vars)

nx.nx_agraph.write_dot(copied_function.blocks.to_graph_info(), "aft.dot")

print(renaming_vars, bef)
print(block_list.name, set(renaming_vars.keys()).difference(bef.keys()))
assert n_renaming_vars == len(renaming_vars), \
"Variable renaming in function duplication should not assign new variables"

Expand Down
85 changes: 22 additions & 63 deletions src/cfg_methods/variable_renaming.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,88 +13,47 @@
def rename_variables_cfg(cfg: CFG) -> None:
# Store which variable names have been already assigned
for object_id, cfg_object in cfg.objectCFG.items():
already_assigned = set()
free_index = 0

free_index = rename_variables_block_list(cfg_object.blocks, already_assigned, dict(), free_index)
renaming_dict, free_index = renaming_dict_from_instrs(cfg_object.blocks, [], free_index)
rename_block_list(cfg_object.blocks, renaming_dict)

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

sub_object = cfg.get_subobject()

if sub_object is not None:
rename_variables_cfg(sub_object)


def rename_cfg_function(cfg_function: CFGFunction, assigned_global: Set[var_id_T],
renaming_dict: Dict[var_id_T, var_id_T], free_index: int, generate_next: bool = True) -> int:
cfg_function.arguments, free_index = modified_var_list(cfg_function.arguments, assigned_global,
renaming_dict, free_index)
free_index = rename_variables_block_list(cfg_function.blocks, assigned_global, renaming_dict, free_index, generate_next)
def new_variables_function(cfg_function: CFGFunction, free_index: int) -> int:
renaming_dict, free_index = renaming_dict_from_instrs(cfg_function.blocks, cfg_function.arguments, free_index)
cfg_function.arguments = rename_var_list(cfg_function.arguments, renaming_dict)
rename_block_list(cfg_function.blocks, renaming_dict)
return free_index


def rename_variables_block_list(block_list: CFGBlockList, variables_assigned: Set[var_id_T],
renaming_dict: Dict[var_id_T, var_id_T], free_index: int, generate_next: bool = True) -> int:
# The renaming dict keeps track of the changes in this block to maintain the coherence
for block_name, block in block_list.blocks.items():
def renaming_dict_from_instrs(block_list: CFGBlockList, input_args: List[var_id_T],
free_index: int) -> Tuple[Dict[var_id_T, var_id_T], int]:
"""
Generates a renaming dict from the output of the instructions, pointing to the next free index
"""
renaming_dict = dict()
# Note that input args from functions must be also assigned a new name
for input_arg in input_args:
renaming_dict[input_arg] = f"v{free_index}"
free_index += 1

for block in block_list.blocks.values():
for instruction in block.get_instructions():
free_index = modify_vars_in_instr(instruction, variables_assigned, renaming_dict, free_index, generate_next)

if block.get_condition() is not None:
new_cond_list, free_index = modified_var_list([block.get_condition()], variables_assigned,
renaming_dict, free_index, generate_next)
block.set_condition(new_cond_list[0])
# We have to update the names with the ones that have already been assigned
variables_assigned.update(renaming_dict.values())
return free_index


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


def modified_var_list(var_list: List[var_id_T], assigned_global: Set[var_id_T],
renaming_dict: Dict[var_id_T, var_id_T], free_index: int, generate_next: bool = True) -> 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 and the already assigned ones are added as is
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)

# If it has already been assigned
elif variable in assigned_global:
assert generate_next, "The renaming shouldn't introduce new elements"
new_variable_name = f"v{free_index}"
renaming_dict[variable] = new_variable_name
updated_var_list.append(new_variable_name)
free_index += 1

# Last case: first time we encounter this value in the block list
else:
if generate_next:
free_index = max(free_index, int(variable[1:]) + 1)
renaming_dict[variable] = variable
updated_var_list.append(variable)

return updated_var_list, free_index
for out_arg in instruction.out_args:
renaming_dict[out_arg] = f"v{free_index}"
free_index += 1

return renaming_dict, free_index

# Methods for renaming just using a dict

def rename_function(cfg_function: CFGFunction, renaming_dict: Dict[var_id_T, var_id_T]) -> None:
cfg_function.arguments = rename_var_list(cfg_function.arguments, renaming_dict)
Expand Down

0 comments on commit 53c9451

Please sign in to comment.