diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index 957b14f348729..d0da88f1cc095 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -11,8 +11,8 @@ use std::fmt::Write; impl<'a, 'hir> LoweringContext<'a, 'hir> { crate fn lower_inline_asm(&mut self, sp: Span, asm: &InlineAsm) -> &'hir hir::InlineAsm<'hir> { - // Rustdoc needs to support asm! from foriegn architectures: don't try - // lowering the register contraints in this case. + // Rustdoc needs to support asm! from foreign architectures: don't try + // lowering the register constraints in this case. let asm_arch = if self.sess.opts.actually_rustdoc { None } else { self.sess.asm_arch }; if asm_arch.is_none() && !self.sess.opts.actually_rustdoc { struct_span_err!(self.sess, sp, E0472, "inline assembly is unsupported on this target") @@ -214,9 +214,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { // means that we disallow passing a value in/out of the asm and // require that the operand name an explicit register, not a // register class. - if reg_class.is_clobber_only(asm_arch.unwrap()) - && !(op.is_clobber() && matches!(reg, asm::InlineAsmRegOrRegClass::Reg(_))) - { + if reg_class.is_clobber_only(asm_arch.unwrap()) && !op.is_clobber() { let msg = format!( "register class `{}` can only be used as a clobber, \ not as an input or output", diff --git a/compiler/rustc_codegen_gcc/src/asm.rs b/compiler/rustc_codegen_gcc/src/asm.rs index 3b77097e9ad00..7c3ed3c5ee9db 100644 --- a/compiler/rustc_codegen_gcc/src/asm.rs +++ b/compiler/rustc_codegen_gcc/src/asm.rs @@ -118,7 +118,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { true } - fn codegen_inline_asm(&mut self, template: &[InlineAsmTemplatePiece], rust_operands: &[InlineAsmOperandRef<'tcx, Self>], options: InlineAsmOptions, _span: &[Span]) { + fn codegen_inline_asm(&mut self, template: &[InlineAsmTemplatePiece], rust_operands: &[InlineAsmOperandRef<'tcx, Self>], options: InlineAsmOptions, _span: &[Span], _instance: Instance<'_>) { let asm_arch = self.tcx.sess.asm_arch.unwrap(); let is_x86 = matches!(asm_arch, InlineAsmArch::X86 | InlineAsmArch::X86_64); let att_dialect = is_x86 && options.contains(InlineAsmOptions::ATT_SYNTAX); diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index 341a888241698..f128f76958092 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -13,7 +13,7 @@ use rustc_codegen_ssa::traits::*; use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; use rustc_middle::ty::layout::TyAndLayout; -use rustc_middle::{bug, span_bug}; +use rustc_middle::{bug, span_bug, ty::Instance}; use rustc_span::{Pos, Span, Symbol}; use rustc_target::abi::*; use rustc_target::asm::*; @@ -120,6 +120,7 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { operands: &[InlineAsmOperandRef<'tcx, Self>], options: InlineAsmOptions, line_spans: &[Span], + instance: Instance<'_>, ) { let asm_arch = self.tcx.sess.asm_arch.unwrap(); @@ -135,7 +136,10 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> { let is_target_supported = |reg_class: InlineAsmRegClass| { for &(_, feature) in reg_class.supported_types(asm_arch) { if let Some(feature) = feature { - if self.tcx.sess.target_features.contains(&Symbol::intern(feature)) + 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_name) + || codegen_fn_attrs.target_features.contains(&feature_name) { return true; } diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index b0a5631549df8..7c25438380a10 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -845,6 +845,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { options: ast::InlineAsmOptions, line_spans: &[Span], destination: Option, + instance: Instance<'_>, ) { let span = terminator.source_info.span; @@ -898,7 +899,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { }) .collect(); - bx.codegen_inline_asm(template, &operands, options, line_spans); + bx.codegen_inline_asm(template, &operands, options, line_spans, instance); if let Some(target) = destination { helper.funclet_br(self, &mut bx, target); @@ -1029,6 +1030,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { options, line_spans, destination, + self.instance, ); } } diff --git a/compiler/rustc_codegen_ssa/src/traits/asm.rs b/compiler/rustc_codegen_ssa/src/traits/asm.rs index 86f2781a7663b..31f539e1b03db 100644 --- a/compiler/rustc_codegen_ssa/src/traits/asm.rs +++ b/compiler/rustc_codegen_ssa/src/traits/asm.rs @@ -58,6 +58,7 @@ pub trait AsmBuilderMethods<'tcx>: BackendTypes { operands: &[InlineAsmOperandRef<'tcx, Self>], options: InlineAsmOptions, line_spans: &[Span], + instance: Instance<'_>, ); } diff --git a/src/test/ui/asm/x86_64/issue-89875.rs b/src/test/ui/asm/x86_64/issue-89875.rs new file mode 100644 index 0000000000000..9b2b21bbda661 --- /dev/null +++ b/src/test/ui/asm/x86_64/issue-89875.rs @@ -0,0 +1,14 @@ +// build-pass +// only-x86_64 + +#![feature(asm, target_feature_11)] + +#[target_feature(enable = "avx")] +fn main() { + unsafe { + asm!( + "/* {} */", + out(ymm_reg) _, + ); + } +}