aboutsummaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
author_ov4 <ov4@ov4.org>2026-10-16 16:25:12 +0000
committer_ov4 <ov4@ov4.org>2026-10-16 16:25:12 +0000
commit838d636d42db87b91f8b37bd39ab71ed3dc90599 (patch)
treea3298100e270bb3a1308915d579865eb0cb30b33 /tools
parentb5b1e5a2a684a1ec96fae3408d322b92c38354e6 (diff)
fix(jit): provide JIT-only stack probe without weak host reference
The weak ___chkstk_ms reference marked the host import weak on COFF and segfaulted the compiler itself. Provide a JIT-only probe under a unique name with the same page-touching behavior instead. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Diffstat (limited to 'tools')
-rw-r--r--tools/driver/EmbeddedRunner.cc39
1 files changed, 32 insertions, 7 deletions
diff --git a/tools/driver/EmbeddedRunner.cc b/tools/driver/EmbeddedRunner.cc
index 8ebffab..0c1346f 100644
--- a/tools/driver/EmbeddedRunner.cc
+++ b/tools/driver/EmbeddedRunner.cc
@@ -276,10 +276,36 @@ __gxx_personality_v0
extern "C" void __cps_jit_noop__main() {}
#endif
-// MinGW inserts ___chkstk_ms stack probes into large frames. dlsym cannot see
-// this static runtime symbol, so reference it weakly: null on platforms
-// without it, host address where present. Same code on all platforms.
-extern "C" void ___chkstk_ms() __attribute__((weak));
+// MinGW emits ___chkstk_ms stack probes for large frames with a custom
+// convention (size in %eax, result in %rax, all else preserved). Never
+// reference the host probe by name: a weak reference marks the host import
+// weak on COFF and segfaults the compiler itself. Provide a JIT-only probe
+// under a unique name and map the JIT symbol to it. Same code on all
+// platforms; the stub is unused where the backend never emits the probe.
+#if defined(__x86_64__)
+extern "C" __attribute__((naked)) void __cps_jit_chkstk_ms() {
+ __asm__ volatile(
+ "pushq %rcx\n\t"
+ "pushq %rax\n\t"
+ "cmpq $0x1000, %rax\n\t"
+ "leaq 0x18(%rsp), %rcx\n\t"
+ "jb 1f\n\t"
+ "0:\n\t"
+ "subq $0x1000, %rcx\n\t"
+ "orq $0, (%rcx)\n\t"
+ "subq $0x1000, %rax\n\t"
+ "cmpq $0x1000, %rax\n\t"
+ "ja 0b\n\t"
+ "1:\n\t"
+ "subq %rax, %rcx\n\t"
+ "orq $0, (%rcx)\n\t"
+ "popq %rax\n\t"
+ "popq %rcx\n\t"
+ "ret\n\t");
+}
+#else
+extern "C" void __cps_jit_chkstk_ms() {}
+#endif
static llvm::Error defineRuntimeSymbols(llvm::orc::LLJIT &J) {
llvm::orc::SymbolMap Symbols;
@@ -322,9 +348,8 @@ static llvm::Error defineRuntimeSymbols(llvm::orc::LLJIT &J) {
Symbols[Intern("__main")] =
ExecutorSymbolDef::fromPtr(&__cps_jit_noop__main);
#endif
- if (___chkstk_ms)
- Symbols[Intern("___chkstk_ms")] =
- ExecutorSymbolDef::fromPtr(reinterpret_cast<void *>(&___chkstk_ms));
+ Symbols[Intern("___chkstk_ms")] =
+ ExecutorSymbolDef::fromPtr(&__cps_jit_chkstk_ms);
return J.getMainJITDylib().define(
llvm::orc::absoluteSymbols(std::move(Symbols)));
}