Skip to content

Commit 80393ca

Browse files
MabezDevGasper
authored andcommitted
Preliminary call abi for xtensa, it almost certainly has mistakes/ missing stuff.
1 parent 2d0e47e commit 80393ca

File tree

2 files changed

+87
-0
lines changed

2 files changed

+87
-0
lines changed

src/librustc_target/abi/call/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ mod wasm32_bindgen_compat;
2222
mod x86;
2323
mod x86_64;
2424
mod x86_win64;
25+
mod xtensa;
2526

2627
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
2728
pub enum PassMode {
@@ -593,6 +594,7 @@ impl<'a, Ty> FnAbi<'a, Ty> {
593594
wasm32_bindgen_compat::compute_abi_info(self)
594595
}
595596
"wasm32" | "asmjs" => wasm32::compute_abi_info(cx, self),
597+
"xtensa" => xtensa::compute_abi_info(self, 32),
596598
a => return Err(format!("unrecognized arch \"{}\" in target specification", a)),
597599
}
598600

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
// reference: https://github.com/espressif/clang-xtensa/commit/6fb488d2553f06029e6611cf81c6efbd45b56e47#diff-aa74ae1e1ab6b7149789237edb78e688R8450
2+
3+
4+
use crate::abi::call::{ArgType, FnType, Reg, Uniform};
5+
6+
const NUM_ARG_GPR: u64 = 6;
7+
const MAX_ARG_IN_REGS_SIZE: u64 = 4 * 32;
8+
// const MAX_ARG_DIRECT_SIZE : u64 = MAX_ARG_IN_REGS_SIZE;
9+
const MAX_RET_IN_REGS_SIZE: u64 = 2 * 32;
10+
11+
fn classify_ret_ty<Ty>(arg: &mut ArgType<'_, Ty>, xlen: u64) {
12+
// The rules for return and argument types are the same, so defer to
13+
// classifyArgumentType.
14+
classify_arg_ty(arg, xlen, &mut 2); // two as max return size
15+
}
16+
17+
18+
fn classify_arg_ty<Ty>(arg: &mut ArgType<'_, Ty>, xlen: u64, remaining_gpr: &mut u64) {
19+
// Determine the number of GPRs needed to pass the current argument
20+
// according to the ABI. 2*XLen-aligned varargs are passed in "aligned"
21+
// register pairs, so may consume 3 registers.
22+
23+
let mut stack_required = false;
24+
let mut required_gpr = 1u64; // at least one to start
25+
let arg_size = arg.layout.size.bits();
26+
// let alignment = arg.layout.details.align.abi.bits();
27+
28+
29+
if arg_size > xlen && arg_size <= MAX_ARG_IN_REGS_SIZE {
30+
required_gpr = arg_size + (xlen - 1) / xlen;
31+
}
32+
33+
if required_gpr > *remaining_gpr {
34+
stack_required = true;
35+
required_gpr = *remaining_gpr; }
36+
37+
38+
*remaining_gpr -= required_gpr;
39+
40+
// if a value can fit in a reg and the
41+
// stack is not required, extend
42+
if !arg.layout.is_aggregate() {
43+
if arg_size < xlen && !stack_required {
44+
arg.extend_integer_width_to(xlen);
45+
}
46+
return;
47+
}
48+
49+
50+
if arg_size as u64 <= MAX_ARG_IN_REGS_SIZE {
51+
let align = arg.layout.align.abi.bytes();
52+
let total = arg.layout.size;
53+
arg.cast_to(Uniform {
54+
unit: if align <= 4 { Reg::i32() } else { Reg::i64() },
55+
total
56+
});
57+
return;
58+
}
59+
60+
// if we get here the stack is required
61+
// assert!(stack_required);
62+
arg.make_indirect();
63+
}
64+
65+
pub fn compute_abi_info<Ty>(fty: &mut FnType<'_, Ty>, xlen: u64) {
66+
if !fty.ret.is_ignore() {
67+
classify_ret_ty(&mut fty.ret, xlen);
68+
}
69+
70+
let return_indirect = fty.ret.layout.size.bits() > MAX_RET_IN_REGS_SIZE ||
71+
fty.ret.is_indirect();
72+
73+
let mut remaining_gpr = if return_indirect {
74+
NUM_ARG_GPR - 1
75+
} else {
76+
NUM_ARG_GPR
77+
};
78+
79+
for arg in &mut fty.args {
80+
if arg.is_ignore() {
81+
continue;
82+
}
83+
classify_arg_ty(arg, xlen, &mut remaining_gpr);
84+
}
85+
}

0 commit comments

Comments
 (0)