rustc_target/callconv/
powerpc.rs1use rustc_abi::{BackendRepr, Float, Primitive, Reg, RegKind, TyAbiInterface};
2use rustc_span::bug;
3
4use crate::callconv::{ArgAbi, CastTarget, FnAbi, Uniform};
5use crate::spec::{Env, HasTargetSpec, Os, RustcAbi};
6
7const NUM_ARG_GPRS: u64 = 8;
8
9fn complex_cast_target<Ty>(arg: &ArgAbi<'_, Ty>) -> CastTarget {
11 let size = arg.layout.size;
12
13 if size.bytes() <= 4 {
14 CastTarget::from(Reg { kind: RegKind::Integer, size })
16 } else if size.bytes() == 8 {
17 CastTarget::from(Reg::i64())
20 } else {
21 CastTarget::from(Uniform::new(Reg::i32(), size))
24 }
25}
26
27fn classify_ret<'a, Ty, C>(cx: &C, ret: &mut ArgAbi<'a, Ty>, gprs_in_use: &mut u64)
28where
29 Ty: TyAbiInterface<'a, C> + Copy,
30{
31 if ret.layout.is_complex_number(cx) {
32 ret.cast_to(complex_cast_target(ret));
33 } else if ret.layout.is_aggregate() {
34 *gprs_in_use += 1;
35 ret.make_indirect();
36 } else {
37 ret.extend_integer_width_to(32);
38 }
39}
40
41fn classify_arg<'a, Ty, C: HasTargetSpec>(cx: &C, arg: &mut ArgAbi<'a, Ty>, gprs_in_use: &mut u64)
42where
43 Ty: TyAbiInterface<'a, C> + Copy,
44{
45 if arg.is_ignore() {
46 if cx.target_spec().os == Os::Linux
48 && #[allow(non_exhaustive_omitted_patterns)] match cx.target_spec().env {
Env::Gnu | Env::Musl | Env::Uclibc => true,
_ => false,
}matches!(cx.target_spec().env, Env::Gnu | Env::Musl | Env::Uclibc)
49 && arg.layout.is_repr_c()
50 {
51 *gprs_in_use += 1;
52 arg.make_indirect_from_ignore();
53 }
54 return;
55 }
56
57 if arg.layout.is_complex_number(cx) {
69 let cast_target = complex_cast_target(arg);
70
71 let is_aligned_pair = arg.layout.size.bytes() == 8;
73 if is_aligned_pair && !gprs_in_use.is_multiple_of(2) {
74 *gprs_in_use += 1;
75 }
76
77 let registers_used = arg.layout.size.bytes().div_ceil(4);
78 if *gprs_in_use + registers_used > NUM_ARG_GPRS {
79 let pad_i32_count = u8::try_from(NUM_ARG_GPRS.saturating_sub(*gprs_in_use)).unwrap();
80 arg.cast_to_and_pad_i32(cast_target, pad_i32_count);
81 } else {
82 arg.cast_to(cast_target);
83 }
84
85 *gprs_in_use += registers_used;
87 } else if arg.layout.pass_indirectly_in_non_rustic_abis(cx) || arg.layout.is_aggregate() {
88 *gprs_in_use += 1;
89 arg.make_indirect();
90 } else {
91 if backend_repr_uses_gprs(cx, arg) {
92 let is_aligned_pair = arg.layout.size.bytes() >= 8;
94 if is_aligned_pair && !gprs_in_use.is_multiple_of(2) {
95 *gprs_in_use += 1;
96 }
97
98 *gprs_in_use += arg.layout.size.bytes().div_ceil(4)
99 }
100
101 arg.extend_integer_width_to(32);
102 }
103}
104
105fn backend_repr_uses_gprs<'a, Ty, C: HasTargetSpec>(cx: &C, arg: &ArgAbi<'a, Ty>) -> bool {
107 let is_softfloat = match cx.target_spec().rustc_abi {
108 Some(RustcAbi::Softfloat) => ::rustc_span::macros::bug_impl(None,
format_args!("there are currently no powerpc softfloat targets"),
Location::caller())bug!("there are currently no powerpc softfloat targets"),
109 Some(RustcAbi::PowerPcSpe) => true, None => false,
111 Some(other) => ::rustc_span::macros::bug_impl(None,
format_args!("unexpected powerpc abi {0:?}", other), Location::caller())bug!("unexpected powerpc abi {other:?}"),
112 };
113
114 match arg.layout.backend_repr {
115 BackendRepr::ScalarPair { .. } | BackendRepr::SimdScalableVector { .. } => {
116 ::rustc_span::macros::bug_impl(None,
format_args!("unexpected backend_repr for 32-bit powerpc: {0:?}",
arg.layout.backend_repr), Location::caller())bug!("unexpected backend_repr for 32-bit powerpc: {:?}", arg.layout.backend_repr)
117 }
118 BackendRepr::Memory { .. } => {
119 ::rustc_span::macros::bug_impl(None,
format_args!("unexpected backend_repr for PassMode::Direct: {0:?}",
arg.layout.backend_repr), Location::caller())bug!("unexpected backend_repr for PassMode::Direct: {:?}", arg.layout.backend_repr)
120 }
121 BackendRepr::Scalar(scalar) => match scalar.primitive() {
122 Primitive::Float(Float::F32 | Float::F64 | Float::F128 | Float::PpcF128) => {
123 is_softfloat
124 }
125
126 _ => true,
127 },
128 BackendRepr::SimdVector { .. } => {
129 false
131 }
132 }
133}
134
135pub(crate) fn compute_abi_info<'a, Ty, C: HasTargetSpec>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
136where
137 Ty: TyAbiInterface<'a, C> + Copy,
138{
139 let mut gprs_in_use: u64 = 0;
144
145 if !fn_abi.ret.is_ignore() {
146 classify_ret(cx, &mut fn_abi.ret, &mut gprs_in_use);
147 }
148
149 for arg in fn_abi.args.iter_mut() {
150 classify_arg(cx, arg, &mut gprs_in_use);
151 }
152}