digitalmars.D - SAOC 2026: ImportC Weekly Update #3
- Niyati Jain (111/111) Oct 07 **SAOC 2026: ImportC Weekly Update #3**
This week I spent most of it in Windows ABI details, stack behavior, and how dmd's ImportC actually generates code versus real cl.exe. It was a genuinely good week for actually understanding D's runtime internals rather than just working around them. With this, I closed out the Windows half of Milestone 1: got sljit's zero-wrapper example building and running correctly via ImportC on Windows, found and fixed the actual root cause, and spent most of the week isolating a second, much harder bug down to a precise, actionable finding in **sljit's own unmodified test suite**. **The real root cause of the Windows link failures:** `sljitLir.c` includes `<windows.h>` but never includes `importc_msvc_builtins.h`, and druntime's own auto-included `importc.h` doesn't pull that in either, so the MSVC-intrinsic-to-D-template redirect in `__builtins_msvc.d` never fires. `__cpuidex`, `_umul128`, the `__readgs*` family, etc. all fell through as plain unresolved externs at link time, 18 symbols total. Fixed by force-including the header with cl's real `/FI` flag (not gcc's `-include`, since dmd shells out to the actual cl.exe preprocessor on Windows), with zero changes to sljit's vendored source. That resolved 16 of 18. The remaining 2 turned out to be a separate issue: `RtlSetVolatileMemory`, `__arch_inverted`, and `__arch_avx10ver` aren't real linkable symbols at all, even in real MSVC builds, they're compiler-recognized pseudo-intrinsics that cl.exe expands inline, and `__builtins_msvc.d` doesn't cover them yet. Wrote real implementations for those three myself. `MapViewOfFileNuma2` just needed `mincore.lib` linked, found by grepping every system `.lib` on the runner for the actual export rather than guessing. With both fixes in, the zero-wrapper example builds and runs clean: it JIT-compiles a function at runtime and calls it successfully, confirmed in real CI, no modifications to sljit's source. **Challenges, and working through them:** The harder part was Milestone 1's other ask: confirm sljit's real test suite runs unmodified from D. Once the link errors above were fixed, the compiled test suite started exiting with code `127` part-way through its 138 tests, non-deterministically, a different test failing on every run. I bisected by inserting checkpoint prints between test calls, and the crash point genuinely moved between runs, once around test 11-29 broadly, once with test 11 completing entirely internally, once making it all the way to test 17. That pointed at real **memory corruption** rather than one deterministic bug, so I pulled in `cdb` and ran the actual test binary under it. That gave a real exception record for the first time: `STATUS_STACK_OVERFLOW (0xc00000fd)`. I ruled out the obvious explanations one at a time against real CI runs: a missing `_chkstk` stack-probe call (tested directly with an 8KB buffer and then a deliberate write to byte 65535 of an untouched 64KB buffer, both ran clean under ImportC, so ImportC's codegen for large single frames checked out fine in isolation), optimized vs. unoptimized codegen (identical crash either way), and a bigger linked stack (made it crash earlier instead of fixing it, which was itself informative). I asked my mentor, Nicholas Wilson, about it, and his suggestion to try AddressSanitizer via LDC was the right instinct for intermittent corruption. Porting it over surfaced a separate finding along the way: LDC's own `importc.h` has no equivalent of dmd's MSVC-intrinsic redirect mechanism at all, confirmed by grepping its entire druntime source for `__cpuidex` and finding nothing. He advised that porting dmd's `#pragma function_decl(ignore, ...)` mechanism to LDC wasn't worth the detour, so I dropped that path. The real breakthrough came from going back to basics: I rebuilt the identical, unmodified sljit source with real `cl.exe` directly, completely bypassing D and ImportC. At first it crashed the exact same way, which told me the problem wasn't specific to ImportC, but it also wasn't sljit's own logic, since applying sljit's real `CMakeLists.txt` flags fixed it. Their build sets `target_compile_definitions(sljit_test PRIVATE SLJIT_HAVE_CONFIG_PRE)` and `/STACK:0x400000` on MSVC, two things our from-source build was never setting since we compile the three files directly rather than through their CMake config. Applying both exactly: **the native cl.exe build now runs all 138 tests clean end to end**, with a real, meaningful exit, and only one genuine logic-level failure (`test34`, unrelated to the crash). The exact same source and exact same flags under dmd's ImportC, though, still segfault. Same everything except the compiler, which isolates this to a real codegen bug in dmd's ImportC specifically. Thank you to Nicholas for the steady direction through this one, especially the nudge toward ASan and the questions that kept me from chasing unrelated paths. If anyone's run into ImportC codegen differing from real cl.exe on a large translation unit like this before, or has a lead on where to start looking in dmd's backend, I'd be glad to hear it, here or once I open the dmd issue. Confirmed — the most recent run (37641216210) has the zero-wrapper example passing cleanly. Here's the Status section to paste: **Status:** - sljit standalone package with the fix applied: https://github.com/niy-ati/sljit - Windows CI, zero-wrapper example passing: https://github.com/niy-ati/importC/actions/runs/37641216210 **Milestone 1 status:** everything is done except this one piece. The zero-wrapper example, the CI matrix, and the earlier dmd fixes are all in. Sljit's own test suite running unmodified is the one requirement still open, and it's now blocked on a real dmd bug rather than anything on our side, so next step is filing that properly rather than more workarounds. **Next week:** write up the ImportC codegen bug with a minimal repro and file it upstream against dmd, upstream the three Windows intrinsic gaps (`__arch_inverted`/`__arch_avx10ver`/`RtlSetVolatileMemory`) as a real PR against `__builtins_msvc.d`, and get the sljit dub package published now that the Windows zero-wrapper example itself is fully green.
Oct 07








Niyati Jain <niyati.jainn15 gmail.com>