def _handle_CallExpr(self, expr_idx: int, expr: Call, stmt_idx: int, stmt: Statement, block: Optional[Block]): changed = False if expr.args: i = 0 new_args = [] while i < len(expr.args): arg = expr.args[i] new_arg = self._handle_expr(i, arg, stmt_idx, stmt, block) if new_arg is not None and new_arg is not arg: if not changed: # initialize new_args new_args = expr.args[:i] new_args.append(new_arg) changed = True else: if changed: new_args.append(arg) i += 1 if changed: expr = expr.copy() expr.args = new_args return expr return None
def _handle_Call(self, stmt_idx: int, stmt: Call, block: Optional[Block]): if stmt.args: changed = False new_args = [] i = 0 while i < len(stmt.args): arg = stmt.args[i] new_arg = self._handle_expr(i, arg, stmt_idx, stmt, block) if new_arg is not None and new_arg is not arg: if not changed: # initialize new_args new_args = stmt.args[:i] new_args.append(new_arg) changed = True else: if changed: new_args.append(arg) i += 1 if changed: new_stmt = Call(stmt.idx, stmt.target, calling_convention=stmt.calling_convention, prototype=stmt.prototype, args=new_args, ret_expr=stmt.ret_expr, **stmt.tags) block.statements[stmt_idx] = new_stmt
def optimize(self, expr: BinaryOp): # bswap_16 # And( # ( # ((Conv(16->32, A) << 0x8<8>) & 0xff00ff00<32>) | # ((Conv(16->32, A) >> 0x8<8>) & 0xff00ff<32>) # ), # 0xffff<32> # ) if expr.op == "And" and len(expr.operands) == 2 and isinstance(expr.operands[1], Const) \ and expr.operands[1].value == 0xffff: inner = expr.operands[0] if isinstance(inner, BinaryOp) and inner.op == "Or" and len( inner.operands) == 2: or_first, or_second = inner.operands[0], inner.operands[1] if isinstance(or_first, BinaryOp) and or_first.op == "And" and len(or_first.operands) == 2 and \ isinstance(or_second, BinaryOp) and or_second.op == "And" and len(or_second.operands) == 2: r, the_expr = self._match_inner(or_first, or_second) if r: return Call(expr.idx, "__builtin_bswap16", args=[the_expr], bits=expr.bits, **expr.tags) r, the_expr = self._match_inner(or_second, or_first) if r: return Call(expr.idx, "__builtin_bswap16", args=[the_expr], bits=expr.bits, **expr.tags) return None return None
def _handle_Call(self, stmt_idx: int, stmt: Call, block: Block): if stmt.args: i = 0 new_exprs = [] while i < len(stmt.args): arg = stmt.args[i] new_expr = self._handle_expr(i, arg, stmt_idx, stmt, block) new_exprs.append(new_expr) i += 1 if any(expr is not None for expr in new_exprs): # create a new statement new_args = [(new_arg if new_arg is not None else old_arg) for new_arg, old_arg in zip(new_exprs, stmt.args)] new_stmt = Call(stmt.idx, stmt.target, calling_convention=stmt.calling_convention, prototype=stmt.prototype, args=new_args, ret_expr=stmt.ret_expr, **stmt.tags) return new_stmt return None