diff options
| author | Erik Desjardins <erikdesjardins@users.noreply.github.com> | 2024-02-27 00:09:12 -0500 |
|---|---|---|
| committer | Erik Desjardins <erikdesjardins@users.noreply.github.com> | 2024-02-27 00:09:12 -0500 |
| commit | 4dabbcb23b0dc605cdb4aa6f3499d0f053f7b600 (patch) | |
| tree | 611a8d10de3f6652d48c63103a04981592bfe82d /compiler | |
| parent | 71ffdf7ff7ac6df5f9f64de7e780b8345797e8a0 (diff) | |
| download | rust-4dabbcb23b0dc605cdb4aa6f3499d0f053f7b600.tar.gz rust-4dabbcb23b0dc605cdb4aa6f3499d0f053f7b600.zip | |
allow using scalarpair with a common prim of ptr/ptr-sized-int
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_abi/src/layout.rs | 41 |
1 files changed, 35 insertions, 6 deletions
diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs index 28e148bddb2..d023c869e8b 100644 --- a/compiler/rustc_abi/src/layout.rs +++ b/compiler/rustc_abi/src/layout.rs @@ -813,15 +813,44 @@ where break; } }; - if let Some(pair) = common_prim { - // This is pretty conservative. We could go fancier - // by conflating things like i32 and u32, or even - // realising that (u8, u8) could just cohabit with - // u16 or even u32. - if pair != (prim, offset) { + if let Some((old_common_prim, common_offset)) = common_prim { + // All variants must be at the same offset + if offset != common_offset { common_prim = None; break; } + // This is pretty conservative. We could go fancier + // by realising that (u8, u8) could just cohabit with + // u16 or even u32. + let new_common_prim = match (old_common_prim, prim) { + // Allow all identical primitives. + (x, y) if x == y => Some(x), + // Allow integers of the same size with differing signedness. + // We arbitrarily choose the signedness of the first variant. + (p @ Primitive::Int(x, _), Primitive::Int(y, _)) if x == y => Some(p), + // Allow integers mixed with pointers of the same layout. + // We must represent this using a pointer, to avoid + // roundtripping pointers through ptrtoint/inttoptr. + (p @ Primitive::Pointer(_), i @ Primitive::Int(..)) + | (i @ Primitive::Int(..), p @ Primitive::Pointer(_)) + if p.size(dl) == i.size(dl) && p.align(dl) == i.align(dl) => + { + Some(p) + } + _ => None, + }; + match new_common_prim { + Some(new_prim) => { + // Primitives are compatible. + // We may be updating the primitive here, for example from int->ptr. + common_prim = Some((new_prim, common_offset)); + } + None => { + // Primitives are incompatible. + common_prim = None; + break; + } + } } else { common_prim = Some((prim, offset)); } |
