From d1ce3bf28d18fa34d3603593dd73d8dde0e10fe5 Mon Sep 17 00:00:00 2001 From: rihi <19492038+rihi@users.noreply.github.com> Date: Wed, 10 Jan 2024 15:59:05 +0100 Subject: [PATCH] Implement configurable swapping of if-else branches based on size --- decompiler/backend/codevisitor.py | 31 +++++++++++++++++++++++-------- decompiler/util/default.json | 20 ++++++++++++++++++++ 2 files changed, 43 insertions(+), 8 deletions(-) diff --git a/decompiler/backend/codevisitor.py b/decompiler/backend/codevisitor.py index cf3bb18da..0fd7ec1e8 100644 --- a/decompiler/backend/codevisitor.py +++ b/decompiler/backend/codevisitor.py @@ -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: @@ -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: diff --git a/decompiler/util/default.json b/decompiler/util/default.json index 25f5be1c9..c266a8246 100644 --- a/decompiler/util/default.json +++ b/decompiler/util/default.json @@ -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,