From 94f414e82dddf60384365d30737d4b935291780a Mon Sep 17 00:00:00 2001 From: Rihi <19492038+rihi@users.noreply.github.com> Date: Thu, 3 Aug 2023 09:13:55 +0200 Subject: [PATCH] Change super type of typing/Float from typing/Integer to typing/Type (#296) --- decompiler/backend/cexpressiongenerator.py | 14 +++++++------- decompiler/backend/codevisitor.py | 2 +- .../expression_simplification.py | 14 ++++++-------- .../variable_name_generation.py | 2 +- .../pipeline/dataflowanalysis/type_propagation.py | 6 +++--- decompiler/structures/pseudo/typing.py | 6 +++--- 6 files changed, 21 insertions(+), 23 deletions(-) diff --git a/decompiler/backend/cexpressiongenerator.py b/decompiler/backend/cexpressiongenerator.py index 5e8fffcd7..f310fe341 100644 --- a/decompiler/backend/cexpressiongenerator.py +++ b/decompiler/backend/cexpressiongenerator.py @@ -4,7 +4,7 @@ from typing import Union from decompiler.structures import pseudo as expressions -from decompiler.structures.pseudo import Float, Integer, OperationType, Pointer, StringSymbol +from decompiler.structures.pseudo import Float, Integer, OperationType, StringSymbol from decompiler.structures.pseudo import instructions as instructions from decompiler.structures.pseudo import operations as operations from decompiler.structures.visitors.interfaces import DataflowObjectVisitorInterface @@ -158,7 +158,7 @@ def visit_unknown_expression(self, expr: expressions.UnknownExpression) -> str: def visit_constant(self, expr: expressions.Constant) -> str: """Return constant in a format that will be parsed correctly by a compiler.""" - if isinstance(expr.type, Integer) and not isinstance(expr.type, (Float, Pointer)): + if isinstance(expr.type, Integer): value = self._get_integer_literal_value(expr) return self._format_integer_literal(expr.type, value) if isinstance(expr, StringSymbol): @@ -186,8 +186,8 @@ def visit_unary_operation(self, op: operations.UnaryOperation) -> str: if op.operation == OperationType.cast: if op.type == op.operand.type: return operand - elif isinstance(op.type, Integer) and isinstance(op.operand.type, Integer): - if isinstance(op.operand, expressions.Constant): + elif isinstance(op.operand, expressions.Constant): + if isinstance(op.type, Integer) and isinstance(op.operand.type, Integer): value = self._get_integer_literal_value(op.operand) eliminated_val = expressions.Constant(value, op.type) try: @@ -195,6 +195,8 @@ def visit_unary_operation(self, op: operations.UnaryOperation) -> str: return self.visit(eliminated_val) except ValueError: pass + elif isinstance(op.type, Float) and isinstance(op.operand.type, Float): + return self.visit(op.operand) return f"({op.type}){operand}" return f"{self.C_SYNTAX[op.operation]}{operand}" @@ -287,13 +289,11 @@ def visit_mem_phi(self, instr: instructions.MemPhi) -> str: """Return a string representation of a mem phi instruction. Only included for completeness.""" return f"{instr}" - def _get_integer_literal_value(self, literal: expressions.Constant[Integer]) -> Union[float, int]: + def _get_integer_literal_value(self, literal: expressions.Constant) -> int: """ Return the right integer value for the given type, assuming that the re-compilation host has the same sizes as the decompilation host. """ - if isinstance(literal.type, Float): - return literal.value if literal.type.is_signed: if handler := self.SIGNED_FORMATS.get(literal.type.size, None): return handler(literal.value) diff --git a/decompiler/backend/codevisitor.py b/decompiler/backend/codevisitor.py index 81b8e18ed..66058b239 100644 --- a/decompiler/backend/codevisitor.py +++ b/decompiler/backend/codevisitor.py @@ -180,7 +180,7 @@ def _is_incrementable(self, instr: Assignment, target_operand: expressions.Expre and isinstance(target_operand, expressions.Constant) and ( (isinstance(target_operand.type, Float) and self._use_increment_float) - or ((isinstance(target_operand.type, Integer) and not isinstance(target_operand.type, Float)) and self._use_increment_int) + or (isinstance(target_operand.type, Integer) and self._use_increment_int) ) and (target_operand.value == 0x1 or target_operand.value == -0x1) ) diff --git a/decompiler/pipeline/controlflowanalysis/expression_simplification.py b/decompiler/pipeline/controlflowanalysis/expression_simplification.py index c7f132840..5064e58a3 100644 --- a/decompiler/pipeline/controlflowanalysis/expression_simplification.py +++ b/decompiler/pipeline/controlflowanalysis/expression_simplification.py @@ -6,7 +6,7 @@ from decompiler.structures.pseudo.expressions import Constant, Expression from decompiler.structures.pseudo.instructions import Instruction from decompiler.structures.pseudo.operations import BinaryOperation, Operation, OperationType, UnaryOperation -from decompiler.structures.pseudo.typing import Integer +from decompiler.structures.pseudo.typing import Float, Integer from decompiler.task import DecompilerTask @@ -128,13 +128,11 @@ def is_minus_one_constant(expression: Expression) -> bool: @staticmethod def negate_expression(expression: Expression) -> Expression: """Negate the given expression and return it.""" - if isinstance(expression, Constant) and expression.value == 0: - return expression - if isinstance(expression, UnaryOperation) and expression.operation == OperationType.negate: - return expression.operand - if isinstance(expression, Constant) and isinstance(expression.type, Integer) and expression.type.is_signed: - return Constant(-expression.value, expression.type) - return UnaryOperation(OperationType.negate, [expression]) + match expression: + case Constant(value=0): return expression + case UnaryOperation(operation=OperationType.negate): return expression.operand + case Constant(type=Integer(is_signed=True) | Float()): return Constant(-expression.value, expression.type) + case _: return UnaryOperation(OperationType.negate, [expression]) @staticmethod def get_other_operand(binary_operation: BinaryOperation, expression: Expression) -> Expression: diff --git a/decompiler/pipeline/controlflowanalysis/variable_name_generation.py b/decompiler/pipeline/controlflowanalysis/variable_name_generation.py index 261349573..97f838cb7 100644 --- a/decompiler/pipeline/controlflowanalysis/variable_name_generation.py +++ b/decompiler/pipeline/controlflowanalysis/variable_name_generation.py @@ -145,7 +145,7 @@ def _hungarian_prefix(self, var_type: Type) -> str: else: return "" if isinstance(var_type, (Integer, Float)): - sign = "" if var_type.is_signed else "u" + sign = "u" if isinstance(var_type, Integer) and not var_type.is_signed else "" prefix = self.type_prefix[type(var_type)].get(var_type.size, "unk") return f"{sign}{prefix}" return "" diff --git a/decompiler/pipeline/dataflowanalysis/type_propagation.py b/decompiler/pipeline/dataflowanalysis/type_propagation.py index 249ba91e9..20213ea9c 100644 --- a/decompiler/pipeline/dataflowanalysis/type_propagation.py +++ b/decompiler/pipeline/dataflowanalysis/type_propagation.py @@ -11,7 +11,7 @@ from decompiler.structures.graphs.cfg import ControlFlowGraph from decompiler.structures.pseudo.expressions import Expression, Variable from decompiler.structures.pseudo.instructions import BaseAssignment, Instruction -from decompiler.structures.pseudo.typing import CustomType, Float, Integer, Pointer, Type, UnknownType +from decompiler.structures.pseudo.typing import CustomType, Integer, Pointer, Type, UnknownType from decompiler.task import DecompilerTask from networkx import DiGraph, Graph, connected_components @@ -133,8 +133,8 @@ def _get_common_type(expressions: List[Expression]) -> Type: @staticmethod def _is_non_primitive_type(type: Type) -> bool: - """Check if the given type is primitive, so ew can ignore it.""" - if isinstance(type, Integer) and not isinstance(type, Float): + """Check if the given type is primitive, so we can ignore it.""" + if isinstance(type, Integer): return False if isinstance(type, Pointer) and type.type == CustomType.void(): return False diff --git a/decompiler/structures/pseudo/typing.py b/decompiler/structures/pseudo/typing.py index c72ac4776..8f367da62 100644 --- a/decompiler/structures/pseudo/typing.py +++ b/decompiler/structures/pseudo/typing.py @@ -131,14 +131,14 @@ def __str__(self): @dataclass(frozen=True, order=True) -class Float(Integer): +class Float(Type): """Class representing the type of a floating point number as defined in IEEE 754.""" SIZE_TYPES = {8: "quarter", 16: "half", 32: "float", 64: "double", 80: "long double", 128: "quadruple", 256: "octuple"} - def __init__(self, size: int, signed=True): + def __init__(self, size: int): """Create a new float type with the given size.""" - super().__init__(size, signed) + super().__init__(size) @classmethod def float(cls) -> Float: