Auto merge of #29543 - Amanieu:asm_mem_constraint, r=alexcrichton
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".
This commit is contained in:
commit
effcd29652
@ -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 '+'");
|
||||
}
|
||||
|
||||
|
39
src/test/run-pass/asm-indirect-memory.rs
Normal file
39
src/test/run-pass/asm-indirect-memory.rs
Normal file
@ -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() {}
|
Loading…
Reference in New Issue
Block a user