1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#![deny(missing_docs)]
use super::*;
impl<'c> Translation<'c> {
pub fn convert_asm(
&self,
ctx: ExprContext,
span: Span,
is_volatile: bool,
asm: &str,
inputs: &[AsmOperand],
outputs: &[AsmOperand],
clobbers: &[String],
) -> Result<Vec<Stmt>, TranslationError> {
if !self.tcfg.translate_asm {
return Err(TranslationError::generic(
"Inline assembly not enabled, to enable use --translate-asm",
));
}
self.use_feature("asm");
fn push_expr(tokens: &mut Vec<Token>, expr: P<Expr>) {
tokens.push(Token::Interpolated(Lrc::new(Nonterminal::NtExpr(expr))));
}
let mut stmts: Vec<Stmt> = vec![];
let mut tokens: Vec<Token> = vec![];
let mut first;
push_expr(&mut tokens, mk().lit_expr(mk().str_lit(asm)));
for list in vec![outputs, inputs] {
first = true;
tokens.push(Token::Colon);
for &AsmOperand {
ref constraints,
expression,
} in list
{
if first {
first = false
} else {
tokens.push(Token::Comma)
}
let mut result = self.convert_expr(ctx.used(), expression)?;
stmts.append(&mut result.stmts);
push_expr(&mut tokens, mk().lit_expr(mk().str_lit(constraints)));
push_expr(&mut tokens, mk().paren_expr(result.val));
}
}
first = true;
tokens.push(Token::Colon);
for clobber in clobbers {
if first {
first = false
} else {
tokens.push(Token::Comma)
}
push_expr(&mut tokens, mk().lit_expr(mk().str_lit(clobber)));
}
if is_volatile {
tokens.push(Token::Colon);
push_expr(&mut tokens, mk().lit_expr(mk().str_lit("volatile")));
}
let mac = mk().mac(
vec!["asm"],
tokens.into_iter().collect::<TokenStream>(),
MacDelimiter::Parenthesis,
);
let mac = mk().mac_expr(mac);
let mac = mk().span(span).expr_stmt(mac);
stmts.push(mac);
Ok(stmts)
}
}