You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
If a value is of a smaller size than the register it is allocated in then the upper bits of that register will have an undefined value for inputs and will be ignored for outputs.
575
587
The only exception is the `freg` register class on RISC-V where `f32` values are NaN-boxed in a `f64` as required by the RISC-V architecture.
576
588
577
-
<!--no_run, this test has a non-deterministic runtime behaviour-->
589
+
<!--no_run, this test has a non-deterministic runtime behavior-->
578
590
```rust,no_run
579
591
# #[cfg(target_arch = "x86_64")] {
580
592
let mut x: i64;
581
593
// Moving a 32-bit value into a 64-bit value, oops.
582
-
#[allow(asm_sub_register)] // rustc warns about this behaviour
594
+
#[allow(asm_sub_register)] // rustc warns about this behavior
# #[cfg(not(target_arch = "x86_64"))] core::compile_error!("Test not supported on this arch");
@@ -787,6 +799,17 @@ The supported modifiers are a subset of LLVM's (and GCC's) [asm template argumen
787
799
> GCC will infer the modifier based on the operand value type, while we default to the full register size.
788
800
> - on x86 `xmm_reg`: the `x`, `t` and `g` LLVM modifiers are not yet implemented in LLVM (they are supported by GCC only), but this should be a simple change.
789
801
802
+
```rust
803
+
# #[cfg(target_arch ="x86_64")] {
804
+
letmutx=0x10u16;
805
+
806
+
// u16::swap_bytes using `xchg`
807
+
// low half of `{x}` is referred to by `{x:l}`, and the high half by `{x:h}`
As stated in the previous section, passing an input value smaller than the register width will result in the upper bits of the register containing undefined values.
792
815
This is not a problem if the inline asm only accesses the lower bits of the register, which can be done by using a template modifier to use a subregister name in the asm code (e.g. `ax` instead of `rax`).
@@ -807,6 +830,7 @@ This will automatically insert the necessary clobber constraints as needed for c
807
830
extern"C"fnfoo() ->i32{ 0 }
808
831
# #[cfg(target_arch ="x86_64")] {
809
832
letz:i32;
833
+
// To call a function, we have to inform the compiler that we're clobbering callee saved registers
This allows the compiler to cache the values of modified global variables in registers across the `asm!` block since it knows that they are not read or written to by the `asm!`.
896
924
The compiler also assumes that this `asm!` block does not perform any kind of synchronization with other threads, e.g. via fences.
897
925
898
-
<!-- no_run: This test has unpredictable or undefined behaviour at runtime -->
926
+
<!-- no_run: This test has unpredictable or undefined behavior at runtime -->
899
927
```rust,no_run
900
928
# #[cfg(target_arch = "x86_64")] {
901
929
let mut x = 0i32;
902
930
let z: i32;
903
-
// The following line has undefined behaviour
931
+
// Accessing memory from a nomem asm block is disallowed
-`readonly`: The `asm!` block does not write to any memory accessible outside of the `asm!` block.
910
953
This allows the compiler to cache the values of unmodified global variables in registers across the `asm!` block since it knows that they are not written to by the `asm!`.
0 commit comments