Skip to content

Commit 05fadf8

Browse files
committed
Update rustc analyses to reflect asm! order-of-eval: outputs, then inputs.
Fix #14962. Also reordered the fields in libsyntax to reflect the order that the expressions occur in an instance of `asm!`, as an attempt to remind others of this ordering. Finally, added a couple notes about cases that may need to be further revised when/if #14936 is addressed.
1 parent 79fca99 commit 05fadf8

File tree

8 files changed

+89
-25
lines changed

8 files changed

+89
-25
lines changed

src/librustc/middle/dataflow.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -606,10 +606,10 @@ impl<'a, 'b, O:DataFlowOperator> PropagationContext<'a, 'b, O> {
606606
}
607607

608608
ast::ExprInlineAsm(ref inline_asm) => {
609-
for &(_, ref expr) in inline_asm.inputs.iter() {
609+
for &(_, ref expr) in inline_asm.outputs.iter() {
610610
self.walk_expr(&**expr, in_out, loop_scopes);
611611
}
612-
for &(_, ref expr) in inline_asm.outputs.iter() {
612+
for &(_, ref expr) in inline_asm.inputs.iter() {
613613
self.walk_expr(&**expr, in_out, loop_scopes);
614614
}
615615
}

src/librustc/middle/expr_use_visitor.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -318,13 +318,16 @@ impl<'d,'t,TYPER:mc::Typer> ExprUseVisitor<'d,'t,TYPER> {
318318
}
319319

320320
ast::ExprInlineAsm(ref ia) => {
321-
for &(_, ref input) in ia.inputs.iter() {
322-
self.consume_expr(&**input);
323-
}
324-
321+
// FIXME(#14936): A read-write output should
322+
// eventually be modelled as a single expression,
323+
// which will then require updating this code.
325324
for &(_, ref output) in ia.outputs.iter() {
326325
self.mutate_expr(expr, &**output, JustWrite);
327326
}
327+
328+
for &(_, ref input) in ia.inputs.iter() {
329+
self.consume_expr(&**input);
330+
}
328331
}
329332

330333
ast::ExprBreak(..) |

src/librustc/middle/liveness.rs

+16-12
Original file line numberDiff line numberDiff line change
@@ -1163,15 +1163,19 @@ impl<'a> Liveness<'a> {
11631163
}
11641164

11651165
ExprInlineAsm(ref ia) => {
1166-
let succ = ia.outputs.iter().rev().fold(succ, |succ, &(_, ref expr)| {
1167-
// see comment on lvalues in
1168-
// propagate_through_lvalue_components()
1169-
let succ = self.write_lvalue(&**expr, succ, ACC_WRITE);
1170-
self.propagate_through_lvalue_components(&**expr, succ)
1166+
let succ = ia.inputs.iter().rev().fold(succ, |succ, &(_, ref expr)| {
1167+
self.propagate_through_expr(&**expr, succ)
11711168
});
1172-
// Inputs are executed first. Propagate last because of rev order
1173-
ia.inputs.iter().rev().fold(succ, |succ, &(_, ref expr)| {
1174-
self.propagate_through_expr(&**expr, succ)
1169+
// Outputs are executed first. Propagate last because of rev order
1170+
ia.outputs.iter().rev().fold(succ, |succ, &(_, ref expr)| {
1171+
// see comment on lvalues in
1172+
// propagate_through_lvalue_components()
1173+
//
1174+
// FIXME(#14936): A read-write output should eventually
1175+
// be modelled as a single expression, which will then
1176+
// require updating this code.
1177+
let succ = self.write_lvalue(&**expr, succ, ACC_WRITE);
1178+
self.propagate_through_lvalue_components(&**expr, succ)
11751179
})
11761180
}
11771181

@@ -1394,16 +1398,16 @@ fn check_expr(this: &mut Liveness, expr: &Expr) {
13941398
}
13951399

13961400
ExprInlineAsm(ref ia) => {
1397-
for &(_, ref input) in ia.inputs.iter() {
1398-
this.visit_expr(&**input, ());
1399-
}
1400-
14011401
// Output operands must be lvalues
14021402
for &(_, ref out) in ia.outputs.iter() {
14031403
this.check_lvalue(&**out);
14041404
this.visit_expr(&**out, ());
14051405
}
14061406

1407+
for &(_, ref input) in ia.inputs.iter() {
1408+
this.visit_expr(&**input, ());
1409+
}
1410+
14071411
visit::walk_expr(this, expr, ());
14081412
}
14091413

src/librustc/middle/trans/debuginfo.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -3572,11 +3572,11 @@ fn populate_scope_map(cx: &CrateContext,
35723572
outputs: ref outputs,
35733573
.. }) => {
35743574
// inputs, outputs: ~[(String, Gc<expr>)]
3575-
for &(_, ref exp) in inputs.iter() {
3575+
for &(_, ref exp) in outputs.iter() {
35763576
walk_expr(cx, &**exp, scope_stack, scope_map);
35773577
}
35783578

3579-
for &(_, ref exp) in outputs.iter() {
3579+
for &(_, ref exp) in inputs.iter() {
35803580
walk_expr(cx, &**exp, scope_stack, scope_map);
35813581
}
35823582
}

src/librustc/middle/typeck/check/mod.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -2859,12 +2859,12 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
28592859
instantiate_path(fcx, pth, tpt, defn, expr.span, expr.id);
28602860
}
28612861
ast::ExprInlineAsm(ref ia) => {
2862-
for &(_, ref input) in ia.inputs.iter() {
2863-
check_expr(fcx, &**input);
2864-
}
28652862
for &(_, ref out) in ia.outputs.iter() {
28662863
check_expr(fcx, &**out);
28672864
}
2865+
for &(_, ref input) in ia.inputs.iter() {
2866+
check_expr(fcx, &**input);
2867+
}
28682868
fcx.write_nil(id);
28692869
}
28702870
ast::ExprMac(_) => tcx.sess.bug("unexpanded macro"),

src/libsyntax/ast.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -802,9 +802,9 @@ pub enum AsmDialect {
802802
pub struct InlineAsm {
803803
pub asm: InternedString,
804804
pub asm_str_style: StrStyle,
805-
pub clobbers: InternedString,
806-
pub inputs: Vec<(InternedString, Gc<Expr>)>,
807805
pub outputs: Vec<(InternedString, Gc<Expr>)>,
806+
pub inputs: Vec<(InternedString, Gc<Expr>)>,
807+
pub clobbers: InternedString,
808808
pub volatile: bool,
809809
pub alignstack: bool,
810810
pub dialect: AsmDialect
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![feature(asm)]
12+
13+
#[cfg(target_arch = "x86")]
14+
#[cfg(target_arch = "x86_64")]
15+
pub fn main() {
16+
let mut x: int = 0;
17+
let y: int;
18+
let z: int;
19+
unsafe {
20+
// Output expressions are evaluated before input expressions.
21+
asm!("mov $1, $0" : "=r"(*{z = y; &mut x}) : "r"({y = 3; 7}));
22+
//~^ ERROR use of possibly uninitialized variable: `y`
23+
}
24+
assert_eq!(x, 7);
25+
assert_eq!(z, 3);
26+
}
27+
28+
#[cfg(not(target_arch = "x86"), not(target_arch = "x86_64"))]
29+
pub fn main() {}
+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![feature(asm)]
12+
13+
#[cfg(target_arch = "x86")]
14+
#[cfg(target_arch = "x86_64")]
15+
pub fn main() {
16+
let mut x: int = 0;
17+
let y: int;
18+
let z: int;
19+
unsafe {
20+
// Output expressions are evaluated before input expressions.
21+
asm!("mov $1, $0" : "=r"(*{y = 3; &mut x}) : "r"({z = y; 7}));
22+
}
23+
assert_eq!(x, 7);
24+
assert_eq!(z, 3);
25+
}
26+
27+
#[cfg(not(target_arch = "x86"), not(target_arch = "x86_64"))]
28+
pub fn main() {}

0 commit comments

Comments
 (0)