-
Notifications
You must be signed in to change notification settings - Fork 13.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
LLVM assertion failure on Wasm exceptions #135665
Comments
I also get |
Downgrading my local repo to 419b3e2, which is what my nightly is based on, does not remove the assertion failures. So perhaps the only reason nightly is working is that assertions are disabled by default. I have not yet confirmed that disabling the assertions makes the complex code (to anyone who wants to play around with this, run |
I could be mistaken but I don't believe we necessarily support enabling unwinding on targets that are abort-by-default? |
Do these problems actually surface for the emscripten target on nightly if you use... hm, we didn't document it...? we should document it here, probably... https://doc.rust-lang.org/nightly/rustc/platform-support/wasm32-unknown-emscripten.html @purplesyringa on nightly, with
|
So: rustc does compile it, but it miscompiles the code. Which is a known issue (#132416) I'm trying to fix, and applying the fix leads to the |
Wasm EH has been a thing in rustc for quite a while, so I'm assuming it was at the very least considered as something we want to support.
So there's two problems: 1) assertion failure in general, and 2) ud2 on manual unwinding. The first one can't be reproduced on nightly under any conditions, because nightly doesn't enable assertions (is that correct?). The second one does not reproduce on nightly because it's hidden by the miscompilation from #132416 due to |
As part of wasip1? I don't believe so, no. |
^ sorry for the wrong label Here's a short reproducer of the #![feature(core_intrinsics, wasm_exception_handling_intrinsics, rustc_attrs)]
fn main() {
unsafe {
core::intrinsics::catch_unwind(
|_| {
core::arch::wasm32::throw::<0>(core::ptr::null_mut());
},
core::ptr::null_mut(),
#[rustc_nounwind]
|_, _| {},
);
};
} It reproduces on both the nightly commit and master if you remove the bit in rustc_codegen_ssa/src/codegen_attrs.rs that makes the The crash affects both wasm32-wasip1 with I don't see anything wrong in this snippet -- it's pretty much what |
My memory says we do produce a variant of the nightly builds that has assertions enabled, but I can't remember unfortunately exactly how to obtain it. |
I can also confirm that the assertion is triggered on emscripten (on empty code, on master, without any rustc modifications). |
I unfortunately know very little about the state of unwinding/exceptions in LLVM. My (very dated) impression is that LLVM supports the what's now called "legacy exceptions" proposal in wasm and is getting support for the official proposal. I don't know how battle-tested either are in practice though in terms of robustness of the LLVM backend. |
I think it has support for both legacy and new exceptions now. As I understand it, Emscripten still is asking llvm to emit the legacy exceptions and then uses binaryen to convert to the new exceptions. But there is a PR to fix this: cc @aheejin |
@purplesyringa Can you provide a bitcode ( Also I don't know what |
I compiled $ RUSTFLAGS="-Z emscripten_wasm_eh -C save-temps -C codegen-units=1" cargo +stage1 rustc --target wasm32-unknown-emscripten -Z build-std This failed when compiling This reproduces the $ llc compiler_builtins.ll -o test.s --exception-model=wasm -wasm-enable-eh
llc: /checkout/src/llvm-project/llvm/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp:1378: void mapWasmLandingPadIndex(MachineBasicBlock *, const CatchPadInst *): Assertion `IntrFound && "wasm.landingpad.index intrinsic not found!"' failed.
PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ and include the crash backtrace.
Stack dump:
0. Program arguments: /home/purplesyringa/rust/build/host/ci-llvm/bin/llc compiler_builtins.ll -o test.s --exception-model=wasm -wasm-enable-eh
1. Running pass 'Function Pass Manager' on module 'compiler_builtins.ll'.
2. Running pass 'WebAssembly Instruction Selection' on function '@_ZN4core10intrinsics19copy_nonoverlapping18precondition_check17hc5243bdde1bb1f76E'
#0 0x00007e9503418167 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/home/purplesyringa/rust/build/x86_64-unknown-linux-gnu/ci-llvm/bin/../lib/libLLVM.so.19.1-rust-1.86.0-nightly+0x5018167)
#1 0x00007e950341857c SignalHandler(int) (/home/purplesyringa/rust/build/x86_64-unknown-linux-gnu/ci-llvm/bin/../lib/libLLVM.so.19.1-rust-1.86.0-nightly+0x501857c)
#2 0x00007e94fe24c1d0 (/usr/lib/libc.so.6+0x3d1d0)
#3 0x00007e94fe2a53f4 (/usr/lib/libc.so.6+0x963f4)
#4 0x00007e94fe24c120 raise (/usr/lib/libc.so.6+0x3d120)
#5 0x00007e94fe2334c3 abort (/usr/lib/libc.so.6+0x244c3)
#6 0x00007e94fe2333df (/usr/lib/libc.so.6+0x243df)
#7 0x00007e94fe244177 (/usr/lib/libc.so.6+0x35177)
#8 0x00007e950732d5e5 llvm::SelectionDAGISel::PrepareEHLandingPad() (.cold) bolt-pseudo.o:0:0
#9 0x00007e9506210a30 llvm::SelectionDAGISel::SelectAllBasicBlocks(llvm::Function const&) (/home/purplesyringa/rust/build/x86_64-unknown-linux-gnu/ci-llvm/bin/../lib/libLLVM.so.19.1-rust-1.86.0-nightly+0x7e10a30)
#10 0x00007e95060e9203 llvm::SelectionDAGISel::runOnMachineFunction(llvm::MachineFunction&) (/home/purplesyringa/rust/build/x86_64-unknown-linux-gnu/ci-llvm/bin/../lib/libLLVM.so.19.1-rust-1.86.0-nightly+0x7ce9203)
#11 0x00007e95060ec6f3 llvm::SelectionDAGISelLegacy::runOnMachineFunction(llvm::MachineFunction&) (/home/purplesyringa/rust/build/x86_64-unknown-linux-gnu/ci-llvm/bin/../lib/libLLVM.so.19.1-rust-1.86.0-nightly+0x7cec6f3)
#12 0x00007e95060ef9f0 llvm::FPPassManager::runOnFunction(llvm::Function&) (/home/purplesyringa/rust/build/x86_64-unknown-linux-gnu/ci-llvm/bin/../lib/libLLVM.so.19.1-rust-1.86.0-nightly+0x7cef9f0)
#13 0x00007e95060ee7b6 llvm::FPPassManager::runOnModule(llvm::Module&) (/home/purplesyringa/rust/build/x86_64-unknown-linux-gnu/ci-llvm/bin/../lib/libLLVM.so.19.1-rust-1.86.0-nightly+0x7cee7b6)
#14 0x00007e95067a3993 llvm::legacy::PassManagerImpl::run(llvm::Module&) (/home/purplesyringa/rust/build/x86_64-unknown-linux-gnu/ci-llvm/bin/../lib/libLLVM.so.19.1-rust-1.86.0-nightly+0x83a3993)
#15 0x00005795b2dc2c43 main (/home/purplesyringa/rust/build/host/ci-llvm/bin/llc+0x15c43)
#16 0x00007e94fe234e08 (/usr/lib/libc.so.6+0x25e08)
#17 0x00007e94fe234ecc __libc_start_main (/usr/lib/libc.so.6+0x25ecc)
#18 0x00005795b2dbff28 _start (/home/purplesyringa/rust/build/host/ci-llvm/bin/llc+0x12f28)
Aborted (core dumped) I have considered minimizing it, but applying |
|
I don't know much about how rustc frontend generates the EH instructions such as Judging by the bitcode, it looks rustc currently generates |
@aheejin rustc emits (pseudocode): declare i32 @rust_try(%try_func, %data, %catch_func) {
%slot = alloca i8*
invoke %try_func(%data) to label %normal unwind label %catchswitch
normal:
ret i32 0
catchswitch:
%cs = catchswitch within none [%catchpad] unwind to caller
catchpad:
%tok = catchpad within %cs [null]
%ptr = call @llvm.wasm.get.exception(token %tok)
%sel = call @llvm.wasm.get.ehselector(token %tok)
call %catch_func(%data, %ptr)
catchret from %tok to label %caught
caught:
ret i32 1
} This seems to match the input |
Oh, I see now: this is not the IR we emit in %7 = catchswitch within none [label %8] unwind to caller
8:
%9 = catchpad within %7 [ptr null, i32 64, ptr null]
call void @llvm.trap()
unreachable which |
This fixes failing LLVM assertions during insnsel. Partially fixes rust-lang#135665.
This fixes failing LLVM assertions during insnsel. Partially fixes rust-lang#135665.
This fixes failing LLVM assertions during insnsel. Improves rust-lang#135665.
Generate correct terminate block under Wasm EH This fixes failing LLVM assertions during insnsel. Improves rust-lang#135665. r? bjorn3 ^ you reviewed the PR bringing Wasm EH in, I assume this is within your area of expertise?
Generate correct terminate block under Wasm EH This fixes failing LLVM assertions during insnsel. Improves rust-lang#135665. r? bjorn3 ^ you reviewed the PR bringing Wasm EH in, I assume this is within your area of expertise?
Generate correct terminate block under Wasm EH This fixes failing LLVM assertions during insnsel. Improves rust-lang#135665. r? bjorn3 ^ you reviewed the PR bringing Wasm EH in, I assume this is within your area of expertise?
Rollup merge of rust-lang#136200 - purplesyringa:wasm-eh-fixes, r=bjorn3 Generate correct terminate block under Wasm EH This fixes failing LLVM assertions during insnsel. Improves rust-lang#135665. r? bjorn3 ^ you reviewed the PR bringing Wasm EH in, I assume this is within your area of expertise?
Asserts should now pass, but the LLVM-side issue (which has been referred above as the |
llvm/llvm-project#124710 is now fixed -- this issue will probably be resolved by an LLVM update. @rustbot label +llvm-fixed-upstream |
Code
:/
Meta
I'm building rustc on the current master (bcd0683) with LLVM assertions enabled. I'm compiling the program above like this:
I'm using the 23.0 WASI sysroot, downloaded from their GitHub releases, if that matters.
Error output
like, everywhere, on all sorts of standard crates like
libc
andunwind
.Disabling assertions hides the bug, and user code works fine. This also does not reproduce on rustup's nightly, probably for the same reason. I have no idea, really. Please tell me I'm doing something wrong.
For context, this seems more important because Emscripten is supposed to switch to Wasm exceptions soon-ish, and I imagine the same problem occurs there (but I haven't checked). Unlike wasm32-wasip1, unwinding is enabled there by default.
@rustbot label +A-LLVM
The text was updated successfully, but these errors were encountered: