Change:
CFGuard::Disabled => {} CFGuard::NoChecks => { // Set `cfguard=1` module flag to emit metadata only. <del> llvm::LLVMRustAddModuleFlag(llmod, "cfguard0".as_ptr() as *const _, 1) </del> <ins> llvm::LLVMRustAddModuleFlag( llmod, llvm::LLVMModFlagBehavior::Warning, "cfguard0".as_ptr() as *const _, 1, ) </ins> } CFGuard::Checks => { // Set `cfguard=2` module flag to emit metadata and checks. <del> llvm::LLVMRustAddModuleFlag(llmod, "cfguard0".as_ptr() as *const _, 2) </del> <ins> llvm::LLVMRustAddModuleFlag( llmod, llvm::LLVMModFlagBehavior::Warning, "cfguard0".as_ptr() as *const _, 2, ) </ins> } } }

Discussion:
After , Firefox builds fail with e.g: This happens when targeting arm64 macos or arm64 windows. Not only did the default change and now diverges from clang (causing the above error when mixing objects from clang and rust), but it's also apparently not possible to disable the feature. Note this also now reached beta. Cc:
It should be off by default. My first guess is that the problem is that , but with a true/false value, so perhaps a false value is not equivalent to an unset value. If that is the problem then there might be something deeper to investigate here, like some BTI mismatch between the Rust and C/C++ code that wasn't previously spotted. It would be interesting to know if the C/C++ code is compiled with BTI enabled. I don't have Firefox (or recent Rust) build environment on my M1 Mac so it'll take me a while to reproduce. I'll make a start, but if others can get there first and unblock this quickly, then please do! We could also revert from beta whilst we investigate. I'm not sure of the process there.
It most probably involves linker-plugin-lto. A default firefox build wouldn't enable that. I suspect it's reproducible with a simple testcase that has both C and C++ code with linker-plugin-lto enabled.
(beware of if you try to use linker-plugin-lto)
Ok, I was also able to reproduce locally with a Linux aarch64 cross-build (modulo ) and it turns out the rust llvm-ir has: while the clang llvm-ir has: llvm-ir from older versions of rust didn't have them at all.
Nor does the llvm-ir from older versions of clang — at least the one I have pre-built — so the simple idea of marking them as () to match the newer clang might cause different problems.
why do you think so? the llvm-ir that doesn't contain these flags at all links fine with the llvm-ir that does (even with behavior set to Error).
It was my own (naive) assumption, based on how BTI itself works: it's not correct to treat non-BTI machine code as BTI because if it lacks the BTI instructions it will be impossible to call any of its functions. However, that's not particularly relevant as this logic is all resolved before code generation.

That leaves two candidate solutions, then: error-on-mismatch for these flags. This is nice because it catches configuration mismatches, and will be compatible with Clang and LTO. 't emit these flags at all if they aren't enabled. This most closely matches the existing (stable) behaviour but means that configuration mismatches (or compatibility issues like this one) may be missed. Given the behaviour you described, and the LTO — "Best results are achieved by using a and that are based on the exact same version of LLVM" — I think we can reasonably prefer option 1. I'll start working on that today.
Assigning priority as discussed in the of the Prioritization Working Group. label -I-prioritize +P-high
Reopening to track beta fix (proposed in ).
resolved by (on beta), on master