From 058d9cebf14caedb1f3815f42fac53fdde4ae11b Mon Sep 17 00:00:00 2001 From: Fish Date: Wed, 25 Sep 2024 22:25:25 -0700 Subject: [PATCH] BinaryOp: Fix a bug that would lead to one of the operands becoming None after replacing. (#242) * BinaryOp: Fix a bug that would lead to one of the operands becoming None after replacing. --- ailment/converter_vex.py | 45 ++++++++++++++++++++++++++++------------ ailment/expression.py | 25 ++++++++++++---------- 2 files changed, 46 insertions(+), 24 deletions(-) diff --git a/ailment/converter_vex.py b/ailment/converter_vex.py index 330e598..01a1ece 100644 --- a/ailment/converter_vex.py +++ b/ailment/converter_vex.py @@ -225,9 +225,13 @@ def Binop(expr, manager): operands[1] = Const(operands[1].idx, None, (1 << op1_bits) - op1_val, op1_bits) signed = False + vector_count = None + vector_size = None if op._vector_count is not None and op._vector_size is not None: # SIMD conversions op_name += "V" # vectorized + vector_count = op._vector_count + vector_size = op._vector_size elif op_name in {"CmpLE", "CmpLT", "CmpGE", "CmpGT", "Div", "DivMod", "Mod", "Mul", "Mull"}: if op.is_signed: signed = True @@ -311,6 +315,8 @@ def Binop(expr, manager): vex_block_addr=manager.block_addr, vex_stmt_idx=manager.vex_stmt_idx, bits=bits, + vector_count=vector_count, + vector_size=vector_size, **extra_kwargs, ) @@ -553,11 +559,23 @@ def CAS(idx, stmt: pyvex.IRStmt.CAS, manager): }[ty] dataHi = VEXExprConverter.convert(stmt.dataHi, manager) dataLo = VEXExprConverter.convert(stmt.dataLo, manager) - data = BinaryOp(idx, "Concat", (dataHi, dataLo), False) + data = BinaryOp(manager.next_atom(), "Concat", (dataHi, dataLo), False) - expdHi = Convert(idx, widen_from_bits, widen_to_bits, False, VEXExprConverter.convert(stmt.dataHi, manager)) - expdLo = Convert(idx, widen_from_bits, widen_to_bits, False, VEXExprConverter.convert(stmt.dataLo, manager)) - expd = BinaryOp(idx, "Concat", (expdHi, expdLo), False) + expdHi = Convert( + manager.next_atom(), + widen_from_bits, + widen_to_bits, + False, + VEXExprConverter.convert(stmt.dataHi, manager), + ) + expdLo = Convert( + manager.next_atom(), + widen_from_bits, + widen_to_bits, + False, + VEXExprConverter.convert(stmt.dataLo, manager), + ) + expd = BinaryOp(manager.next_atom(), "Concat", (expdHi, expdLo), False) else: narrow_to_bits = widen_to_bits = None data = VEXExprConverter.convert(stmt.dataLo, manager) @@ -579,9 +597,9 @@ def CAS(idx, stmt: pyvex.IRStmt.CAS, manager): size, stmt.endness, ) - cmp = BinaryOp(idx, "CmpEQ", (val, expd), False) + cmp = BinaryOp(manager.next_atom(), "CmpEQ", (val, expd), False) store = Store( - idx, + manager.next_atom(), addr.copy(), data, size, @@ -594,13 +612,14 @@ def CAS(idx, stmt: pyvex.IRStmt.CAS, manager): stmts.append(store) if double: - val_shifted = BinaryOp(idx, "Shr", (val, narrow_to_bits), False) - valHi = Convert(idx, widen_to_bits, narrow_to_bits, False, val_shifted) - valLo = Convert(idx, widen_to_bits, narrow_to_bits, False, val) + narrow_to_bits_con = Const(manager.next_atom(), None, narrow_to_bits, 8) + val_shifted = BinaryOp(manager.next_atom(), "Shr", [val, narrow_to_bits_con], False) + valHi = Convert(manager.next_atom(), widen_to_bits, narrow_to_bits, False, val_shifted) + valLo = Convert(manager.next_atom(), widen_to_bits, narrow_to_bits, False, val) wrtmp_0 = Assignment( - idx, - Tmp(idx, None, stmt.oldLo, narrow_to_bits), + manager.next_atom(), + Tmp(manager.next_atom(), None, stmt.oldLo, narrow_to_bits), valLo, ins_addr=manager.ins_addr, vex_block_addr=manager.block_addr, @@ -608,7 +627,7 @@ def CAS(idx, stmt: pyvex.IRStmt.CAS, manager): ) wrtmp_1 = Assignment( idx, - Tmp(idx, None, stmt.oldHi, narrow_to_bits), + Tmp(manager.next_atom(), None, stmt.oldHi, narrow_to_bits), valHi, ins_addr=manager.ins_addr, vex_block_addr=manager.block_addr, @@ -619,7 +638,7 @@ def CAS(idx, stmt: pyvex.IRStmt.CAS, manager): else: wrtmp = Assignment( idx, - Tmp(idx, None, stmt.oldLo, size), + Tmp(manager.next_atom(), None, stmt.oldLo, size), val, ins_addr=manager.ins_addr, vex_block_addr=manager.block_addr, diff --git a/ailment/expression.py b/ailment/expression.py index 94355a9..36b8eb7 100644 --- a/ailment/expression.py +++ b/ailment/expression.py @@ -727,6 +727,8 @@ class BinaryOp(Op): "rounding_mode", "from_bits", # for divmod "to_bits", # for divmod + "vector_count", + "vector_size", ) OPSTR_MAP = { @@ -791,10 +793,12 @@ def __init__( variable=None, variable_offset=None, bits=None, - floating_point=False, - rounding_mode=None, - from_bits=None, - to_bits=None, + floating_point: bool = False, + rounding_mode: str | None = None, + from_bits: int | None = None, + to_bits: int | None = None, + vector_count: int | None = None, + vector_size: int | None = None, **kwargs, ): depth = ( @@ -841,7 +845,9 @@ def __init__( self.variable = variable self.variable_offset = variable_offset self.floating_point = floating_point - self.rounding_mode = rounding_mode + self.rounding_mode: str | None = rounding_mode + self.vector_count = vector_count + self.vector_size = vector_size self.from_bits = from_bits self.to_bits = to_bits @@ -924,24 +930,21 @@ def replace(self, old_expr, new_expr): else: r1, replaced_operand_1 = False, None + r2, replaced_rm = False, None if self.rounding_mode is not None: if self.rounding_mode == old_expr: r2 = True replaced_rm = new_expr - elif isinstance(self.rounding_mode, Expression): - r2, replaced_rm = self.rounding_mode.replace(old_expr, new_expr) - else: - r2, replaced_rm = False, None if r0 or r1: return True, BinaryOp( self.idx, self.op, - [replaced_operand_0, replaced_operand_1], + [replaced_operand_0 if r0 else self.operands[0], replaced_operand_1 if r1 else self.operands[1]], self.signed, bits=self.bits, floating_point=self.floating_point, - rounding_mode=self.rounding_mode, + rounding_mode=replaced_rm if r2 else self.rounding_mode, from_bits=self.from_bits, to_bits=self.to_bits, **self.tags,