Skip to content

Commit

Permalink
AILBlockWalker: Implement Phi handler. (#247)
Browse files Browse the repository at this point in the history
* AILBlockWalker: Implement Phi handler.

* Handle cases where vvar is None.

* Default to the read-only version of Phi handler.
  • Loading branch information
ltfish authored Oct 15, 2024
1 parent eec89b1 commit 6e68179
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 2 deletions.
32 changes: 31 additions & 1 deletion ailment/block_walker.py
Original file line number Diff line number Diff line change
Expand Up @@ -198,11 +198,17 @@ class AILBlockWalker(AILBlockWalkerBase):
:ivar update_block: True if the block should be updated in place, False if a new block should be created and
returned as the result of walk().
:ivar replace_phi_stmt: True if you want _handle_Phi be called and vvars potentially replaced; False otherwise.
Default to False because in the most majority cases you do not want vvars in a Phi
variable be replaced.
"""

def __init__(self, stmt_handlers=None, expr_handlers=None, update_block: bool = True):
def __init__(
self, stmt_handlers=None, expr_handlers=None, update_block: bool = True, replace_phi_stmt: bool = False
):
super().__init__(stmt_handlers=stmt_handlers, expr_handlers=expr_handlers)
self._update_block = update_block
self._replace_phi_stmt = replace_phi_stmt

def walk(self, block: Block) -> Block | None:
"""
Expand Down Expand Up @@ -537,6 +543,30 @@ def _handle_ITE(self, expr_idx: int, expr: ITE, stmt_idx: int, stmt: Statement,
return new_expr
return None

def _handle_Phi(self, expr_id: int, expr: Phi, stmt_idx: int, stmt: Statement, block: Block | None) -> Phi | None:
if not self._replace_phi_stmt:
# fallback to the read-only version
return super()._handle_Phi(expr_id, expr, stmt_idx, stmt, block)

changed = False

src_and_vvars = None
for idx, (src, vvar) in enumerate(expr.src_and_vvars):
if vvar is None:
if src_and_vvars is not None:
src_and_vvars.append((src, None))
continue
new_vvar = self._handle_expr(idx, vvar, stmt_idx, stmt, block)
if new_vvar is not None and new_vvar is not vvar:
changed = True
if src_and_vvars is None:
src_and_vvars = expr.src_and_vvars[:idx]
src_and_vvars.append((src, new_vvar))
elif src_and_vvars is not None:
src_and_vvars.append((src, vvar))

return Phi(expr.idx, expr.bits, src_and_vvars, **expr.tags) if changed else None

def _handle_DirtyExpression(
self, expr_idx: int, expr: DirtyExpression, stmt_idx: int, stmt: Statement, block: Block | None
):
Expand Down
2 changes: 1 addition & 1 deletion ailment/expression.py
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ def __init__(
self,
idx,
bits,
src_and_vvars: list[tuple[tuple[int, int], VirtualVariable]],
src_and_vvars: list[tuple[tuple[int, int], VirtualVariable | None]],
**kwargs,
):
super().__init__(idx, **kwargs)
Expand Down

0 comments on commit 6e68179

Please sign in to comment.