From 42763b367e83b6aab544d31c0366e462a2ee0d42 Mon Sep 17 00:00:00 2001 From: Xinlong Hu Date: Fri, 1 Aug 2025 19:54:28 -0500 Subject: [PATCH] 3.13 Preventing Loops from matching --- .../templates/Block.py | 17 +++++++++++------ pylingual/control_flow_reconstruction/utils.py | 2 ++ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/pylingual/control_flow_reconstruction/templates/Block.py b/pylingual/control_flow_reconstruction/templates/Block.py index 0398879..c93af82 100644 --- a/pylingual/control_flow_reconstruction/templates/Block.py +++ b/pylingual/control_flow_reconstruction/templates/Block.py @@ -7,7 +7,7 @@ from pylingual.editable_bytecode import Inst import networkx as nx from ..cft import ControlFlowTemplate, EdgeKind, SourceContext, SourceLine, register_template, EdgeCategory, out_edge_dict, MetaTemplate, indent_str -from ..utils import E, N, T, defer_source_to, remove_nodes, versions_from, without_instructions, has_no_lines, exact_instructions, make_try_match +from ..utils import E, N, T, defer_source_to, no_self_edges, remove_nodes, versions_from, without_instructions, has_no_lines, exact_instructions, make_try_match if TYPE_CHECKING: from pylingual.control_flow_reconstruction.cfg import CFG @@ -58,14 +58,18 @@ class RemoveUnreachable(ControlFlowTemplate): class JumpTemplate(ControlFlowTemplate): template = T( body=~N("jump", None).with_cond(without_instructions("CLEANUP_THROW")), - jump=N("tail", "block?").with_in_deg(1).with_cond( + jump=N("tail", "block?") + .with_cond(no_self_edges) + .with_in_deg(1) + .with_cond( exact_instructions("JUMP_BACKWARD_NO_INTERRUPT"), - exact_instructions("POP_JUMP_IF_TRUE"), + exact_instructions("POP_JUMP_IF_TRUE"), exact_instructions("JUMP_FORWARD"), exact_instructions("JUMP_BACKWARD"), - exact_instructions("POP_JUMP_IF_NOT_NONE"), - exact_instructions("POP_JUMP_IF_NONE"), - exact_instructions("POP_JUMP_IF_FALSE")), + exact_instructions("POP_JUMP_IF_NOT_NONE"), + exact_instructions("POP_JUMP_IF_NONE"), + exact_instructions("POP_JUMP_IF_FALSE"), + ), block=N.tail(), tail=N.tail(), ) @@ -81,6 +85,7 @@ class JumpTemplate(ControlFlowTemplate): to_indented_source = defer_source_to("body") + @register_template(0, 0, *versions_from(3, 11)) class NopTemplate(ControlFlowTemplate): template = T( diff --git a/pylingual/control_flow_reconstruction/utils.py b/pylingual/control_flow_reconstruction/utils.py index 6320723..16edadb 100644 --- a/pylingual/control_flow_reconstruction/utils.py +++ b/pylingual/control_flow_reconstruction/utils.py @@ -119,6 +119,8 @@ def has_type(*template_type: type[ControlFlowTemplate]): def no_back_edges(cfg: CFG, node: ControlFlowTemplate | None) -> bool: return node is None or not any(cfg.dominates(succ, node) for succ in cfg.successors(node)) +def no_self_edges(cfg: CFG, node: ControlFlowTemplate | None) -> bool: + return node is None or not any(cfg.has_edge(succ, node) and cfg.has_edge(node, succ) for succ in cfg.successors(node)) def has_incoming_edge_of_categories(*categories: str): def check(cfg: CFG, node: ControlFlowTemplate | None) -> bool: