Skip to content

Commit b6ce72d

Browse files
committed
Merge branch 'xtensa-target-master' into xtensa-target
2 parents 209b2be + af8f75a commit b6ce72d

File tree

11 files changed

+278
-3
lines changed

11 files changed

+278
-3
lines changed

README.md

+9-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,12 @@
1-
# The Rust Programming Language
1+
# The Rust Programming Language For Xtensa processors
2+
3+
This fork enables projects to be built for the ESP32 and ESP8266 using [espressif's llvm fork](https://github.com/espressif/llvm-xtensa). The [esp-rs](https://github.com/esp-rs) organization has been formed to develop runtime, pac and hal crates for the esp32 and eventually esp8266.
4+
5+
Join in on the discussion: https://matrix.to/#/#esp-rs:matrix.org!
6+
7+
## Using this fork
8+
9+
The [quickstart repo](https://github.com/MabezDev/xtensa-rust-quickstart) has more information on how to build this fork and use it to build xtensa compatible code.
210

311
This is the main source code repository for [Rust]. It contains the compiler,
412
standard library, and documentation.

src/bootstrap/config.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -544,7 +544,7 @@ impl Config {
544544
set(&mut config.llvm_static_stdcpp, llvm.static_libstdcpp);
545545
set(&mut config.llvm_link_shared, llvm.link_shared);
546546
config.llvm_targets = llvm.targets.clone();
547-
config.llvm_experimental_targets = llvm.experimental_targets.clone();
547+
config.llvm_experimental_targets = Some(llvm.experimental_targets.clone().unwrap_or("Xtensa".to_string()));
548548
config.llvm_link_jobs = llvm.link_jobs;
549549
config.llvm_version_suffix = llvm.version_suffix.clone();
550550
config.llvm_clang_cl = llvm.clang_cl.clone();

src/librustc_llvm/build.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ fn main() {
7777
"sparc",
7878
"nvptx",
7979
"hexagon",
80+
"xtensa",
8081
];
8182

8283
let mut version_cmd = Command::new(&llvm_config);
@@ -250,7 +251,11 @@ fn main() {
250251
let llvm_use_libcxx = env::var_os("LLVM_USE_LIBCXX");
251252

252253
let stdcppname = if target.contains("openbsd") {
253-
if target.contains("sparc64") { "estdc++" } else { "c++" }
254+
if target.contains("sparc64") {
255+
"estdc++"
256+
} else {
257+
"c++"
258+
}
254259
} else if target.contains("freebsd") {
255260
"c++"
256261
} else if target.contains("darwin") {

src/librustc_llvm/lib.rs

+8
Original file line numberDiff line numberDiff line change
@@ -155,4 +155,12 @@ pub fn initialize_available_targets() {
155155
LLVMInitializeWebAssemblyTargetMC,
156156
LLVMInitializeWebAssemblyAsmPrinter
157157
);
158+
init_target!(
159+
llvm_component = "xtensa",
160+
LLVMInitializeXtensaTargetInfo,
161+
LLVMInitializeXtensaTarget,
162+
LLVMInitializeXtensaTargetMC,
163+
LLVMInitializeXtensaAsmPrinter,
164+
LLVMInitializeXtensaAsmParser
165+
);
158166
}

src/librustc_target/abi/call/mod.rs

+2
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

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

src/librustc_target/spec/mod.rs

+2
Original file line numberDiff line numberDiff line change
@@ -478,6 +478,8 @@ supported_targets! {
478478
("armv7a-none-eabihf", armv7a_none_eabihf),
479479

480480
("msp430-none-elf", msp430_none_elf),
481+
("xtensa-esp32-none-elf", xtensa_esp32_none_elf),
482+
("xtensa-esp8266-none-elf", xtensa_esp8266_none_elf),
481483

482484
("aarch64-unknown-cloudabi", aarch64_unknown_cloudabi),
483485
("armv7-unknown-cloudabi-eabihf", armv7_unknown_cloudabi_eabihf),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
use crate::spec::{abi::Abi, LinkerFlavor, PanicStrategy, Target, TargetOptions, TargetResult};
2+
3+
pub fn target() -> TargetResult {
4+
Ok(Target {
5+
llvm_target: "xtensa-none-elf".to_string(),
6+
target_endian: "little".to_string(),
7+
target_pointer_width: "32".to_string(),
8+
target_c_int_width: "32".to_string(),
9+
data_layout: "e-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-n32".to_string(),
10+
arch: "xtensa".to_string(),
11+
target_os: "none".to_string(),
12+
target_env: String::new(),
13+
target_vendor: String::new(),
14+
linker_flavor: LinkerFlavor::Gcc,
15+
16+
options: TargetOptions {
17+
executables: true,
18+
cpu: "esp32".to_string(),
19+
linker: Some("xtensa-esp32-elf-gcc".to_string()),
20+
21+
max_atomic_width: Some(32),
22+
23+
// Because these devices have very little resources having an
24+
// unwinder is too onerous so we default to "abort" because the
25+
// "unwind" strategy is very rare.
26+
panic_strategy: PanicStrategy::Abort,
27+
28+
// Similarly, one almost always never wants to use relocatable
29+
// code because of the extra costs it involves.
30+
relocation_model: "static".to_string(),
31+
32+
// See the thumb_base.rs file for an explanation of this value
33+
emit_debug_gdb_scripts: false,
34+
35+
abi_blacklist: vec![
36+
Abi::Stdcall,
37+
Abi::Fastcall,
38+
Abi::Vectorcall,
39+
Abi::Thiscall,
40+
Abi::Win64,
41+
Abi::SysV64,
42+
],
43+
44+
..Default::default()
45+
},
46+
})
47+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
use crate::spec::{abi::Abi, LinkerFlavor, PanicStrategy, Target, TargetOptions, TargetResult};
2+
3+
pub fn target() -> TargetResult {
4+
Ok(Target {
5+
llvm_target: "xtensa-none-elf".to_string(),
6+
target_endian: "little".to_string(),
7+
target_pointer_width: "32".to_string(),
8+
target_c_int_width: "32".to_string(),
9+
data_layout: "e-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-n32".to_string(),
10+
arch: "xtensa".to_string(),
11+
target_os: "none".to_string(),
12+
target_env: String::new(),
13+
target_vendor: String::new(),
14+
linker_flavor: LinkerFlavor::Gcc,
15+
16+
options: TargetOptions {
17+
cpu: "esp8266".to_string(),
18+
linker: Some("xtensa-esp32-elf-ld".to_string()),
19+
20+
max_atomic_width: Some(32),
21+
22+
// Because these devices have very little resources having an
23+
// unwinder is too onerous so we default to "abort" because the
24+
// "unwind" strategy is very rare.
25+
panic_strategy: PanicStrategy::Abort,
26+
27+
// Similarly, one almost always never wants to use relocatable
28+
// code because of the extra costs it involves.
29+
relocation_model: "static".to_string(),
30+
31+
// See the thumb_base.rs file for an explanation of this value
32+
emit_debug_gdb_scripts: false,
33+
34+
abi_blacklist: vec![
35+
Abi::Stdcall,
36+
Abi::Fastcall,
37+
Abi::Vectorcall,
38+
Abi::Thiscall,
39+
Abi::Win64,
40+
Abi::SysV64,
41+
],
42+
43+
..Default::default()
44+
},
45+
})
46+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
use crate::spec::{abi::Abi, LinkerFlavor, PanicStrategy, Target, TargetOptions, TargetResult};
2+
3+
pub fn target() -> TargetResult {
4+
Ok(Target {
5+
llvm_target: "xtensa-none-elf".to_string(),
6+
target_endian: "little".to_string(),
7+
target_pointer_width: "32".to_string(),
8+
target_c_int_width: "32".to_string(),
9+
data_layout: "e-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-n32".to_string(),
10+
arch: "xtensa".to_string(),
11+
target_os: "none".to_string(),
12+
target_env: String::new(),
13+
target_vendor: String::new(),
14+
linker_flavor: LinkerFlavor::Gcc,
15+
16+
options: TargetOptions {
17+
executables: true,
18+
linker: Some("xtensa-esp32-elf-gcc".to_string()),
19+
20+
max_atomic_width: Some(32),
21+
22+
// Because these devices have very little resources having an
23+
// unwinder is too onerous so we default to "abort" because the
24+
// "unwind" strategy is very rare.
25+
panic_strategy: PanicStrategy::Abort,
26+
27+
// Similarly, one almost always never wants to use relocatable
28+
// code because of the extra costs it involves.
29+
relocation_model: "static".to_string(),
30+
31+
// See the thumb_base.rs file for an explanation of this value
32+
emit_debug_gdb_scripts: false,
33+
34+
abi_blacklist: vec![
35+
Abi::Stdcall,
36+
Abi::Fastcall,
37+
Abi::Vectorcall,
38+
Abi::Thiscall,
39+
Abi::Win64,
40+
Abi::SysV64,
41+
],
42+
43+
..Default::default()
44+
},
45+
})
46+
}

src/rustllvm/PassWrapper.cpp

+9
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,14 @@ void LLVMRustAddLastExtensionPasses(
251251
#define SUBTARGET_HEXAGON
252252
#endif
253253

254+
#ifdef LLVM_COMPONENT_XTENSA
255+
#define SUBTARGET_XTENSA SUBTARGET(XTENSA)
256+
#else
257+
#define SUBTARGET_XTENSA
258+
#endif
259+
260+
261+
254262
#define GEN_SUBTARGETS \
255263
SUBTARGET_X86 \
256264
SUBTARGET_ARM \
@@ -262,6 +270,7 @@ void LLVMRustAddLastExtensionPasses(
262270
SUBTARGET_SPARC \
263271
SUBTARGET_HEXAGON \
264272
SUBTARGET_RISCV \
273+
SUBTARGET_XTENSA \
265274

266275
#define SUBTARGET(x) \
267276
namespace llvm { \

0 commit comments

Comments
 (0)