From f5cbb9b9e6e8c2d2e1932b0e7b6556f689d44b0d Mon Sep 17 00:00:00 2001
From: Yuki Okushi <yuki.okushi@huawei.com>
Date: Sat, 16 Oct 2021 14:04:21 +0900
Subject: [PATCH 1/4] Fix some typos

---
 compiler/rustc_ast_lowering/src/asm.rs | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs
index 957b14f3487..8aea37749c7 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")

From 630df7c54ab1b6d227893aae98bfdbf77228e637 Mon Sep 17 00:00:00 2001
From: Yuki Okushi <yuki.okushi@huawei.com>
Date: Tue, 19 Oct 2021 11:34:58 +0900
Subject: [PATCH 2/4] Remove unnecessary check for registers

`is_clobber()` already checks if `reg` is a register and the both
values should be the same.
---
 compiler/rustc_ast_lowering/src/asm.rs | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs
index 8aea37749c7..d0da88f1cc0 100644
--- a/compiler/rustc_ast_lowering/src/asm.rs
+++ b/compiler/rustc_ast_lowering/src/asm.rs
@@ -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",

From bd309e4628f5d7d1fa6cbe6a1776e74bcac6292a Mon Sep 17 00:00:00 2001
From: Yuki Okushi <yuki.okushi@huawei.com>
Date: Wed, 20 Oct 2021 04:50:34 +0900
Subject: [PATCH 3/4] Add a regression test for issue-89875

---
 src/test/ui/asm/x86_64/issue-89875.rs | 14 ++++++++++++++
 1 file changed, 14 insertions(+)
 create mode 100644 src/test/ui/asm/x86_64/issue-89875.rs

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 00000000000..9b2b21bbda6
--- /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) _,
+        );
+    }
+}

From 12647eab7945df1ceddd4d191cdb489abfb05276 Mon Sep 17 00:00:00 2001
From: Yuki Okushi <yuki.okushi@huawei.com>
Date: Thu, 21 Oct 2021 04:56:36 +0900
Subject: [PATCH 4/4] Properly check `target_features` not to trigger an
 assertion

---
 compiler/rustc_codegen_gcc/src/asm.rs        | 2 +-
 compiler/rustc_codegen_llvm/src/asm.rs       | 8 ++++++--
 compiler/rustc_codegen_ssa/src/mir/block.rs  | 4 +++-
 compiler/rustc_codegen_ssa/src/traits/asm.rs | 1 +
 4 files changed, 11 insertions(+), 4 deletions(-)

diff --git a/compiler/rustc_codegen_gcc/src/asm.rs b/compiler/rustc_codegen_gcc/src/asm.rs
index 3b77097e9ad..7c3ed3c5ee9 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 341a8882416..f128f769580 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 b0a5631549d..7c25438380a 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<mir::BasicBlock>,
+        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 86f2781a766..31f539e1b03 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<'_>,
     );
 }