diff options
Diffstat (limited to 'compiler/rustc_target/src/asm/mod.rs')
| -rw-r--r-- | compiler/rustc_target/src/asm/mod.rs | 162 |
1 files changed, 121 insertions, 41 deletions
diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs index 85422aefbeb..a84410d0f3c 100644 --- a/compiler/rustc_target/src/asm/mod.rs +++ b/compiler/rustc_target/src/asm/mod.rs @@ -81,14 +81,14 @@ macro_rules! def_regs { pub fn parse( _arch: super::InlineAsmArch, - mut _has_feature: impl FnMut(&str) -> bool, + _target_features: &rustc_data_structures::fx::FxHashSet<Symbol>, _target: &crate::spec::Target, name: &str, ) -> Result<Self, &'static str> { match name { $( $($alias)|* | $reg_name => { - $($filter(_arch, &mut _has_feature, _target)?;)? + $($filter(_arch, _target_features, _target)?;)? Ok(Self::$reg) } )* @@ -102,7 +102,7 @@ macro_rules! def_regs { pub(super) fn fill_reg_map( _arch: super::InlineAsmArch, - mut _has_feature: impl FnMut(&str) -> bool, + _target_features: &rustc_data_structures::fx::FxHashSet<Symbol>, _target: &crate::spec::Target, _map: &mut rustc_data_structures::fx::FxHashMap< super::InlineAsmRegClass, @@ -112,7 +112,7 @@ macro_rules! def_regs { #[allow(unused_imports)] use super::{InlineAsmReg, InlineAsmRegClass}; $( - if $($filter(_arch, &mut _has_feature, _target).is_ok() &&)? true { + if $($filter(_arch, _target_features, _target).is_ok() &&)? true { if let Some(set) = _map.get_mut(&InlineAsmRegClass::$arch($arch_regclass::$class)) { set.insert(InlineAsmReg::$arch($arch_reg::$reg)); } @@ -130,7 +130,7 @@ macro_rules! def_regs { macro_rules! types { ( $(_ : $($ty:expr),+;)? - $($feature:literal: $($ty2:expr),+;)* + $($feature:ident: $($ty2:expr),+;)* ) => { { use super::InlineAsmType::*; @@ -139,7 +139,7 @@ macro_rules! types { ($ty, None), )*)? $($( - ($ty2, Some($feature)), + ($ty2, Some(rustc_span::sym::$feature)), )*)* ] } @@ -148,9 +148,11 @@ macro_rules! types { mod aarch64; mod arm; +mod avr; mod bpf; mod hexagon; mod mips; +mod msp430; mod nvptx; mod powerpc; mod riscv; @@ -161,9 +163,11 @@ mod x86; pub use aarch64::{AArch64InlineAsmReg, AArch64InlineAsmRegClass}; pub use arm::{ArmInlineAsmReg, ArmInlineAsmRegClass}; +pub use avr::{AvrInlineAsmReg, AvrInlineAsmRegClass}; pub use bpf::{BpfInlineAsmReg, BpfInlineAsmRegClass}; pub use hexagon::{HexagonInlineAsmReg, HexagonInlineAsmRegClass}; pub use mips::{MipsInlineAsmReg, MipsInlineAsmRegClass}; +pub use msp430::{Msp430InlineAsmReg, Msp430InlineAsmRegClass}; pub use nvptx::{NvptxInlineAsmReg, NvptxInlineAsmRegClass}; pub use powerpc::{PowerPCInlineAsmReg, PowerPCInlineAsmRegClass}; pub use riscv::{RiscVInlineAsmReg, RiscVInlineAsmRegClass}; @@ -189,7 +193,10 @@ pub enum InlineAsmArch { S390x, SpirV, Wasm32, + Wasm64, Bpf, + Avr, + Msp430, } impl FromStr for InlineAsmArch { @@ -212,7 +219,10 @@ impl FromStr for InlineAsmArch { "s390x" => Ok(Self::S390x), "spirv" => Ok(Self::SpirV), "wasm32" => Ok(Self::Wasm32), + "wasm64" => Ok(Self::Wasm64), "bpf" => Ok(Self::Bpf), + "avr" => Ok(Self::Avr), + "msp430" => Ok(Self::Msp430), _ => Err(()), } } @@ -243,6 +253,8 @@ pub enum InlineAsmReg { SpirV(SpirVInlineAsmReg), Wasm(WasmInlineAsmReg), Bpf(BpfInlineAsmReg), + Avr(AvrInlineAsmReg), + Msp430(Msp430InlineAsmReg), // Placeholder for invalid register constraints for the current target Err, } @@ -259,6 +271,8 @@ impl InlineAsmReg { Self::Mips(r) => r.name(), Self::S390x(r) => r.name(), Self::Bpf(r) => r.name(), + Self::Avr(r) => r.name(), + Self::Msp430(r) => r.name(), Self::Err => "<reg>", } } @@ -274,13 +288,15 @@ impl InlineAsmReg { Self::Mips(r) => InlineAsmRegClass::Mips(r.reg_class()), Self::S390x(r) => InlineAsmRegClass::S390x(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()), Self::Err => InlineAsmRegClass::Err, } } pub fn parse( arch: InlineAsmArch, - has_feature: impl FnMut(&str) -> bool, + target_features: &FxHashSet<Symbol>, target: &Target, name: Symbol, ) -> Result<Self, &'static str> { @@ -289,40 +305,46 @@ impl InlineAsmReg { let name = name.as_str(); Ok(match arch { InlineAsmArch::X86 | InlineAsmArch::X86_64 => { - Self::X86(X86InlineAsmReg::parse(arch, has_feature, target, &name)?) + Self::X86(X86InlineAsmReg::parse(arch, target_features, target, name)?) } InlineAsmArch::Arm => { - Self::Arm(ArmInlineAsmReg::parse(arch, has_feature, target, &name)?) + Self::Arm(ArmInlineAsmReg::parse(arch, target_features, target, name)?) } InlineAsmArch::AArch64 => { - Self::AArch64(AArch64InlineAsmReg::parse(arch, has_feature, target, &name)?) + Self::AArch64(AArch64InlineAsmReg::parse(arch, target_features, target, name)?) } InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => { - Self::RiscV(RiscVInlineAsmReg::parse(arch, has_feature, target, &name)?) + Self::RiscV(RiscVInlineAsmReg::parse(arch, target_features, target, name)?) } InlineAsmArch::Nvptx64 => { - Self::Nvptx(NvptxInlineAsmReg::parse(arch, has_feature, target, &name)?) + Self::Nvptx(NvptxInlineAsmReg::parse(arch, target_features, target, name)?) } InlineAsmArch::PowerPC | InlineAsmArch::PowerPC64 => { - Self::PowerPC(PowerPCInlineAsmReg::parse(arch, has_feature, target, &name)?) + Self::PowerPC(PowerPCInlineAsmReg::parse(arch, target_features, target, name)?) } InlineAsmArch::Hexagon => { - Self::Hexagon(HexagonInlineAsmReg::parse(arch, has_feature, target, &name)?) + Self::Hexagon(HexagonInlineAsmReg::parse(arch, target_features, target, name)?) } InlineAsmArch::Mips | InlineAsmArch::Mips64 => { - Self::Mips(MipsInlineAsmReg::parse(arch, has_feature, target, &name)?) + Self::Mips(MipsInlineAsmReg::parse(arch, target_features, target, name)?) } InlineAsmArch::S390x => { - Self::S390x(S390xInlineAsmReg::parse(arch, has_feature, target, &name)?) + Self::S390x(S390xInlineAsmReg::parse(arch, target_features, target, name)?) } InlineAsmArch::SpirV => { - Self::SpirV(SpirVInlineAsmReg::parse(arch, has_feature, target, &name)?) + Self::SpirV(SpirVInlineAsmReg::parse(arch, target_features, target, name)?) } - InlineAsmArch::Wasm32 => { - Self::Wasm(WasmInlineAsmReg::parse(arch, has_feature, target, &name)?) + InlineAsmArch::Wasm32 | InlineAsmArch::Wasm64 => { + Self::Wasm(WasmInlineAsmReg::parse(arch, target_features, target, name)?) } InlineAsmArch::Bpf => { - Self::Bpf(BpfInlineAsmReg::parse(arch, has_feature, target, &name)?) + Self::Bpf(BpfInlineAsmReg::parse(arch, target_features, target, name)?) + } + InlineAsmArch::Avr => { + Self::Avr(AvrInlineAsmReg::parse(arch, target_features, target, name)?) + } + InlineAsmArch::Msp430 => { + Self::Msp430(Msp430InlineAsmReg::parse(arch, target_features, target, name)?) } }) } @@ -345,6 +367,8 @@ impl InlineAsmReg { Self::Mips(r) => r.emit(out, arch, modifier), Self::S390x(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), Self::Err => unreachable!("Use of InlineAsmReg::Err"), } } @@ -360,6 +384,8 @@ impl InlineAsmReg { Self::Mips(_) => cb(self), Self::S390x(_) => 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), Self::Err => unreachable!("Use of InlineAsmReg::Err"), } } @@ -390,6 +416,8 @@ pub enum InlineAsmRegClass { SpirV(SpirVInlineAsmRegClass), Wasm(WasmInlineAsmRegClass), Bpf(BpfInlineAsmRegClass), + Avr(AvrInlineAsmRegClass), + Msp430(Msp430InlineAsmRegClass), // Placeholder for invalid register constraints for the current target Err, } @@ -409,6 +437,8 @@ impl InlineAsmRegClass { Self::SpirV(r) => r.name(), Self::Wasm(r) => r.name(), Self::Bpf(r) => r.name(), + Self::Avr(r) => r.name(), + Self::Msp430(r) => r.name(), Self::Err => rustc_span::symbol::sym::reg, } } @@ -430,6 +460,8 @@ impl InlineAsmRegClass { Self::SpirV(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::SpirV), Self::Wasm(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Wasm), 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), Self::Err => unreachable!("Use of InlineAsmRegClass::Err"), } } @@ -458,6 +490,8 @@ impl InlineAsmRegClass { Self::SpirV(r) => r.suggest_modifier(arch, ty), Self::Wasm(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), Self::Err => unreachable!("Use of InlineAsmRegClass::Err"), } } @@ -482,6 +516,8 @@ impl InlineAsmRegClass { Self::SpirV(r) => r.default_modifier(arch), Self::Wasm(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), Self::Err => unreachable!("Use of InlineAsmRegClass::Err"), } } @@ -491,7 +527,7 @@ impl InlineAsmRegClass { pub fn supported_types( self, arch: InlineAsmArch, - ) -> &'static [(InlineAsmType, Option<&'static str>)] { + ) -> &'static [(InlineAsmType, Option<Symbol>)] { match self { Self::X86(r) => r.supported_types(arch), Self::Arm(r) => r.supported_types(arch), @@ -505,6 +541,8 @@ impl InlineAsmRegClass { Self::SpirV(r) => r.supported_types(arch), Self::Wasm(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), Self::Err => unreachable!("Use of InlineAsmRegClass::Err"), } } @@ -529,8 +567,12 @@ impl InlineAsmRegClass { } InlineAsmArch::S390x => Self::S390x(S390xInlineAsmRegClass::parse(arch, name)?), InlineAsmArch::SpirV => Self::SpirV(SpirVInlineAsmRegClass::parse(arch, name)?), - InlineAsmArch::Wasm32 => Self::Wasm(WasmInlineAsmRegClass::parse(arch, name)?), + InlineAsmArch::Wasm32 | InlineAsmArch::Wasm64 => { + Self::Wasm(WasmInlineAsmRegClass::parse(arch, name)?) + } InlineAsmArch::Bpf => Self::Bpf(BpfInlineAsmRegClass::parse(arch, name)?), + InlineAsmArch::Avr => Self::Avr(AvrInlineAsmRegClass::parse(arch, name)?), + InlineAsmArch::Msp430 => Self::Msp430(Msp430InlineAsmRegClass::parse(arch, name)?), }) } @@ -550,6 +592,8 @@ impl InlineAsmRegClass { Self::SpirV(r) => r.valid_modifiers(arch), Self::Wasm(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), Self::Err => unreachable!("Use of InlineAsmRegClass::Err"), } } @@ -671,68 +715,78 @@ impl fmt::Display for InlineAsmType { // falling back to an external assembler. pub fn allocatable_registers( arch: InlineAsmArch, - has_feature: impl FnMut(&str) -> bool, + target_features: &FxHashSet<Symbol>, target: &crate::spec::Target, ) -> FxHashMap<InlineAsmRegClass, FxHashSet<InlineAsmReg>> { match arch { InlineAsmArch::X86 | InlineAsmArch::X86_64 => { let mut map = x86::regclass_map(); - x86::fill_reg_map(arch, has_feature, target, &mut map); + x86::fill_reg_map(arch, target_features, target, &mut map); map } InlineAsmArch::Arm => { let mut map = arm::regclass_map(); - arm::fill_reg_map(arch, has_feature, target, &mut map); + arm::fill_reg_map(arch, target_features, target, &mut map); map } InlineAsmArch::AArch64 => { let mut map = aarch64::regclass_map(); - aarch64::fill_reg_map(arch, has_feature, target, &mut map); + aarch64::fill_reg_map(arch, target_features, target, &mut map); map } InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => { let mut map = riscv::regclass_map(); - riscv::fill_reg_map(arch, has_feature, target, &mut map); + riscv::fill_reg_map(arch, target_features, target, &mut map); map } InlineAsmArch::Nvptx64 => { let mut map = nvptx::regclass_map(); - nvptx::fill_reg_map(arch, has_feature, target, &mut map); + nvptx::fill_reg_map(arch, target_features, target, &mut map); map } InlineAsmArch::PowerPC | InlineAsmArch::PowerPC64 => { let mut map = powerpc::regclass_map(); - powerpc::fill_reg_map(arch, has_feature, target, &mut map); + powerpc::fill_reg_map(arch, target_features, target, &mut map); map } InlineAsmArch::Hexagon => { let mut map = hexagon::regclass_map(); - hexagon::fill_reg_map(arch, has_feature, target, &mut map); + hexagon::fill_reg_map(arch, target_features, target, &mut map); map } InlineAsmArch::Mips | InlineAsmArch::Mips64 => { let mut map = mips::regclass_map(); - mips::fill_reg_map(arch, has_feature, target, &mut map); + mips::fill_reg_map(arch, target_features, target, &mut map); map } InlineAsmArch::S390x => { let mut map = s390x::regclass_map(); - s390x::fill_reg_map(arch, has_feature, target, &mut map); + s390x::fill_reg_map(arch, target_features, target, &mut map); map } InlineAsmArch::SpirV => { let mut map = spirv::regclass_map(); - spirv::fill_reg_map(arch, has_feature, target, &mut map); + spirv::fill_reg_map(arch, target_features, target, &mut map); map } - InlineAsmArch::Wasm32 => { + InlineAsmArch::Wasm32 | InlineAsmArch::Wasm64 => { let mut map = wasm::regclass_map(); - wasm::fill_reg_map(arch, has_feature, target, &mut map); + wasm::fill_reg_map(arch, target_features, target, &mut map); map } InlineAsmArch::Bpf => { let mut map = bpf::regclass_map(); - bpf::fill_reg_map(arch, has_feature, target, &mut map); + bpf::fill_reg_map(arch, target_features, target, &mut map); + map + } + InlineAsmArch::Avr => { + let mut map = avr::regclass_map(); + avr::fill_reg_map(arch, target_features, target, &mut map); + map + } + InlineAsmArch::Msp430 => { + let mut map = msp430::regclass_map(); + msp430::fill_reg_map(arch, target_features, target, &mut map); map } } @@ -756,6 +810,7 @@ pub enum InlineAsmClobberAbi { X86_64SysV, Arm, AArch64, + AArch64NoX18, RiscV, } @@ -764,10 +819,11 @@ impl InlineAsmClobberAbi { /// clobber ABIs for the target. pub fn parse( arch: InlineAsmArch, + target_features: &FxHashSet<Symbol>, target: &Target, name: Symbol, ) -> Result<Self, &'static [&'static str]> { - let name = &*name.as_str(); + let name = name.as_str(); match arch { InlineAsmArch::X86 => match name { "C" | "system" | "efiapi" | "cdecl" | "stdcall" | "fastcall" => { @@ -787,7 +843,13 @@ impl InlineAsmClobberAbi { _ => Err(&["C", "system", "efiapi", "aapcs"]), }, InlineAsmArch::AArch64 => match name { - "C" | "system" | "efiapi" => Ok(InlineAsmClobberAbi::AArch64), + "C" | "system" | "efiapi" => { + Ok(if aarch64::reserved_x18(arch, target_features, target).is_err() { + InlineAsmClobberAbi::AArch64NoX18 + } else { + InlineAsmClobberAbi::AArch64 + }) + } _ => Err(&["C", "system", "efiapi"]), }, InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => match name { @@ -862,8 +924,25 @@ impl InlineAsmClobberAbi { AArch64 AArch64InlineAsmReg { x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, - // x18 is platform-reserved or temporary, but we exclude it - // here since it is a reserved register. + x16, x17, x18, x30, + + // Technically the low 64 bits of v8-v15 are preserved, but + // we have no way of expressing this using clobbers. + v0, v1, v2, v3, v4, v5, v6, v7, + v8, v9, v10, v11, v12, v13, v14, v15, + v16, v17, v18, v19, v20, v21, v22, v23, + v24, v25, v26, v27, v28, v29, v30, v31, + + p0, p1, p2, p3, p4, p5, p6, p7, + p8, p9, p10, p11, p12, p13, p14, p15, + ffr, + + } + }, + InlineAsmClobberAbi::AArch64NoX18 => clobbered_regs! { + AArch64 AArch64InlineAsmReg { + x0, x1, x2, x3, x4, x5, x6, x7, + x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x30, // Technically the low 64 bits of v8-v15 are preserved, but @@ -881,7 +960,8 @@ impl InlineAsmClobberAbi { }, InlineAsmClobberAbi::Arm => clobbered_regs! { Arm ArmInlineAsmReg { - // r9 is platform-reserved and is treated as callee-saved. + // r9 is either platform-reserved or callee-saved. Either + // way we don't need to clobber it. r0, r1, r2, r3, r12, r14, // The finest-grained register variant is used here so that |
