Use a struct instead of a tuple for inline asm output operands
This commit is contained in:
parent
ce5b0351a5
commit
65707dfc00
@ -368,8 +368,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
|
||||
}), pred);
|
||||
let post_outputs = self.exprs(outputs.map(|a| {
|
||||
debug!("cfg::construct InlineAsm id:{} output:{:?}", expr.id, a);
|
||||
let &(_, ref expr, _, _) = a;
|
||||
&**expr
|
||||
&*a.expr
|
||||
}), post_inputs);
|
||||
self.add_ast_node(expr.id, &[post_outputs])
|
||||
}
|
||||
|
@ -458,12 +458,12 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
|
||||
self.consume_expr(&**input);
|
||||
}
|
||||
|
||||
for &(_, ref output, is_rw, is_indirect) in &ia.outputs {
|
||||
if is_indirect {
|
||||
self.consume_expr(&**output);
|
||||
for output in &ia.outputs {
|
||||
if output.is_indirect {
|
||||
self.consume_expr(&*output.expr);
|
||||
} else {
|
||||
self.mutate_expr(expr, &**output,
|
||||
if is_rw { WriteAndRead } else { JustWrite });
|
||||
self.mutate_expr(expr, &*output.expr,
|
||||
if output.is_rw { WriteAndRead } else { JustWrite });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1167,15 +1167,15 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
||||
hir::ExprInlineAsm(ref ia) => {
|
||||
|
||||
let succ = ia.outputs.iter().rev().fold(succ,
|
||||
|succ, &(_, ref expr, is_rw, is_indirect)| {
|
||||
|succ, out| {
|
||||
// see comment on lvalues
|
||||
// in propagate_through_lvalue_components()
|
||||
if is_indirect {
|
||||
self.propagate_through_expr(&**expr, succ)
|
||||
if out.is_indirect {
|
||||
self.propagate_through_expr(&*out.expr, succ)
|
||||
} else {
|
||||
let acc = if is_rw { ACC_WRITE|ACC_READ } else { ACC_WRITE };
|
||||
let succ = self.write_lvalue(&**expr, succ, acc);
|
||||
self.propagate_through_lvalue_components(&**expr, succ)
|
||||
let acc = if out.is_rw { ACC_WRITE|ACC_READ } else { ACC_WRITE };
|
||||
let succ = self.write_lvalue(&*out.expr, succ, acc);
|
||||
self.propagate_through_lvalue_components(&*out.expr, succ)
|
||||
}
|
||||
}
|
||||
);
|
||||
@ -1423,11 +1423,11 @@ fn check_expr(this: &mut Liveness, expr: &Expr) {
|
||||
}
|
||||
|
||||
// Output operands must be lvalues
|
||||
for &(_, ref out, _, is_indirect) in &ia.outputs {
|
||||
if !is_indirect {
|
||||
this.check_lvalue(&**out);
|
||||
for out in &ia.outputs {
|
||||
if !out.is_indirect {
|
||||
this.check_lvalue(&*out.expr);
|
||||
}
|
||||
this.visit_expr(&**out);
|
||||
this.visit_expr(&*out.expr);
|
||||
}
|
||||
|
||||
intravisit::walk_expr(this, expr);
|
||||
|
@ -1127,8 +1127,13 @@ pub fn noop_fold_expr<T: Folder>(Expr { id, node, span, attrs }: Expr, folder: &
|
||||
expn_id,
|
||||
}) => ExprInlineAsm(InlineAsm {
|
||||
inputs: inputs.move_map(|(c, input)| (c, folder.fold_expr(input))),
|
||||
outputs: outputs.move_map(|(c, out, is_rw, is_indirect)| {
|
||||
(c, folder.fold_expr(out), is_rw, is_indirect)
|
||||
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,
|
||||
|
@ -887,11 +887,19 @@ pub enum Ty_ {
|
||||
TyInfer,
|
||||
}
|
||||
|
||||
#[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, bool)>,
|
||||
pub outputs: Vec<InlineAsmOutput>,
|
||||
pub inputs: Vec<(InternedString, P<Expr>)>,
|
||||
pub clobbers: Vec<InternedString>,
|
||||
pub volatile: bool,
|
||||
|
@ -803,8 +803,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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1202,8 +1202,13 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
|
||||
.map(|&(ref c, ref input)| (c.clone(), lower_expr(lctx, input)))
|
||||
.collect(),
|
||||
outputs: outputs.iter()
|
||||
.map(|&(ref c, ref out, is_rw, is_indirect)| {
|
||||
(c.clone(), lower_expr(lctx, out), is_rw, is_indirect)
|
||||
.map(|out| {
|
||||
hir::InlineAsmOutput {
|
||||
constraint: out.constraint.clone(),
|
||||
expr: lower_expr(lctx, &out.expr),
|
||||
is_rw: out.is_rw,
|
||||
is_indirect: out.is_indirect,
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
asm: asm.clone(),
|
||||
|
@ -1502,15 +1502,15 @@ impl<'a> State<'a> {
|
||||
try!(self.print_string(&a.asm, a.asm_str_style));
|
||||
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 => {
|
||||
try!(self.commasep(Inconsistent, &a.outputs, |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(())
|
||||
}));
|
||||
|
@ -41,27 +41,27 @@ pub fn trans_inline_asm<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ia: &ast::InlineAsm)
|
||||
// Prepare the output operands
|
||||
let mut outputs = Vec::new();
|
||||
let mut inputs = Vec::new();
|
||||
for (i, &(ref c, ref out, is_rw, is_indirect)) in ia.outputs.iter().enumerate() {
|
||||
constraints.push((*c).clone());
|
||||
for (i, out) in ia.outputs.iter().enumerate() {
|
||||
constraints.push(out.constraint.clone());
|
||||
|
||||
let out_datum = unpack_datum!(bcx, expr::trans(bcx, &**out));
|
||||
if is_indirect {
|
||||
let out_datum = unpack_datum!(bcx, expr::trans(bcx, &*out.expr));
|
||||
if out.is_indirect {
|
||||
bcx = callee::trans_arg_datum(bcx,
|
||||
expr_ty(bcx, &**out),
|
||||
expr_ty(bcx, &*out.expr),
|
||||
out_datum,
|
||||
cleanup::CustomScope(temp_scope),
|
||||
callee::DontAutorefArg,
|
||||
&mut inputs);
|
||||
if is_rw {
|
||||
if out.is_rw {
|
||||
ext_inputs.push(*inputs.last().unwrap());
|
||||
ext_constraints.push(i.to_string());
|
||||
}
|
||||
} else {
|
||||
output_types.push(type_of::type_of(bcx.ccx(), out_datum.ty));
|
||||
outputs.push(out_datum.val);
|
||||
if is_rw {
|
||||
if out.is_rw {
|
||||
bcx = callee::trans_arg_datum(bcx,
|
||||
expr_ty(bcx, &**out),
|
||||
expr_ty(bcx, &*out.expr),
|
||||
out_datum,
|
||||
cleanup::CustomScope(temp_scope),
|
||||
callee::DontAutorefArg,
|
||||
|
@ -480,8 +480,8 @@ fn walk_expr(cx: &CrateContext,
|
||||
walk_expr(cx, &**exp, scope_stack, scope_map);
|
||||
}
|
||||
|
||||
for &(_, ref exp, _, _) in outputs {
|
||||
walk_expr(cx, &**exp, scope_stack, scope_map);
|
||||
for out in outputs {
|
||||
walk_expr(cx, &*out.expr, scope_stack, scope_map);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3393,8 +3393,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
for &(_, ref input) in &ia.inputs {
|
||||
check_expr(fcx, &**input);
|
||||
}
|
||||
for &(_, ref out, _, _) in &ia.outputs {
|
||||
check_expr(fcx, &**out);
|
||||
for out in &ia.outputs {
|
||||
check_expr(fcx, &*out.expr);
|
||||
}
|
||||
fcx.write_nil(id);
|
||||
}
|
||||
|
@ -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, bool)>,
|
||||
pub outputs: Vec<InlineAsmOutput>,
|
||||
pub inputs: Vec<(InternedString, P<Expr>)>,
|
||||
pub clobbers: Vec<InternedString>,
|
||||
pub volatile: bool,
|
||||
|
@ -126,7 +126,12 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
|
||||
|
||||
let is_rw = output.is_some();
|
||||
let is_indirect = constraint.contains("*");
|
||||
outputs.push((output.unwrap_or(constraint), out, is_rw, is_indirect));
|
||||
outputs.push(ast::InlineAsmOutput {
|
||||
constraint: output.unwrap_or(constraint),
|
||||
expr: out,
|
||||
is_rw: is_rw,
|
||||
is_indirect: is_indirect,
|
||||
});
|
||||
}
|
||||
}
|
||||
Inputs => {
|
||||
|
@ -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, is_indirect)| {
|
||||
(c, folder.fold_expr(out), is_rw, is_indirect)
|
||||
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,
|
||||
|
@ -2221,16 +2221,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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user