|
1 | 1 | use crate::abi::call::{ArgAbi, FnAbi, PassMode, Reg, Size, Uniform};
|
2 | 2 | use crate::abi::{HasDataLayout, TyAbiInterface};
|
3 | 3 |
|
| 4 | +use super::{ArgAttribute, ArgAttributes, ArgExtension, CastTarget}; |
| 5 | + |
4 | 6 | fn classify_ret<Ty>(ret: &mut ArgAbi<'_, Ty>) {
|
5 |
| - if ret.layout.is_aggregate() && ret.layout.size.bits() > 64 { |
6 |
| - ret.make_indirect(); |
7 |
| - } else { |
8 |
| - // FIXME: this is wrong! Need to decide which ABI we really want here. |
9 |
| - ret.make_direct_deprecated(); |
| 7 | + if ret.layout.is_aggregate() && ret.layout.is_sized() { |
| 8 | + classify_aggregate(ret) |
| 9 | + } else if ret.layout.size.bits() < 32 && ret.layout.is_sized() { |
| 10 | + ret.extend_integer_width_to(32); |
10 | 11 | }
|
11 | 12 | }
|
12 | 13 |
|
13 | 14 | fn classify_arg<Ty>(arg: &mut ArgAbi<'_, Ty>) {
|
14 |
| - if arg.layout.is_aggregate() { |
15 |
| - arg.make_indirect_byval(None); |
16 |
| - } else if arg.layout.size.bits() < 32 { |
| 15 | + if arg.layout.is_aggregate() && arg.layout.is_sized() { |
| 16 | + classify_aggregate(arg) |
| 17 | + } else if arg.layout.size.bits() < 32 && arg.layout.is_sized() { |
17 | 18 | arg.extend_integer_width_to(32);
|
18 | 19 | }
|
19 | 20 | }
|
20 | 21 |
|
| 22 | +/// the pass mode used for aggregates in arg and ret position |
| 23 | +fn classify_aggregate<Ty>(arg: &mut ArgAbi<'_, Ty>) { |
| 24 | + let align_bytes = arg.layout.align.abi.bytes(); |
| 25 | + let size = arg.layout.size; |
| 26 | + |
| 27 | + let reg = match align_bytes { |
| 28 | + 1 => Reg::i8(), |
| 29 | + 2 => Reg::i16(), |
| 30 | + 4 => Reg::i32(), |
| 31 | + 8 => Reg::i64(), |
| 32 | + 16 => Reg::i128(), |
| 33 | + _ => unreachable!("Align is given as power of 2 no larger than 16 bytes"), |
| 34 | + }; |
| 35 | + |
| 36 | + if align_bytes == size.bytes() { |
| 37 | + arg.cast_to(CastTarget { |
| 38 | + prefix: [Some(reg), None, None, None, None, None, None, None], |
| 39 | + rest: Uniform::new(Reg::i8(), Size::from_bytes(0)), |
| 40 | + attrs: ArgAttributes { |
| 41 | + regular: ArgAttribute::default(), |
| 42 | + arg_ext: ArgExtension::None, |
| 43 | + pointee_size: Size::ZERO, |
| 44 | + pointee_align: None, |
| 45 | + }, |
| 46 | + }); |
| 47 | + } else { |
| 48 | + arg.cast_to(Uniform::new(reg, size)); |
| 49 | + } |
| 50 | +} |
| 51 | + |
21 | 52 | fn classify_arg_kernel<'a, Ty, C>(_cx: &C, arg: &mut ArgAbi<'a, Ty>)
|
22 | 53 | where
|
23 | 54 | Ty: TyAbiInterface<'a, C> + Copy,
|
|
0 commit comments