@@ -95,6 +95,7 @@ class InstructionKind(enum.Enum):
9595 JUMP = enum .auto ()
9696 LONG_BRANCH = enum .auto ()
9797 SHORT_BRANCH = enum .auto ()
98+ CALL = enum .auto ()
9899 RETURN = enum .auto ()
99100 SMALL_CONST_1 = enum .auto ()
100101 SMALL_CONST_2 = enum .auto ()
@@ -182,6 +183,8 @@ class Optimizer:
182183 # Two groups (instruction and target):
183184 _re_branch : typing .ClassVar [re .Pattern [str ]] = _RE_NEVER_MATCH
184185 # One group (target):
186+ _re_call : typing .ClassVar [re .Pattern [str ]] = _RE_NEVER_MATCH
187+ # One group (target):
185188 _re_jump : typing .ClassVar [re .Pattern [str ]] = _RE_NEVER_MATCH
186189 # No groups:
187190 _re_return : typing .ClassVar [re .Pattern [str ]] = _RE_NEVER_MATCH
@@ -220,7 +223,7 @@ def __post_init__(self) -> None:
220223 block .link = block = _Block ()
221224 inst = self ._parse_instruction (line )
222225 block .instructions .append (inst )
223- if inst .is_branch ():
226+ if inst .is_branch () or inst . kind == InstructionKind . CALL :
224227 # A block ending in a branch has a target and fallthrough:
225228 assert inst .target is not None
226229 block .target = self ._lookup_label (inst .target )
@@ -256,6 +259,10 @@ def _parse_instruction(self, line: str) -> Instruction:
256259 target = match ["target" ]
257260 name = line [: - len (target )].strip ()
258261 kind = InstructionKind .JUMP
262+ elif match := self ._re_call .match (line ):
263+ target = match ["target" ]
264+ name = line [: - len (target )].strip ()
265+ kind = InstructionKind .JUMP
259266 elif match := self ._re_return .match (line ):
260267 name = line
261268 kind = InstructionKind .RETURN
@@ -566,6 +573,8 @@ class OptimizerAArch64(Optimizer): # pylint: disable = too-few-public-methods
566573 rf"\s*(?P<instruction>{ '|' .join (_branch_patterns )} )\s+(.+,\s+)*(?P<target>[\w.]+)"
567574 )
568575
576+ # https://developer.arm.com/documentation/ddi0406/b/Application-Level-Architecture/Instruction-Details/Alphabetical-list-of-instructions/BL--BLX--immediate-
577+ _re_call = re .compile (r"\s*blx??\s+(?P<target>[\w.]+)" )
569578 # https://developer.arm.com/documentation/ddi0602/2025-03/Base-Instructions/B--Branch-
570579 _re_jump = re .compile (r"\s*b\s+(?P<target>[\w.]+)" )
571580 # https://developer.arm.com/documentation/ddi0602/2025-09/Base-Instructions/RET--Return-from-subroutine-
@@ -628,9 +637,9 @@ class OptimizerX86(Optimizer): # pylint: disable = too-few-public-methods
628637 _re_branch = re .compile (
629638 rf"\s*(?P<instruction>{ '|' .join (_X86_BRANCHES )} )\s+(?P<target>[\w.]+)"
630639 )
631- # https://www.felixcloutier.com/x86/jmp
632640 # https://www.felixcloutier.com/x86/call
633- # Calls are also logically jumps to labels.
634- _re_jump = re .compile (r"\s*((?:jmp)|(?:callq?))\s+(?P<target>[\w.]+)" )
641+ _re_call = re .compile (r"\s*callq?\s+(?P<target>[\w.]+)" )
642+ # https://www.felixcloutier.com/x86/jmp
643+ _re_jump = re .compile (r"\s*jmp\s+(?P<target>[\w.]+)" )
635644 # https://www.felixcloutier.com/x86/ret
636645 _re_return = re .compile (r"\s*ret\b" )
0 commit comments