rustc_target/callconv/
xtensa.rs
1use rustc_abi::{BackendRepr, HasDataLayout, Size, TyAbiInterface};
9
10use crate::callconv::{ArgAbi, FnAbi, 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>(arg: &mut ArgAbi<'_, 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(arg, &mut arg_gprs_left, MAX_RET_IN_REGS_SIZE);
30 match arg.mode {
32 super::PassMode::Indirect { attrs: _, meta_attrs: _, ref mut on_stack } => {
33 *on_stack = false;
34 }
35 _ => {}
36 }
37}
38
39fn classify_arg_ty<'a, Ty, C>(arg: &mut ArgAbi<'_, Ty>, arg_gprs_left: &mut u64, max_size: u64)
40where
41 Ty: TyAbiInterface<'a, C> + Copy,
42{
43 assert!(*arg_gprs_left <= NUM_ARG_GPRS, "Arg GPR tracking underflow");
44
45 if arg.layout.is_zst() {
47 return;
48 }
49
50 let size = arg.layout.size.bits();
51 let needed_align = arg.layout.align.abi.bits();
52 let mut must_use_stack = false;
53
54 let mut needed_arg_gprs = (size + 32 - 1) / 32;
58 if needed_align == 64 {
59 needed_arg_gprs += *arg_gprs_left % 2;
60 }
61
62 if needed_arg_gprs > *arg_gprs_left
63 || needed_align > 128
64 || (*arg_gprs_left < (max_size / 32) && needed_align == 128)
65 {
66 must_use_stack = true;
67 needed_arg_gprs = *arg_gprs_left;
68 }
69 *arg_gprs_left -= needed_arg_gprs;
70
71 if must_use_stack {
72 arg.pass_by_stack_offset(None);
73 } else if is_xtensa_aggregate(arg) {
74 if size <= 32 {
81 arg.cast_to(Reg::i32());
82 } else {
83 let reg = if needed_align == 2 * 32 { Reg::i64() } else { Reg::i32() };
84 let total = Size::from_bits(((size + 32 - 1) / 32) * 32);
85 arg.cast_to(Uniform::new(reg, total));
86 }
87 } else {
88 if size < 32 {
93 arg.extend_integer_width_to(32);
94 }
95 }
96}
97
98pub(crate) fn compute_abi_info<'a, Ty, C>(_cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
99where
100 Ty: TyAbiInterface<'a, C> + Copy,
101 C: HasDataLayout + HasTargetSpec,
102{
103 if !fn_abi.ret.is_ignore() {
104 classify_ret_ty(&mut fn_abi.ret);
105 }
106
107 let mut arg_gprs_left = NUM_ARG_GPRS;
108
109 for arg in fn_abi.args.iter_mut() {
110 if arg.is_ignore() {
111 continue;
112 }
113 classify_arg_ty(arg, &mut arg_gprs_left, MAX_ARG_IN_REGS_SIZE);
114 }
115}
116
117fn is_xtensa_aggregate<'a, Ty>(arg: &ArgAbi<'a, Ty>) -> bool {
118 match arg.layout.backend_repr {
119 BackendRepr::Vector { .. } => true,
120 _ => arg.layout.is_aggregate(),
121 }
122}