about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_ast_lowering/expr.rs68
-rw-r--r--src/test/ui/asm/issue-72570.rs7
2 files changed, 42 insertions, 33 deletions
diff --git a/src/librustc_ast_lowering/expr.rs b/src/librustc_ast_lowering/expr.rs
index 5bcd111706f..d8002bd3e19 100644
--- a/src/librustc_ast_lowering/expr.rs
+++ b/src/librustc_ast_lowering/expr.rs
@@ -974,20 +974,18 @@ impl<'hir> LoweringContext<'_, 'hir> {
     }
 
     fn lower_expr_asm(&mut self, sp: Span, asm: &InlineAsm) -> hir::ExprKind<'hir> {
-        let asm_arch = if let Some(asm_arch) = self.sess.asm_arch {
-            asm_arch
-        } else {
+        if self.sess.asm_arch.is_none() {
             struct_span_err!(self.sess, sp, E0472, "asm! is unsupported on this target").emit();
-            return hir::ExprKind::Err;
         };
-        if asm.options.contains(InlineAsmOptions::ATT_SYNTAX) {
-            match asm_arch {
-                asm::InlineAsmArch::X86 | asm::InlineAsmArch::X86_64 => {}
-                _ => self
-                    .sess
-                    .struct_span_err(sp, "the `att_syntax` option is only supported on x86")
-                    .emit(),
-            }
+        if asm.options.contains(InlineAsmOptions::ATT_SYNTAX)
+            && !matches!(
+                self.sess.asm_arch,
+                Some(asm::InlineAsmArch::X86 | asm::InlineAsmArch::X86_64)
+            )
+        {
+            self.sess
+                .struct_span_err(sp, "the `att_syntax` option is only supported on x86")
+                .emit();
         }
 
         // Lower operands to HIR, filter_map skips any operands with invalid
@@ -1001,10 +999,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     Some(match reg {
                         InlineAsmRegOrRegClass::Reg(s) => asm::InlineAsmRegOrRegClass::Reg(
                             asm::InlineAsmReg::parse(
-                                asm_arch,
-                                |feature| {
-                                    self.sess.target_features.contains(&Symbol::intern(feature))
-                                },
+                                sess.asm_arch?,
+                                |feature| sess.target_features.contains(&Symbol::intern(feature)),
                                 s,
                             )
                             .map_err(|e| {
@@ -1015,7 +1011,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                         ),
                         InlineAsmRegOrRegClass::RegClass(s) => {
                             asm::InlineAsmRegOrRegClass::RegClass(
-                                asm::InlineAsmRegClass::parse(asm_arch, s)
+                                asm::InlineAsmRegClass::parse(sess.asm_arch?, s)
                                     .map_err(|e| {
                                         let msg = format!(
                                             "invalid register class `{}`: {}",
@@ -1029,33 +1025,38 @@ impl<'hir> LoweringContext<'_, 'hir> {
                         }
                     })
                 };
-                let op = match op {
-                    InlineAsmOperand::In { reg, expr } => hir::InlineAsmOperand::In {
-                        reg: lower_reg(*reg)?,
+
+                // lower_reg is executed last because we need to lower all
+                // sub-expressions even if we throw them away later.
+                let op = match *op {
+                    InlineAsmOperand::In { reg, ref expr } => hir::InlineAsmOperand::In {
                         expr: self.lower_expr_mut(expr),
+                        reg: lower_reg(reg)?,
                     },
-                    InlineAsmOperand::Out { reg, late, expr } => hir::InlineAsmOperand::Out {
-                        reg: lower_reg(*reg)?,
-                        late: *late,
+                    InlineAsmOperand::Out { reg, late, ref expr } => hir::InlineAsmOperand::Out {
+                        late,
                         expr: expr.as_ref().map(|expr| self.lower_expr_mut(expr)),
+                        reg: lower_reg(reg)?,
                     },
-                    InlineAsmOperand::InOut { reg, late, expr } => hir::InlineAsmOperand::InOut {
-                        reg: lower_reg(*reg)?,
-                        late: *late,
-                        expr: self.lower_expr_mut(expr),
-                    },
-                    InlineAsmOperand::SplitInOut { reg, late, in_expr, out_expr } => {
+                    InlineAsmOperand::InOut { reg, late, ref expr } => {
+                        hir::InlineAsmOperand::InOut {
+                            late,
+                            expr: self.lower_expr_mut(expr),
+                            reg: lower_reg(reg)?,
+                        }
+                    }
+                    InlineAsmOperand::SplitInOut { reg, late, ref in_expr, ref out_expr } => {
                         hir::InlineAsmOperand::SplitInOut {
-                            reg: lower_reg(*reg)?,
-                            late: *late,
+                            late,
                             in_expr: self.lower_expr_mut(in_expr),
                             out_expr: out_expr.as_ref().map(|expr| self.lower_expr_mut(expr)),
+                            reg: lower_reg(reg)?,
                         }
                     }
-                    InlineAsmOperand::Const { expr } => {
+                    InlineAsmOperand::Const { ref expr } => {
                         hir::InlineAsmOperand::Const { expr: self.lower_expr_mut(expr) }
                     }
-                    InlineAsmOperand::Sym { expr } => {
+                    InlineAsmOperand::Sym { ref expr } => {
                         hir::InlineAsmOperand::Sym { expr: self.lower_expr_mut(expr) }
                     }
                 };
@@ -1069,6 +1070,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         }
 
         // Validate template modifiers against the register classes for the operands
+        let asm_arch = sess.asm_arch.unwrap();
         for p in &asm.template {
             if let InlineAsmTemplatePiece::Placeholder {
                 operand_idx,
diff --git a/src/test/ui/asm/issue-72570.rs b/src/test/ui/asm/issue-72570.rs
new file mode 100644
index 00000000000..df508e90458
--- /dev/null
+++ b/src/test/ui/asm/issue-72570.rs
@@ -0,0 +1,7 @@
+#![feature(asm)]
+
+fn main() {
+    unsafe {
+        asm!("", in("invalid") "".len());
+    }
+}