1
Fork 0

Rollup merge of #133932 - bjorn3:fix_ptx_kernel_abi, r=wesleywiser

Avoid using make_direct_deprecated() in extern "ptx-kernel"

This method will be removed in the future as it produces a broken ABI that depends on cg_llvm implementation details. After this PR wasm32-unknown-unknown is the only remaining user of make_direct_deprecated().

Fixes https://github.com/rust-lang/rust/issues/117271
Blocks https://github.com/rust-lang/rust/issues/38788
This commit is contained in:
Jubilee 2025-02-05 19:53:45 -08:00 committed by GitHub
commit cc0f3efe7b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 34 additions and 39 deletions

View file

@ -1,5 +1,5 @@
use super::{ArgAttribute, ArgAttributes, ArgExtension, CastTarget};
use crate::abi::call::{ArgAbi, FnAbi, PassMode, Reg, Size, Uniform};
use crate::abi::call::{ArgAbi, FnAbi, Reg, Size, Uniform};
use crate::abi::{HasDataLayout, TyAbiInterface};
fn classify_ret<Ty>(ret: &mut ArgAbi<'_, Ty>) {
@ -53,21 +53,37 @@ where
Ty: TyAbiInterface<'a, C> + Copy,
C: HasDataLayout,
{
if matches!(arg.mode, PassMode::Pair(..)) && (arg.layout.is_adt() || arg.layout.is_tuple()) {
let align_bytes = arg.layout.align.abi.bytes();
match arg.mode {
super::PassMode::Ignore | super::PassMode::Direct(_) => return,
super::PassMode::Pair(_, _) => {}
super::PassMode::Cast { .. } => unreachable!(),
super::PassMode::Indirect { .. } => {}
}
let unit = match align_bytes {
1 => Reg::i8(),
2 => Reg::i16(),
4 => Reg::i32(),
8 => Reg::i64(),
16 => Reg::i128(),
_ => unreachable!("Align is given as power of 2 no larger than 16 bytes"),
};
arg.cast_to(Uniform::new(unit, Size::from_bytes(2 * align_bytes)));
// FIXME only allow structs and wide pointers here
// panic!(
// "`extern \"ptx-kernel\"` doesn't allow passing types other than primitives and structs"
// );
let align_bytes = arg.layout.align.abi.bytes();
let unit = match align_bytes {
1 => Reg::i8(),
2 => Reg::i16(),
4 => Reg::i32(),
8 => Reg::i64(),
16 => Reg::i128(),
_ => unreachable!("Align is given as power of 2 no larger than 16 bytes"),
};
if arg.layout.size.bytes() / align_bytes == 1 {
// Make sure we pass the struct as array at the LLVM IR level and not as a single integer.
arg.cast_to(CastTarget {
prefix: [Some(unit), None, None, None, None, None, None, None],
rest: Uniform::new(unit, Size::ZERO),
attrs: ArgAttributes::new(),
});
} else {
// FIXME: find a better way to do this. See https://github.com/rust-lang/rust/issues/117271.
arg.make_direct_deprecated();
arg.cast_to(Uniform::new(unit, arg.layout.size));
}
}