about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAmanieu d'Antras <amanieu@gmail.com>2020-02-12 17:32:41 +0000
committerAmanieu d'Antras <amanieu@gmail.com>2020-05-18 14:39:54 +0100
commitd5b1501d8c3deda64c5b43ce2c9a0c51dd91169a (patch)
treeaaee3ee5b6b1c32f92db1582b1b3a6ee12389366
parenta0adf53bc97d6e79c8c2e9b3f8a548bc65c7adf6 (diff)
downloadrust-d5b1501d8c3deda64c5b43ce2c9a0c51dd91169a.tar.gz
rust-d5b1501d8c3deda64c5b43ce2c9a0c51dd91169a.zip
Add asm! to HIR
-rw-r--r--src/librustc_hir/hir.rs54
-rw-r--r--src/librustc_hir/intravisit.rs21
-rw-r--r--src/librustc_hir_pretty/lib.rs102
3 files changed, 177 insertions, 0 deletions
diff --git a/src/librustc_hir/hir.rs b/src/librustc_hir/hir.rs
index eafff6705ba..19cea3a3466 100644
--- a/src/librustc_hir/hir.rs
+++ b/src/librustc_hir/hir.rs
@@ -15,6 +15,7 @@ use rustc_macros::HashStable_Generic;
 use rustc_span::source_map::{SourceMap, Spanned};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{MultiSpan, Span, DUMMY_SP};
+use rustc_target::asm::{InlineAsmOptions, InlineAsmRegOrRegClass, InlineAsmTemplatePiece};
 use rustc_target::spec::abi::Abi;
 
 use smallvec::SmallVec;
@@ -1391,6 +1392,7 @@ impl Expr<'_> {
             ExprKind::Break(..) => ExprPrecedence::Break,
             ExprKind::Continue(..) => ExprPrecedence::Continue,
             ExprKind::Ret(..) => ExprPrecedence::Ret,
+            ExprKind::InlineAsm(..) => ExprPrecedence::InlineAsm,
             ExprKind::LlvmInlineAsm(..) => ExprPrecedence::InlineAsm,
             ExprKind::Struct(..) => ExprPrecedence::Struct,
             ExprKind::Repeat(..) => ExprPrecedence::Repeat,
@@ -1446,6 +1448,7 @@ impl Expr<'_> {
             | ExprKind::Ret(..)
             | ExprKind::Loop(..)
             | ExprKind::Assign(..)
+            | ExprKind::InlineAsm(..)
             | ExprKind::LlvmInlineAsm(..)
             | ExprKind::AssignOp(..)
             | ExprKind::Lit(_)
@@ -1622,6 +1625,8 @@ pub enum ExprKind<'hir> {
     /// A `return`, with an optional value to be returned.
     Ret(Option<&'hir Expr<'hir>>),
 
+    /// Inline assembly (from `asm!`), with its outputs and inputs.
+    InlineAsm(&'hir InlineAsm<'hir>),
     /// Inline assembly (from `llvm_asm!`), with its outputs and inputs.
     LlvmInlineAsm(&'hir LlvmInlineAsm<'hir>),
 
@@ -2054,6 +2059,55 @@ pub enum TyKind<'hir> {
     Err,
 }
 
+#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+pub enum InlineAsmOperand<'hir> {
+    In {
+        reg: InlineAsmRegOrRegClass,
+        expr: Expr<'hir>,
+    },
+    Out {
+        reg: InlineAsmRegOrRegClass,
+        late: bool,
+        expr: Option<Expr<'hir>>,
+    },
+    InOut {
+        reg: InlineAsmRegOrRegClass,
+        late: bool,
+        expr: Expr<'hir>,
+    },
+    SplitInOut {
+        reg: InlineAsmRegOrRegClass,
+        late: bool,
+        in_expr: Expr<'hir>,
+        out_expr: Option<Expr<'hir>>,
+    },
+    Const {
+        expr: Expr<'hir>,
+    },
+    Sym {
+        expr: Expr<'hir>,
+    },
+}
+
+impl<'hir> InlineAsmOperand<'hir> {
+    pub fn reg(&self) -> Option<InlineAsmRegOrRegClass> {
+        match *self {
+            Self::In { reg, .. }
+            | Self::Out { reg, .. }
+            | Self::InOut { reg, .. }
+            | Self::SplitInOut { reg, .. } => Some(reg),
+            Self::Const { .. } | Self::Sym { .. } => None,
+        }
+    }
+}
+
+#[derive(RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
+pub struct InlineAsm<'hir> {
+    pub template: &'hir [InlineAsmTemplatePiece],
+    pub operands: &'hir [InlineAsmOperand<'hir>],
+    pub options: InlineAsmOptions,
+}
+
 #[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, HashStable_Generic, PartialEq)]
 pub struct LlvmInlineAsmOutput {
     pub constraint: Symbol,
diff --git a/src/librustc_hir/intravisit.rs b/src/librustc_hir/intravisit.rs
index 0270d0de5c7..97601a3e1ac 100644
--- a/src/librustc_hir/intravisit.rs
+++ b/src/librustc_hir/intravisit.rs
@@ -1157,6 +1157,27 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr<'v>)
         ExprKind::Ret(ref optional_expression) => {
             walk_list!(visitor, visit_expr, optional_expression);
         }
+        ExprKind::InlineAsm(ref asm) => {
+            for op in asm.operands {
+                match op {
+                    InlineAsmOperand::In { expr, .. }
+                    | InlineAsmOperand::InOut { expr, .. }
+                    | InlineAsmOperand::Const { expr, .. }
+                    | InlineAsmOperand::Sym { expr, .. } => visitor.visit_expr(expr),
+                    InlineAsmOperand::Out { expr, .. } => {
+                        if let Some(expr) = expr {
+                            visitor.visit_expr(expr);
+                        }
+                    }
+                    InlineAsmOperand::SplitInOut { in_expr, out_expr, .. } => {
+                        visitor.visit_expr(in_expr);
+                        if let Some(out_expr) = out_expr {
+                            visitor.visit_expr(out_expr);
+                        }
+                    }
+                }
+            }
+        }
         ExprKind::LlvmInlineAsm(ref asm) => {
             walk_list!(visitor, visit_expr, asm.outputs_exprs);
             walk_list!(visitor, visit_expr, asm.inputs_exprs);
diff --git a/src/librustc_hir_pretty/lib.rs b/src/librustc_hir_pretty/lib.rs
index f8a42376d14..918b5901375 100644
--- a/src/librustc_hir_pretty/lib.rs
+++ b/src/librustc_hir_pretty/lib.rs
@@ -12,6 +12,7 @@ use rustc_hir::{GenericBound, PatKind, RangeEnd, TraitBoundModifier};
 use rustc_span::source_map::{SourceMap, Spanned};
 use rustc_span::symbol::{kw, Ident, IdentPrinter, Symbol};
 use rustc_span::{self, BytePos, FileName};
+use rustc_target::asm::{InlineAsmOptions, InlineAsmTemplatePiece};
 use rustc_target::spec::abi::Abi;
 
 use std::borrow::Cow;
@@ -1409,6 +1410,107 @@ impl<'a> State<'a> {
                     self.print_expr_maybe_paren(&expr, parser::PREC_JUMP);
                 }
             }
+            hir::ExprKind::InlineAsm(ref a) => {
+                enum AsmArg<'a> {
+                    Template(String),
+                    Operand(&'a hir::InlineAsmOperand<'a>),
+                    Options(InlineAsmOptions),
+                }
+
+                let mut args = vec![];
+                args.push(AsmArg::Template(InlineAsmTemplatePiece::to_string(&a.template)));
+                args.extend(a.operands.iter().map(|o| AsmArg::Operand(o)));
+                if !a.options.is_empty() {
+                    args.push(AsmArg::Options(a.options));
+                }
+
+                self.word("asm!");
+                self.popen();
+                self.commasep(Consistent, &args, |s, arg| match arg {
+                    AsmArg::Template(template) => s.print_string(&template, ast::StrStyle::Cooked),
+                    AsmArg::Operand(op) => match op {
+                        hir::InlineAsmOperand::In { reg, expr } => {
+                            s.word("in");
+                            s.popen();
+                            s.word(format!("{}", reg));
+                            s.pclose();
+                            s.space();
+                            s.print_expr(expr);
+                        }
+                        hir::InlineAsmOperand::Out { reg, late, expr } => {
+                            s.word(if *late { "lateout" } else { "out" });
+                            s.popen();
+                            s.word(format!("{}", reg));
+                            s.pclose();
+                            s.space();
+                            match expr {
+                                Some(expr) => s.print_expr(expr),
+                                None => s.word("_"),
+                            }
+                        }
+                        hir::InlineAsmOperand::InOut { reg, late, expr } => {
+                            s.word(if *late { "inlateout" } else { "inout" });
+                            s.popen();
+                            s.word(format!("{}", reg));
+                            s.pclose();
+                            s.space();
+                            s.print_expr(expr);
+                        }
+                        hir::InlineAsmOperand::SplitInOut { reg, late, in_expr, out_expr } => {
+                            s.word(if *late { "inlateout" } else { "inout" });
+                            s.popen();
+                            s.word(format!("{}", reg));
+                            s.pclose();
+                            s.space();
+                            s.print_expr(in_expr);
+                            s.space();
+                            s.word_space("=>");
+                            match out_expr {
+                                Some(out_expr) => s.print_expr(out_expr),
+                                None => s.word("_"),
+                            }
+                        }
+                        hir::InlineAsmOperand::Const { expr } => {
+                            s.word("const");
+                            s.space();
+                            s.print_expr(expr);
+                        }
+                        hir::InlineAsmOperand::Sym { expr } => {
+                            s.word("sym");
+                            s.space();
+                            s.print_expr(expr);
+                        }
+                    },
+                    AsmArg::Options(opts) => {
+                        s.word("options");
+                        s.popen();
+                        let mut options = vec![];
+                        if opts.contains(InlineAsmOptions::PURE) {
+                            options.push("pure");
+                        }
+                        if opts.contains(InlineAsmOptions::NOMEM) {
+                            options.push("nomem");
+                        }
+                        if opts.contains(InlineAsmOptions::READONLY) {
+                            options.push("readonly");
+                        }
+                        if opts.contains(InlineAsmOptions::PRESERVES_FLAGS) {
+                            options.push("preserves_flags");
+                        }
+                        if opts.contains(InlineAsmOptions::NORETURN) {
+                            options.push("noreturn");
+                        }
+                        if opts.contains(InlineAsmOptions::NOSTACK) {
+                            options.push("nostack");
+                        }
+                        s.commasep(Inconsistent, &options, |s, &opt| {
+                            s.word(opt);
+                        });
+                        s.pclose();
+                    }
+                });
+                self.pclose();
+            }
             hir::ExprKind::LlvmInlineAsm(ref a) => {
                 let i = &a.inner;
                 self.s.word("llvm_asm!");