Skip to content

Commit 5e226dd

Browse files
authored
Rollup merge of rust-lang#129649 - RalfJung:unadjusted-abi-mismatch, r=petrochenkov
ABI compat check: detect unadjusted ABI mismatches
2 parents 489eb23 + ab7b03e commit 5e226dd

File tree

4 files changed

+26
-6
lines changed

4 files changed

+26
-6
lines changed

compiler/rustc_abi/src/lib.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -1700,7 +1700,9 @@ impl<FieldIdx: Idx, VariantIdx: Idx> LayoutS<FieldIdx, VariantIdx> {
17001700

17011701
/// Checks if these two `Layout` are equal enough to be considered "the same for all function
17021702
/// call ABIs". Note however that real ABIs depend on more details that are not reflected in the
1703-
/// `Layout`; the `PassMode` need to be compared as well.
1703+
/// `Layout`; the `PassMode` need to be compared as well. Also note that we assume
1704+
/// aggregates are passed via `PassMode::Indirect` or `PassMode::Cast`; more strict
1705+
/// checks would otherwise be required.
17041706
pub fn eq_abi(&self, other: &Self) -> bool {
17051707
// The one thing that we are not capturing here is that for unsized types, the metadata must
17061708
// also have the same ABI, and moreover that the same metadata leads to the same size. The

compiler/rustc_target/src/abi/call/mod.rs

+17-2
Original file line numberDiff line numberDiff line change
@@ -745,10 +745,25 @@ impl<'a, Ty> ArgAbi<'a, Ty> {
745745

746746
/// Checks if these two `ArgAbi` are equal enough to be considered "the same for all
747747
/// function call ABIs".
748-
pub fn eq_abi(&self, other: &Self) -> bool {
748+
pub fn eq_abi(&self, other: &Self) -> bool
749+
where
750+
Ty: PartialEq,
751+
{
749752
// Ideally we'd just compare the `mode`, but that is not enough -- for some modes LLVM will look
750753
// at the type.
751-
self.layout.eq_abi(&other.layout) && self.mode.eq_abi(&other.mode)
754+
self.layout.eq_abi(&other.layout) && self.mode.eq_abi(&other.mode) && {
755+
// `fn_arg_sanity_check` accepts `PassMode::Direct` for some aggregates.
756+
// That elevates any type difference to an ABI difference since we just use the
757+
// full Rust type as the LLVM argument/return type.
758+
if matches!(self.mode, PassMode::Direct(..))
759+
&& matches!(self.layout.abi, Abi::Aggregate { .. })
760+
{
761+
// For aggregates in `Direct` mode to be compatible, the types need to be equal.
762+
self.layout.ty == other.layout.ty
763+
} else {
764+
true
765+
}
766+
}
752767
}
753768
}
754769

compiler/rustc_target/src/spec/abi/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ pub enum Abi {
5353
},
5454
RustIntrinsic,
5555
RustCall,
56+
/// *Not* a stable ABI, just directly use the Rust types to describe the ABI for LLVM. Even
57+
/// normally ABI-compatible Rust types can become ABI-incompatible with this ABI!
5658
Unadjusted,
5759
/// For things unlikely to be called, where reducing register pressure in
5860
/// `extern "Rust"` callers is worth paying extra cost in the callee.

tests/ui/abi/compatibility.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,10 @@
4040
//@[loongarch64] compile-flags: --target loongarch64-unknown-linux-gnu
4141
//@[loongarch64] needs-llvm-components: loongarch
4242
//@[loongarch64] min-llvm-version: 18
43-
//@ revisions: wasm
44-
//@[wasm] compile-flags: --target wasm32-unknown-unknown
45-
//@[wasm] needs-llvm-components: webassembly
43+
//FIXME: wasm is disabled due to <https://github.com/rust-lang/rust/issues/115666>.
44+
//FIXME @ revisions: wasm
45+
//FIXME @[wasm] compile-flags: --target wasm32-unknown-unknown
46+
//FIXME @[wasm] needs-llvm-components: webassembly
4647
//@ revisions: wasip1
4748
//@[wasip1] compile-flags: --target wasm32-wasip1
4849
//@[wasip1] needs-llvm-components: webassembly

0 commit comments

Comments
 (0)