"""Low-level optimization of textual assembly.""" import dataclasses import pathlib import re import typing # Same as saying "not string.startswith('')": _RE_NEVER_MATCH = re.compile(r"(?!)") # Dictionary mapping branch instructions to their inverted branch instructions. # If a branch cannot be inverted, the value is None: _X86_BRANCHES = { # https://www.felixcloutier.com/x86/jcc "ja": "jna", "jae": "jnae", "jb": "jnb", "jbe": "jnbe", "jc": "jnc", "jcxz": None, "je": "jne", "jecxz": None, "jg": "jng", "jge": "jnge", "jl": "jnl", "jle": "jnle", "jo": "jno", "jp": "jnp", "jpe": "jpo", "jrcxz": None, "js": "jns", "jz": "jnz", # https://www.felixcloutier.com/x86/loop:loopcc "loop": None, "loope": None, "loopne": None, "loopnz": None, "loopz": None, } # Update with all of the inverted branches, too: _X86_BRANCHES |= {v: k for k, v in _X86_BRANCHES.items() if v} @dataclasses.dataclass class _Block: label: str | None = None # Non-instruction lines like labels, directives, and comments: noninstructions: list[str] = dataclasses.field(default_factory=list) # Instruction lines: instructions: list[str] = dataclasses.field(default_factory=list) # If this block ends in a jump, where to? target: typing.Self | None = None # The next block in the linked list: link: typing.Self | None = None # Whether control flow can fall through to the linked block above: fallthrough: bool = True # Whether this block can eventually reach the next uop (_JIT_CONTINUE): hot: bool = False def resolve(self) -> typing.Self: """Find the first non-empty block reachable from this one.""" block = self while block.link and not block.instructions: block = block.link return block @dataclasses.dataclass class Optimizer: """Several passes of analysis and optimization for textual assembly.""" path: pathlib.Path _: dataclasses.KW_ONLY # prefix used to mangle symbols on some platforms: prefix: str = "" # The first block in the linked list: _root: _Block = dataclasses.field(init=False, default_factory=_Block) _labels: dict[str, _Block] = dataclasses.field(init=False, default_factory=dict) # No groups: _re_noninstructions: typing.ClassVar[re.Pattern[str]] = re.compile( r"\s*(?:\.|#|//|$)" ) # One group (label): _re_label: typing.ClassVar[re.Pattern[str]] = re.compile( r'\s*(?P