|
1 | 1 | use super::{ArgAttribute, ArgAttributes, ArgExtension, CastTarget};
|
2 |
| -use crate::abi::call::{ArgAbi, FnAbi, PassMode, Reg, Size, Uniform}; |
| 2 | +use crate::abi::call::{ArgAbi, FnAbi, Reg, Size, Uniform}; |
3 | 3 | use crate::abi::{HasDataLayout, TyAbiInterface};
|
4 | 4 |
|
5 | 5 | fn classify_ret<Ty>(ret: &mut ArgAbi<'_, Ty>) {
|
@@ -53,21 +53,37 @@ where
|
53 | 53 | Ty: TyAbiInterface<'a, C> + Copy,
|
54 | 54 | C: HasDataLayout,
|
55 | 55 | {
|
56 |
| - if matches!(arg.mode, PassMode::Pair(..)) && (arg.layout.is_adt() || arg.layout.is_tuple()) { |
57 |
| - let align_bytes = arg.layout.align.abi.bytes(); |
| 56 | + match arg.mode { |
| 57 | + super::PassMode::Ignore | super::PassMode::Direct(_) => return, |
| 58 | + super::PassMode::Pair(_, _) => {} |
| 59 | + super::PassMode::Cast { .. } => unreachable!(), |
| 60 | + super::PassMode::Indirect { .. } => {} |
| 61 | + } |
| 62 | + |
| 63 | + // FIXME only allow structs and wide pointers here |
| 64 | + // panic!( |
| 65 | + // "`extern \"ptx-kernel\"` doesn't allow passing types other than primitives and structs" |
| 66 | + // ); |
| 67 | + |
| 68 | + let align_bytes = arg.layout.align.abi.bytes(); |
58 | 69 |
|
59 |
| - let unit = match align_bytes { |
60 |
| - 1 => Reg::i8(), |
61 |
| - 2 => Reg::i16(), |
62 |
| - 4 => Reg::i32(), |
63 |
| - 8 => Reg::i64(), |
64 |
| - 16 => Reg::i128(), |
65 |
| - _ => unreachable!("Align is given as power of 2 no larger than 16 bytes"), |
66 |
| - }; |
67 |
| - arg.cast_to(Uniform::new(unit, Size::from_bytes(2 * align_bytes))); |
| 70 | + let unit = match align_bytes { |
| 71 | + 1 => Reg::i8(), |
| 72 | + 2 => Reg::i16(), |
| 73 | + 4 => Reg::i32(), |
| 74 | + 8 => Reg::i64(), |
| 75 | + 16 => Reg::i128(), |
| 76 | + _ => unreachable!("Align is given as power of 2 no larger than 16 bytes"), |
| 77 | + }; |
| 78 | + if arg.layout.size.bytes() / align_bytes == 1 { |
| 79 | + // Make sure we pass the struct as array at the LLVM IR level and not as a single integer. |
| 80 | + arg.cast_to(CastTarget { |
| 81 | + prefix: [Some(unit), None, None, None, None, None, None, None], |
| 82 | + rest: Uniform::new(unit, Size::ZERO), |
| 83 | + attrs: ArgAttributes::new(), |
| 84 | + }); |
68 | 85 | } else {
|
69 |
| - // FIXME: find a better way to do this. See https://github.com/rust-lang/rust/issues/117271. |
70 |
| - arg.make_direct_deprecated(); |
| 86 | + arg.cast_to(Uniform::new(unit, arg.layout.size)); |
71 | 87 | }
|
72 | 88 | }
|
73 | 89 |
|
|
0 commit comments