Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update rustc analyses to reflect asm! order-of-eval: outputs, then inputs #14966

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/librustc/middle/dataflow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
Expand Down
11 changes: 7 additions & 4 deletions src/librustc/middle/expr_use_visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(..) |
Expand Down
28 changes: 16 additions & 12 deletions src/librustc/middle/liveness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
})
}

Expand Down Expand Up @@ -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, ());
}

Expand Down
4 changes: 2 additions & 2 deletions src/librustc/middle/trans/debuginfo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3572,11 +3572,11 @@ fn populate_scope_map(cx: &CrateContext,
outputs: ref outputs,
.. }) => {
// inputs, outputs: ~[(String, Gc<expr>)]
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);
}
}
Expand Down
6 changes: 3 additions & 3 deletions src/librustc/middle/typeck/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"),
Expand Down
4 changes: 2 additions & 2 deletions src/libsyntax/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Expr>)>,
pub outputs: Vec<(InternedString, Gc<Expr>)>,
pub inputs: Vec<(InternedString, Gc<Expr>)>,
pub clobbers: InternedString,
pub volatile: bool,
pub alignstack: bool,
pub dialect: AsmDialect
Expand Down
29 changes: 29 additions & 0 deletions src/test/compile-fail/asm-disorder-of-eval.rs
Original file line number Diff line number Diff line change
@@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
28 changes: 28 additions & 0 deletions src/test/run-pass/asm-order-of-eval.rs
Original file line number Diff line number Diff line change
@@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}