From 6480297f86369fcfd811af1f4b6ae6f4a74b24cf Mon Sep 17 00:00:00 2001 From: Savannah Ostrowski Date: Fri, 10 Apr 2026 13:33:43 -0700 Subject: [PATCH 1/9] Strip CFI directives in JIT stencils --- Tools/jit/_optimizers.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Tools/jit/_optimizers.py b/Tools/jit/_optimizers.py index ef28e0c0ddeac8..0e993e0d8d98de 100644 --- a/Tools/jit/_optimizers.py +++ b/Tools/jit/_optimizers.py @@ -251,7 +251,15 @@ def _preprocess(self, text: str) -> str: # references to a local _JIT_CONTINUE label (which we will add later): continue_symbol = rf"\b{re.escape(self.symbol_prefix)}_JIT_CONTINUE\b" continue_label = f"{self.label_prefix}_JIT_CONTINUE" - return re.sub(continue_symbol, continue_label, text) + text = re.sub(continue_symbol, continue_label, text) + # Strip CFI directives. JIT stencils are compiled with + # -fno-asynchronous-unwind-tables and don't use DWARF CFI unwind + # tables (.eh_frame). + # The optimizer's dead code elimination can remove blocks containing + # .cfi_endproc while keeping the corresponding .cfi_startproc, + # producing unbalanced CFI frames that some assemblers reject: + text = re.sub(r"^\s*\.cfi_\w+[^\n]*$", "", text, flags=re.MULTILINE) + return text def _parse_instruction(self, line: str) -> Instruction: target = None From 244480a042c3021b0a11210e9e1cb21ddedff678 Mon Sep 17 00:00:00 2001 From: Savannah Ostrowski Date: Fri, 10 Apr 2026 13:44:20 -0700 Subject: [PATCH 2/9] Clean up comment --- Tools/jit/_optimizers.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Tools/jit/_optimizers.py b/Tools/jit/_optimizers.py index 0e993e0d8d98de..6035d4f674bbd0 100644 --- a/Tools/jit/_optimizers.py +++ b/Tools/jit/_optimizers.py @@ -252,10 +252,9 @@ def _preprocess(self, text: str) -> str: continue_symbol = rf"\b{re.escape(self.symbol_prefix)}_JIT_CONTINUE\b" continue_label = f"{self.label_prefix}_JIT_CONTINUE" text = re.sub(continue_symbol, continue_label, text) - # Strip CFI directives. JIT stencils are compiled with + # Strip CFI directives as JIT stencils are compiled with # -fno-asynchronous-unwind-tables and don't use DWARF CFI unwind - # tables (.eh_frame). - # The optimizer's dead code elimination can remove blocks containing + # tables (.eh_frame). The optimizer can remove blocks containing # .cfi_endproc while keeping the corresponding .cfi_startproc, # producing unbalanced CFI frames that some assemblers reject: text = re.sub(r"^\s*\.cfi_\w+[^\n]*$", "", text, flags=re.MULTILINE) From d84337a4a2d335e84cd6caad6cf24ec63951e131 Mon Sep 17 00:00:00 2001 From: Savannah Ostrowski Date: Fri, 10 Apr 2026 13:45:20 -0700 Subject: [PATCH 3/9] Clean up comment --- Tools/jit/_optimizers.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Tools/jit/_optimizers.py b/Tools/jit/_optimizers.py index 6035d4f674bbd0..efd03c09975711 100644 --- a/Tools/jit/_optimizers.py +++ b/Tools/jit/_optimizers.py @@ -253,10 +253,10 @@ def _preprocess(self, text: str) -> str: continue_label = f"{self.label_prefix}_JIT_CONTINUE" text = re.sub(continue_symbol, continue_label, text) # Strip CFI directives as JIT stencils are compiled with - # -fno-asynchronous-unwind-tables and don't use DWARF CFI unwind - # tables (.eh_frame). The optimizer can remove blocks containing - # .cfi_endproc while keeping the corresponding .cfi_startproc, - # producing unbalanced CFI frames that some assemblers reject: + # -fno-asynchronous-unwind-tables. The optimizer can remove blocks + # containing .cfi_endproc while keeping the corresponding + # .cfi_startproc, producing unbalanced CFI frames that some + # assemblers reject: text = re.sub(r"^\s*\.cfi_\w+[^\n]*$", "", text, flags=re.MULTILINE) return text From e29673e146f23c0244816a724a37b03f713edbd7 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Fri, 10 Apr 2026 20:57:36 +0000 Subject: [PATCH 4/9] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20blu?= =?UTF-8?q?rb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../next/Build/2026-04-10-20-57-30.gh-issue-146475.SWxwGM.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Build/2026-04-10-20-57-30.gh-issue-146475.SWxwGM.rst diff --git a/Misc/NEWS.d/next/Build/2026-04-10-20-57-30.gh-issue-146475.SWxwGM.rst b/Misc/NEWS.d/next/Build/2026-04-10-20-57-30.gh-issue-146475.SWxwGM.rst new file mode 100644 index 00000000000000..04984242ae30f4 --- /dev/null +++ b/Misc/NEWS.d/next/Build/2026-04-10-20-57-30.gh-issue-146475.SWxwGM.rst @@ -0,0 +1 @@ +Strip CFI directives from JIT stencil assembly to fix build failures with Apple LLVM 21. From 00dfe93599bb542b8d2fa5e697709812d0f9043c Mon Sep 17 00:00:00 2001 From: Savannah Ostrowski Date: Fri, 10 Apr 2026 14:10:40 -0700 Subject: [PATCH 5/9] Blurb --- .../next/Build/2026-04-10-20-57-30.gh-issue-146475.SWxwGM.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Misc/NEWS.d/next/Build/2026-04-10-20-57-30.gh-issue-146475.SWxwGM.rst b/Misc/NEWS.d/next/Build/2026-04-10-20-57-30.gh-issue-146475.SWxwGM.rst index 04984242ae30f4..9c70f04c43179f 100644 --- a/Misc/NEWS.d/next/Build/2026-04-10-20-57-30.gh-issue-146475.SWxwGM.rst +++ b/Misc/NEWS.d/next/Build/2026-04-10-20-57-30.gh-issue-146475.SWxwGM.rst @@ -1 +1 @@ -Strip CFI directives from JIT stencil assembly to fix build failures with Apple LLVM 21. +Strip CFI directives from JIT stencils to fix build failures with Apple LLVM 21. From 55069d8339e8d5ae4179ea4ea50e85754b89f6d5 Mon Sep 17 00:00:00 2001 From: Savannah Ostrowski Date: Fri, 10 Apr 2026 14:35:05 -0700 Subject: [PATCH 6/9] oooo there is a flag --- .../Build/2026-04-10-20-57-30.gh-issue-146475.SWxwGM.rst | 2 +- Tools/jit/_optimizers.py | 9 +-------- Tools/jit/_targets.py | 9 +++++---- 3 files changed, 7 insertions(+), 13 deletions(-) diff --git a/Misc/NEWS.d/next/Build/2026-04-10-20-57-30.gh-issue-146475.SWxwGM.rst b/Misc/NEWS.d/next/Build/2026-04-10-20-57-30.gh-issue-146475.SWxwGM.rst index 9c70f04c43179f..dac4894b685957 100644 --- a/Misc/NEWS.d/next/Build/2026-04-10-20-57-30.gh-issue-146475.SWxwGM.rst +++ b/Misc/NEWS.d/next/Build/2026-04-10-20-57-30.gh-issue-146475.SWxwGM.rst @@ -1 +1 @@ -Strip CFI directives from JIT stencils to fix build failures with Apple LLVM 21. +Use ``-fno-unwind-tables`` for JIT stencils to fix build failures with Apple LLVM 21. diff --git a/Tools/jit/_optimizers.py b/Tools/jit/_optimizers.py index efd03c09975711..ef28e0c0ddeac8 100644 --- a/Tools/jit/_optimizers.py +++ b/Tools/jit/_optimizers.py @@ -251,14 +251,7 @@ def _preprocess(self, text: str) -> str: # references to a local _JIT_CONTINUE label (which we will add later): continue_symbol = rf"\b{re.escape(self.symbol_prefix)}_JIT_CONTINUE\b" continue_label = f"{self.label_prefix}_JIT_CONTINUE" - text = re.sub(continue_symbol, continue_label, text) - # Strip CFI directives as JIT stencils are compiled with - # -fno-asynchronous-unwind-tables. The optimizer can remove blocks - # containing .cfi_endproc while keeping the corresponding - # .cfi_startproc, producing unbalanced CFI frames that some - # assemblers reject: - text = re.sub(r"^\s*\.cfi_\w+[^\n]*$", "", text, flags=re.MULTILINE) - return text + return re.sub(continue_symbol, continue_label, text) def _parse_instruction(self, line: str) -> Instruction: target = None diff --git a/Tools/jit/_targets.py b/Tools/jit/_targets.py index ea0a9722c3cdf8..f5fbd150e0ee2b 100644 --- a/Tools/jit/_targets.py +++ b/Tools/jit/_targets.py @@ -163,10 +163,11 @@ async def _compile( # __FILE__ macro and assert failure messages) for reproducibility: f"-ffile-prefix-map={CPYTHON}=.", f"-ffile-prefix-map={tempdir}=.", - # This debug info isn't necessary, and bloats out the JIT'ed code. - # We *may* be able to re-enable this, process it, and JIT it for a - # nicer debugging experience... but that needs a lot more research: - "-fno-asynchronous-unwind-tables", + # Don't emit unwind tables or CFI directives. JIT stencils are + # not standard functions and their unwind info is not usable at + # runtime. The optimizer can produce unbalanced CFI directives + # that some assemblers reject (e.g. Apple LLVM 21): + "-fno-unwind-tables", # Don't call built-in functions that we can't find or patch: "-fno-builtin", # Don't call stack-smashing canaries that we can't find or patch: From 3e7cf60ac1be1b64c9505843637b29b3b7c7cae6 Mon Sep 17 00:00:00 2001 From: Savannah Ostrowski Date: Fri, 10 Apr 2026 14:38:52 -0700 Subject: [PATCH 7/9] Make comment more concise --- Tools/jit/_targets.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/Tools/jit/_targets.py b/Tools/jit/_targets.py index f5fbd150e0ee2b..dac19e9b391fe7 100644 --- a/Tools/jit/_targets.py +++ b/Tools/jit/_targets.py @@ -163,10 +163,8 @@ async def _compile( # __FILE__ macro and assert failure messages) for reproducibility: f"-ffile-prefix-map={CPYTHON}=.", f"-ffile-prefix-map={tempdir}=.", - # Don't emit unwind tables or CFI directives. JIT stencils are - # not standard functions and their unwind info is not usable at - # runtime. The optimizer can produce unbalanced CFI directives - # that some assemblers reject (e.g. Apple LLVM 21): + # Don't emit CFI directives. The optimizer can produce unbalanced + # CFI directives that some assemblers reject (e.g. Apple LLVM 21): "-fno-unwind-tables", # Don't call built-in functions that we can't find or patch: "-fno-builtin", From f110a958fa5eb6cdab558a75a447fc751846fad4 Mon Sep 17 00:00:00 2001 From: Savannah Ostrowski Date: Fri, 10 Apr 2026 14:40:47 -0700 Subject: [PATCH 8/9] Appease linter --- Tools/jit/_targets.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tools/jit/_targets.py b/Tools/jit/_targets.py index dac19e9b391fe7..126735555afffd 100644 --- a/Tools/jit/_targets.py +++ b/Tools/jit/_targets.py @@ -163,7 +163,7 @@ async def _compile( # __FILE__ macro and assert failure messages) for reproducibility: f"-ffile-prefix-map={CPYTHON}=.", f"-ffile-prefix-map={tempdir}=.", - # Don't emit CFI directives. The optimizer can produce unbalanced + # Don't emit CFI directives. The optimizer can produce unbalanced # CFI directives that some assemblers reject (e.g. Apple LLVM 21): "-fno-unwind-tables", # Don't call built-in functions that we can't find or patch: From 4e2a5d315310d4f7ad0467c4aa186eeab4392d4c Mon Sep 17 00:00:00 2001 From: Savannah Ostrowski Date: Fri, 10 Apr 2026 14:49:49 -0700 Subject: [PATCH 9/9] Just kidding, the flag breaks x86 linux --- .../Build/2026-04-10-20-57-30.gh-issue-146475.SWxwGM.rst | 2 +- Tools/jit/_optimizers.py | 9 ++++++++- Tools/jit/_targets.py | 7 ++++--- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/Misc/NEWS.d/next/Build/2026-04-10-20-57-30.gh-issue-146475.SWxwGM.rst b/Misc/NEWS.d/next/Build/2026-04-10-20-57-30.gh-issue-146475.SWxwGM.rst index dac4894b685957..9c70f04c43179f 100644 --- a/Misc/NEWS.d/next/Build/2026-04-10-20-57-30.gh-issue-146475.SWxwGM.rst +++ b/Misc/NEWS.d/next/Build/2026-04-10-20-57-30.gh-issue-146475.SWxwGM.rst @@ -1 +1 @@ -Use ``-fno-unwind-tables`` for JIT stencils to fix build failures with Apple LLVM 21. +Strip CFI directives from JIT stencils to fix build failures with Apple LLVM 21. diff --git a/Tools/jit/_optimizers.py b/Tools/jit/_optimizers.py index ef28e0c0ddeac8..4050f089ff9be3 100644 --- a/Tools/jit/_optimizers.py +++ b/Tools/jit/_optimizers.py @@ -251,7 +251,14 @@ def _preprocess(self, text: str) -> str: # references to a local _JIT_CONTINUE label (which we will add later): continue_symbol = rf"\b{re.escape(self.symbol_prefix)}_JIT_CONTINUE\b" continue_label = f"{self.label_prefix}_JIT_CONTINUE" - return re.sub(continue_symbol, continue_label, text) + text = re.sub(continue_symbol, continue_label, text) + # Strip CFI directives as JIT stencils are compiled with + # -fno-asynchronous-unwind-tables. The optimizer can remove + # blocks containing .cfi_endproc while keeping the corresponding + # .cfi_startproc, producing unbalanced CFI frames that some + # assemblers reject (e.g. Apple LLVM 21): + text = re.sub(r"^\s*\.cfi_\w+[^\n]*$", "", text, flags=re.MULTILINE) + return text def _parse_instruction(self, line: str) -> Instruction: target = None diff --git a/Tools/jit/_targets.py b/Tools/jit/_targets.py index 126735555afffd..ea0a9722c3cdf8 100644 --- a/Tools/jit/_targets.py +++ b/Tools/jit/_targets.py @@ -163,9 +163,10 @@ async def _compile( # __FILE__ macro and assert failure messages) for reproducibility: f"-ffile-prefix-map={CPYTHON}=.", f"-ffile-prefix-map={tempdir}=.", - # Don't emit CFI directives. The optimizer can produce unbalanced - # CFI directives that some assemblers reject (e.g. Apple LLVM 21): - "-fno-unwind-tables", + # This debug info isn't necessary, and bloats out the JIT'ed code. + # We *may* be able to re-enable this, process it, and JIT it for a + # nicer debugging experience... but that needs a lot more research: + "-fno-asynchronous-unwind-tables", # Don't call built-in functions that we can't find or patch: "-fno-builtin", # Don't call stack-smashing canaries that we can't find or patch: