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.
586
598
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.
587
599
588
-
<!--no_run, this test has a non-deterministic runtime behaviour-->
600
+
<!--no_run, this test has a non-deterministic runtime behavior-->
589
601
```rust,no_run
590
602
# #[cfg(target_arch = "x86_64")] {
591
603
let mut x: i64;
592
604
// Moving a 32-bit value into a 64-bit value, oops.
593
-
#[allow(asm_sub_register)] // rustc warns about this behaviour
605
+
#[allow(asm_sub_register)] // rustc warns about this behavior
# #[cfg(not(target_arch = "x86_64"))] core::compile_error!("Test not supported on this arch");
@@ -810,6 +822,17 @@ The supported modifiers are a subset of LLVM's (and GCC's) [asm template argumen
810
822
> GCC will infer the modifier based on the operand value type, while we default to the full register size.
811
823
> - 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.
812
824
825
+
```rust
826
+
# #[cfg(target_arch ="x86_64")] {
827
+
letmutx=0x10u16;
828
+
829
+
// u16::swap_bytes using `xchg`
830
+
// 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.
815
838
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`).
@@ -829,6 +852,7 @@ This will automatically insert the necessary clobber constraints as needed for c
829
852
extern"C"fnfoo() ->i32{ 0 }
830
853
# #[cfg(target_arch ="x86_64")] {
831
854
letz:i32;
855
+
// 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!`.
920
948
The compiler also assumes that this `asm!` block does not perform any kind of synchronization with other threads, e.g. via fences.
921
949
922
-
<!-- no_run: This test has unpredictable or undefined behaviour at runtime -->
950
+
<!-- no_run: This test has unpredictable or undefined behavior at runtime -->
923
951
```rust,no_run
924
952
# #[cfg(target_arch = "x86_64")] {
925
953
let mut x = 0i32;
926
954
let z: i32;
927
-
// The following line has undefined behaviour
955
+
// 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.
934
977
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