Skip to content

Commit effcd29

Browse files
committed
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".
2 parents 4ee11cd + 59c5191 commit effcd29

File tree

2 files changed

+41
-2
lines changed

2 files changed

+41
-2
lines changed

src/libsyntax/ext/asm.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -139,9 +139,9 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
139139

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

142-
if constraint.starts_with("=") {
142+
if constraint.starts_with("=") && !constraint.contains("*") {
143143
cx.span_err(p.last_span, "input operand constraint contains '='");
144-
} else if constraint.starts_with("+") {
144+
} else if constraint.starts_with("+") && !constraint.contains("*") {
145145
cx.span_err(p.last_span, "input operand constraint contains '+'");
146146
}
147147

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Copyright 2015 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(any(target_arch = "x86", target_arch = "x86_64"))]
14+
fn read(ptr: &u32) -> u32 {
15+
let out: u32;
16+
unsafe {
17+
asm!("mov $1, $0" : "=r" (out) : "*m" (ptr));
18+
}
19+
out
20+
}
21+
22+
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
23+
fn write(ptr: &mut u32, val: u32) {
24+
unsafe {
25+
asm!("mov $1, $0" :: "=*m" (ptr), "r" (val));
26+
}
27+
}
28+
29+
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
30+
pub fn main() {
31+
let a = 1;
32+
let mut b = 2;
33+
assert_eq!(read(&a), 1);
34+
write(&mut b, 3);
35+
assert_eq!(b, 3);
36+
}
37+
38+
#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
39+
pub fn main() {}

0 commit comments

Comments
 (0)