-
Notifications
You must be signed in to change notification settings - Fork 12.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Inline asm: The "m" constraint is broken #16383
Comments
Possibly related: #13366 |
I tested the first example with Rust master (34dfa45) on x86-64 Linux. It only crashes when asm!("lea $0, %rax" :: "m"(foo) : "rax"); So I'd guess it's something with LLVM not knowing the operand size — I tried adding It seems like that's not related to the second issue, which also manifests with AT&T syntax. |
The "g" constraint doesn't work, either: #![feature(asm)]
fn main() {
let mut foo = 42u;
// unsafe { asm!("leaq $0, %rax" : : "m"(foo) : "rax"); }
unsafe { asm!("pushq $0; popq $0" : "+g"(foo) ); }
}
But I could confirm Clang/LLVM 3.0 corectly understood it: #include <inttypes.h>
int main() {
uint64_t a = 42;
__asm__ __volatile__ ( "push %0; pop %0" : "+g"(a) );
printf("%016" PRIu64 "x\n", a);
return 0;
}
|
The original examples seem to work now, but @nodakai 's still don't. |
@steveklabnik Not on playpen though (as of right now). There, my first example still crashes (as @kmcallister mentioned, it will only crash with optimizations enabled) while the second one still miscompiles. The only difference is that after one year of optimization improvements, LLVM is now able to load the two 64-bit qwords as one 128-bit xmmword. |
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".
Try loading a type larger than #![feature(asm)]
fn main() {
struct Descriptor{
size: usize,
ptr: usize,
}
let descriptor = Descriptor {
size: 0,
ptr: 0,
};
unsafe {
asm!("lidt $0" :: "m"(descriptor) :: "intel");
}
}
On |
The recent blog post "How a Rust upgrade more than tripled the speed of my code" describes an issue that I think is caused by this bug. The author wrote See also #29543:
|
This issue does not apply to the new The legacy |
fix: Fix progress reporting getting stuck Fixes rust-lang/rust-analyzer#16382
Expected result:
rax
contains the address offoo
However:
Using a struct instead of an
uint
:Now the compiler doesn't crash. But the emitted
lea
instruction references the memory location of the address offoo
instead offoo
itself:So basically
"m"(foo)
generates the code for"m"(&foo)
iffoo
is a struct.The text was updated successfully, but these errors were encountered: