mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-30 02:33:55 +00:00
Add asm! to HIR
This commit is contained in:
parent
a0adf53bc9
commit
d5b1501d8c
@ -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,
|
||||
|
@ -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);
|
||||
|
@ -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!");
|
||||
|
Loading…
Reference in New Issue
Block a user