diff --git a/compiler/rustc_codegen_gcc/src/asm.rs b/compiler/rustc_codegen_gcc/src/asm.rs index f237861b1595a..ff6c7dc9be791 100644 --- a/compiler/rustc_codegen_gcc/src/asm.rs +++ b/compiler/rustc_codegen_gcc/src/asm.rs @@ -732,6 +732,8 @@ 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::SpirV(SpirVInlineAsmRegClass::reg) => { bug!("GCC backend does not support SPIR-V") } @@ -842,6 +844,8 @@ 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::Err => unreachable!(), } } @@ -1033,6 +1037,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 8cd4bdc372789..816f956cb8e5e 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()); @@ -682,6 +683,8 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'_>>) -> | X86InlineAsmRegClass::kreg0 | X86InlineAsmRegClass::tmm_reg, ) => unreachable!("clobber-only"), + Xtensa(XtensaInlineAsmRegClass::freg) => "f", + Xtensa(XtensaInlineAsmRegClass::reg) => "r", Wasm(WasmInlineAsmRegClass::local) => "r", Bpf(BpfInlineAsmRegClass::reg) => "r", Bpf(BpfInlineAsmRegClass::wreg) => "w", @@ -787,6 +790,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) @@ -862,6 +866,8 @@ 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(), 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 a4d86e5df9a91..1fb27d45aee24 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -525,6 +525,7 @@ symbols! { async_iterator, async_iterator_poll_next, async_trait_bounds, + atomctl, atomic, atomic_and, atomic_cxchg, @@ -768,6 +769,7 @@ symbols! { contracts_requires, convert, convert_identity, + coprocessor, copy, copy_closures, copy_nonoverlapping, @@ -954,6 +956,7 @@ symbols! { ermsb_target_feature, exact_div, except, + exception, exception_handling: "exception-handling", exchange_malloc, exclusive_range_pattern, @@ -980,6 +983,7 @@ symbols! { expr_fragment_specifier_2024, extended_key_value_attributes, extended_varargs_abi_support, + extendedl32r, extern_absolute_paths, extern_crate_item_prelude, extern_crate_self, @@ -1097,6 +1101,9 @@ symbols! { format_argument, format_arguments, format_macro, + format_placeholder, + format_unsafe_arg, + fp, framework, freeze, freeze_impls, @@ -1170,6 +1177,7 @@ symbols! { hexagon_target_feature, hidden, hide, + highpriinterrupts, hint, homogeneous_aggregate, host, @@ -1256,6 +1264,7 @@ symbols! { integral, internal, internal_features, + interrupt, into_async_iter_into_iter, into_future, into_iter, @@ -1362,6 +1371,7 @@ symbols! { lt, m68k, m68k_target_feature, + mac16, macro_at_most_once_rep, macro_attr, macro_attributes_in_derive_output, @@ -1415,6 +1425,7 @@ symbols! { mem_variant_count, mem_zeroed, member_constraints, + memctl, memory, memtag, message, @@ -1477,6 +1488,8 @@ symbols! { mir_unwind_unreachable, mir_variant, miri, + misc, + miscsr, mmx_reg, modifiers, module, @@ -1731,6 +1744,8 @@ symbols! { prelude_import, preserves_flags, prfchw_target_feature, + prid, + primitive, print_macro, println_macro, proc_dash_macro: "proc-macro", @@ -2001,8 +2016,10 @@ symbols! { rustdoc_missing_doc_code_examples, rustfmt, rvalue_static_promotion, + rvector, rwpi, s, + s32c1i, s390x, s390x_target_feature, s390x_target_feature_vector, @@ -2245,9 +2262,12 @@ symbols! { thread, thread_local, thread_local_macro, + threadptr, three_way_compare, thumb2, thumb_mode: "thumb-mode", + time, + timerint, tmm_reg, to_owned_method, to_string, @@ -2467,6 +2487,7 @@ symbols! { while_let, whole_dash_archive: "whole-archive", width, + windowed, windows, windows_subsystem, with_negative_coherence, @@ -2490,9 +2511,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 57d9cdad454ac..2cb2545d0c542 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..c02b96b1df249 --- /dev/null +++ b/compiler/rustc_target/src/asm/xtensa.rs @@ -0,0 +1,127 @@ +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, + } +} + +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; }, + } + } +} + +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, + + #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/target_features.rs b/compiler/rustc_target/src/target_features.rs index 990928774731c..ee431a92c6ef4 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -883,6 +883,33 @@ static M68K_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ // tidy-alphabetical-end ]; +const XTENSA_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ + ("fp", Unstable(sym::xtensa_target_feature), &["coprocessor"]), + ("coprocessor", Unstable(sym::xtensa_target_feature), &[]), + ("highpriinterrupts", Unstable(sym::xtensa_target_feature), &["interrupt"]), + ("interrupt", Unstable(sym::xtensa_target_feature), &[]), + ("windowed", 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), &[]), + ("mac16", Unstable(sym::xtensa_target_feature), &[]), + ("s32c1i", Unstable(sym::xtensa_target_feature), &[]), + ("threadptr", Unstable(sym::xtensa_target_feature), &[]), + ("extendedl32r", Unstable(sym::xtensa_target_feature), &[]), + ("atomctl", Unstable(sym::xtensa_target_feature), &[]), + ("memctl", Unstable(sym::xtensa_target_feature), &[]), + ("debug", Unstable(sym::xtensa_target_feature), &[]), + ("exception", Unstable(sym::xtensa_target_feature), &[]), + ("rvector", Unstable(sym::xtensa_target_feature), &[]), + ("timerint", Unstable(sym::xtensa_target_feature), &[]), + ("prid", Unstable(sym::xtensa_target_feature), &[]), + ("regprotect", Unstable(sym::xtensa_target_feature), &[]), + ("miscsr", Unstable(sym::xtensa_target_feature), &[]), +]; + /// When rustdoc is running, provide a list of all known features so that all their respective /// primitives may be documented. /// @@ -899,6 +926,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 +999,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/tests/assembly-llvm/asm/xtensa-types.rs b/tests/assembly-llvm/asm/xtensa-types.rs new file mode 100644 index 0000000000000..8f222d092fc59 --- /dev/null +++ b/tests/assembly-llvm/asm/xtensa-types.rs @@ -0,0 +1,118 @@ +//@ add-minicore +//@ 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`