Skip to content

Commit

Permalink
Auto merge of #29543 - Amanieu:asm_mem_constraint, r=alexcrichton
Browse files Browse the repository at this point in the history
The "m" memory constraint in inline assembly is broken (generates incorrect code or triggers LLVM asserts) and should not be used. Instead, indirect memory operands should be used with "\*m", "=\*m" and "+\*m".

Clang does this transparently by transforming "m" constraints into "\*m" indirect constraints, but for now just being able to use "\*m" directly is enough since asm! isn't stable.

While "\*m" works fine as an input operand, "=\*m" and "+\*m" need to be specified as input operands because they take a pointer value as an input. This PR relaxes the constraint checker to allow constraints starting with "=" or "+" if the constraint string contains a "\*", which indicates an indirect operand.

This (indirectly) fixes these issues: #29382, #16383 and #13366. The code will need to be changed to use "\*m" instead of "m".
  • Loading branch information
bors committed Nov 4, 2015
2 parents 4ee11cd + 59c5191 commit effcd29
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 2 deletions.
4 changes: 2 additions & 2 deletions src/libsyntax/ext/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,9 +139,9 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])

let (constraint, _str_style) = panictry!(p.parse_str());

if constraint.starts_with("=") {
if constraint.starts_with("=") && !constraint.contains("*") {
cx.span_err(p.last_span, "input operand constraint contains '='");
} else if constraint.starts_with("+") {
} else if constraint.starts_with("+") && !constraint.contains("*") {
cx.span_err(p.last_span, "input operand constraint contains '+'");
}

Expand Down
39 changes: 39 additions & 0 deletions src/test/run-pass/asm-indirect-memory.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright 2015 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(any(target_arch = "x86", target_arch = "x86_64"))]
fn read(ptr: &u32) -> u32 {
let out: u32;
unsafe {
asm!("mov $1, $0" : "=r" (out) : "*m" (ptr));
}
out
}

#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
fn write(ptr: &mut u32, val: u32) {
unsafe {
asm!("mov $1, $0" :: "=*m" (ptr), "r" (val));
}
}

#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub fn main() {
let a = 1;
let mut b = 2;
assert_eq!(read(&a), 1);
write(&mut b, 3);
assert_eq!(b, 3);
}

#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
pub fn main() {}

0 comments on commit effcd29

Please sign in to comment.