diff --git a/src/librustc/middle/dataflow.rs b/src/librustc/middle/dataflow.rs index bc083dac6ac75..98ac5e86097f8 100644 --- a/src/librustc/middle/dataflow.rs +++ b/src/librustc/middle/dataflow.rs @@ -606,10 +606,10 @@ impl<'a, 'b, O:DataFlowOperator> PropagationContext<'a, 'b, O> { } ast::ExprInlineAsm(ref inline_asm) => { - for &(_, ref expr) in inline_asm.inputs.iter() { + for &(_, ref expr) in inline_asm.outputs.iter() { self.walk_expr(&**expr, in_out, loop_scopes); } - for &(_, ref expr) in inline_asm.outputs.iter() { + for &(_, ref expr) in inline_asm.inputs.iter() { self.walk_expr(&**expr, in_out, loop_scopes); } } diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 86cd3c53804de..785146b514070 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -318,13 +318,16 @@ impl<'d,'t,TYPER:mc::Typer> ExprUseVisitor<'d,'t,TYPER> { } ast::ExprInlineAsm(ref ia) => { - for &(_, ref input) in ia.inputs.iter() { - self.consume_expr(&**input); - } - + // FIXME(#14936): A read-write output should + // eventually be modelled as a single expression, + // which will then require updating this code. for &(_, ref output) in ia.outputs.iter() { self.mutate_expr(expr, &**output, JustWrite); } + + for &(_, ref input) in ia.inputs.iter() { + self.consume_expr(&**input); + } } ast::ExprBreak(..) | diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index cd876113807a9..3adfbc4545864 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -1163,15 +1163,19 @@ impl<'a> Liveness<'a> { } ExprInlineAsm(ref ia) => { - let succ = ia.outputs.iter().rev().fold(succ, |succ, &(_, ref expr)| { - // see comment on lvalues in - // propagate_through_lvalue_components() - let succ = self.write_lvalue(&**expr, succ, ACC_WRITE); - self.propagate_through_lvalue_components(&**expr, succ) + let succ = ia.inputs.iter().rev().fold(succ, |succ, &(_, ref expr)| { + self.propagate_through_expr(&**expr, succ) }); - // Inputs are executed first. Propagate last because of rev order - ia.inputs.iter().rev().fold(succ, |succ, &(_, ref expr)| { - self.propagate_through_expr(&**expr, succ) + // Outputs are executed first. Propagate last because of rev order + ia.outputs.iter().rev().fold(succ, |succ, &(_, ref expr)| { + // see comment on lvalues in + // propagate_through_lvalue_components() + // + // FIXME(#14936): A read-write output should eventually + // be modelled as a single expression, which will then + // require updating this code. + let succ = self.write_lvalue(&**expr, succ, ACC_WRITE); + self.propagate_through_lvalue_components(&**expr, succ) }) } @@ -1394,16 +1398,16 @@ fn check_expr(this: &mut Liveness, expr: &Expr) { } ExprInlineAsm(ref ia) => { - for &(_, ref input) in ia.inputs.iter() { - this.visit_expr(&**input, ()); - } - // Output operands must be lvalues for &(_, ref out) in ia.outputs.iter() { this.check_lvalue(&**out); this.visit_expr(&**out, ()); } + for &(_, ref input) in ia.inputs.iter() { + this.visit_expr(&**input, ()); + } + visit::walk_expr(this, expr, ()); } diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index b934f23abb48c..0521eff93616b 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -3572,11 +3572,11 @@ fn populate_scope_map(cx: &CrateContext, outputs: ref outputs, .. }) => { // inputs, outputs: ~[(String, Gc)] - for &(_, ref exp) in inputs.iter() { + for &(_, ref exp) in outputs.iter() { walk_expr(cx, &**exp, scope_stack, scope_map); } - for &(_, ref exp) in outputs.iter() { + for &(_, ref exp) in inputs.iter() { walk_expr(cx, &**exp, scope_stack, scope_map); } } diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 73b92e5b8684c..be34515b49144 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -2859,12 +2859,12 @@ fn check_expr_with_unifier(fcx: &FnCtxt, instantiate_path(fcx, pth, tpt, defn, expr.span, expr.id); } ast::ExprInlineAsm(ref ia) => { - for &(_, ref input) in ia.inputs.iter() { - check_expr(fcx, &**input); - } for &(_, ref out) in ia.outputs.iter() { check_expr(fcx, &**out); } + for &(_, ref input) in ia.inputs.iter() { + check_expr(fcx, &**input); + } fcx.write_nil(id); } ast::ExprMac(_) => tcx.sess.bug("unexpanded macro"), diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 86dd736ceea48..63f0c98db7c65 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -802,9 +802,9 @@ pub enum AsmDialect { pub struct InlineAsm { pub asm: InternedString, pub asm_str_style: StrStyle, - pub clobbers: InternedString, - pub inputs: Vec<(InternedString, Gc)>, pub outputs: Vec<(InternedString, Gc)>, + pub inputs: Vec<(InternedString, Gc)>, + pub clobbers: InternedString, pub volatile: bool, pub alignstack: bool, pub dialect: AsmDialect diff --git a/src/test/compile-fail/asm-disorder-of-eval.rs b/src/test/compile-fail/asm-disorder-of-eval.rs new file mode 100644 index 0000000000000..5a93e2a39b5a7 --- /dev/null +++ b/src/test/compile-fail/asm-disorder-of-eval.rs @@ -0,0 +1,29 @@ +// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(asm)] + +#[cfg(target_arch = "x86")] +#[cfg(target_arch = "x86_64")] +pub fn main() { + let mut x: int = 0; + let y: int; + let z: int; + unsafe { + // Output expressions are evaluated before input expressions. + asm!("mov $1, $0" : "=r"(*{z = y; &mut x}) : "r"({y = 3; 7})); + //~^ ERROR use of possibly uninitialized variable: `y` + } + assert_eq!(x, 7); + assert_eq!(z, 3); +} + +#[cfg(not(target_arch = "x86"), not(target_arch = "x86_64"))] +pub fn main() {} diff --git a/src/test/run-pass/asm-order-of-eval.rs b/src/test/run-pass/asm-order-of-eval.rs new file mode 100644 index 0000000000000..8b0a571f50c4b --- /dev/null +++ b/src/test/run-pass/asm-order-of-eval.rs @@ -0,0 +1,28 @@ +// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(asm)] + +#[cfg(target_arch = "x86")] +#[cfg(target_arch = "x86_64")] +pub fn main() { + let mut x: int = 0; + let y: int; + let z: int; + unsafe { + // Output expressions are evaluated before input expressions. + asm!("mov $1, $0" : "=r"(*{y = 3; &mut x}) : "r"({z = y; 7})); + } + assert_eq!(x, 7); + assert_eq!(z, 3); +} + +#[cfg(not(target_arch = "x86"), not(target_arch = "x86_64"))] +pub fn main() {}