Skip to content

fix(alloc): keep free_inline's asm goto out of MSVC cleanup funclets (2.2.5) - #50

Merged
Ttimmahlax merged 4 commits into
mainfrom
fix/msvc-funclet-asm-goto
Oct 8, 2026
Merged

Ttimmahlax merged 4 commits into
mainfrom
fix/msvc-funclet-asm-goto

Conversation

@Ttimmahlax

Copy link
Copy Markdown
Contributor

Intended release: 2.2.5. Details: docs/plans/msvc-funclet-asm-goto.md §8.

Bug. 2.2.1–2.2.4 fail to build in an MSVC consumer that unwinds, with LTO (rusty_sloth: thin LTO, codegen-units = 1, panic = "unwind"): GlobalAlloc::dealloc inlines free_inline's asm! goto (LLVM callbr) into EH cleanup funclets, which LLVM rejects ("Bogus funclet pad use … Broken module found").

Fix. On all(target_env = "msvc", panic = "unwind"), free_inline uses the plain-Rust decrement aarch64 and Miri already use. Gated in free_inline itself, so every caller is covered (alloc::free, rusty_alloc_api::Heap::dealloc), not only dealloc. MSVC + panic = "abort" and all other targets: unchanged.

Cost, affected builds only (callgrind, same code forced on Linux): +3 Ir per local free; Rust GlobalAlloc workloads +0.30 % to +3.56 %, checksums identical. Linux/macOS/wasm/embedded code is byte-for-byte the same path as 2.2.4.

Regression gate. rusty_sloth joins the downstream corpus as a build = "release" row; run.sh builds such rows in the consumer's own release profile and attributes an LLVM verifier failure to us. No small consumer reproduces the defect (rustc marks cleanup calls cold; four shapes tried, thin and fat LTO), so this is a local gate, not a CI job.

🤖 Generated with Claude Code

tim-almond-house and others added 4 commits October 7, 2026 20:37
… update it needs

A run that skipped 'cargo update' compiled the locked 2.2.0 and tested nothing.
The steps are re-run from a clean rusty_sloth against the published 2.2.4 (it
fails as reported), with how to check the version before building and how to
point the consumer at a rusty_alloc tree.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2.2.1-2.2.4 failed to build in an MSVC consumer that unwinds, with LTO
(rusty_sloth: thin LTO, one codegen unit, panic = unwind). free_inline's
fast path is an asm! goto (LLVM callbr); since 2.2.1 GlobalAlloc::dealloc
inlines it into every Rust drop, including the drops a panic runs, which
on MSVC are EH cleanup funclets. LLVM cannot place a callbr in a funclet:
"Bogus funclet pad use ... Broken module found".

On all(target_env = "msvc", panic = "unwind") free_inline now takes the
plain-Rust decrement aarch64 and Miri already use. The gate is in
free_inline itself, so it covers every caller (rusty_alloc::alloc::free and
rusty_alloc_api::Heap::dealloc as well as dealloc), unlike outlining
dealloc alone (7037d8d, not merged). MSVC builds with panic = abort and all
other targets are unchanged.

Cost on affected builds only, callgrind with the same code forced on
Linux: +3 Ir per local free (small 52.26 -> 55.26); Rust GlobalAlloc
workloads +0.30 % to +3.56 %, checksums identical.

Regression gate: rusty_sloth joins the downstream corpus as a
`build = "release"` row (run.sh builds such rows in the consumer's own
release profile, and blames an LLVM verifier failure on us even though it
names no crate). No small consumer reproduced the defect: rustc marks
cleanup calls cold, so the inliner keeps drops out of funclets in every
shape tried (docs/plans/msvc-funclet-asm-goto.md section 8).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Without it the release build is green on unfixed 2.2.4: the drops that
land in an MSVC funclet are in the CUDA paths. cuda is also the shipped
shape.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A path-repointed candidate cannot reproduce the MSVC funclet defect: unfixed
2.2.4 as a path dependency built rusty_sloth green, the same source from
crates.io failed (package id -> symbol hashes -> inlining). identity =
"registry" vendors the consumer's dependencies and swaps only the vendored
rusty_alloc src, so the candidate keeps the crates.io identity.

Verified by hand on rusty_sloth --release --features cuda: published 2.2.4
fails (4 x Bogus funclet pad use), 2.2.4 + the fix builds and runs.
Corrects the previous commit's note: cuda is the shipped shape, not the
trigger.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Ttimmahlax
Ttimmahlax merged commit 6110491 into main Oct 8, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants