Skip to content

asm! evaluates read-write constraint ("+r") expression twice #14936

Closed
@pnkfelix

Description

@pnkfelix

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
% 

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-inline-assemblyArea: Inline assembly (`asm!(…)`)

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions