diff --git a/.gitmodules b/.gitmodules
index 8617643a12029..038fbc8ea7447 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -24,8 +24,8 @@
shallow = true
[submodule "src/llvm-project"]
path = src/llvm-project
- url = https://github.com/rust-lang/llvm-project.git
- branch = rustc/21.1-2025-08-01
+ url = https://github.com/espressif/llvm-project
+ branch = release/esp_21.x
shallow = true
[submodule "src/doc/embedded-book"]
path = src/doc/embedded-book
diff --git a/README.md b/README.md
index 611260470f12b..da3a135a46778 100644
--- a/README.md
+++ b/README.md
@@ -1,56 +1,24 @@
-
-
-
-
-
-
+# The Rust Programming Language for Espressif chips
-[Website][Rust] | [Getting started] | [Learn] | [Documentation] | [Contributing]
-
+This fork enables projects to be built for the Xtensa-based ESP32, ESP32-SXX and ESP8266 using [Espressif's llvm fork](https://github.com/espressif/llvm-project). (RiscV chips like ESP32-CXX are already supported in stock Rust.)
-This is the main source code repository for [Rust]. It contains the compiler,
-standard library, and documentation.
+Moreover, this fork enables Rust STD support (networking, threads, and filesystem) for all chips in the ESP32 family (Xtensa and RiscV), by optionally linking with the ESP-IDF framework.
-[Rust]: https://www.rust-lang.org/
-[Getting Started]: https://www.rust-lang.org/learn/get-started
-[Learn]: https://www.rust-lang.org/learn
-[Documentation]: https://www.rust-lang.org/learn#learn-use
-[Contributing]: CONTRIBUTING.md
+The [esp-rs](https://github.com/esp-rs) organization has been formed to develop runtime, pac and hal crates for the Espressif chips (bare-metal as well as ESP-IDF based).
-## Why Rust?
+Join in on the discussion: https://matrix.to/#/#esp-rs:matrix.org!
-- **Performance:** Fast and memory-efficient, suitable for critical services, embedded devices, and easily integrated with other languages.
+## Installation
-- **Reliability:** Our rich type system and ownership model ensure memory and thread safety, reducing bugs at compile-time.
+Please see the most up to date instructions in the [esp rust book](https://esp-rs.github.io/book/).
-- **Productivity:** Comprehensive documentation, a compiler committed to providing great diagnostics, and advanced tooling including package manager and build tool ([Cargo]), auto-formatter ([rustfmt]), linter ([Clippy]) and editor support ([rust-analyzer]).
+## Building from source
-[Cargo]: https://github.com/rust-lang/cargo
-[rustfmt]: https://github.com/rust-lang/rustfmt
-[Clippy]: https://github.com/rust-lang/rust-clippy
-[rust-analyzer]: https://github.com/rust-lang/rust-analyzer
+If you wish to build this fork from source, the instructions are almost identical to the ones upstream ([follow here](https://github.com/rust-lang/rust#installing-from-source)), however before beginning the build, run the following `./configure` command:
-## Quick Start
-
-Read ["Installation"] from [The Book].
-
-["Installation"]: https://doc.rust-lang.org/book/ch01-01-installation.html
-[The Book]: https://doc.rust-lang.org/book/index.html
-
-## Installing from Source
-
-If you really want to install from source (though this is not recommended), see
-[INSTALL.md](INSTALL.md).
-
-## Getting Help
-
-See https://www.rust-lang.org/community for a list of chat platforms and forums.
-
-## Contributing
-
-See [CONTRIBUTING.md](CONTRIBUTING.md).
+```
+./configure --experimental-targets=Xtensa --release-channel=nightly --enable-extended --tools=clippy,cargo,rustfmt --enable-lld
+```
## License
diff --git a/compiler/rustc_codegen_gcc/src/asm.rs b/compiler/rustc_codegen_gcc/src/asm.rs
index ceb3dd3ffedfc..90e3fd7b03eee 100644
--- a/compiler/rustc_codegen_gcc/src/asm.rs
+++ b/compiler/rustc_codegen_gcc/src/asm.rs
@@ -740,6 +740,9 @@ fn reg_class_to_gcc(reg_class: InlineAsmRegClass) -> &'static str {
| X86InlineAsmRegClass::mmx_reg
| X86InlineAsmRegClass::tmm_reg,
) => unreachable!("clobber-only"),
+ InlineAsmRegClass::Xtensa(XtensaInlineAsmRegClass::reg) => "r",
+ InlineAsmRegClass::Xtensa(XtensaInlineAsmRegClass::freg) => "f",
+ InlineAsmRegClass::Xtensa(XtensaInlineAsmRegClass::qreg) => "p",
InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => {
bug!("GCC backend does not support SPIR-V")
}
@@ -851,6 +854,9 @@ fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegCl
InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => {
bug!("GCC backend does not support SPIR-V")
}
+ InlineAsmRegClass::Xtensa(XtensaInlineAsmRegClass::reg) => cx.type_i32(),
+ InlineAsmRegClass::Xtensa(XtensaInlineAsmRegClass::freg) => cx.type_f32(),
+ InlineAsmRegClass::Xtensa(XtensaInlineAsmRegClass::qreg) => cx.type_vector(cx.type_i8(), 16),
InlineAsmRegClass::Err => unreachable!(),
}
}
@@ -1042,6 +1048,7 @@ fn modifier_to_gcc(
InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => {
bug!("LLVM backend does not support SPIR-V")
}
+ InlineAsmRegClass::Xtensa(_) => None,
InlineAsmRegClass::Err => unreachable!(),
}
}
diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs
index ee1b6d45e149d..1a50a83bf131d 100644
--- a/compiler/rustc_codegen_llvm/src/asm.rs
+++ b/compiler/rustc_codegen_llvm/src/asm.rs
@@ -278,6 +278,7 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
}
InlineAsmArch::SpirV => {}
InlineAsmArch::Wasm32 | InlineAsmArch::Wasm64 => {}
+ InlineAsmArch::Xtensa => {}
InlineAsmArch::Bpf => {}
InlineAsmArch::Msp430 => {
constraints.push("~{sr}".to_string());
@@ -683,6 +684,9 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'_>>) ->
| X86InlineAsmRegClass::kreg0
| X86InlineAsmRegClass::tmm_reg,
) => unreachable!("clobber-only"),
+ Xtensa(XtensaInlineAsmRegClass::qreg) => "p",
+ Xtensa(XtensaInlineAsmRegClass::freg) => "f",
+ Xtensa(XtensaInlineAsmRegClass::reg) => "r",
Wasm(WasmInlineAsmRegClass::local) => "r",
Bpf(BpfInlineAsmRegClass::reg) => "r",
Bpf(BpfInlineAsmRegClass::wreg) => "w",
@@ -788,6 +792,7 @@ fn modifier_to_llvm(
| X86InlineAsmRegClass::kreg0
| X86InlineAsmRegClass::tmm_reg,
) => unreachable!("clobber-only"),
+ Xtensa(_) => None,
Wasm(WasmInlineAsmRegClass::local) => None,
Bpf(_) => None,
Avr(AvrInlineAsmRegClass::reg_pair)
@@ -864,6 +869,9 @@ fn dummy_output_type<'ll>(cx: &CodegenCx<'ll, '_>, reg: InlineAsmRegClass) -> &'
| X86InlineAsmRegClass::kreg0
| X86InlineAsmRegClass::tmm_reg,
) => unreachable!("clobber-only"),
+ Xtensa(XtensaInlineAsmRegClass::reg) => cx.type_i32(),
+ Xtensa(XtensaInlineAsmRegClass::freg) => cx.type_f32(),
+ Xtensa(XtensaInlineAsmRegClass::qreg) => cx.type_vector(cx.type_i8(), 16),
Wasm(WasmInlineAsmRegClass::local) => cx.type_i32(),
Bpf(BpfInlineAsmRegClass::reg) => cx.type_i64(),
Bpf(BpfInlineAsmRegClass::wreg) => cx.type_i32(),
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 7e513160de0c3..09d054d7d70dd 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -993,6 +993,7 @@ symbols! {
external,
external_doc,
f,
+ fp,
f16,
f16_consts_mod,
f16_epsilon,
@@ -1480,6 +1481,7 @@ symbols! {
mir_unwind_unreachable,
mir_variant,
miri,
+ misc,
mmx_reg,
modifiers,
module,
@@ -1736,6 +1738,7 @@ symbols! {
prelude_import,
preserves_flags,
prfchw_target_feature,
+ primitive,
print_macro,
println_macro,
proc_dash_macro: "proc-macro",
@@ -2256,6 +2259,7 @@ symbols! {
three_way_compare,
thumb2,
thumb_mode: "thumb-mode",
+ time,
tmm_reg,
to_owned_method,
to_string,
@@ -2499,9 +2503,11 @@ symbols! {
x87_reg,
x87_target_feature,
xer,
+ xloop,
xmm_reg,
xop_target_feature,
xtensa,
+ xtensa_target_feature,
yeet_desugar_details,
yeet_expr,
yes,
diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs
index c6d22a51774c6..bf8fc1f159050 100644
--- a/compiler/rustc_target/src/asm/mod.rs
+++ b/compiler/rustc_target/src/asm/mod.rs
@@ -194,6 +194,7 @@ mod sparc;
mod spirv;
mod wasm;
mod x86;
+mod xtensa;
pub use aarch64::{AArch64InlineAsmReg, AArch64InlineAsmRegClass};
pub use arm::{ArmInlineAsmReg, ArmInlineAsmRegClass};
@@ -213,6 +214,7 @@ pub use sparc::{SparcInlineAsmReg, SparcInlineAsmRegClass};
pub use spirv::{SpirVInlineAsmReg, SpirVInlineAsmRegClass};
pub use wasm::{WasmInlineAsmReg, WasmInlineAsmRegClass};
pub use x86::{X86InlineAsmReg, X86InlineAsmRegClass};
+pub use xtensa::{XtensaInlineAsmReg, XtensaInlineAsmRegClass};
#[derive(Copy, Clone, Encodable, Decodable, Debug, Eq, PartialEq, Hash)]
pub enum InlineAsmArch {
@@ -237,6 +239,7 @@ pub enum InlineAsmArch {
SpirV,
Wasm32,
Wasm64,
+ Xtensa,
Bpf,
Avr,
Msp430,
@@ -273,7 +276,8 @@ impl InlineAsmArch {
Arch::Msp430 => Some(Self::Msp430),
Arch::M68k => Some(Self::M68k),
Arch::CSky => Some(Self::CSKY),
- Arch::AmdGpu | Arch::Xtensa | Arch::Other(_) => None,
+ Arch::Xtensa => Some(Self::Xtensa),
+ Arch::AmdGpu | Arch::Other(_) => None,
}
}
}
@@ -294,6 +298,7 @@ pub enum InlineAsmReg {
Sparc(SparcInlineAsmReg),
SpirV(SpirVInlineAsmReg),
Wasm(WasmInlineAsmReg),
+ Xtensa(XtensaInlineAsmReg),
Bpf(BpfInlineAsmReg),
Avr(AvrInlineAsmReg),
Msp430(Msp430InlineAsmReg),
@@ -316,6 +321,7 @@ impl InlineAsmReg {
Self::Mips(r) => r.name(),
Self::S390x(r) => r.name(),
Self::Sparc(r) => r.name(),
+ Self::Xtensa(r) => r.name(),
Self::Bpf(r) => r.name(),
Self::Avr(r) => r.name(),
Self::Msp430(r) => r.name(),
@@ -337,6 +343,7 @@ impl InlineAsmReg {
Self::Mips(r) => InlineAsmRegClass::Mips(r.reg_class()),
Self::S390x(r) => InlineAsmRegClass::S390x(r.reg_class()),
Self::Sparc(r) => InlineAsmRegClass::Sparc(r.reg_class()),
+ Self::Xtensa(r) => InlineAsmRegClass::Xtensa(r.reg_class()),
Self::Bpf(r) => InlineAsmRegClass::Bpf(r.reg_class()),
Self::Avr(r) => InlineAsmRegClass::Avr(r.reg_class()),
Self::Msp430(r) => InlineAsmRegClass::Msp430(r.reg_class()),
@@ -370,6 +377,7 @@ impl InlineAsmReg {
InlineAsmArch::Mips | InlineAsmArch::Mips64 => {
Self::Mips(MipsInlineAsmReg::parse(name)?)
}
+ InlineAsmArch::Xtensa => Self::Xtensa(XtensaInlineAsmReg::parse(name)?),
InlineAsmArch::S390x => Self::S390x(S390xInlineAsmReg::parse(name)?),
InlineAsmArch::Sparc | InlineAsmArch::Sparc64 => {
Self::Sparc(SparcInlineAsmReg::parse(name)?)
@@ -409,6 +417,7 @@ impl InlineAsmReg {
Self::Sparc(r) => r.validate(arch, reloc_model, target_features, target, is_clobber),
Self::Bpf(r) => r.validate(arch, reloc_model, target_features, target, is_clobber),
Self::Avr(r) => r.validate(arch, reloc_model, target_features, target, is_clobber),
+ Self::Xtensa(r) => r.validate(arch, reloc_model, target_features, target, is_clobber),
Self::Msp430(r) => r.validate(arch, reloc_model, target_features, target, is_clobber),
Self::M68k(r) => r.validate(arch, reloc_model, target_features, target, is_clobber),
Self::CSKY(r) => r.validate(arch, reloc_model, target_features, target, is_clobber),
@@ -435,6 +444,7 @@ impl InlineAsmReg {
Self::Mips(r) => r.emit(out, arch, modifier),
Self::S390x(r) => r.emit(out, arch, modifier),
Self::Sparc(r) => r.emit(out, arch, modifier),
+ Self::Xtensa(r) => r.emit(out, arch, modifier),
Self::Bpf(r) => r.emit(out, arch, modifier),
Self::Avr(r) => r.emit(out, arch, modifier),
Self::Msp430(r) => r.emit(out, arch, modifier),
@@ -456,6 +466,7 @@ impl InlineAsmReg {
Self::Mips(_) => cb(self),
Self::S390x(r) => r.overlapping_regs(|r| cb(Self::S390x(r))),
Self::Sparc(_) => cb(self),
+ Self::Xtensa(_) => cb(self),
Self::Bpf(r) => r.overlapping_regs(|r| cb(Self::Bpf(r))),
Self::Avr(r) => r.overlapping_regs(|r| cb(Self::Avr(r))),
Self::Msp430(_) => cb(self),
@@ -482,6 +493,7 @@ pub enum InlineAsmRegClass {
Sparc(SparcInlineAsmRegClass),
SpirV(SpirVInlineAsmRegClass),
Wasm(WasmInlineAsmRegClass),
+ Xtensa(XtensaInlineAsmRegClass),
Bpf(BpfInlineAsmRegClass),
Avr(AvrInlineAsmRegClass),
Msp430(Msp430InlineAsmRegClass),
@@ -507,6 +519,7 @@ impl InlineAsmRegClass {
Self::Sparc(r) => r.name(),
Self::SpirV(r) => r.name(),
Self::Wasm(r) => r.name(),
+ Self::Xtensa(r) => r.name(),
Self::Bpf(r) => r.name(),
Self::Avr(r) => r.name(),
Self::Msp430(r) => r.name(),
@@ -534,6 +547,7 @@ impl InlineAsmRegClass {
Self::Sparc(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Sparc),
Self::SpirV(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::SpirV),
Self::Wasm(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Wasm),
+ Self::Xtensa(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Xtensa),
Self::Bpf(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Bpf),
Self::Avr(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Avr),
Self::Msp430(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Msp430),
@@ -564,6 +578,7 @@ impl InlineAsmRegClass {
Self::Sparc(r) => r.suggest_modifier(arch, ty),
Self::SpirV(r) => r.suggest_modifier(arch, ty),
Self::Wasm(r) => r.suggest_modifier(arch, ty),
+ Self::Xtensa(r) => r.suggest_modifier(arch, ty),
Self::Bpf(r) => r.suggest_modifier(arch, ty),
Self::Avr(r) => r.suggest_modifier(arch, ty),
Self::Msp430(r) => r.suggest_modifier(arch, ty),
@@ -594,6 +609,7 @@ impl InlineAsmRegClass {
Self::Sparc(r) => r.default_modifier(arch),
Self::SpirV(r) => r.default_modifier(arch),
Self::Wasm(r) => r.default_modifier(arch),
+ Self::Xtensa(r) => r.default_modifier(arch),
Self::Bpf(r) => r.default_modifier(arch),
Self::Avr(r) => r.default_modifier(arch),
Self::Msp430(r) => r.default_modifier(arch),
@@ -627,6 +643,7 @@ impl InlineAsmRegClass {
Self::Sparc(r) => r.supported_types(arch),
Self::SpirV(r) => r.supported_types(arch),
Self::Wasm(r) => r.supported_types(arch),
+ Self::Xtensa(r) => r.supported_types(arch),
Self::Bpf(r) => r.supported_types(arch),
Self::Avr(r) => r.supported_types(arch),
Self::Msp430(r) => r.supported_types(arch),
@@ -669,6 +686,7 @@ impl InlineAsmRegClass {
}
InlineAsmArch::Bpf => Self::Bpf(BpfInlineAsmRegClass::parse(name)?),
InlineAsmArch::Avr => Self::Avr(AvrInlineAsmRegClass::parse(name)?),
+ InlineAsmArch::Xtensa => Self::Xtensa(XtensaInlineAsmRegClass::parse(name)?),
InlineAsmArch::Msp430 => Self::Msp430(Msp430InlineAsmRegClass::parse(name)?),
InlineAsmArch::M68k => Self::M68k(M68kInlineAsmRegClass::parse(name)?),
InlineAsmArch::CSKY => Self::CSKY(CSKYInlineAsmRegClass::parse(name)?),
@@ -692,6 +710,7 @@ impl InlineAsmRegClass {
Self::Sparc(r) => r.valid_modifiers(arch),
Self::SpirV(r) => r.valid_modifiers(arch),
Self::Wasm(r) => r.valid_modifiers(arch),
+ Self::Xtensa(r) => r.valid_modifiers(arch),
Self::Bpf(r) => r.valid_modifiers(arch),
Self::Avr(r) => r.valid_modifiers(arch),
Self::Msp430(r) => r.valid_modifiers(arch),
@@ -893,6 +912,11 @@ pub fn allocatable_registers(
wasm::fill_reg_map(arch, reloc_model, target_features, target, &mut map);
map
}
+ InlineAsmArch::Xtensa => {
+ let mut map = xtensa::regclass_map();
+ xtensa::fill_reg_map(arch, reloc_model, target_features, target, &mut map);
+ map
+ }
InlineAsmArch::Bpf => {
let mut map = bpf::regclass_map();
bpf::fill_reg_map(arch, reloc_model, target_features, target, &mut map);
diff --git a/compiler/rustc_target/src/asm/xtensa.rs b/compiler/rustc_target/src/asm/xtensa.rs
new file mode 100644
index 0000000000000..1e34bd522ad58
--- /dev/null
+++ b/compiler/rustc_target/src/asm/xtensa.rs
@@ -0,0 +1,150 @@
+use std::fmt;
+
+use rustc_data_structures::fx::FxIndexSet;
+use rustc_span::{Symbol, sym};
+
+use super::{InlineAsmArch, InlineAsmType, ModifierInfo};
+use crate::spec::{FramePointer, RelocModel, Target};
+
+def_reg_class! {
+ Xtensa XtensaInlineAsmRegClass {
+ reg,
+ freg,
+ qreg,
+ }
+}
+
+impl XtensaInlineAsmRegClass {
+ pub fn valid_modifiers(self, _arch: super::InlineAsmArch) -> &'static [char] {
+ &[]
+ }
+
+ pub fn suggest_class(self, _arch: InlineAsmArch, _ty: InlineAsmType) -> Option {
+ None
+ }
+
+ pub fn suggest_modifier(
+ self,
+ _arch: InlineAsmArch,
+ _ty: InlineAsmType,
+ ) -> Option {
+ None
+ }
+
+ pub fn default_modifier(self, _arch: InlineAsmArch) -> Option {
+ None
+ }
+
+ pub fn supported_types(
+ self,
+ _arch: InlineAsmArch,
+ ) -> &'static [(InlineAsmType, Option)] {
+ match self {
+ Self::reg => types! { _: I8, I16, I32; },
+ Self::freg => types! { fp: F32; },
+ Self::qreg => types! { _: VecI8(16), VecI16(8), VecI32(4); },
+ }
+ }
+}
+
+fn has_qr(
+ _arch: InlineAsmArch,
+ _reloc_model: RelocModel,
+ _target_features: &FxIndexSet,
+ target: &Target,
+ _is_clobber: bool,
+) -> Result<(), &'static str> {
+ match target.cpu.as_ref() {
+ "esp32-s3" => Ok(()),
+ _ => Err("target does not support 128-bit vector QR registers")
+ }
+}
+
+fn has_fp(
+ _arch: InlineAsmArch,
+ _reloc_model: RelocModel,
+ target_features: &FxIndexSet,
+ _target: &Target,
+ _is_clobber: bool,
+) -> Result<(), &'static str> {
+ if target_features.contains(&sym::fp) {
+ Ok(())
+ } else {
+ Err("target does not support floating point registers")
+ }
+}
+
+fn is_frame_pointer(
+ _arch: InlineAsmArch,
+ _reloc_model: RelocModel,
+ _target_features: &FxIndexSet,
+ target: &Target,
+ _is_clobber: bool,
+) -> Result<(), &'static str> {
+ // The Xtensa arch doesn't require, nor use, a dedicated frame pointer register
+ // therefore if it is not force enabled, we can assume it won't be generated.
+ // If frame pointers are enabled, we cannot use the register as a general purpose one.
+ if target.options.frame_pointer != FramePointer::MayOmit {
+ Err("frame pointer register cannot be used when frame pointers are enabled")
+ } else {
+ Ok(())
+ }
+}
+
+def_regs! {
+ Xtensa XtensaInlineAsmReg XtensaInlineAsmRegClass {
+ a2: reg = ["a2"],
+ a3: reg = ["a3"],
+ a4: reg = ["a4"],
+ a5: reg = ["a5"],
+ a6: reg = ["a6"],
+ a7: reg = ["a7"],
+ a8: reg = ["a8"],
+ a9: reg = ["a9"],
+ a10: reg = ["a10"],
+ a11: reg = ["a11"],
+ a12: reg = ["a12"],
+ a13: reg = ["a13"],
+ a14: reg = ["a14"],
+ a15: reg = ["a15"] % is_frame_pointer,
+ sar: reg = ["sar"],
+ f0: freg = ["f0"] % has_fp,
+ f1: freg = ["f1"] % has_fp,
+ f2: freg = ["f2"] % has_fp,
+ f3: freg = ["f3"] % has_fp,
+ f4: freg = ["f4"] % has_fp,
+ f5: freg = ["f5"] % has_fp,
+ f6: freg = ["f6"] % has_fp,
+ f7: freg = ["f7"] % has_fp,
+ f8: freg = ["f8"] % has_fp,
+ f9: freg = ["f9"] % has_fp,
+ f10: freg = ["f10"] % has_fp,
+ f11: freg = ["f11"] % has_fp,
+ f12: freg = ["f12"] % has_fp,
+ f13: freg = ["f13"] % has_fp,
+ f14: freg = ["f14"] % has_fp,
+ f15: freg = ["f15"] % has_fp,
+ q0: qreg = ["q0"] % has_qr,
+ q1: qreg = ["q1"] % has_qr,
+ q2: qreg = ["q2"] % has_qr,
+ q3: qreg = ["q3"] % has_qr,
+ q4: qreg = ["q4"] % has_qr,
+ q5: qreg = ["q5"] % has_qr,
+ q6: qreg = ["q6"] % has_qr,
+ q7: qreg = ["q7"] % has_qr,
+
+ #error = ["a0"] => "a0 is used internally by LLVM and cannot be used as an operand for inline asm",
+ #error = ["sp", "a1"] => "sp is used internally by LLVM and cannot be used as an operand for inline asm",
+ }
+}
+
+impl XtensaInlineAsmReg {
+ pub fn emit(
+ self,
+ out: &mut dyn fmt::Write,
+ _arch: InlineAsmArch,
+ _modifier: Option,
+ ) -> fmt::Result {
+ out.write_str(self.name())
+ }
+}
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index 424026bdceab8..9c32e4f8fd6f3 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -1720,6 +1720,7 @@ supported_targets! {
("xtensa-esp32s2-espidf", xtensa_esp32s2_espidf),
("xtensa-esp32s3-none-elf", xtensa_esp32s3_none_elf),
("xtensa-esp32s3-espidf", xtensa_esp32s3_espidf),
+ ("xtensa-esp8266-none-elf", xtensa_esp8266_none_elf),
("i686-wrs-vxworks", i686_wrs_vxworks),
("x86_64-wrs-vxworks", x86_64_wrs_vxworks),
diff --git a/compiler/rustc_target/src/spec/targets/xtensa_esp8266_none_elf.rs b/compiler/rustc_target/src/spec/targets/xtensa_esp8266_none_elf.rs
new file mode 100644
index 0000000000000..bd3cb4f58d243
--- /dev/null
+++ b/compiler/rustc_target/src/spec/targets/xtensa_esp8266_none_elf.rs
@@ -0,0 +1,24 @@
+use crate::spec::{Arch, base::xtensa, Target, TargetOptions};
+
+pub(crate) fn target() -> Target {
+ Target {
+ llvm_target: "xtensa-none-elf".into(),
+ pointer_width: 32,
+ data_layout: "e-m:e-p:32:32-v1:8:8-i64:64-i128:128-n32".into(),
+ arch: Arch::Xtensa,
+ metadata: crate::spec::TargetMetadata {
+ description: Some("Xtensa ESP8266".into()),
+ tier: Some(3),
+ host_tools: Some(false),
+ std: Some(false),
+ },
+
+ options: TargetOptions {
+ cpu: "esp8266".into(),
+ linker: Some("xtensa-lx106-elf-gcc".into()),
+ max_atomic_width: Some(32),
+ features: "+forced-atomics".into(),
+ ..xtensa::opts()
+ },
+ }
+}
\ No newline at end of file
diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs
index 990928774731c..3466ab8ab45a5 100644
--- a/compiler/rustc_target/src/target_features.rs
+++ b/compiler/rustc_target/src/target_features.rs
@@ -883,6 +883,37 @@ static M68K_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
// tidy-alphabetical-end
];
+const XTENSA_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
+ ("fp", Unstable(sym::xtensa_target_feature), &["coprocessor"]),
+ ("windowed", Unstable(sym::xtensa_target_feature), &[]),
+ ("mac16", Unstable(sym::xtensa_target_feature), &[]),
+ ("loop", Unstable(sym::xtensa_target_feature), &[]),
+ ("sext", Unstable(sym::xtensa_target_feature), &[]),
+ ("nsa", Unstable(sym::xtensa_target_feature), &[]),
+ ("mul32", Unstable(sym::xtensa_target_feature), &[]),
+ ("mul32high", Unstable(sym::xtensa_target_feature), &[]),
+ ("div32", Unstable(sym::xtensa_target_feature), &[]),
+ ("s32c1i", Unstable(sym::xtensa_target_feature), &[]),
+ ("regprotect", Unstable(sym::xtensa_target_feature), &[]),
+ ("rvector", Unstable(sym::xtensa_target_feature), &[]),
+ ("miscsr", Unstable(sym::xtensa_target_feature), &[]),
+ ("extendedl32r", Unstable(sym::xtensa_target_feature), &[]),
+ ("threadptr", Unstable(sym::xtensa_target_feature), &[]),
+ ("highpriinterrupts", Unstable(sym::xtensa_target_feature), &["interrupt"]),
+ ("interrupt", Unstable(sym::xtensa_target_feature), &[]),
+ ("exception", Unstable(sym::xtensa_target_feature), &[]),
+ ("debug", Unstable(sym::xtensa_target_feature), &[]),
+ ("prid", Unstable(sym::xtensa_target_feature), &[]),
+ ("coprocessor", Unstable(sym::xtensa_target_feature), &[]),
+
+ ("density", Unstable(sym::xtensa_target_feature), &[]),
+ ("bool", Unstable(sym::xtensa_target_feature), &[]),
+ ("clamps", Unstable(sym::xtensa_target_feature), &[]),
+ ("minmax", Unstable(sym::xtensa_target_feature), &[]),
+ ("mul16", Unstable(sym::xtensa_target_feature), &[]),
+ // ("dcache", Unstable(sym::xtensa_target_feature), &[]), not supported in LLVM yet, will be in 21.2
+];
+
/// When rustdoc is running, provide a list of all known features so that all their respective
/// primitives may be documented.
///
@@ -899,6 +930,7 @@ pub fn all_rust_features() -> impl Iterator- {
.chain(RISCV_FEATURES.iter())
.chain(WASM_FEATURES.iter())
.chain(BPF_FEATURES.iter())
+ .chain(XTENSA_FEATURES.iter())
.chain(CSKY_FEATURES)
.chain(LOONGARCH_FEATURES)
.chain(IBMZ_FEATURES)
@@ -971,12 +1003,12 @@ impl Target {
Arch::S390x => IBMZ_FEATURES,
Arch::Sparc | Arch::Sparc64 => SPARC_FEATURES,
Arch::M68k => M68K_FEATURES,
+ Arch::Xtensa => XTENSA_FEATURES,
Arch::AmdGpu
| Arch::Avr
| Arch::Msp430
| Arch::PowerPC64LE
| Arch::SpirV
- | Arch::Xtensa
| Arch::Other(_) => &[],
}
}
diff --git a/src/llvm-project b/src/llvm-project
index 85a90d119deb2..6e296b40d1d4b 160000
--- a/src/llvm-project
+++ b/src/llvm-project
@@ -1 +1 @@
-Subproject commit 85a90d119deb25b518867cd37d62c7b93b575a6f
+Subproject commit 6e296b40d1d4b754522c6c3733a17b242a25f1fa
diff --git a/tests/assembly-llvm/asm/xtensa-types.rs b/tests/assembly-llvm/asm/xtensa-types.rs
new file mode 100644
index 0000000000000..2ee2059a5575b
--- /dev/null
+++ b/tests/assembly-llvm/asm/xtensa-types.rs
@@ -0,0 +1,118 @@
+//@ add-core-stubs
+//@ assembly-output: emit-asm
+//@ compile-flags: --target xtensa-esp32-none-elf
+//@ needs-llvm-components: xtensa
+
+#![feature(no_core, lang_items, rustc_attrs, repr_simd, asm_experimental_arch)]
+#![crate_type = "rlib"]
+#![no_core]
+#![allow(asm_sub_register, non_camel_case_types)]
+
+extern crate minicore;
+use minicore::*;
+
+type ptr = *mut u8;
+
+extern "C" {
+ fn extern_func();
+}
+
+// Hack to avoid function merging
+extern "Rust" {
+ fn dont_merge(s: &str);
+}
+
+// CHECK-LABEL: sym_fn:
+// CHECK: #APP
+// CHECK: call4 extern_func
+// CHECK: #NO_APP
+#[no_mangle]
+pub unsafe fn sym_fn() {
+ asm!("call4 {}", sym extern_func);
+}
+
+macro_rules! check_general_reg {
+ ($func:ident $ty:ident $class:ident $mov:literal) => {
+ #[no_mangle]
+ pub unsafe fn $func(x: $ty) -> $ty {
+ dont_merge(stringify!($func));
+
+ let y;
+ asm!(concat!($mov, " {}, {}"), out($class) y, in($class) x);
+ y
+ }
+ };
+}
+
+// CHECK-LABEL: reg_i8:
+// CHECK: #APP
+// CHECK: or a{{[0-9]+}}, a{{[0-9]+}}, a{{[0-9]+}}
+// CHECK: #NO_APP
+check_general_reg!(reg_i8 i8 reg "mov");
+
+// CHECK-LABEL: reg_i16:
+// CHECK: #APP
+// CHECK: or a{{[0-9]+}}, a{{[0-9]+}}, a{{[0-9]+}}
+// CHECK: #NO_APP
+check_general_reg!(reg_i16 i16 reg "mov");
+
+// CHECK-LABEL: reg_i32:
+// CHECK: #APP
+// CHECK: or a{{[0-9]+}}, a{{[0-9]+}}, a{{[0-9]+}}
+// CHECK: #NO_APP
+check_general_reg!(reg_i32 i32 reg "mov");
+
+// CHECK-LABEL: reg_ptr:
+// CHECK: #APP
+// CHECK: or a{{[0-9]+}}, a{{[0-9]+}}, a{{[0-9]+}}
+// CHECK: #NO_APP
+check_general_reg!(reg_ptr ptr reg "mov");
+
+// CHECK-LABEL: freg_f32:
+// CHECK: #APP
+// CHECK: mov.s f{{[0-9]+}}, f{{[0-9]+}}
+// CHECK: #NO_APP
+check_general_reg!(freg_f32 f32 freg "mov.s");
+
+macro_rules! check_explicit_reg {
+ ($func:ident $ty:ident $reg:tt $mov:literal) => {
+ #[no_mangle]
+ pub unsafe fn $func(x: $ty) -> $ty {
+ dont_merge(stringify!($func));
+
+ let y;
+ asm!(concat!($mov, " ", $reg, ", ", $reg), lateout($reg) y, in($reg) x);
+ y
+ }
+ };
+}
+
+// CHECK-LABEL: a5_i8:
+// CHECK: #APP
+// CHECK: or a5, a5, a5
+// CHECK: #NO_APP
+check_explicit_reg!(a5_i8 i8 "a5" "mov");
+
+// CHECK-LABEL: a5_i16:
+// CHECK: #APP
+// CHECK: or a5, a5, a5
+// CHECK: #NO_APP
+check_explicit_reg!(a5_i16 i16 "a5" "mov");
+
+// CHECK-LABEL: a5_i32:
+// CHECK: #APP
+// CHECK: or a5, a5, a5
+// CHECK: #NO_APP
+check_explicit_reg!(a5_i32 i32 "a5" "mov");
+
+// CHECK-LABEL: a5_ptr:
+// CHECK: #APP
+// CHECK: or a5, a5, a5
+// CHECK: #NO_APP
+check_explicit_reg!(a5_ptr ptr "a5" "mov");
+
+// CHECK-LABEL: f0_f32:
+// CHECK: #APP
+// CHECK: mov.s f0, f0
+// CHECK: #NO_APP
+check_explicit_reg!(f0_f32 f32 "f0" "mov.s");
diff --git a/tests/ui/check-cfg/target_feature.stderr b/tests/ui/check-cfg/target_feature.stderr
index d25e7f094964e..0170d3741f02b 100644
--- a/tests/ui/check-cfg/target_feature.stderr
+++ b/tests/ui/check-cfg/target_feature.stderr
@@ -28,6 +28,7 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE");
`amx-tf32`
`amx-tile`
`apxf`
+`atomctl`
`atomics`
`avx`
`avx10.1`
@@ -63,11 +64,13 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE");
`cache`
`cmpxchg16b`
`concurrent-functions`
+`coprocessor`
`crc`
`crt-static`
`cssc`
`d`
`d32`
+`debug`
`deflate-conversion`
`dit`
`div32`
@@ -86,8 +89,10 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE");
`elrw`
`enhanced-sort`
`ermsb`
+`exception`
`exception-handling`
`extended-const`
+`extendedl32r`
`f`
`f16c`
`f32mm`
@@ -104,6 +109,7 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE");
`float7e60`
`floate1`
`fma`
+`fp`
`fp-armv8`
`fp16`
`fp64`
@@ -129,10 +135,12 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE");
`hbc`
`high-registers`
`high-word`
+`highpriinterrupts`
`hvx`
`hvx-length128b`
`hwdiv`
`i8mm`
+`interrupt`
`isa-68000`
`isa-68010`
`isa-68020`
@@ -150,6 +158,7 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE");
`lbt`
`ld-seq-sa`
`leoncasa`
+`loop`
`lor`
`lse`
`lse128`
@@ -159,7 +168,9 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE");
`lvz`
`lzcnt`
`m`
+`mac16`
`mclass`
+`memctl`
`message-security-assist-extension12`
`message-security-assist-extension3`
`message-security-assist-extension4`
@@ -169,6 +180,7 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE");
`miscellaneous-extensions-2`
`miscellaneous-extensions-3`
`miscellaneous-extensions-4`
+`miscsr`
`mops`
`movbe`
`movrs`
@@ -177,11 +189,14 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE");
`msa`
`msync`
`mte`
+`mul32`
+`mul32high`
`multivalue`
`mutable-globals`
`neon`
`nnp-assist`
`nontrapping-fptoint`
+`nsa`
`nvic`
`outline-atomics`
`paca`
@@ -199,6 +214,7 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE");
`power9-altivec`
`power9-vector`
`prfchw`
+`prid`
`ptx32`
`ptx40`
`ptx41`
@@ -239,12 +255,16 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE");
`rdrand`
`rdseed`
`reference-types`
+`regprotect`
`relax`
`relaxed-simd`
`rtm`
`rva23u64`
+`rvector`
+`s32c1i`
`sb`
`scq`
+`sext`
`sha`
`sha2`
`sha3`
@@ -315,8 +335,10 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE");
`sve2p1`
`tail-call`
`tbm`
+`threadptr`
`thumb-mode`
`thumb2`
+`timerint`
`tme`
`transactional-execution`
`trust`
@@ -371,6 +393,7 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE");
`wfxt`
`wide-arithmetic`
`widekl`
+`windowed`
`x87`
`xop`
`xsave`