-
Notifications
You must be signed in to change notification settings - Fork 3
/
0003-Teach-rustc-about-the-Xtensa-call-ABI.patch
151 lines (148 loc) · 5.25 KB
/
0003-Teach-rustc-about-the-Xtensa-call-ABI.patch
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
From bfc577ab2208db442ee7d356a21ae9c78e2b2d25 Mon Sep 17 00:00:00 2001
From: Scott Mabin <scott@mabez.dev>
Date: Sat, 12 Sep 2020 23:31:14 +0100
Subject: [PATCH 3/5] Teach rustc about the Xtensa call ABI.
---
compiler/rustc_target/src/abi/call/mod.rs | 2 +
compiler/rustc_target/src/abi/call/xtensa.rs | 110 +++++++++++++++++++
2 files changed, 112 insertions(+)
create mode 100644 compiler/rustc_target/src/abi/call/xtensa.rs
diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs
index 9c49922c286..5045e9d5d4d 100644
--- a/compiler/rustc_target/src/abi/call/mod.rs
+++ b/compiler/rustc_target/src/abi/call/mod.rs
@@ -7,6 +7,7 @@
mod arm;
mod avr;
mod hexagon;
+mod xtensa;
mod mips;
mod mips64;
mod msp430;
@@ -636,6 +637,7 @@ pub fn adjust_for_cabi<C>(&mut self, cx: &C, abi: spec::abi::Abi) -> Result<(),
"nvptx" => nvptx::compute_abi_info(self),
"nvptx64" => nvptx64::compute_abi_info(self),
"hexagon" => hexagon::compute_abi_info(self),
+ "xtensa" => xtensa::compute_abi_info(cx, self),
"riscv32" | "riscv64" => riscv::compute_abi_info(cx, self),
"wasm32" => match cx.target_spec().os.as_str() {
"emscripten" | "wasi" => wasm32::compute_abi_info(cx, self),
diff --git a/compiler/rustc_target/src/abi/call/xtensa.rs b/compiler/rustc_target/src/abi/call/xtensa.rs
new file mode 100644
index 00000000000..422745d0a9e
--- /dev/null
+++ b/compiler/rustc_target/src/abi/call/xtensa.rs
@@ -0,0 +1,110 @@
+// reference: https://github.com/MabezDev/llvm-project/blob/xtensa_release_9.0.1_with_rust_patches-31-05-2020-cherry-pick/clang/lib/CodeGen/TargetInfo.cpp#L9668-L9767
+
+use crate::abi::call::{ArgAbi, FnAbi, Reg, Uniform};
+use crate::abi::{HasDataLayout, LayoutOf, TyAndLayout, TyAndLayoutMethods,Abi, Size};
+use crate::spec::HasTargetSpec;
+
+const NUM_ARG_GPRS: u64 = 6;
+const MAX_ARG_IN_REGS_SIZE: u64 = 4 * 32;
+const MAX_RET_IN_REGS_SIZE: u64 = 2 * 32;
+
+fn classify_ret_ty<Ty>(arg: &mut ArgAbi<'_, Ty>, xlen: u64) {
+ if arg.is_ignore() {
+ return;
+ }
+
+ // The rules for return and argument types are the same,
+ // so defer to `classify_arg_ty`.
+ let mut arg_gprs_left = 2;
+ let fixed = true;
+ classify_arg_ty(arg, xlen, fixed, &mut arg_gprs_left);
+}
+
+fn classify_arg_ty<Ty>(arg: &mut ArgAbi<'_, Ty>, xlen: u64, fixed: bool, arg_gprs_left: &mut u64) {
+ assert!(*arg_gprs_left <= NUM_ARG_GPRS, "Arg GPR tracking underflow");
+
+ // Ignore empty structs/unions.
+ if arg.layout.is_zst() {
+ return;
+ }
+
+ let size = arg.layout.size.bits();
+ let needed_align = arg.layout.align.abi.bits();
+ let mut must_use_stack = false;
+
+ // Determine the number of GPRs needed to pass the current argument
+ // according to the ABI. 2*XLen-aligned varargs are passed in "aligned"
+ // register pairs, so may consume 3 registers.
+ let mut needed_arg_gprs = 1u64;
+
+ if !fixed && needed_align == 2 * xlen {
+ needed_arg_gprs = 2 + (*arg_gprs_left % 2);
+ } else if size > xlen && size <= MAX_ARG_IN_REGS_SIZE {
+ needed_arg_gprs = (size + xlen - 1) / xlen;
+ }
+
+ if needed_arg_gprs > *arg_gprs_left {
+ must_use_stack = true;
+ needed_arg_gprs = *arg_gprs_left;
+ }
+ *arg_gprs_left -= needed_arg_gprs;
+
+ if !arg.layout.is_aggregate() && !matches!(arg.layout.abi, Abi::Vector { .. }) {
+ // All integral types are promoted to `xlen`
+ // width, unless passed on the stack.
+ if size < xlen && !must_use_stack {
+ arg.extend_integer_width_to(xlen);
+ return;
+ }
+
+ return;
+ }
+
+ // Aggregates which are <= 4 * 32 will be passed in
+ // registers if possible, so coerce to integers.
+ if size as u64 <= MAX_ARG_IN_REGS_SIZE {
+ let alignment = arg.layout.align.abi.bits();
+
+ // Use a single `xlen` int if possible, 2 * `xlen` if 2 * `xlen` alignment
+ // is required, and a 2-element `xlen` array if only `xlen` alignment is
+ // required.
+ if size <= xlen {
+ arg.cast_to(Reg::i32());
+ return;
+ } else if alignment == 2 * xlen {
+ arg.cast_to(Reg::i64());
+ return;
+ } else {
+ let total = Size::from_bits(((size + xlen - 1) / xlen) * xlen);
+ arg.cast_to(Uniform { unit: Reg::i32(), total });
+ return;
+ }
+ }
+
+ arg.make_indirect();
+}
+
+pub fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>)
+where
+ Ty: TyAndLayoutMethods<'a, C> + Copy,
+ C: LayoutOf<Ty = Ty, TyAndLayout = TyAndLayout<'a, Ty>> + HasDataLayout + HasTargetSpec,
+{
+ let xlen = cx.data_layout().pointer_size.bits();
+
+ if !fn_abi.ret.is_ignore() {
+ classify_ret_ty(&mut fn_abi.ret, xlen);
+ }
+
+ let is_ret_indirect =
+ fn_abi.ret.is_indirect() || fn_abi.ret.layout.size.bits() > MAX_RET_IN_REGS_SIZE;
+
+ let mut arg_gprs_left = if is_ret_indirect { NUM_ARG_GPRS - 1 } else { NUM_ARG_GPRS };
+
+ for arg in &mut fn_abi.args {
+ if arg.is_ignore() {
+ continue;
+ }
+ let fixed = true;
+ classify_arg_ty(arg, xlen, fixed, &mut arg_gprs_left);
+ }
+}
\ No newline at end of file
--
2.26.3