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
The compiler is allowed to instantiate multiple copies an `asm!` block, for example when the function containing it is inlined in multiple places. As a consequence, you should only use GNU assembler [local labels] inside inline assembly code. Defining symbols in assembly code may lead to assembler and/or linker errors due to duplicate symbol definitions.
378
+
379
+
Moreover, due to [an llvm bug], you shouldn't use labels exclusively made of `0` and `1` digits, e.g. `0`, `11` or `101010`, as they may end up being interpreted as binary values.
380
+
381
+
```rust,allow_fail
382
+
#![feature(asm)]
383
+
384
+
let mut a = 0;
385
+
unsafe {
386
+
asm!(
387
+
"mov {0}, 10",
388
+
"2:",
389
+
"sub {0}, 1",
390
+
"cmp {0}, 3",
391
+
"jle 2f",
392
+
"jmp 2b",
393
+
"2:",
394
+
"add {0}, 2",
395
+
out(reg) a
396
+
);
397
+
}
398
+
assert_eq!(a, 5);
399
+
```
400
+
401
+
This will decrement the `{0}` register value from 10 to 3, then add 2 and store it in `a`.
402
+
403
+
This example show a few thing:
404
+
405
+
First that the same number can be used as a label multiple times in the same inline block.
406
+
407
+
Second, that when a numeric label is used as a reference (as an instruction operand, for example), the suffixes b (“backward”) or f (“forward”) should be added to the numeric label. It will then refer to the nearest label defined by this number in this direction.
By default, an inline assembly block is treated the same way as an external FFI function call with a custom calling convention: it may read/write memory, have observable side effects, etc. However in many cases, it is desirable to give the compiler more information about what the assembly code is actually doing so that it can optimize better.
378
415
379
416
Let's take our previous example of an `add` instruction:
380
417
381
418
```rust,allow_fail
382
-
# #![feature(asm)]
419
+
#![feature(asm)]
383
420
let mut a: u64 = 4;
384
421
let b: u64 = 4;
385
422
unsafe {
@@ -787,8 +824,5 @@ The compiler performs some additional checks on options:
787
824
- You are responsible for switching any target-specific state (e.g. thread-local storage, stack bounds).
788
825
- The set of memory locations that you may access is the intersection of those allowed by the `asm!` blocks you entered and exited.
789
826
- You cannot assume that an `asm!` block will appear exactly once in the output binary. The compiler is allowed to instantiate multiple copies of the `asm!` block, for example when the function containing it is inlined in multiple places.
790
-
- As a consequence, you should only use [local labels] inside inline assembly code. Defining symbols in assembly code may lead to assembler and/or linker errors due to duplicate symbol definitions.
791
827
792
828
> **Note**: As a general rule, the flags covered by `preserves_flags` are those which are *not* preserved when performing a function call.
0 commit comments