rustc_target/callconv/
xtensa.rs1use rustc_abi::{BackendRepr, HasDataLayout, Size, TyAbiInterface};
9
10use crate::callconv::{ArgAbi, FnAbi, IndirectMode, Reg, Uniform};
11use crate::spec::HasTargetSpec;
12
13const NUM_ARG_GPRS: u64 = 6;
14const NUM_RET_GPRS: u64 = 4;
15const MAX_ARG_IN_REGS_SIZE: u64 = NUM_ARG_GPRS * 32;
16const MAX_RET_IN_REGS_SIZE: u64 = NUM_RET_GPRS * 32;
17
18fn classify_ret_ty<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>)
19where
20 Ty: TyAbiInterface<'a, C> + Copy,
21{
22 if arg.is_ignore() {
23 return;
24 }
25
26 let mut arg_gprs_left = NUM_RET_GPRS;
29 classify_arg_ty(cx, arg, &mut arg_gprs_left, true);
30 match arg.mode {
32 super::PassMode::Indirect { attrs: _, address_space: _, ref mut mode } => {
33 *mode = IndirectMode::Pointer;
34 }
35 super::PassMode::IndirectUnsized { .. } => {
::core::panicking::panic_fmt(format_args!("unsized returns are not supported"));
}panic!("unsized returns are not supported"),
36 _ => {}
37 }
38}
39
40fn classify_arg_ty<'a, Ty, C>(
41 cx: &C,
42 arg: &mut ArgAbi<'a, Ty>,
43 arg_gprs_left: &mut u64,
44 is_ret: bool,
45) where
46 Ty: TyAbiInterface<'a, C> + Copy,
47{
48 if !(*arg_gprs_left <= NUM_ARG_GPRS) {
{
::core::panicking::panic_fmt(format_args!("Arg GPR tracking underflow"));
}
};assert!(*arg_gprs_left <= NUM_ARG_GPRS, "Arg GPR tracking underflow");
49
50 let max_size = if is_ret { MAX_RET_IN_REGS_SIZE } else { MAX_ARG_IN_REGS_SIZE };
51
52 if !is_ret && arg.layout.pass_indirectly_in_non_rustic_abis(cx) {
53 *arg_gprs_left = arg_gprs_left.saturating_sub(1);
54 arg.make_indirect();
55 return;
56 }
57
58 if arg.layout.is_zst() {
60 return;
61 }
62
63 let size = arg.layout.size.bits();
64 let needed_align = arg.layout.align.bits();
65 let mut must_use_stack = false;
66
67 let mut needed_arg_gprs = size.div_ceil(32);
71 if needed_align == 64 {
72 needed_arg_gprs += *arg_gprs_left % 2;
73 }
74
75 if needed_arg_gprs > *arg_gprs_left
76 || needed_align > 128
77 || (*arg_gprs_left < (max_size / 32) && needed_align == 128)
78 {
79 must_use_stack = true;
80 needed_arg_gprs = *arg_gprs_left;
81 }
82 *arg_gprs_left -= needed_arg_gprs;
83
84 if must_use_stack {
85 arg.pass_by_stack_offset(None);
86 } else if is_xtensa_aggregate(arg) {
87 if size <= 32 {
94 arg.cast_to(Reg::i32());
95 } else {
96 let reg = if needed_align == 2 * 32 { Reg::i64() } else { Reg::i32() };
97 let total = Size::from_bits(((size + 32 - 1) / 32) * 32);
98 arg.cast_to(Uniform::new(reg, total));
99 }
100 } else {
101 if size < 32 {
106 arg.extend_integer_width_to(32);
107 }
108 }
109}
110
111pub(crate) fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
112where
113 Ty: TyAbiInterface<'a, C> + Copy,
114 C: HasDataLayout + HasTargetSpec,
115{
116 if !fn_abi.ret.is_ignore() {
117 classify_ret_ty(cx, &mut fn_abi.ret);
118 }
119
120 let mut arg_gprs_left = NUM_ARG_GPRS;
121
122 for arg in fn_abi.args.iter_mut() {
123 if arg.is_ignore() {
124 continue;
125 }
126 classify_arg_ty(cx, arg, &mut arg_gprs_left, false);
127 }
128}
129
130fn is_xtensa_aggregate<'a, Ty>(arg: &ArgAbi<'a, Ty>) -> bool {
131 match arg.layout.backend_repr {
132 BackendRepr::SimdVector { .. } => true,
133 _ => arg.layout.is_aggregate(),
134 }
135}