]> git.proxmox.com Git - rustc.git/blobdiff - compiler/rustc_ast_lowering/src/asm.rs
New upstream version 1.56.0~beta.4+dfsg1
[rustc.git] / compiler / rustc_ast_lowering / src / asm.rs
index 9ea09a2cf31a15f46d50abc8418346d923b5868f..7165b3bcb9fc1eee77267759de7c315c8e02548f 100644 (file)
@@ -27,11 +27,41 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 .emit();
         }
 
+        let mut clobber_abi = None;
+        if let Some(asm_arch) = asm_arch {
+            if let Some((abi_name, abi_span)) = asm.clobber_abi {
+                match asm::InlineAsmClobberAbi::parse(asm_arch, &self.sess.target, abi_name) {
+                    Ok(abi) => clobber_abi = Some((abi, abi_span)),
+                    Err(&[]) => {
+                        self.sess
+                            .struct_span_err(
+                                abi_span,
+                                "`clobber_abi` is not supported on this target",
+                            )
+                            .emit();
+                    }
+                    Err(supported_abis) => {
+                        let mut err =
+                            self.sess.struct_span_err(abi_span, "invalid ABI for `clobber_abi`");
+                        let mut abis = format!("`{}`", supported_abis[0]);
+                        for m in &supported_abis[1..] {
+                            let _ = write!(abis, ", `{}`", m);
+                        }
+                        err.note(&format!(
+                            "the following ABIs are supported on this target: {}",
+                            abis
+                        ));
+                        err.emit();
+                    }
+                }
+            }
+        }
+
         // Lower operands to HIR. We use dummy register classes if an error
         // occurs during lowering because we still need to be able to produce a
         // valid HIR.
         let sess = self.sess;
-        let operands: Vec<_> = asm
+        let mut operands: Vec<_> = asm
             .operands
             .iter()
             .map(|(op, op_sp)| {
@@ -98,7 +128,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                         hir::InlineAsmOperand::Sym { expr: self.lower_expr_mut(expr) }
                     }
                 };
-                (op, *op_sp)
+                (op, self.lower_span(*op_sp))
             })
             .collect();
 
@@ -336,10 +366,41 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             }
         }
 
+        // If a clobber_abi is specified, add the necessary clobbers to the
+        // operands list.
+        if let Some((abi, abi_span)) = clobber_abi {
+            for &clobber in abi.clobbered_regs() {
+                let mut output_used = false;
+                clobber.overlapping_regs(|reg| {
+                    if used_output_regs.contains_key(&reg) {
+                        output_used = true;
+                    }
+                });
+
+                if !output_used {
+                    operands.push((
+                        hir::InlineAsmOperand::Out {
+                            reg: asm::InlineAsmRegOrRegClass::Reg(clobber),
+                            late: true,
+                            expr: None,
+                        },
+                        self.lower_span(abi_span),
+                    ));
+                }
+            }
+        }
+
         let operands = self.arena.alloc_from_iter(operands);
         let template = self.arena.alloc_from_iter(asm.template.iter().cloned());
-        let line_spans = self.arena.alloc_slice(&asm.line_spans[..]);
-        let hir_asm = hir::InlineAsm { template, operands, options: asm.options, line_spans };
+        let template_strs = self.arena.alloc_from_iter(
+            asm.template_strs
+                .iter()
+                .map(|(sym, snippet, span)| (*sym, *snippet, self.lower_span(*span))),
+        );
+        let line_spans =
+            self.arena.alloc_from_iter(asm.line_spans.iter().map(|span| self.lower_span(*span)));
+        let hir_asm =
+            hir::InlineAsm { template, template_strs, operands, options: asm.options, line_spans };
         self.arena.alloc(hir_asm)
     }
 }