Skip to content

Commit

Permalink
Implement configurable swapping of if-else branches based on size
Browse files Browse the repository at this point in the history
  • Loading branch information
rihi committed Jan 10, 2024
1 parent 50e0bbd commit d1ce3bf
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 8 deletions.
31 changes: 23 additions & 8 deletions decompiler/backend/codevisitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ def __init__(self, task: DecompilerTask):
self._int_repr_scope: int = task.options.getint("code-generator.int_representation_scope", fallback=256)
self._neg_hex_as_twos_complement: bool = task.options.getboolean("code-generator.negative_hex_as_twos_complement", fallback=True)
self._aggressive_array_detection: bool = task.options.getboolean("code-generator.aggressive_array_detection", fallback=False)
self._preferred_true_branch: str = task.options.getstring("code-generator.preferred_true_branch", fallback="none")
self.task = task

def visit_seq_node(self, node: ast_nodes.SeqNode) -> str:
Expand Down Expand Up @@ -70,16 +71,30 @@ def visit_condition_node(self, node: ast_nodes.ConditionNode) -> str:
true_str = self.visit(node.true_branch_child)
if node.false_branch is None:
return f"if ({self._condition_string(node.condition)}) {{{true_str}}}"

false_str = self.visit(node.false_branch_child)
if isinstance(node.true_branch_child, ast_nodes.ConditionNode) or isinstance(node.false_branch_child, ast_nodes.ConditionNode):
negate_condition = isinstance(node.true_branch_child, ast_nodes.ConditionNode) and not isinstance(
node.false_branch_child, ast_nodes.ConditionNode
)

condition = node.condition
if negate_condition:
true_str, false_str = false_str, true_str
condition = ~condition
condition = node.condition
true_child = node.true_branch_child
false_child = node.false_branch_child

def swap_branches():
nonlocal condition, true_child, false_child, true_str, false_str
condition = ~condition
true_child, false_child = false_child, true_child
true_str, false_str = false_str, true_str

length_comparisons = {
"none": False,
"smallest": len(true_str) > len(false_str),
"largest": len(true_str) < len(false_str)
}
if length_comparisons[self._preferred_true_branch]:
swap_branches()

if isinstance(true_child, ast_nodes.ConditionNode) or isinstance(false_child, ast_nodes.ConditionNode):
if not isinstance(false_child, ast_nodes.ConditionNode):
swap_branches()

return f"if ({self._condition_string(condition)}) {{{true_str}}} else {false_str}"
else:
Expand Down
20 changes: 20 additions & 0 deletions decompiler/util/default.json
Original file line number Diff line number Diff line change
Expand Up @@ -418,6 +418,26 @@
"is_hidden_from_cli": false,
"argument_name": "--variable-declarations-per-line"
},
{
"dest": "code-generator.preferred_true_branch",
"default": "smallest",
"title": "Preferred type of true branch in if-else",
"type": "string",
"enum": [
"smallest",
"largest",
"none"
],
"enumDescriptions": [
"smallest",
"largest",
"none"
],
"description": "Swap branches of if-else structures based on the given criteria",
"is_hidden_from_gui": false,
"is_hidden_from_cli": false,
"argument_name": "--preferred_true_branch"
},
{
"dest": "pattern-independent-restructuring.switch_reconstruction",
"default": true,
Expand Down

0 comments on commit d1ce3bf

Please sign in to comment.