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: A language empowering everyone to build reliable and efficient software - +# 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`