]> git.proxmox.com Git - rustc.git/blobdiff - compiler/rustc_target/src/asm/mod.rs
New upstream version 1.61.0+dfsg1
[rustc.git] / compiler / rustc_target / src / asm / mod.rs
index fd95b0338a6e14ebedee1d38e1227f09d328ca6e..5bc4b566daf67f86a241082c544ba75b90a6444d 100644 (file)
@@ -1,5 +1,5 @@
-use crate::abi::Size;
 use crate::spec::Target;
+use crate::{abi::Size, spec::RelocModel};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_macros::HashStable_Generic;
 use rustc_span::Symbol;
@@ -25,7 +25,7 @@ macro_rules! def_reg_class {
                 }
             }
 
-            pub fn parse(_arch: super::InlineAsmArch, name: rustc_span::Symbol) -> Result<Self, &'static str> {
+            pub fn parse(name: rustc_span::Symbol) -> Result<Self, &'static str> {
                 match name {
                     $(
                         rustc_span::sym::$class => Ok(Self::$class),
@@ -79,19 +79,10 @@ macro_rules! def_regs {
                 }
             }
 
-            pub fn parse(
-                _arch: super::InlineAsmArch,
-                _target_features: &rustc_data_structures::fx::FxHashSet<Symbol>,
-                _target: &crate::spec::Target,
-                _is_clobber: bool,
-                name: &str,
-            ) -> Result<Self, &'static str> {
+            pub fn parse(name: &str) -> Result<Self, &'static str> {
                 match name {
                     $(
-                        $($alias)|* | $reg_name => {
-                            $($filter(_arch, _target_features, _target, _is_clobber)?;)?
-                            Ok(Self::$reg)
-                        }
+                        $($alias)|* | $reg_name => Ok(Self::$reg),
                     )*
                     $(
                         $($bad_reg)|* => Err($error),
@@ -99,10 +90,34 @@ macro_rules! def_regs {
                     _ => Err("unknown register"),
                 }
             }
+
+            pub fn validate(self,
+                _arch: super::InlineAsmArch,
+                _reloc_model: crate::spec::RelocModel,
+                _target_features: &rustc_data_structures::fx::FxHashSet<Symbol>,
+                _target: &crate::spec::Target,
+                _is_clobber: bool,
+            ) -> Result<(), &'static str> {
+                match self {
+                    $(
+                        Self::$reg => {
+                            $($filter(
+                                _arch,
+                                _reloc_model,
+                                _target_features,
+                                _target,
+                                _is_clobber
+                            )?;)?
+                            Ok(())
+                        }
+                    )*
+                }
+            }
         }
 
         pub(super) fn fill_reg_map(
             _arch: super::InlineAsmArch,
+            _reloc_model: crate::spec::RelocModel,
             _target_features: &rustc_data_structures::fx::FxHashSet<Symbol>,
             _target: &crate::spec::Target,
             _map: &mut rustc_data_structures::fx::FxHashMap<
@@ -113,7 +128,7 @@ macro_rules! def_regs {
             #[allow(unused_imports)]
             use super::{InlineAsmReg, InlineAsmRegClass};
             $(
-                if $($filter(_arch, _target_features, _target, false).is_ok() &&)? true {
+                if $($filter(_arch, _reloc_model, _target_features, _target, false).is_ok() &&)? true {
                     if let Some(set) = _map.get_mut(&InlineAsmRegClass::$arch($arch_regclass::$class)) {
                         set.insert(InlineAsmReg::$arch($arch_reg::$reg));
                     }
@@ -295,94 +310,60 @@ impl InlineAsmReg {
         }
     }
 
-    pub fn parse(
-        arch: InlineAsmArch,
-        target_features: &FxHashSet<Symbol>,
-        target: &Target,
-        is_clobber: bool,
-        name: Symbol,
-    ) -> Result<Self, &'static str> {
+    pub fn parse(arch: InlineAsmArch, name: Symbol) -> Result<Self, &'static str> {
         // FIXME: use direct symbol comparison for register names
         // Use `Symbol::as_str` instead of `Symbol::with` here because `has_feature` may access `Symbol`.
         let name = name.as_str();
         Ok(match arch {
-            InlineAsmArch::X86 | InlineAsmArch::X86_64 => {
-                Self::X86(X86InlineAsmReg::parse(arch, target_features, target, is_clobber, name)?)
+            InlineAsmArch::X86 | InlineAsmArch::X86_64 => Self::X86(X86InlineAsmReg::parse(name)?),
+            InlineAsmArch::Arm => Self::Arm(ArmInlineAsmReg::parse(name)?),
+            InlineAsmArch::AArch64 => Self::AArch64(AArch64InlineAsmReg::parse(name)?),
+            InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => {
+                Self::RiscV(RiscVInlineAsmReg::parse(name)?)
             }
-            InlineAsmArch::Arm => {
-                Self::Arm(ArmInlineAsmReg::parse(arch, target_features, target, is_clobber, name)?)
+            InlineAsmArch::Nvptx64 => Self::Nvptx(NvptxInlineAsmReg::parse(name)?),
+            InlineAsmArch::PowerPC | InlineAsmArch::PowerPC64 => {
+                Self::PowerPC(PowerPCInlineAsmReg::parse(name)?)
             }
-            InlineAsmArch::AArch64 => Self::AArch64(AArch64InlineAsmReg::parse(
-                arch,
-                target_features,
-                target,
-                is_clobber,
-                name,
-            )?),
-            InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => Self::RiscV(
-                RiscVInlineAsmReg::parse(arch, target_features, target, is_clobber, name)?,
-            ),
-            InlineAsmArch::Nvptx64 => Self::Nvptx(NvptxInlineAsmReg::parse(
-                arch,
-                target_features,
-                target,
-                is_clobber,
-                name,
-            )?),
-            InlineAsmArch::PowerPC | InlineAsmArch::PowerPC64 => Self::PowerPC(
-                PowerPCInlineAsmReg::parse(arch, target_features, target, is_clobber, name)?,
-            ),
-            InlineAsmArch::Hexagon => Self::Hexagon(HexagonInlineAsmReg::parse(
-                arch,
-                target_features,
-                target,
-                is_clobber,
-                name,
-            )?),
-            InlineAsmArch::Mips | InlineAsmArch::Mips64 => Self::Mips(MipsInlineAsmReg::parse(
-                arch,
-                target_features,
-                target,
-                is_clobber,
-                name,
-            )?),
-            InlineAsmArch::S390x => Self::S390x(S390xInlineAsmReg::parse(
-                arch,
-                target_features,
-                target,
-                is_clobber,
-                name,
-            )?),
-            InlineAsmArch::SpirV => Self::SpirV(SpirVInlineAsmReg::parse(
-                arch,
-                target_features,
-                target,
-                is_clobber,
-                name,
-            )?),
-            InlineAsmArch::Wasm32 | InlineAsmArch::Wasm64 => Self::Wasm(WasmInlineAsmReg::parse(
-                arch,
-                target_features,
-                target,
-                is_clobber,
-                name,
-            )?),
-            InlineAsmArch::Bpf => {
-                Self::Bpf(BpfInlineAsmReg::parse(arch, target_features, target, is_clobber, name)?)
+            InlineAsmArch::Hexagon => Self::Hexagon(HexagonInlineAsmReg::parse(name)?),
+            InlineAsmArch::Mips | InlineAsmArch::Mips64 => {
+                Self::Mips(MipsInlineAsmReg::parse(name)?)
             }
-            InlineAsmArch::Avr => {
-                Self::Avr(AvrInlineAsmReg::parse(arch, target_features, target, is_clobber, name)?)
+            InlineAsmArch::S390x => Self::S390x(S390xInlineAsmReg::parse(name)?),
+            InlineAsmArch::SpirV => Self::SpirV(SpirVInlineAsmReg::parse(name)?),
+            InlineAsmArch::Wasm32 | InlineAsmArch::Wasm64 => {
+                Self::Wasm(WasmInlineAsmReg::parse(name)?)
             }
-            InlineAsmArch::Msp430 => Self::Msp430(Msp430InlineAsmReg::parse(
-                arch,
-                target_features,
-                target,
-                is_clobber,
-                name,
-            )?),
+            InlineAsmArch::Bpf => Self::Bpf(BpfInlineAsmReg::parse(name)?),
+            InlineAsmArch::Avr => Self::Avr(AvrInlineAsmReg::parse(name)?),
+            InlineAsmArch::Msp430 => Self::Msp430(Msp430InlineAsmReg::parse(name)?),
         })
     }
 
+    pub fn validate(
+        self,
+        arch: InlineAsmArch,
+        reloc_model: RelocModel,
+        target_features: &FxHashSet<Symbol>,
+        target: &Target,
+        is_clobber: bool,
+    ) -> Result<(), &'static str> {
+        match self {
+            Self::X86(r) => r.validate(arch, reloc_model, target_features, target, is_clobber),
+            Self::Arm(r) => r.validate(arch, reloc_model, target_features, target, is_clobber),
+            Self::AArch64(r) => r.validate(arch, reloc_model, target_features, target, is_clobber),
+            Self::RiscV(r) => r.validate(arch, reloc_model, target_features, target, is_clobber),
+            Self::PowerPC(r) => r.validate(arch, reloc_model, target_features, target, is_clobber),
+            Self::Hexagon(r) => r.validate(arch, reloc_model, target_features, target, is_clobber),
+            Self::Mips(r) => r.validate(arch, reloc_model, target_features, target, is_clobber),
+            Self::S390x(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::Msp430(r) => r.validate(arch, reloc_model, target_features, target, is_clobber),
+            Self::Err => unreachable!(),
+        }
+    }
+
     // NOTE: This function isn't used at the moment, but is needed to support
     // falling back to an external assembler.
     pub fn emit(
@@ -584,29 +565,29 @@ impl InlineAsmRegClass {
     pub fn parse(arch: InlineAsmArch, name: Symbol) -> Result<Self, &'static str> {
         Ok(match arch {
             InlineAsmArch::X86 | InlineAsmArch::X86_64 => {
-                Self::X86(X86InlineAsmRegClass::parse(arch, name)?)
+                Self::X86(X86InlineAsmRegClass::parse(name)?)
             }
-            InlineAsmArch::Arm => Self::Arm(ArmInlineAsmRegClass::parse(arch, name)?),
-            InlineAsmArch::AArch64 => Self::AArch64(AArch64InlineAsmRegClass::parse(arch, name)?),
+            InlineAsmArch::Arm => Self::Arm(ArmInlineAsmRegClass::parse(name)?),
+            InlineAsmArch::AArch64 => Self::AArch64(AArch64InlineAsmRegClass::parse(name)?),
             InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => {
-                Self::RiscV(RiscVInlineAsmRegClass::parse(arch, name)?)
+                Self::RiscV(RiscVInlineAsmRegClass::parse(name)?)
             }
-            InlineAsmArch::Nvptx64 => Self::Nvptx(NvptxInlineAsmRegClass::parse(arch, name)?),
+            InlineAsmArch::Nvptx64 => Self::Nvptx(NvptxInlineAsmRegClass::parse(name)?),
             InlineAsmArch::PowerPC | InlineAsmArch::PowerPC64 => {
-                Self::PowerPC(PowerPCInlineAsmRegClass::parse(arch, name)?)
+                Self::PowerPC(PowerPCInlineAsmRegClass::parse(name)?)
             }
-            InlineAsmArch::Hexagon => Self::Hexagon(HexagonInlineAsmRegClass::parse(arch, name)?),
+            InlineAsmArch::Hexagon => Self::Hexagon(HexagonInlineAsmRegClass::parse(name)?),
             InlineAsmArch::Mips | InlineAsmArch::Mips64 => {
-                Self::Mips(MipsInlineAsmRegClass::parse(arch, name)?)
+                Self::Mips(MipsInlineAsmRegClass::parse(name)?)
             }
-            InlineAsmArch::S390x => Self::S390x(S390xInlineAsmRegClass::parse(arch, name)?),
-            InlineAsmArch::SpirV => Self::SpirV(SpirVInlineAsmRegClass::parse(arch, name)?),
+            InlineAsmArch::S390x => Self::S390x(S390xInlineAsmRegClass::parse(name)?),
+            InlineAsmArch::SpirV => Self::SpirV(SpirVInlineAsmRegClass::parse(name)?),
             InlineAsmArch::Wasm32 | InlineAsmArch::Wasm64 => {
-                Self::Wasm(WasmInlineAsmRegClass::parse(arch, name)?)
+                Self::Wasm(WasmInlineAsmRegClass::parse(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)?),
+            InlineAsmArch::Bpf => Self::Bpf(BpfInlineAsmRegClass::parse(name)?),
+            InlineAsmArch::Avr => Self::Avr(AvrInlineAsmRegClass::parse(name)?),
+            InlineAsmArch::Msp430 => Self::Msp430(Msp430InlineAsmRegClass::parse(name)?),
         })
     }
 
@@ -749,78 +730,79 @@ impl fmt::Display for InlineAsmType {
 // falling back to an external assembler.
 pub fn allocatable_registers(
     arch: InlineAsmArch,
+    reloc_model: RelocModel,
     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, target_features, target, &mut map);
+            x86::fill_reg_map(arch, reloc_model, target_features, target, &mut map);
             map
         }
         InlineAsmArch::Arm => {
             let mut map = arm::regclass_map();
-            arm::fill_reg_map(arch, target_features, target, &mut map);
+            arm::fill_reg_map(arch, reloc_model, target_features, target, &mut map);
             map
         }
         InlineAsmArch::AArch64 => {
             let mut map = aarch64::regclass_map();
-            aarch64::fill_reg_map(arch, target_features, target, &mut map);
+            aarch64::fill_reg_map(arch, reloc_model, target_features, target, &mut map);
             map
         }
         InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => {
             let mut map = riscv::regclass_map();
-            riscv::fill_reg_map(arch, target_features, target, &mut map);
+            riscv::fill_reg_map(arch, reloc_model, target_features, target, &mut map);
             map
         }
         InlineAsmArch::Nvptx64 => {
             let mut map = nvptx::regclass_map();
-            nvptx::fill_reg_map(arch, target_features, target, &mut map);
+            nvptx::fill_reg_map(arch, reloc_model, target_features, target, &mut map);
             map
         }
         InlineAsmArch::PowerPC | InlineAsmArch::PowerPC64 => {
             let mut map = powerpc::regclass_map();
-            powerpc::fill_reg_map(arch, target_features, target, &mut map);
+            powerpc::fill_reg_map(arch, reloc_model, target_features, target, &mut map);
             map
         }
         InlineAsmArch::Hexagon => {
             let mut map = hexagon::regclass_map();
-            hexagon::fill_reg_map(arch, target_features, target, &mut map);
+            hexagon::fill_reg_map(arch, reloc_model, target_features, target, &mut map);
             map
         }
         InlineAsmArch::Mips | InlineAsmArch::Mips64 => {
             let mut map = mips::regclass_map();
-            mips::fill_reg_map(arch, target_features, target, &mut map);
+            mips::fill_reg_map(arch, reloc_model, target_features, target, &mut map);
             map
         }
         InlineAsmArch::S390x => {
             let mut map = s390x::regclass_map();
-            s390x::fill_reg_map(arch, target_features, target, &mut map);
+            s390x::fill_reg_map(arch, reloc_model, target_features, target, &mut map);
             map
         }
         InlineAsmArch::SpirV => {
             let mut map = spirv::regclass_map();
-            spirv::fill_reg_map(arch, target_features, target, &mut map);
+            spirv::fill_reg_map(arch, reloc_model, target_features, target, &mut map);
             map
         }
         InlineAsmArch::Wasm32 | InlineAsmArch::Wasm64 => {
             let mut map = wasm::regclass_map();
-            wasm::fill_reg_map(arch, target_features, target, &mut map);
+            wasm::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, target_features, target, &mut map);
+            bpf::fill_reg_map(arch, reloc_model, target_features, target, &mut map);
             map
         }
         InlineAsmArch::Avr => {
             let mut map = avr::regclass_map();
-            avr::fill_reg_map(arch, target_features, target, &mut map);
+            avr::fill_reg_map(arch, reloc_model, target_features, target, &mut map);
             map
         }
         InlineAsmArch::Msp430 => {
             let mut map = msp430::regclass_map();
-            msp430::fill_reg_map(arch, target_features, target, &mut map);
+            msp430::fill_reg_map(arch, reloc_model, target_features, target, &mut map);
             map
         }
     }
@@ -853,7 +835,6 @@ 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]> {
@@ -877,13 +858,11 @@ impl InlineAsmClobberAbi {
                 _ => Err(&["C", "system", "efiapi", "aapcs"]),
             },
             InlineAsmArch::AArch64 => match name {
-                "C" | "system" | "efiapi" => {
-                    Ok(if aarch64::reserved_x18(arch, target_features, target, true).is_err() {
-                        InlineAsmClobberAbi::AArch64NoX18
-                    } else {
-                        InlineAsmClobberAbi::AArch64
-                    })
-                }
+                "C" | "system" | "efiapi" => Ok(if aarch64::target_reserves_x18(target) {
+                    InlineAsmClobberAbi::AArch64NoX18
+                } else {
+                    InlineAsmClobberAbi::AArch64
+                }),
                 _ => Err(&["C", "system", "efiapi"]),
             },
             InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => match name {