Auto merge of #29735 - Amanieu:asm_indirect_constraint, r=pnkfelix
This PR reverts #29543 and instead implements proper support for "=*m" and "+*m" indirect output operands. This provides a framework on top of which support for plain memory operands ("m", "=m" and "+m") can be implemented. This also fixes the liveness analysis pass not handling read/write operands correctly.
This commit is contained in:
@@ -1458,11 +1458,19 @@ pub enum AsmDialect {
|
||||
Intel,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
||||
pub struct InlineAsmOutput {
|
||||
pub constraint: InternedString,
|
||||
pub expr: P<Expr>,
|
||||
pub is_rw: bool,
|
||||
pub is_indirect: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
|
||||
pub struct InlineAsm {
|
||||
pub asm: InternedString,
|
||||
pub asm_str_style: StrStyle,
|
||||
pub outputs: Vec<(InternedString, P<Expr>, bool)>,
|
||||
pub outputs: Vec<InlineAsmOutput>,
|
||||
pub inputs: Vec<(InternedString, P<Expr>)>,
|
||||
pub clobbers: Vec<InternedString>,
|
||||
pub volatile: bool,
|
||||
|
||||
@@ -125,7 +125,13 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
|
||||
};
|
||||
|
||||
let is_rw = output.is_some();
|
||||
outputs.push((output.unwrap_or(constraint), out, is_rw));
|
||||
let is_indirect = constraint.contains("*");
|
||||
outputs.push(ast::InlineAsmOutput {
|
||||
constraint: output.unwrap_or(constraint),
|
||||
expr: out,
|
||||
is_rw: is_rw,
|
||||
is_indirect: is_indirect,
|
||||
});
|
||||
}
|
||||
}
|
||||
Inputs => {
|
||||
@@ -139,9 +145,9 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
|
||||
|
||||
let (constraint, _str_style) = panictry!(p.parse_str());
|
||||
|
||||
if constraint.starts_with("=") && !constraint.contains("*") {
|
||||
if constraint.starts_with("=") {
|
||||
cx.span_err(p.last_span, "input operand constraint contains '='");
|
||||
} else if constraint.starts_with("+") && !constraint.contains("*") {
|
||||
} else if constraint.starts_with("+") {
|
||||
cx.span_err(p.last_span, "input operand constraint contains '+'");
|
||||
}
|
||||
|
||||
|
||||
@@ -1303,8 +1303,13 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span, attrs}: Expr, folder: &mu
|
||||
inputs: inputs.move_map(|(c, input)| {
|
||||
(c, folder.fold_expr(input))
|
||||
}),
|
||||
outputs: outputs.move_map(|(c, out, is_rw)| {
|
||||
(c, folder.fold_expr(out), is_rw)
|
||||
outputs: outputs.move_map(|out| {
|
||||
InlineAsmOutput {
|
||||
constraint: out.constraint,
|
||||
expr: folder.fold_expr(out.expr),
|
||||
is_rw: out.is_rw,
|
||||
is_indirect: out.is_indirect,
|
||||
}
|
||||
}),
|
||||
asm: asm,
|
||||
asm_str_style: asm_str_style,
|
||||
|
||||
@@ -2219,16 +2219,16 @@ impl<'a> State<'a> {
|
||||
try!(self.word_space(":"));
|
||||
|
||||
try!(self.commasep(Inconsistent, &a.outputs,
|
||||
|s, &(ref co, ref o, is_rw)| {
|
||||
match co.slice_shift_char() {
|
||||
Some(('=', operand)) if is_rw => {
|
||||
|s, out| {
|
||||
match out.constraint.slice_shift_char() {
|
||||
Some(('=', operand)) if out.is_rw => {
|
||||
try!(s.print_string(&format!("+{}", operand),
|
||||
ast::CookedStr))
|
||||
}
|
||||
_ => try!(s.print_string(&co, ast::CookedStr))
|
||||
_ => try!(s.print_string(&out.constraint, ast::CookedStr))
|
||||
}
|
||||
try!(s.popen());
|
||||
try!(s.print_expr(&**o));
|
||||
try!(s.print_expr(&*out.expr));
|
||||
try!(s.pclose());
|
||||
Ok(())
|
||||
}));
|
||||
|
||||
@@ -786,8 +786,8 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
|
||||
for &(_, ref input) in &ia.inputs {
|
||||
visitor.visit_expr(&input)
|
||||
}
|
||||
for &(_, ref output, _) in &ia.outputs {
|
||||
visitor.visit_expr(&output)
|
||||
for output in &ia.outputs {
|
||||
visitor.visit_expr(&output.expr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user