Auto merge of #92731 - bjorn3:asm_support_changes, r=nagisa

Avoid unnecessary monomorphization of inline asm related functions

This should reduce build time for codegen backends by avoiding duplicated monomorphization of certain inline asm related functions for each passed in closure type.
This commit is contained in:
bors 2022-01-18 14:32:52 +00:00
commit 9ad5d82f82
21 changed files with 133 additions and 105 deletions

View file

@ -6,7 +6,7 @@ use rustc_data_structures::stable_set::FxHashSet;
use rustc_errors::struct_span_err; use rustc_errors::struct_span_err;
use rustc_hir as hir; use rustc_hir as hir;
use rustc_session::parse::feature_err; use rustc_session::parse::feature_err;
use rustc_span::{sym, Span, Symbol}; use rustc_span::{sym, Span};
use rustc_target::asm; use rustc_target::asm;
use std::collections::hash_map::Entry; use std::collections::hash_map::Entry;
use std::fmt::Write; use std::fmt::Write;
@ -66,7 +66,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
for (abi_name, abi_span) in &asm.clobber_abis { for (abi_name, abi_span) in &asm.clobber_abis {
match asm::InlineAsmClobberAbi::parse( match asm::InlineAsmClobberAbi::parse(
asm_arch, asm_arch,
|feature| self.sess.target_features.contains(&Symbol::intern(feature)), &self.sess.target_features,
&self.sess.target, &self.sess.target,
*abi_name, *abi_name,
) { ) {
@ -134,7 +134,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
asm::InlineAsmRegOrRegClass::Reg(if let Some(asm_arch) = asm_arch { asm::InlineAsmRegOrRegClass::Reg(if let Some(asm_arch) = asm_arch {
asm::InlineAsmReg::parse( asm::InlineAsmReg::parse(
asm_arch, asm_arch,
|feature| sess.target_features.contains(&Symbol::intern(feature)), &sess.target_features,
&sess.target, &sess.target,
s, s,
) )

View file

@ -6,7 +6,7 @@ use std::fmt::Write;
use rustc_ast::ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_ast::ast::{InlineAsmOptions, InlineAsmTemplatePiece};
use rustc_middle::mir::InlineAsmOperand; use rustc_middle::mir::InlineAsmOperand;
use rustc_span::Symbol; use rustc_span::sym;
use rustc_target::asm::*; use rustc_target::asm::*;
pub(crate) fn codegen_inline_asm<'tcx>( pub(crate) fn codegen_inline_asm<'tcx>(
@ -182,11 +182,7 @@ struct InlineAssemblyGenerator<'a, 'tcx> {
impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> { impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
fn allocate_registers(&mut self) { fn allocate_registers(&mut self) {
let sess = self.tcx.sess; let sess = self.tcx.sess;
let map = allocatable_registers( let map = allocatable_registers(self.arch, &sess.target_features, &sess.target);
self.arch,
|feature| sess.target_features.contains(&Symbol::intern(feature)),
&sess.target,
);
let mut allocated = FxHashMap::<_, (bool, bool)>::default(); let mut allocated = FxHashMap::<_, (bool, bool)>::default();
let mut regs = vec![None; self.operands.len()]; let mut regs = vec![None; self.operands.len()];
@ -319,9 +315,9 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
// Allocate stack slots for saving clobbered registers // Allocate stack slots for saving clobbered registers
let abi_clobber = InlineAsmClobberAbi::parse( let abi_clobber = InlineAsmClobberAbi::parse(
self.arch, self.arch,
|feature| self.tcx.sess.target_features.contains(&Symbol::intern(feature)), &self.tcx.sess.target_features,
&self.tcx.sess.target, &self.tcx.sess.target,
Symbol::intern("C"), sym::C,
) )
.unwrap() .unwrap()
.clobbered_regs(); .clobbered_regs();

View file

@ -5,7 +5,7 @@ use rustc_codegen_ssa::mir::place::PlaceRef;
use rustc_codegen_ssa::traits::{AsmBuilderMethods, AsmMethods, BaseTypeMethods, BuilderMethods, GlobalAsmOperandRef, InlineAsmOperandRef}; use rustc_codegen_ssa::traits::{AsmBuilderMethods, AsmMethods, BaseTypeMethods, BuilderMethods, GlobalAsmOperandRef, InlineAsmOperandRef};
use rustc_middle::{bug, ty::Instance}; use rustc_middle::{bug, ty::Instance};
use rustc_span::{Span, Symbol}; use rustc_span::Span;
use rustc_target::asm::*; use rustc_target::asm::*;
use std::borrow::Cow; use std::borrow::Cow;
@ -172,7 +172,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
let is_target_supported = reg.reg_class().supported_types(asm_arch).iter() let is_target_supported = reg.reg_class().supported_types(asm_arch).iter()
.any(|&(_, feature)| { .any(|&(_, feature)| {
if let Some(feature) = feature { if let Some(feature) = feature {
self.tcx.sess.target_features.contains(&Symbol::intern(feature)) self.tcx.sess.target_features.contains(&feature)
} else { } else {
true // Register class is unconditionally supported true // Register class is unconditionally supported
} }

View file

@ -13,7 +13,7 @@ use rustc_codegen_ssa::traits::*;
use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxHashMap;
use rustc_middle::ty::layout::TyAndLayout; use rustc_middle::ty::layout::TyAndLayout;
use rustc_middle::{bug, span_bug, ty::Instance}; use rustc_middle::{bug, span_bug, ty::Instance};
use rustc_span::{Pos, Span, Symbol}; use rustc_span::{Pos, Span};
use rustc_target::abi::*; use rustc_target::abi::*;
use rustc_target::asm::*; use rustc_target::asm::*;
@ -45,9 +45,8 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
for &(_, feature) in reg_class.supported_types(asm_arch) { for &(_, feature) in reg_class.supported_types(asm_arch) {
if let Some(feature) = feature { if let Some(feature) = feature {
let codegen_fn_attrs = self.tcx.codegen_fn_attrs(instance.def_id()); let codegen_fn_attrs = self.tcx.codegen_fn_attrs(instance.def_id());
let feature_name = Symbol::intern(feature); if self.tcx.sess.target_features.contains(&feature)
if self.tcx.sess.target_features.contains(&feature_name) || codegen_fn_attrs.target_features.contains(&feature)
|| codegen_fn_attrs.target_features.contains(&feature_name)
{ {
return true; return true;
} }

View file

@ -294,9 +294,8 @@ impl<'tcx> ExprVisitor<'tcx> {
// (!). In that case we still need the earlier check to verify that the // (!). In that case we still need the earlier check to verify that the
// register class is usable at all. // register class is usable at all.
if let Some(feature) = feature { if let Some(feature) = feature {
let feat_sym = Symbol::intern(feature); if !self.tcx.sess.target_features.contains(&feature)
if !self.tcx.sess.target_features.contains(&feat_sym) && !target_features.contains(&feature)
&& !target_features.contains(&feat_sym)
{ {
let msg = &format!("`{}` target feature is not enabled", feature); let msg = &format!("`{}` target feature is not enabled", feature);
let mut err = self.tcx.sess.struct_span_err(expr.span, msg); let mut err = self.tcx.sess.struct_span_err(expr.span, msg);
@ -377,9 +376,8 @@ impl<'tcx> ExprVisitor<'tcx> {
{ {
match feature { match feature {
Some(feature) => { Some(feature) => {
let feat_sym = Symbol::intern(feature); if self.tcx.sess.target_features.contains(&feature)
if self.tcx.sess.target_features.contains(&feat_sym) || attrs.target_features.contains(&feature)
|| attrs.target_features.contains(&feat_sym)
{ {
missing_required_features.clear(); missing_required_features.clear();
break; break;
@ -413,7 +411,11 @@ impl<'tcx> ExprVisitor<'tcx> {
let msg = format!( let msg = format!(
"register class `{}` requires at least one of the following target features: {}", "register class `{}` requires at least one of the following target features: {}",
reg_class.name(), reg_class.name(),
features.join(", ") features
.iter()
.map(|f| f.as_str())
.intersperse(", ")
.collect::<String>(),
); );
self.tcx.sess.struct_span_err(*op_sp, &msg).emit(); self.tcx.sess.struct_span_err(*op_sp, &msg).emit();
// register isn't enabled, don't do more checks // register isn't enabled, don't do more checks

View file

@ -6,6 +6,7 @@
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
#![feature(crate_visibility_modifier)] #![feature(crate_visibility_modifier)]
#![feature(iter_intersperse)]
#![feature(let_else)] #![feature(let_else)]
#![feature(map_try_insert)] #![feature(map_try_insert)]
#![feature(min_specialization)] #![feature(min_specialization)]

View file

@ -316,6 +316,7 @@ symbols! {
allow_internal_unsafe, allow_internal_unsafe,
allow_internal_unstable, allow_internal_unstable,
allowed, allowed,
alu32,
always, always,
and, and,
and_then, and_then,
@ -362,7 +363,10 @@ symbols! {
augmented_assignments, augmented_assignments,
auto_traits, auto_traits,
automatically_derived, automatically_derived,
avx,
avx512_target_feature, avx512_target_feature,
avx512bw,
avx512f,
await_macro, await_macro,
bang, bang,
begin_panic, begin_panic,
@ -593,6 +597,7 @@ symbols! {
dylib, dylib,
dyn_metadata, dyn_metadata,
dyn_trait, dyn_trait,
e,
edition_macro_pats, edition_macro_pats,
edition_panic, edition_panic,
eh_catch_typeinfo, eh_catch_typeinfo,
@ -683,6 +688,7 @@ symbols! {
format_args_macro, format_args_macro,
format_args_nl, format_args_nl,
format_macro, format_macro,
fp,
freeze, freeze,
freg, freg,
frem_fast, frem_fast,
@ -908,6 +914,7 @@ symbols! {
neg, neg,
negate_unsigned, negate_unsigned,
negative_impls, negative_impls,
neon,
never, never,
never_type, never_type,
never_type_fallback, never_type_fallback,
@ -1102,6 +1109,7 @@ symbols! {
repr_packed, repr_packed,
repr_simd, repr_simd,
repr_transparent, repr_transparent,
reserved_r9: "reserved-r9",
residual, residual,
result, result,
rhs, rhs,
@ -1296,6 +1304,7 @@ symbols! {
sqrtf64, sqrtf64,
sreg, sreg,
sreg_low16, sreg_low16,
sse,
sse4a_target_feature, sse4a_target_feature,
stable, stable,
staged_api, staged_api,
@ -1362,6 +1371,8 @@ symbols! {
thread, thread,
thread_local, thread_local,
thread_local_macro, thread_local_macro,
thumb2,
thumb_mode: "thumb-mode",
todo_macro, todo_macro,
tool_attributes, tool_attributes,
tool_lints, tool_lints,
@ -1455,6 +1466,7 @@ symbols! {
vec, vec,
vec_macro, vec_macro,
version, version,
vfp2,
vis, vis,
visible_private_types, visible_private_types,
volatile, volatile,

View file

@ -1,6 +1,8 @@
use super::{InlineAsmArch, InlineAsmType}; use super::{InlineAsmArch, InlineAsmType};
use crate::spec::Target; use crate::spec::Target;
use rustc_data_structures::stable_set::FxHashSet;
use rustc_macros::HashStable_Generic; use rustc_macros::HashStable_Generic;
use rustc_span::Symbol;
use std::fmt; use std::fmt;
def_reg_class! { def_reg_class! {
@ -58,11 +60,11 @@ impl AArch64InlineAsmRegClass {
pub fn supported_types( pub fn supported_types(
self, self,
_arch: InlineAsmArch, _arch: InlineAsmArch,
) -> &'static [(InlineAsmType, Option<&'static str>)] { ) -> &'static [(InlineAsmType, Option<Symbol>)] {
match self { match self {
Self::reg => types! { _: I8, I16, I32, I64, F32, F64; }, Self::reg => types! { _: I8, I16, I32, I64, F32, F64; },
Self::vreg | Self::vreg_low16 => types! { Self::vreg | Self::vreg_low16 => types! {
"fp": I8, I16, I32, I64, F32, F64, fp: I8, I16, I32, I64, F32, F64,
VecI8(8), VecI16(4), VecI32(2), VecI64(1), VecF32(2), VecF64(1), VecI8(8), VecI16(4), VecI32(2), VecI64(1), VecF32(2), VecF64(1),
VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF32(4), VecF64(2); VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF32(4), VecF64(2);
}, },
@ -73,7 +75,7 @@ impl AArch64InlineAsmRegClass {
pub fn reserved_x18( pub fn reserved_x18(
_arch: InlineAsmArch, _arch: InlineAsmArch,
_has_feature: impl FnMut(&str) -> bool, _target_features: &FxHashSet<Symbol>,
target: &Target, target: &Target,
) -> Result<(), &'static str> { ) -> Result<(), &'static str> {
if target.os == "android" if target.os == "android"

View file

@ -1,6 +1,8 @@
use super::{InlineAsmArch, InlineAsmType}; use super::{InlineAsmArch, InlineAsmType};
use crate::spec::Target; use crate::spec::Target;
use rustc_data_structures::stable_set::FxHashSet;
use rustc_macros::HashStable_Generic; use rustc_macros::HashStable_Generic;
use rustc_span::{sym, Symbol};
use std::fmt; use std::fmt;
def_reg_class! { def_reg_class! {
@ -44,31 +46,31 @@ impl ArmInlineAsmRegClass {
pub fn supported_types( pub fn supported_types(
self, self,
_arch: InlineAsmArch, _arch: InlineAsmArch,
) -> &'static [(InlineAsmType, Option<&'static str>)] { ) -> &'static [(InlineAsmType, Option<Symbol>)] {
match self { match self {
Self::reg => types! { _: I8, I16, I32, F32; }, Self::reg => types! { _: I8, I16, I32, F32; },
Self::sreg | Self::sreg_low16 => types! { "vfp2": I32, F32; }, Self::sreg | Self::sreg_low16 => types! { vfp2: I32, F32; },
Self::dreg | Self::dreg_low16 | Self::dreg_low8 => types! { Self::dreg | Self::dreg_low16 | Self::dreg_low8 => types! {
"vfp2": I64, F64, VecI8(8), VecI16(4), VecI32(2), VecI64(1), VecF32(2); vfp2: I64, F64, VecI8(8), VecI16(4), VecI32(2), VecI64(1), VecF32(2);
}, },
Self::qreg | Self::qreg_low8 | Self::qreg_low4 => types! { Self::qreg | Self::qreg_low8 | Self::qreg_low4 => types! {
"neon": VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF32(4); neon: VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF32(4);
}, },
} }
} }
} }
// This uses the same logic as useR7AsFramePointer in LLVM // This uses the same logic as useR7AsFramePointer in LLVM
fn frame_pointer_is_r7(mut has_feature: impl FnMut(&str) -> bool, target: &Target) -> bool { fn frame_pointer_is_r7(target_features: &FxHashSet<Symbol>, target: &Target) -> bool {
target.is_like_osx || (!target.is_like_windows && has_feature("thumb-mode")) target.is_like_osx || (!target.is_like_windows && target_features.contains(&sym::thumb_mode))
} }
fn frame_pointer_r11( fn frame_pointer_r11(
_arch: InlineAsmArch, _arch: InlineAsmArch,
has_feature: impl FnMut(&str) -> bool, target_features: &FxHashSet<Symbol>,
target: &Target, target: &Target,
) -> Result<(), &'static str> { ) -> Result<(), &'static str> {
if !frame_pointer_is_r7(has_feature, target) { if !frame_pointer_is_r7(target_features, target) {
Err("the frame pointer (r11) cannot be used as an operand for inline asm") Err("the frame pointer (r11) cannot be used as an operand for inline asm")
} else { } else {
Ok(()) Ok(())
@ -77,10 +79,10 @@ fn frame_pointer_r11(
fn frame_pointer_r7( fn frame_pointer_r7(
_arch: InlineAsmArch, _arch: InlineAsmArch,
has_feature: impl FnMut(&str) -> bool, target_features: &FxHashSet<Symbol>,
target: &Target, target: &Target,
) -> Result<(), &'static str> { ) -> Result<(), &'static str> {
if frame_pointer_is_r7(has_feature, target) { if frame_pointer_is_r7(target_features, target) {
Err("the frame pointer (r7) cannot be used as an operand for inline asm") Err("the frame pointer (r7) cannot be used as an operand for inline asm")
} else { } else {
Ok(()) Ok(())
@ -89,10 +91,10 @@ fn frame_pointer_r7(
fn not_thumb1( fn not_thumb1(
_arch: InlineAsmArch, _arch: InlineAsmArch,
mut has_feature: impl FnMut(&str) -> bool, target_features: &FxHashSet<Symbol>,
_target: &Target, _target: &Target,
) -> Result<(), &'static str> { ) -> Result<(), &'static str> {
if has_feature("thumb-mode") && !has_feature("thumb2") { if target_features.contains(&sym::thumb_mode) && !target_features.contains(&sym::thumb2) {
Err("high registers (r8+) cannot be used in Thumb-1 code") Err("high registers (r8+) cannot be used in Thumb-1 code")
} else { } else {
Ok(()) Ok(())
@ -101,14 +103,14 @@ fn not_thumb1(
fn reserved_r9( fn reserved_r9(
arch: InlineAsmArch, arch: InlineAsmArch,
mut has_feature: impl FnMut(&str) -> bool, target_features: &FxHashSet<Symbol>,
target: &Target, target: &Target,
) -> Result<(), &'static str> { ) -> Result<(), &'static str> {
not_thumb1(arch, &mut has_feature, target)?; not_thumb1(arch, target_features, target)?;
// We detect this using the reserved-r9 feature instead of using the target // We detect this using the reserved-r9 feature instead of using the target
// because the relocation model can be changed with compiler options. // because the relocation model can be changed with compiler options.
if has_feature("reserved-r9") { if target_features.contains(&sym::reserved_r9) {
Err("the RWPI static base register (r9) cannot be used as an operand for inline asm") Err("the RWPI static base register (r9) cannot be used as an operand for inline asm")
} else { } else {
Ok(()) Ok(())

View file

@ -1,5 +1,6 @@
use super::{InlineAsmArch, InlineAsmType}; use super::{InlineAsmArch, InlineAsmType};
use rustc_macros::HashStable_Generic; use rustc_macros::HashStable_Generic;
use rustc_span::Symbol;
use std::fmt; use std::fmt;
def_reg_class! { def_reg_class! {
@ -39,7 +40,7 @@ impl AvrInlineAsmRegClass {
pub fn supported_types( pub fn supported_types(
self, self,
_arch: InlineAsmArch, _arch: InlineAsmArch,
) -> &'static [(InlineAsmType, Option<&'static str>)] { ) -> &'static [(InlineAsmType, Option<Symbol>)] {
match self { match self {
Self::reg => types! { _: I8; }, Self::reg => types! { _: I8; },
Self::reg_upper => types! { _: I8; }, Self::reg_upper => types! { _: I8; },

View file

@ -1,5 +1,7 @@
use super::{InlineAsmArch, InlineAsmType, Target}; use super::{InlineAsmArch, InlineAsmType, Target};
use rustc_data_structures::stable_set::FxHashSet;
use rustc_macros::HashStable_Generic; use rustc_macros::HashStable_Generic;
use rustc_span::{sym, Symbol};
use std::fmt; use std::fmt;
def_reg_class! { def_reg_class! {
@ -33,20 +35,20 @@ impl BpfInlineAsmRegClass {
pub fn supported_types( pub fn supported_types(
self, self,
_arch: InlineAsmArch, _arch: InlineAsmArch,
) -> &'static [(InlineAsmType, Option<&'static str>)] { ) -> &'static [(InlineAsmType, Option<Symbol>)] {
match self { match self {
Self::reg => types! { _: I8, I16, I32, I64; }, Self::reg => types! { _: I8, I16, I32, I64; },
Self::wreg => types! { "alu32": I8, I16, I32; }, Self::wreg => types! { alu32: I8, I16, I32; },
} }
} }
} }
fn only_alu32( fn only_alu32(
_arch: InlineAsmArch, _arch: InlineAsmArch,
mut has_feature: impl FnMut(&str) -> bool, target_features: &FxHashSet<Symbol>,
_target: &Target, _target: &Target,
) -> Result<(), &'static str> { ) -> Result<(), &'static str> {
if !has_feature("alu32") { if !target_features.contains(&sym::alu32) {
Err("register can't be used without the `alu32` target feature") Err("register can't be used without the `alu32` target feature")
} else { } else {
Ok(()) Ok(())

View file

@ -1,5 +1,6 @@
use super::{InlineAsmArch, InlineAsmType}; use super::{InlineAsmArch, InlineAsmType};
use rustc_macros::HashStable_Generic; use rustc_macros::HashStable_Generic;
use rustc_span::Symbol;
use std::fmt; use std::fmt;
def_reg_class! { def_reg_class! {
@ -32,7 +33,7 @@ impl HexagonInlineAsmRegClass {
pub fn supported_types( pub fn supported_types(
self, self,
_arch: InlineAsmArch, _arch: InlineAsmArch,
) -> &'static [(InlineAsmType, Option<&'static str>)] { ) -> &'static [(InlineAsmType, Option<Symbol>)] {
match self { match self {
Self::reg => types! { _: I8, I16, I32, F32; }, Self::reg => types! { _: I8, I16, I32, F32; },
} }

View file

@ -1,5 +1,6 @@
use super::{InlineAsmArch, InlineAsmType}; use super::{InlineAsmArch, InlineAsmType};
use rustc_macros::HashStable_Generic; use rustc_macros::HashStable_Generic;
use rustc_span::Symbol;
use std::fmt; use std::fmt;
def_reg_class! { def_reg_class! {
@ -33,7 +34,7 @@ impl MipsInlineAsmRegClass {
pub fn supported_types( pub fn supported_types(
self, self,
arch: InlineAsmArch, arch: InlineAsmArch,
) -> &'static [(InlineAsmType, Option<&'static str>)] { ) -> &'static [(InlineAsmType, Option<Symbol>)] {
match (self, arch) { match (self, arch) {
(Self::reg, InlineAsmArch::Mips64) => types! { _: I8, I16, I32, I64, F32, F64; }, (Self::reg, InlineAsmArch::Mips64) => types! { _: I8, I16, I32, I64, F32, F64; },
(Self::reg, _) => types! { _: I8, I16, I32, F32; }, (Self::reg, _) => types! { _: I8, I16, I32, F32; },

View file

@ -81,14 +81,14 @@ macro_rules! def_regs {
pub fn parse( pub fn parse(
_arch: super::InlineAsmArch, _arch: super::InlineAsmArch,
mut _has_feature: impl FnMut(&str) -> bool, _target_features: &rustc_data_structures::fx::FxHashSet<Symbol>,
_target: &crate::spec::Target, _target: &crate::spec::Target,
name: &str, name: &str,
) -> Result<Self, &'static str> { ) -> Result<Self, &'static str> {
match name { match name {
$( $(
$($alias)|* | $reg_name => { $($alias)|* | $reg_name => {
$($filter(_arch, &mut _has_feature, _target)?;)? $($filter(_arch, _target_features, _target)?;)?
Ok(Self::$reg) Ok(Self::$reg)
} }
)* )*
@ -102,7 +102,7 @@ macro_rules! def_regs {
pub(super) fn fill_reg_map( pub(super) fn fill_reg_map(
_arch: super::InlineAsmArch, _arch: super::InlineAsmArch,
mut _has_feature: impl FnMut(&str) -> bool, _target_features: &rustc_data_structures::fx::FxHashSet<Symbol>,
_target: &crate::spec::Target, _target: &crate::spec::Target,
_map: &mut rustc_data_structures::fx::FxHashMap< _map: &mut rustc_data_structures::fx::FxHashMap<
super::InlineAsmRegClass, super::InlineAsmRegClass,
@ -112,7 +112,7 @@ macro_rules! def_regs {
#[allow(unused_imports)] #[allow(unused_imports)]
use super::{InlineAsmReg, InlineAsmRegClass}; 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)) { if let Some(set) = _map.get_mut(&InlineAsmRegClass::$arch($arch_regclass::$class)) {
set.insert(InlineAsmReg::$arch($arch_reg::$reg)); set.insert(InlineAsmReg::$arch($arch_reg::$reg));
} }
@ -130,7 +130,7 @@ macro_rules! def_regs {
macro_rules! types { macro_rules! types {
( (
$(_ : $($ty:expr),+;)? $(_ : $($ty:expr),+;)?
$($feature:literal: $($ty2:expr),+;)* $($feature:ident: $($ty2:expr),+;)*
) => { ) => {
{ {
use super::InlineAsmType::*; use super::InlineAsmType::*;
@ -139,7 +139,7 @@ macro_rules! types {
($ty, None), ($ty, None),
)*)? )*)?
$($( $($(
($ty2, Some($feature)), ($ty2, Some(rustc_span::sym::$feature)),
)*)* )*)*
] ]
} }
@ -289,7 +289,7 @@ impl InlineAsmReg {
pub fn parse( pub fn parse(
arch: InlineAsmArch, arch: InlineAsmArch,
has_feature: impl FnMut(&str) -> bool, target_features: &FxHashSet<Symbol>,
target: &Target, target: &Target,
name: Symbol, name: Symbol,
) -> Result<Self, &'static str> { ) -> Result<Self, &'static str> {
@ -298,43 +298,43 @@ impl InlineAsmReg {
let name = name.as_str(); let name = name.as_str();
Ok(match arch { Ok(match arch {
InlineAsmArch::X86 | InlineAsmArch::X86_64 => { 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 => { InlineAsmArch::Arm => {
Self::Arm(ArmInlineAsmReg::parse(arch, has_feature, target, name)?) Self::Arm(ArmInlineAsmReg::parse(arch, target_features, target, name)?)
} }
InlineAsmArch::AArch64 => { InlineAsmArch::AArch64 => {
Self::AArch64(AArch64InlineAsmReg::parse(arch, has_feature, target, name)?) Self::AArch64(AArch64InlineAsmReg::parse(arch, target_features, target, name)?)
} }
InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => { InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => {
Self::RiscV(RiscVInlineAsmReg::parse(arch, has_feature, target, name)?) Self::RiscV(RiscVInlineAsmReg::parse(arch, target_features, target, name)?)
} }
InlineAsmArch::Nvptx64 => { InlineAsmArch::Nvptx64 => {
Self::Nvptx(NvptxInlineAsmReg::parse(arch, has_feature, target, name)?) Self::Nvptx(NvptxInlineAsmReg::parse(arch, target_features, target, name)?)
} }
InlineAsmArch::PowerPC | InlineAsmArch::PowerPC64 => { InlineAsmArch::PowerPC | InlineAsmArch::PowerPC64 => {
Self::PowerPC(PowerPCInlineAsmReg::parse(arch, has_feature, target, name)?) Self::PowerPC(PowerPCInlineAsmReg::parse(arch, target_features, target, name)?)
} }
InlineAsmArch::Hexagon => { InlineAsmArch::Hexagon => {
Self::Hexagon(HexagonInlineAsmReg::parse(arch, has_feature, target, name)?) Self::Hexagon(HexagonInlineAsmReg::parse(arch, target_features, target, name)?)
} }
InlineAsmArch::Mips | InlineAsmArch::Mips64 => { InlineAsmArch::Mips | InlineAsmArch::Mips64 => {
Self::Mips(MipsInlineAsmReg::parse(arch, has_feature, target, name)?) Self::Mips(MipsInlineAsmReg::parse(arch, target_features, target, name)?)
} }
InlineAsmArch::S390x => { InlineAsmArch::S390x => {
Self::S390x(S390xInlineAsmReg::parse(arch, has_feature, target, name)?) Self::S390x(S390xInlineAsmReg::parse(arch, target_features, target, name)?)
} }
InlineAsmArch::SpirV => { InlineAsmArch::SpirV => {
Self::SpirV(SpirVInlineAsmReg::parse(arch, has_feature, target, name)?) Self::SpirV(SpirVInlineAsmReg::parse(arch, target_features, target, name)?)
} }
InlineAsmArch::Wasm32 | InlineAsmArch::Wasm64 => { InlineAsmArch::Wasm32 | InlineAsmArch::Wasm64 => {
Self::Wasm(WasmInlineAsmReg::parse(arch, has_feature, target, name)?) Self::Wasm(WasmInlineAsmReg::parse(arch, target_features, target, name)?)
} }
InlineAsmArch::Bpf => { InlineAsmArch::Bpf => {
Self::Bpf(BpfInlineAsmReg::parse(arch, has_feature, target, name)?) Self::Bpf(BpfInlineAsmReg::parse(arch, target_features, target, name)?)
} }
InlineAsmArch::Avr => { InlineAsmArch::Avr => {
Self::Avr(AvrInlineAsmReg::parse(arch, has_feature, target, name)?) Self::Avr(AvrInlineAsmReg::parse(arch, target_features, target, name)?)
} }
}) })
} }
@ -510,7 +510,7 @@ impl InlineAsmRegClass {
pub fn supported_types( pub fn supported_types(
self, self,
arch: InlineAsmArch, arch: InlineAsmArch,
) -> &'static [(InlineAsmType, Option<&'static str>)] { ) -> &'static [(InlineAsmType, Option<Symbol>)] {
match self { match self {
Self::X86(r) => r.supported_types(arch), Self::X86(r) => r.supported_types(arch),
Self::Arm(r) => r.supported_types(arch), Self::Arm(r) => r.supported_types(arch),
@ -695,73 +695,73 @@ impl fmt::Display for InlineAsmType {
// falling back to an external assembler. // falling back to an external assembler.
pub fn allocatable_registers( pub fn allocatable_registers(
arch: InlineAsmArch, arch: InlineAsmArch,
has_feature: impl FnMut(&str) -> bool, target_features: &FxHashSet<Symbol>,
target: &crate::spec::Target, target: &crate::spec::Target,
) -> FxHashMap<InlineAsmRegClass, FxHashSet<InlineAsmReg>> { ) -> FxHashMap<InlineAsmRegClass, FxHashSet<InlineAsmReg>> {
match arch { match arch {
InlineAsmArch::X86 | InlineAsmArch::X86_64 => { InlineAsmArch::X86 | InlineAsmArch::X86_64 => {
let mut map = x86::regclass_map(); 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 map
} }
InlineAsmArch::Arm => { InlineAsmArch::Arm => {
let mut map = arm::regclass_map(); 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 map
} }
InlineAsmArch::AArch64 => { InlineAsmArch::AArch64 => {
let mut map = aarch64::regclass_map(); 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 map
} }
InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => { InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => {
let mut map = riscv::regclass_map(); 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 map
} }
InlineAsmArch::Nvptx64 => { InlineAsmArch::Nvptx64 => {
let mut map = nvptx::regclass_map(); 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 map
} }
InlineAsmArch::PowerPC | InlineAsmArch::PowerPC64 => { InlineAsmArch::PowerPC | InlineAsmArch::PowerPC64 => {
let mut map = powerpc::regclass_map(); 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 map
} }
InlineAsmArch::Hexagon => { InlineAsmArch::Hexagon => {
let mut map = hexagon::regclass_map(); 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 map
} }
InlineAsmArch::Mips | InlineAsmArch::Mips64 => { InlineAsmArch::Mips | InlineAsmArch::Mips64 => {
let mut map = mips::regclass_map(); 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 map
} }
InlineAsmArch::S390x => { InlineAsmArch::S390x => {
let mut map = s390x::regclass_map(); 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 map
} }
InlineAsmArch::SpirV => { InlineAsmArch::SpirV => {
let mut map = spirv::regclass_map(); 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 map
} }
InlineAsmArch::Wasm32 | InlineAsmArch::Wasm64 => { InlineAsmArch::Wasm32 | InlineAsmArch::Wasm64 => {
let mut map = wasm::regclass_map(); 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 map
} }
InlineAsmArch::Bpf => { InlineAsmArch::Bpf => {
let mut map = bpf::regclass_map(); 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 map
} }
InlineAsmArch::Avr => { InlineAsmArch::Avr => {
let mut map = avr::regclass_map(); let mut map = avr::regclass_map();
avr::fill_reg_map(arch, has_feature, target, &mut map); avr::fill_reg_map(arch, target_features, target, &mut map);
map map
} }
} }
@ -794,7 +794,7 @@ impl InlineAsmClobberAbi {
/// clobber ABIs for the target. /// clobber ABIs for the target.
pub fn parse( pub fn parse(
arch: InlineAsmArch, arch: InlineAsmArch,
has_feature: impl FnMut(&str) -> bool, target_features: &FxHashSet<Symbol>,
target: &Target, target: &Target,
name: Symbol, name: Symbol,
) -> Result<Self, &'static [&'static str]> { ) -> Result<Self, &'static [&'static str]> {
@ -819,7 +819,7 @@ impl InlineAsmClobberAbi {
}, },
InlineAsmArch::AArch64 => match name { InlineAsmArch::AArch64 => match name {
"C" | "system" | "efiapi" => { "C" | "system" | "efiapi" => {
Ok(if aarch64::reserved_x18(arch, has_feature, target).is_err() { Ok(if aarch64::reserved_x18(arch, target_features, target).is_err() {
InlineAsmClobberAbi::AArch64NoX18 InlineAsmClobberAbi::AArch64NoX18
} else { } else {
InlineAsmClobberAbi::AArch64 InlineAsmClobberAbi::AArch64

View file

@ -1,5 +1,6 @@
use super::{InlineAsmArch, InlineAsmType}; use super::{InlineAsmArch, InlineAsmType};
use rustc_macros::HashStable_Generic; use rustc_macros::HashStable_Generic;
use rustc_span::Symbol;
def_reg_class! { def_reg_class! {
Nvptx NvptxInlineAsmRegClass { Nvptx NvptxInlineAsmRegClass {
@ -33,7 +34,7 @@ impl NvptxInlineAsmRegClass {
pub fn supported_types( pub fn supported_types(
self, self,
_arch: InlineAsmArch, _arch: InlineAsmArch,
) -> &'static [(InlineAsmType, Option<&'static str>)] { ) -> &'static [(InlineAsmType, Option<Symbol>)] {
match self { match self {
Self::reg16 => types! { _: I8, I16; }, Self::reg16 => types! { _: I8, I16; },
Self::reg32 => types! { _: I8, I16, I32, F32; }, Self::reg32 => types! { _: I8, I16, I32, F32; },

View file

@ -1,5 +1,6 @@
use super::{InlineAsmArch, InlineAsmType}; use super::{InlineAsmArch, InlineAsmType};
use rustc_macros::HashStable_Generic; use rustc_macros::HashStable_Generic;
use rustc_span::Symbol;
use std::fmt; use std::fmt;
def_reg_class! { def_reg_class! {
@ -36,7 +37,7 @@ impl PowerPCInlineAsmRegClass {
pub fn supported_types( pub fn supported_types(
self, self,
arch: InlineAsmArch, arch: InlineAsmArch,
) -> &'static [(InlineAsmType, Option<&'static str>)] { ) -> &'static [(InlineAsmType, Option<Symbol>)] {
match self { match self {
Self::reg | Self::reg_nonzero => { Self::reg | Self::reg_nonzero => {
if arch == InlineAsmArch::PowerPC { if arch == InlineAsmArch::PowerPC {

View file

@ -1,6 +1,8 @@
use super::{InlineAsmArch, InlineAsmType}; use super::{InlineAsmArch, InlineAsmType};
use crate::spec::Target; use crate::spec::Target;
use rustc_data_structures::stable_set::FxHashSet;
use rustc_macros::HashStable_Generic; use rustc_macros::HashStable_Generic;
use rustc_span::{sym, Symbol};
use std::fmt; use std::fmt;
def_reg_class! { def_reg_class! {
@ -35,7 +37,7 @@ impl RiscVInlineAsmRegClass {
pub fn supported_types( pub fn supported_types(
self, self,
arch: InlineAsmArch, arch: InlineAsmArch,
) -> &'static [(InlineAsmType, Option<&'static str>)] { ) -> &'static [(InlineAsmType, Option<Symbol>)] {
match self { match self {
Self::reg => { Self::reg => {
if arch == InlineAsmArch::RiscV64 { if arch == InlineAsmArch::RiscV64 {
@ -44,7 +46,7 @@ impl RiscVInlineAsmRegClass {
types! { _: I8, I16, I32, F32; } types! { _: I8, I16, I32, F32; }
} }
} }
Self::freg => types! { "f": F32; "d": F64; }, Self::freg => types! { f: F32; d: F64; },
Self::vreg => &[], Self::vreg => &[],
} }
} }
@ -52,10 +54,10 @@ impl RiscVInlineAsmRegClass {
fn not_e( fn not_e(
_arch: InlineAsmArch, _arch: InlineAsmArch,
mut has_feature: impl FnMut(&str) -> bool, target_features: &FxHashSet<Symbol>,
_target: &Target, _target: &Target,
) -> Result<(), &'static str> { ) -> Result<(), &'static str> {
if has_feature("e") { if target_features.contains(&sym::e) {
Err("register can't be used with the `e` target feature") Err("register can't be used with the `e` target feature")
} else { } else {
Ok(()) Ok(())

View file

@ -1,5 +1,6 @@
use super::{InlineAsmArch, InlineAsmType}; use super::{InlineAsmArch, InlineAsmType};
use rustc_macros::HashStable_Generic; use rustc_macros::HashStable_Generic;
use rustc_span::Symbol;
use std::fmt; use std::fmt;
def_reg_class! { def_reg_class! {
@ -33,7 +34,7 @@ impl S390xInlineAsmRegClass {
pub fn supported_types( pub fn supported_types(
self, self,
arch: InlineAsmArch, arch: InlineAsmArch,
) -> &'static [(InlineAsmType, Option<&'static str>)] { ) -> &'static [(InlineAsmType, Option<Symbol>)] {
match (self, arch) { match (self, arch) {
(Self::reg, _) => types! { _: I8, I16, I32, I64; }, (Self::reg, _) => types! { _: I8, I16, I32, I64; },
(Self::freg, _) => types! { _: F32, F64; }, (Self::freg, _) => types! { _: F32, F64; },

View file

@ -1,5 +1,6 @@
use super::{InlineAsmArch, InlineAsmType}; use super::{InlineAsmArch, InlineAsmType};
use rustc_macros::HashStable_Generic; use rustc_macros::HashStable_Generic;
use rustc_span::Symbol;
def_reg_class! { def_reg_class! {
SpirV SpirVInlineAsmRegClass { SpirV SpirVInlineAsmRegClass {
@ -31,7 +32,7 @@ impl SpirVInlineAsmRegClass {
pub fn supported_types( pub fn supported_types(
self, self,
_arch: InlineAsmArch, _arch: InlineAsmArch,
) -> &'static [(InlineAsmType, Option<&'static str>)] { ) -> &'static [(InlineAsmType, Option<Symbol>)] {
match self { match self {
Self::reg => { Self::reg => {
types! { _: I8, I16, I32, I64, F32, F64; } types! { _: I8, I16, I32, I64, F32, F64; }

View file

@ -1,5 +1,6 @@
use super::{InlineAsmArch, InlineAsmType}; use super::{InlineAsmArch, InlineAsmType};
use rustc_macros::HashStable_Generic; use rustc_macros::HashStable_Generic;
use rustc_span::Symbol;
def_reg_class! { def_reg_class! {
Wasm WasmInlineAsmRegClass { Wasm WasmInlineAsmRegClass {
@ -31,7 +32,7 @@ impl WasmInlineAsmRegClass {
pub fn supported_types( pub fn supported_types(
self, self,
_arch: InlineAsmArch, _arch: InlineAsmArch,
) -> &'static [(InlineAsmType, Option<&'static str>)] { ) -> &'static [(InlineAsmType, Option<Symbol>)] {
match self { match self {
Self::local => { Self::local => {
types! { _: I8, I16, I32, I64, F32, F64; } types! { _: I8, I16, I32, I64, F32, F64; }

View file

@ -1,6 +1,8 @@
use super::{InlineAsmArch, InlineAsmType}; use super::{InlineAsmArch, InlineAsmType};
use crate::spec::Target; use crate::spec::Target;
use rustc_data_structures::stable_set::FxHashSet;
use rustc_macros::HashStable_Generic; use rustc_macros::HashStable_Generic;
use rustc_span::Symbol;
use std::fmt; use std::fmt;
def_reg_class! { def_reg_class! {
@ -101,7 +103,7 @@ impl X86InlineAsmRegClass {
pub fn supported_types( pub fn supported_types(
self, self,
arch: InlineAsmArch, arch: InlineAsmArch,
) -> &'static [(InlineAsmType, Option<&'static str>)] { ) -> &'static [(InlineAsmType, Option<Symbol>)] {
match self { match self {
Self::reg | Self::reg_abcd => { Self::reg | Self::reg_abcd => {
if arch == InlineAsmArch::X86_64 { if arch == InlineAsmArch::X86_64 {
@ -112,23 +114,23 @@ impl X86InlineAsmRegClass {
} }
Self::reg_byte => types! { _: I8; }, Self::reg_byte => types! { _: I8; },
Self::xmm_reg => types! { Self::xmm_reg => types! {
"sse": I32, I64, F32, F64, sse: I32, I64, F32, F64,
VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF32(4), VecF64(2); VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF32(4), VecF64(2);
}, },
Self::ymm_reg => types! { Self::ymm_reg => types! {
"avx": I32, I64, F32, F64, avx: I32, I64, F32, F64,
VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF32(4), VecF64(2), VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF32(4), VecF64(2),
VecI8(32), VecI16(16), VecI32(8), VecI64(4), VecF32(8), VecF64(4); VecI8(32), VecI16(16), VecI32(8), VecI64(4), VecF32(8), VecF64(4);
}, },
Self::zmm_reg => types! { Self::zmm_reg => types! {
"avx512f": I32, I64, F32, F64, avx512f: I32, I64, F32, F64,
VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF32(4), VecF64(2), VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF32(4), VecF64(2),
VecI8(32), VecI16(16), VecI32(8), VecI64(4), VecF32(8), VecF64(4), VecI8(32), VecI16(16), VecI32(8), VecI64(4), VecF32(8), VecF64(4),
VecI8(64), VecI16(32), VecI32(16), VecI64(8), VecF32(16), VecF64(8); VecI8(64), VecI16(32), VecI32(16), VecI64(8), VecF32(16), VecF64(8);
}, },
Self::kreg => types! { Self::kreg => types! {
"avx512f": I8, I16; avx512f: I8, I16;
"avx512bw": I32, I64; avx512bw: I32, I64;
}, },
Self::mmx_reg | Self::x87_reg => &[], Self::mmx_reg | Self::x87_reg => &[],
} }
@ -137,7 +139,7 @@ impl X86InlineAsmRegClass {
fn x86_64_only( fn x86_64_only(
arch: InlineAsmArch, arch: InlineAsmArch,
_has_feature: impl FnMut(&str) -> bool, _target_features: &FxHashSet<Symbol>,
_target: &Target, _target: &Target,
) -> Result<(), &'static str> { ) -> Result<(), &'static str> {
match arch { match arch {
@ -149,7 +151,7 @@ fn x86_64_only(
fn high_byte( fn high_byte(
arch: InlineAsmArch, arch: InlineAsmArch,
_has_feature: impl FnMut(&str) -> bool, _target_features: &FxHashSet<Symbol>,
_target: &Target, _target: &Target,
) -> Result<(), &'static str> { ) -> Result<(), &'static str> {
match arch { match arch {
@ -160,7 +162,7 @@ fn high_byte(
fn rbx_reserved( fn rbx_reserved(
arch: InlineAsmArch, arch: InlineAsmArch,
_has_feature: impl FnMut(&str) -> bool, _target_features: &FxHashSet<Symbol>,
_target: &Target, _target: &Target,
) -> Result<(), &'static str> { ) -> Result<(), &'static str> {
match arch { match arch {
@ -174,7 +176,7 @@ fn rbx_reserved(
fn esi_reserved( fn esi_reserved(
arch: InlineAsmArch, arch: InlineAsmArch,
_has_feature: impl FnMut(&str) -> bool, _target_features: &FxHashSet<Symbol>,
_target: &Target, _target: &Target,
) -> Result<(), &'static str> { ) -> Result<(), &'static str> {
match arch { match arch {