Closed
Description
When you use "=r"(x)
, it evaluates x
once.
When you use "+r"(x)
, it evaluates x
twice.
You would not notice the multiple evaluation of x
when it is just a variable reference. But when it is another expression, you can observe it.
I suspect this is just an oversight in the construction of the asm!
macro (in that it should expand into a single occurrence of each of its operands, but it is probably expanding into two occurrences of the output operand expression when it is +r
).
Here is some demo code:
#![feature(macro_rules)]
#![feature(asm)]
type History = Vec<&'static str>;
fn wrap<A>(x:A, where: &'static str, history: &mut History) -> A {
history.push(where);
x
}
macro_rules! demo {
( $output_constraint:tt ) => {
{
let mut x: int = 0;
let y: int = 1;
let mut history: History = vec!();
unsafe {
asm!("mov ($1), $0"
: $output_constraint (*wrap(&mut x, "out", &mut history))
: "r"(&wrap(y, "in", &mut history)));
}
assert_eq!((x,y), (1,1));
assert_eq!(history.as_slice(), &["out", "in"]);
}
}
}
#[cfg(target_arch = "x86")]
#[cfg(target_arch = "x86_64")]
fn main() {
fn out_write_only_expr_then_in_expr() {
demo!("=r")
}
fn out_read_write_expr_then_in_expr() {
demo!("+r")
}
out_write_only_expr_then_in_expr();
out_read_write_expr_then_in_expr();
}
#[cfg(not(target_arch = "x86"), not(target_arch = "x86_64"))]
pub fn main() {}
Transcript of run (note the assertion failure shows that the out case is evaluated multiple times):
% rustc --version
rustc 0.11.0-pre (7ec7805 2014-06-16 08:16:49 +0000)
host: x86_64-apple-darwin
% rustc asm-multiple-eval.rs && ./asm-multiple-eval
task '<main>' failed at 'assertion failed: `(left == right) && (right == left)` (left: `[out, in, out]`, right: `[out, in]`)', asm-multiple-eval.rs:37
%