Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AILBlockWalker: Implement Phi handler. #247

Merged
merged 3 commits into from
Oct 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading