Skip to content

Commit 813a9fc

Browse files
committed
Add asm! to AST
1 parent 989edf6 commit 813a9fc

File tree

7 files changed

+214
-1
lines changed

7 files changed

+214
-1
lines changed

Cargo.lock

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3631,6 +3631,7 @@ dependencies = [
36313631
"rustc_lexer",
36323632
"rustc_macros",
36333633
"rustc_span",
3634+
"rustc_target",
36343635
"scoped-tls",
36353636
"serialize",
36363637
"smallvec 1.4.0",
@@ -3678,6 +3679,7 @@ dependencies = [
36783679
"log",
36793680
"rustc_ast",
36803681
"rustc_span",
3682+
"rustc_target",
36813683
]
36823684

36833685
[[package]]

src/librustc_ast/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,4 @@ rustc_index = { path = "../librustc_index" }
1919
rustc_lexer = { path = "../librustc_lexer" }
2020
rustc_macros = { path = "../librustc_macros" }
2121
smallvec = { version = "1.0", features = ["union", "may_dangle"] }
22+
rustc_target = { path = "../librustc_target" }

src/librustc_ast/ast.rs

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ use rustc_serialize::{self, Decoder, Encoder};
3434
use rustc_span::source_map::{respan, Spanned};
3535
use rustc_span::symbol::{kw, sym, Ident, Symbol};
3636
use rustc_span::{Span, DUMMY_SP};
37+
use rustc_target::asm::{InlineAsmOptions, InlineAsmTemplatePiece};
3738

3839
use std::convert::TryFrom;
3940
use std::fmt;
@@ -1121,7 +1122,7 @@ impl Expr {
11211122
ExprKind::Break(..) => ExprPrecedence::Break,
11221123
ExprKind::Continue(..) => ExprPrecedence::Continue,
11231124
ExprKind::Ret(..) => ExprPrecedence::Ret,
1124-
ExprKind::LlvmInlineAsm(..) => ExprPrecedence::InlineAsm,
1125+
ExprKind::InlineAsm(..) | ExprKind::LlvmInlineAsm(..) => ExprPrecedence::InlineAsm,
11251126
ExprKind::MacCall(..) => ExprPrecedence::Mac,
11261127
ExprKind::Struct(..) => ExprPrecedence::Struct,
11271128
ExprKind::Repeat(..) => ExprPrecedence::Repeat,
@@ -1250,6 +1251,8 @@ pub enum ExprKind {
12501251
/// A `return`, with an optional value to be returned.
12511252
Ret(Option<P<Expr>>),
12521253

1254+
/// Output of the `asm!()` macro.
1255+
InlineAsm(InlineAsm),
12531256
/// Output of the `llvm_asm!()` macro.
12541257
LlvmInlineAsm(P<LlvmInlineAsm>),
12551258

@@ -1864,6 +1867,58 @@ pub enum TraitObjectSyntax {
18641867
None,
18651868
}
18661869

1870+
/// Inline assembly operand explicit register or register class.
1871+
///
1872+
/// E.g., `"eax"` as in `asm!("mov eax, 2", out("eax") result)`.
1873+
#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)]
1874+
pub enum InlineAsmRegOrRegClass {
1875+
Reg(Symbol),
1876+
RegClass(Symbol),
1877+
}
1878+
1879+
/// Inline assembly operand.
1880+
///
1881+
/// E.g., `out("eax") result` as in `asm!("mov eax, 2", out("eax") result)`.
1882+
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
1883+
pub enum InlineAsmOperand {
1884+
In {
1885+
reg: InlineAsmRegOrRegClass,
1886+
expr: P<Expr>,
1887+
},
1888+
Out {
1889+
reg: InlineAsmRegOrRegClass,
1890+
late: bool,
1891+
expr: Option<P<Expr>>,
1892+
},
1893+
InOut {
1894+
reg: InlineAsmRegOrRegClass,
1895+
late: bool,
1896+
expr: P<Expr>,
1897+
},
1898+
SplitInOut {
1899+
reg: InlineAsmRegOrRegClass,
1900+
late: bool,
1901+
in_expr: P<Expr>,
1902+
out_expr: Option<P<Expr>>,
1903+
},
1904+
Const {
1905+
expr: P<Expr>,
1906+
},
1907+
Sym {
1908+
expr: P<Expr>,
1909+
},
1910+
}
1911+
1912+
/// Inline assembly.
1913+
///
1914+
/// E.g., `asm!("NOP");`.
1915+
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
1916+
pub struct InlineAsm {
1917+
pub template: Vec<InlineAsmTemplatePiece>,
1918+
pub operands: Vec<(InlineAsmOperand, Span)>,
1919+
pub options: InlineAsmOptions,
1920+
}
1921+
18671922
/// Inline assembly dialect.
18681923
///
18691924
/// E.g., `"intel"` as in `llvm_asm!("mov eax, 2" : "={eax}"(result) : : : "intel")`.

src/librustc_ast/mut_visit.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1205,6 +1205,27 @@ pub fn noop_visit_expr<T: MutVisitor>(Expr { kind, id, span, attrs }: &mut Expr,
12051205
ExprKind::Ret(expr) => {
12061206
visit_opt(expr, |expr| vis.visit_expr(expr));
12071207
}
1208+
ExprKind::InlineAsm(asm) => {
1209+
for (op, _) in &mut asm.operands {
1210+
match op {
1211+
InlineAsmOperand::In { expr, .. }
1212+
| InlineAsmOperand::InOut { expr, .. }
1213+
| InlineAsmOperand::Const { expr, .. }
1214+
| InlineAsmOperand::Sym { expr, .. } => vis.visit_expr(expr),
1215+
InlineAsmOperand::Out { expr, .. } => {
1216+
if let Some(expr) = expr {
1217+
vis.visit_expr(expr);
1218+
}
1219+
}
1220+
InlineAsmOperand::SplitInOut { in_expr, out_expr, .. } => {
1221+
vis.visit_expr(in_expr);
1222+
if let Some(out_expr) = out_expr {
1223+
vis.visit_expr(out_expr);
1224+
}
1225+
}
1226+
}
1227+
}
1228+
}
12081229
ExprKind::LlvmInlineAsm(asm) => {
12091230
let LlvmInlineAsm {
12101231
asm: _,

src/librustc_ast/visit.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -818,6 +818,27 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
818818
}
819819
ExprKind::MacCall(ref mac) => visitor.visit_mac(mac),
820820
ExprKind::Paren(ref subexpression) => visitor.visit_expr(subexpression),
821+
ExprKind::InlineAsm(ref ia) => {
822+
for (op, _) in &ia.operands {
823+
match op {
824+
InlineAsmOperand::In { expr, .. }
825+
| InlineAsmOperand::InOut { expr, .. }
826+
| InlineAsmOperand::Const { expr, .. }
827+
| InlineAsmOperand::Sym { expr, .. } => visitor.visit_expr(expr),
828+
InlineAsmOperand::Out { expr, .. } => {
829+
if let Some(expr) = expr {
830+
visitor.visit_expr(expr);
831+
}
832+
}
833+
InlineAsmOperand::SplitInOut { in_expr, out_expr, .. } => {
834+
visitor.visit_expr(in_expr);
835+
if let Some(out_expr) = out_expr {
836+
visitor.visit_expr(out_expr);
837+
}
838+
}
839+
}
840+
}
841+
}
821842
ExprKind::LlvmInlineAsm(ref ia) => {
822843
for &(_, ref input) in &ia.inputs {
823844
visitor.visit_expr(input)

src/librustc_ast_pretty/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,4 @@ doctest = false
1313
log = "0.4"
1414
rustc_span = { path = "../librustc_span" }
1515
rustc_ast = { path = "../librustc_ast" }
16+
rustc_target = { path = "../librustc_target" }

src/librustc_ast_pretty/pprust.rs

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use crate::pp::{self, Breaks};
44
use rustc_ast::ast::{self, BlockCheckMode, PatKind, RangeEnd, RangeSyntax};
55
use rustc_ast::ast::{Attribute, GenericArg, MacArgs};
66
use rustc_ast::ast::{GenericBound, SelfKind, TraitBoundModifier};
7+
use rustc_ast::ast::{InlineAsmOperand, InlineAsmRegOrRegClass};
78
use rustc_ast::attr;
89
use rustc_ast::ptr::P;
910
use rustc_ast::token::{self, BinOpToken, DelimToken, Nonterminal, Token, TokenKind};
@@ -14,6 +15,7 @@ use rustc_span::edition::Edition;
1415
use rustc_span::source_map::{SourceMap, Spanned};
1516
use rustc_span::symbol::{kw, sym, Ident, IdentPrinter, Symbol};
1617
use rustc_span::{BytePos, FileName, Span};
18+
use rustc_target::asm::{InlineAsmOptions, InlineAsmTemplatePiece};
1719

1820
use std::borrow::Cow;
1921

@@ -2014,6 +2016,116 @@ impl<'a> State<'a> {
20142016
self.print_expr_maybe_paren(expr, parser::PREC_JUMP);
20152017
}
20162018
}
2019+
ast::ExprKind::InlineAsm(ref a) => {
2020+
enum AsmArg<'a> {
2021+
Template(String),
2022+
Operand(&'a InlineAsmOperand),
2023+
Options(InlineAsmOptions),
2024+
}
2025+
2026+
let mut args = vec![];
2027+
args.push(AsmArg::Template(InlineAsmTemplatePiece::to_string(&a.template)));
2028+
args.extend(a.operands.iter().map(|(o, _)| AsmArg::Operand(o)));
2029+
if !a.options.is_empty() {
2030+
args.push(AsmArg::Options(a.options));
2031+
}
2032+
2033+
self.word("asm!");
2034+
self.popen();
2035+
self.commasep(Consistent, &args, |s, arg| match arg {
2036+
AsmArg::Template(template) => s.print_string(&template, ast::StrStyle::Cooked),
2037+
AsmArg::Operand(op) => {
2038+
let print_reg_or_class = |s: &mut Self, r: &InlineAsmRegOrRegClass| match r
2039+
{
2040+
InlineAsmRegOrRegClass::Reg(r) => {
2041+
s.print_string(&r.as_str(), ast::StrStyle::Cooked)
2042+
}
2043+
InlineAsmRegOrRegClass::RegClass(r) => s.word(r.to_string()),
2044+
};
2045+
match op {
2046+
InlineAsmOperand::In { reg, expr } => {
2047+
s.word("in");
2048+
s.popen();
2049+
print_reg_or_class(s, reg);
2050+
s.pclose();
2051+
s.space();
2052+
s.print_expr(expr);
2053+
}
2054+
InlineAsmOperand::Out { reg, late, expr } => {
2055+
s.word(if *late { "lateout" } else { "out" });
2056+
s.popen();
2057+
print_reg_or_class(s, reg);
2058+
s.pclose();
2059+
s.space();
2060+
match expr {
2061+
Some(expr) => s.print_expr(expr),
2062+
None => s.word("_"),
2063+
}
2064+
}
2065+
InlineAsmOperand::InOut { reg, late, expr } => {
2066+
s.word(if *late { "inlateout" } else { "inout" });
2067+
s.popen();
2068+
print_reg_or_class(s, reg);
2069+
s.pclose();
2070+
s.space();
2071+
s.print_expr(expr);
2072+
}
2073+
InlineAsmOperand::SplitInOut { reg, late, in_expr, out_expr } => {
2074+
s.word(if *late { "inlateout" } else { "inout" });
2075+
s.popen();
2076+
print_reg_or_class(s, reg);
2077+
s.pclose();
2078+
s.space();
2079+
s.print_expr(in_expr);
2080+
s.space();
2081+
s.word_space("=>");
2082+
match out_expr {
2083+
Some(out_expr) => s.print_expr(out_expr),
2084+
None => s.word("_"),
2085+
}
2086+
}
2087+
InlineAsmOperand::Const { expr } => {
2088+
s.word("const");
2089+
s.space();
2090+
s.print_expr(expr);
2091+
}
2092+
InlineAsmOperand::Sym { expr } => {
2093+
s.word("sym");
2094+
s.space();
2095+
s.print_expr(expr);
2096+
}
2097+
}
2098+
}
2099+
AsmArg::Options(opts) => {
2100+
s.word("options");
2101+
s.popen();
2102+
let mut options = vec![];
2103+
if opts.contains(InlineAsmOptions::PURE) {
2104+
options.push("pure");
2105+
}
2106+
if opts.contains(InlineAsmOptions::NOMEM) {
2107+
options.push("nomem");
2108+
}
2109+
if opts.contains(InlineAsmOptions::READONLY) {
2110+
options.push("readonly");
2111+
}
2112+
if opts.contains(InlineAsmOptions::PRESERVES_FLAGS) {
2113+
options.push("preserves_flags");
2114+
}
2115+
if opts.contains(InlineAsmOptions::NORETURN) {
2116+
options.push("noreturn");
2117+
}
2118+
if opts.contains(InlineAsmOptions::NOSTACK) {
2119+
options.push("nostack");
2120+
}
2121+
s.commasep(Inconsistent, &options, |s, &opt| {
2122+
s.word(opt);
2123+
});
2124+
s.pclose();
2125+
}
2126+
});
2127+
self.pclose();
2128+
}
20172129
ast::ExprKind::LlvmInlineAsm(ref a) => {
20182130
self.s.word("llvm_asm!");
20192131
self.popen();

0 commit comments

Comments
 (0)