Build failure on aarch64 and riscv64 with recent nightlies
This is blocking https://github.com/sunfishcode/c-ward/pull/139.
$ rustc -vV
rustc 1.82.0-nightly (6de928dce 2024-08-18)
binary: rustc
commit-hash: 6de928dce9472b864f4e5d590dd7aa2075cb7551
commit-date: 2024-08-18
host: aarch64-unknown-linux-gnu
release: 1.82.0-nightly
LLVM version: 19.1.0
$ CARGO_INCREMENTAL=0 cargo build --no-default-features --features "unwinder dwarf-expr fde-phdr-dl"
Compiling unwinding v0.2.2 (/home/gh-bjorn3/c-ward/unwinding)
inlinable function call in a function with debug info must have a !dbg location
call void @_Unwind_Resume(ptr %202) #16
rustc-LLVM ERROR: Broken module found, compilation aborted!
error: could not compile `unwinding` (lib)
The error message is from the LLVM IR verifier rule that "each inlinable callsite of a debug-info-bearing function in a debug-info-bearing function has a debug location attached to it". The compiler may be emitting a call to _Unwind_Resume without a debug location somewhere, which would normally work because _Unwind_Resume is normally not defined and thus not inlinable. In the unwinding crate though, _Unwind_Resume is defined, so it's inlinable, and it can have debug info, so the call with no debug info hits this rule.
A workaround is to add this to Cargo.toml:
[profile.dev]
debug = false
because then the function containing the callsite isn't debug-info-bearing and the rule doesn't apply.
Unwinding marks _Unwind_Resume as #[inline(never)].
The code in LLVM doesn't check any inlining attributes.
My current theory is that the bug happens here where it creates a _Unwind_Resume call that doesn't seem to get a debug location. It's suspicious because a different _Unwind_Resume call here does have code to add a debug location, and even has a comment about how the verifier requires calls of debug-info-bearing functions from debug-info-bearing functions to have a debug location. However, I haven't yet confirmed that this is the problem.
I guess I could check the IR to see where resume calls are generated, and try to tweak the code to not generate them... This will be fragile though
Another option would be to put the _Unwind_Resume definition in a separate crate which doesn't contain anything else, right? That would force it to be generated in a different codegen unit. You did still have LTO to worry about, but I don't think there is anything that can be done against that other than fixing LLVM as _Unwind_Resume calls will be coming from other crates than unwinding anyway.
Or defining _Unwind_Resume using inline asm, but rust currently doesn't have a way to then ensure the function gets exported from dylibs.
I've now confirmed my theory above, and posted https://github.com/llvm/llvm-project/pull/105513 to fix the bug in LLVM.
BTW I tried to reproduce this on my x64 machine with rustc cross-compiling to aarch64 and riscv64 but can't reproduce it. Maybe Rustc's LLVM is compiled with different flags on x64/aarch64?
I can reproduce it on an x86_64 host in a clean unwinding checkout with the command CARGO_INCREMENTAL=0 cargo build --no-default-features --features "unwinder dwarf-expr fde-phdr-dl" --target=aarch64-unknown-linux-gnu.
Ah I can produce it by downloading the prebuilt standard library, but not with -Zbuild-std, weird.
It looks like things work with a non-zero opt-level even with debug info enabled. @sunfishcode maybe you workaround on c-ward side by something like this while waiting for LLVM fix to be merged?
[profile.dev.package.unwinding]
opt-level = 1
The LLVM fix is now merged, and the backport to the release/19.x branch is now merged. It'll be some time before that's in a Rust builid, so thanks for the [profile.dev.package.unwinding] workaround idea, c-ward is now using until it's ready.
The LLVM fix is now in LLVM 19.1.0-rc4.
The LLVM fix is now in LLVM 19.1.0.
The LLVM fix is now in the rust LLVM tree 19.1-2024-07-30 branch, which is now in Rust nightly, and c-ward's CI now passes with the workarounds removed. So I think we can consider this issue fixed.
Thanks!