Skip to content

Commit fae87b9

Browse files
Verify that JIT stencils preserve frame pointer
1 parent e44993a commit fae87b9

File tree

2 files changed

+24
-8
lines changed

2 files changed

+24
-8
lines changed

Tools/jit/_optimizers.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@ class Optimizer:
162162
label_prefix: str
163163
symbol_prefix: str
164164
re_global: re.Pattern[str]
165+
frame_pointers: bool
165166
# The first block in the linked list:
166167
_root: _Block = dataclasses.field(init=False, default_factory=_Block)
167168
_labels: dict[str, _Block] = dataclasses.field(init=False, default_factory=dict)
@@ -193,6 +194,7 @@ class Optimizer:
193194
_re_small_const_1 = _RE_NEVER_MATCH
194195
_re_small_const_2 = _RE_NEVER_MATCH
195196
const_reloc = "<Not supported>"
197+
_frame_pointer_prologue: typing.ClassVar[re.Pattern[str]] = _RE_NEVER_MATCH
196198

197199
def __post_init__(self) -> None:
198200
# Split the code into a linked list of basic blocks. A basic block is an
@@ -553,6 +555,14 @@ def _small_const_2(self, inst: Instruction) -> tuple[str, Instruction | None]:
553555
def _small_consts_match(self, inst1: Instruction, inst2: Instruction) -> bool:
554556
raise NotImplementedError()
555557

558+
def _validate(self):
559+
for block in self._blocks():
560+
if not block.instructions:
561+
continue
562+
for inst in block.instructions:
563+
if self.frame_pointers:
564+
assert self._frame_pointer_prologue.match(inst.text) is None, "Frame pointer should not be modified"
565+
556566
def run(self) -> None:
557567
"""Run this optimizer."""
558568
self._insert_continue_label()
@@ -565,6 +575,7 @@ def run(self) -> None:
565575
self._remove_unreachable()
566576
self._fixup_external_labels()
567577
self._fixup_constants()
578+
self._validate()
568579
self.path.write_text(self._body())
569580

570581

@@ -595,6 +606,7 @@ class OptimizerAArch64(Optimizer): # pylint: disable = too-few-public-methods
595606
r"\s*(?P<instruction>ldr)\s+.*(?P<value>_JIT_OP(ARG|ERAND(0|1))_(16|32)).*"
596607
)
597608
const_reloc = "CUSTOM_AARCH64_CONST"
609+
_frame_pointer_prologue = re.compile(r"\s*stp\s+x29.*")
598610

599611
def _get_reg(self, inst: Instruction) -> str:
600612
_, rest = inst.text.split(inst.name)
@@ -649,4 +661,5 @@ class OptimizerX86(Optimizer): # pylint: disable = too-few-public-methods
649661
# https://www.felixcloutier.com/x86/jmp
650662
_re_jump = re.compile(r"\s*jmp\s+(?P<target>[\w.]+)")
651663
# https://www.felixcloutier.com/x86/ret
652-
_re_return = re.compile(r"\s*ret\b")
664+
_re_return = re.compile(r"\s*retq?\b")
665+
_frame_pointer_prologue = re.compile(r"\s*pushq\s+%rbp.*")

Tools/jit/_targets.py

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -176,21 +176,24 @@ async def _compile(
176176
f"{s}",
177177
f"{c}",
178178
]
179+
is_shim = opname == "shim"
179180
if self.frame_pointers:
180-
frame_pointer = "all" if opname == "shim" else "reserved"
181+
frame_pointer = "all" if is_shim else "reserved"
181182
args_s += ["-Xclang", f"-mframe-pointer={frame_pointer}"]
182183
args_s += self.args
183184
# Allow user-provided CFLAGS to override any defaults
184185
args_s += shlex.split(self.cflags)
185186
await _llvm.run(
186187
"clang", args_s, echo=self.verbose, llvm_version=self.llvm_version
187188
)
188-
self.optimizer(
189-
s,
190-
label_prefix=self.label_prefix,
191-
symbol_prefix=self.symbol_prefix,
192-
re_global=self.re_global,
193-
).run()
189+
if not is_shim:
190+
self.optimizer(
191+
s,
192+
label_prefix=self.label_prefix,
193+
symbol_prefix=self.symbol_prefix,
194+
re_global=self.re_global,
195+
frame_pointers=self.frame_pointers
196+
).run()
194197
args_o = [f"--target={self.triple}", "-c", "-o", f"{o}", f"{s}"]
195198
await _llvm.run(
196199
"clang", args_o, echo=self.verbose, llvm_version=self.llvm_version

0 commit comments

Comments
 (0)