Skip to content

Commit

Permalink
default Aggregate ABI to Indirect, and make sure it's never used for …
Browse files Browse the repository at this point in the history
…unsized
  • Loading branch information
RalfJung committed Nov 1, 2023
1 parent 7b0df22 commit 94200f6
Show file tree
Hide file tree
Showing 13 changed files with 102 additions and 13 deletions.
8 changes: 8 additions & 0 deletions compiler/rustc_target/src/abi/call/aarch64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ where
Ty: TyAbiInterface<'a, C> + Copy,
C: HasDataLayout,
{
if !ret.layout.is_sized() {
// Not touching this...
return;
}
if !ret.layout.is_aggregate() {
if kind == AbiKind::DarwinPCS {
// On Darwin, when returning an i8/i16, it must be sign-extended to 32 bits,
Expand Down Expand Up @@ -67,6 +71,10 @@ where
Ty: TyAbiInterface<'a, C> + Copy,
C: HasDataLayout,
{
if !arg.layout.is_sized() {
// Not touching this...
return;
}
if !arg.layout.is_aggregate() {
if kind == AbiKind::DarwinPCS {
// On Darwin, when passing an i8/i16, it must be sign-extended to 32 bits,
Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_target/src/abi/call/arm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ where
Ty: TyAbiInterface<'a, C> + Copy,
C: HasDataLayout,
{
if !ret.layout.is_sized() {
// Not touching this...
return;
}
if !ret.layout.is_aggregate() {
ret.extend_integer_width_to(32);
return;
Expand All @@ -56,6 +60,10 @@ where
Ty: TyAbiInterface<'a, C> + Copy,
C: HasDataLayout,
{
if !arg.layout.is_sized() {
// Not touching this...
return;
}
if !arg.layout.is_aggregate() {
arg.extend_integer_width_to(32);
return;
Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_target/src/abi/call/loongarch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,10 @@ fn classify_ret<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>, xlen: u64, flen: u6
where
Ty: TyAbiInterface<'a, C> + Copy,
{
if !arg.layout.is_sized() {
// Not touching this...
return false; // I guess? return value of this function is not documented
}
if let Some(conv) = should_use_fp_conv(cx, &arg.layout, xlen, flen) {
match conv {
FloatConv::Float(f) => {
Expand Down Expand Up @@ -214,6 +218,10 @@ fn classify_arg<'a, Ty, C>(
) where
Ty: TyAbiInterface<'a, C> + Copy,
{
if !arg.layout.is_sized() {
// Not touching this...
return;
}
if !is_vararg {
match should_use_fp_conv(cx, &arg.layout, xlen, flen) {
Some(FloatConv::Float(f)) if *avail_fprs >= 1 => {
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_target/src/abi/call/mips.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ fn classify_arg<Ty, C>(cx: &C, arg: &mut ArgAbi<'_, Ty>, offset: &mut Size)
where
C: HasDataLayout,
{
if !arg.layout.is_sized() {
// Not touching this...
return;
}
let dl = cx.data_layout();
let size = arg.layout.size;
let align = arg.layout.align.max(dl.i32_align).min(dl.i64_align).abi;
Expand Down
18 changes: 14 additions & 4 deletions compiler/rustc_target/src/abi/call/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,7 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
}))
}

Abi::ScalarPair(..) | Abi::Aggregate { .. } => {
Abi::ScalarPair(..) | Abi::Aggregate { sized: true } => {
// Helper for computing `homogeneous_aggregate`, allowing a custom
// starting offset (used below for handling variants).
let from_fields_at =
Expand Down Expand Up @@ -520,6 +520,7 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
Ok(result)
}
}
Abi::Aggregate { sized: false } => Err(Heterogeneous),
}
}
}
Expand Down Expand Up @@ -555,8 +556,7 @@ impl<'a, Ty> ArgAbi<'a, Ty> {
scalar_attrs(&layout, b, a.size(cx).align_to(b.align(cx).abi)),
),
Abi::Vector { .. } => PassMode::Direct(ArgAttributes::new()),
// The `Aggregate` ABI should always be adjusted later.
Abi::Aggregate { .. } => PassMode::Direct(ArgAttributes::new()),
Abi::Aggregate { .. } => Self::indirect_pass_mode(&layout),
};
ArgAbi { layout, mode }
}
Expand All @@ -580,10 +580,20 @@ impl<'a, Ty> ArgAbi<'a, Ty> {
PassMode::Indirect { attrs, meta_attrs, on_stack: false }
}

/// Pass this argument directly instead. Should NOT be used!
/// Only exists because of past ABI mistakes that will take time to fix
/// (see https://github.com/rust-lang/rust/issues/115666).
pub fn make_direct_deprecated(&mut self) {
self.mode = PassMode::Direct(ArgAttributes::new());
}

pub fn make_indirect(&mut self) {
match self.mode {
PassMode::Direct(_) | PassMode::Pair(_, _) => {}
PassMode::Indirect { attrs: _, meta_attrs: None, on_stack: false } => return,
PassMode::Indirect { attrs: _, meta_attrs: _, on_stack: false } => {
// already indirect
return;
}
_ => panic!("Tried to make {:?} indirect", self.mode),
}

Expand Down
9 changes: 9 additions & 0 deletions compiler/rustc_target/src/abi/call/nvptx64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,18 @@ use crate::abi::{HasDataLayout, TyAbiInterface};
fn classify_ret<Ty>(ret: &mut ArgAbi<'_, Ty>) {
if ret.layout.is_aggregate() && ret.layout.size.bits() > 64 {
ret.make_indirect();
} else {
// FIXME: this is wrong! Need to decide which ABI we really want here.
ret.make_direct_deprecated();
}
}

fn classify_arg<Ty>(arg: &mut ArgAbi<'_, Ty>) {
if arg.layout.is_aggregate() && arg.layout.size.bits() > 64 {
arg.make_indirect();
} else {
// FIXME: this is wrong! Need to decide which ABI we really want here.
arg.make_direct_deprecated();
}
}

Expand All @@ -30,6 +36,9 @@ where
_ => unreachable!("Align is given as power of 2 no larger than 16 bytes"),
};
arg.cast_to(Uniform { unit, total: Size::from_bytes(2 * align_bytes) });
} else {
// FIXME: find a better way to do this. See https://github.com/rust-lang/rust/issues/117271.
arg.make_direct_deprecated();
}
}

Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_target/src/abi/call/powerpc64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ where
Ty: TyAbiInterface<'a, C> + Copy,
C: HasDataLayout,
{
if !ret.layout.is_sized() {
// Not touching this...
return;
}
if !ret.layout.is_aggregate() {
ret.extend_integer_width_to(64);
return;
Expand Down Expand Up @@ -89,6 +93,10 @@ where
Ty: TyAbiInterface<'a, C> + Copy,
C: HasDataLayout,
{
if !arg.layout.is_sized() {
// Not touching this...
return;
}
if !arg.layout.is_aggregate() {
arg.extend_integer_width_to(64);
return;
Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_target/src/abi/call/riscv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,10 @@ fn classify_ret<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>, xlen: u64, flen: u6
where
Ty: TyAbiInterface<'a, C> + Copy,
{
if !arg.layout.is_sized() {
// Not touching this...
return false; // I guess? return value of this function is not documented
}
if let Some(conv) = should_use_fp_conv(cx, &arg.layout, xlen, flen) {
match conv {
FloatConv::Float(f) => {
Expand Down Expand Up @@ -220,6 +224,10 @@ fn classify_arg<'a, Ty, C>(
) where
Ty: TyAbiInterface<'a, C> + Copy,
{
if !arg.layout.is_sized() {
// Not touching this...
return;
}
if !is_vararg {
match should_use_fp_conv(cx, &arg.layout, xlen, flen) {
Some(FloatConv::Float(f)) if *avail_fprs >= 1 => {
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_target/src/abi/call/s390x.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ where
Ty: TyAbiInterface<'a, C> + Copy,
C: HasDataLayout,
{
if !arg.layout.is_sized() {
// Not touching this...
return;
}
if !arg.layout.is_aggregate() && arg.layout.size.bits() <= 64 {
arg.extend_integer_width_to(64);
return;
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_target/src/abi/call/sparc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ fn classify_arg<Ty, C>(cx: &C, arg: &mut ArgAbi<'_, Ty>, offset: &mut Size)
where
C: HasDataLayout,
{
if !arg.layout.is_sized() {
// Not touching this...
return;
}
let dl = cx.data_layout();
let size = arg.layout.size;
let align = arg.layout.align.max(dl.i32_align).min(dl.i64_align).abi;
Expand Down
24 changes: 20 additions & 4 deletions compiler/rustc_target/src/abi/call/wasm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ where
Ty: TyAbiInterface<'a, C> + Copy,
C: HasDataLayout,
{
if !arg.layout.is_sized() {
// Not touching this...
return;
}
arg.extend_integer_width_to(32);
if arg.layout.is_aggregate() && !unwrap_trivial_aggregate(cx, arg) {
arg.make_indirect_byval(None);
Expand Down Expand Up @@ -67,21 +71,33 @@ where
/// Also see <https://github.com/rust-lang/rust/issues/115666>.
pub fn compute_wasm_abi_info<Ty>(fn_abi: &mut FnAbi<'_, Ty>) {
if !fn_abi.ret.is_ignore() {
classify_ret(&mut fn_abi.ret);
classify_ret_wasm_abi(&mut fn_abi.ret);
}

for arg in fn_abi.args.iter_mut() {
if arg.is_ignore() {
continue;
}
classify_arg(arg);
classify_arg_wasm_abi(arg);
}

fn classify_ret<Ty>(ret: &mut ArgAbi<'_, Ty>) {
fn classify_ret_wasm_abi<Ty>(ret: &mut ArgAbi<'_, Ty>) {
if !ret.layout.is_sized() {
// Not touching this...
return;
}
// FIXME: this is bad! https://github.com/rust-lang/rust/issues/115666
ret.make_direct_deprecated();
ret.extend_integer_width_to(32);
}

fn classify_arg<Ty>(arg: &mut ArgAbi<'_, Ty>) {
fn classify_arg_wasm_abi<Ty>(arg: &mut ArgAbi<'_, Ty>) {
if !arg.layout.is_sized() {
// Not touching this...
return;
}
// FIXME: this is bad! https://github.com/rust-lang/rust/issues/115666
arg.make_direct_deprecated();
arg.extend_integer_width_to(32);
}
}
11 changes: 6 additions & 5 deletions compiler/rustc_ty_utils/src/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -589,13 +589,14 @@ fn fn_abi_adjust_for_abi<'tcx>(

_ => return,
}
// `Aggregate` ABI must be adjusted to ensure that ABI-compatible Rust types are passed
// the same way.
// Compute `Aggregate` ABI.

let is_indirect_not_on_stack =
matches!(arg.mode, PassMode::Indirect { on_stack: false, .. });
assert!(is_indirect_not_on_stack, "{:?}", arg);

let size = arg.layout.size;
if arg.layout.is_unsized() || size > Pointer(AddressSpace::DATA).size(cx) {
arg.make_indirect();
} else {
if !arg.layout.is_unsized() && size <= Pointer(AddressSpace::DATA).size(cx) {
// We want to pass small aggregates as immediates, but using
// an LLVM aggregate type for this leads to bad optimizations,
// so we pick an appropriately sized integer type instead.
Expand Down
1 change: 1 addition & 0 deletions tests/ui/abi/compatibility.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
//[wasi] compile-flags: --target wasm32-wasi
//[wasi] needs-llvm-components: webassembly
// FIXME: disabled on nvptx64 since the target ABI fails the sanity check
// see https://github.com/rust-lang/rust/issues/117480
/* revisions: nvptx64
[nvptx64] compile-flags: --target nvptx64-nvidia-cuda
[nvptx64] needs-llvm-components: nvptx
Expand Down

0 comments on commit 94200f6

Please sign in to comment.