Skip to content

Commit 47264b9

Browse files
committed
Add precise definition of preserves_flags
Also add ABI-clobbers as a future extension. Fixes #5
1 parent d40eb58 commit 47264b9

File tree

1 file changed

+29
-2
lines changed

1 file changed

+29
-2
lines changed

rfcs/0000-inline-asm.md

+29-2
Original file line numberDiff line numberDiff line change
@@ -517,12 +517,33 @@ Currently the following flags are defined:
517517
- `pure`: The `asm` block has no side effects, and its outputs depend only on its direct inputs (i.e. the values themselves, not what they point to). This allows the compiler to execute the `asm` block fewer times than specified in the program (e.g. by hoisting it out of a loop) or even eliminate it entirely if the outputs are not used. A warning is emitted if this flag is used on an `asm` with no outputs.
518518
- `nomem`: The `asm` blocks does not read or write to any memory. 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`.
519519
- `readonly`: The `asm` block does not write to any memory. 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`.
520-
- `preserves_flags`: The `asm` block does not modify the condition flags. This allows the compiler to avoid recomputing the condition flags after the `asm` block.
520+
- `preserves_flags`: The `asm` block does not modify the flags register (defined below). This allows the compiler to avoid recomputing the condition flags after the `asm` block.
521521
- `noreturn`: The `asm` block never returns, and its return type is defined as `!` (never). Behavior is undefined if execution falls through past the end of the asm code.
522522
- `nostack`: The `asm` block does not push data to the stack, or write to the stack red-zone (if supported by the target). If this flag is *not* used then the stack pointer is guaranteed to be suitably aligned (according to the target ABI) for a function call.
523523

524524
The `nomem` and `readonly` flags are mutually exclusive: it is an error to specify both. Specifying `pure` on an asm block with no outputs is linted against since such a block will be optimized away to nothing.
525525

526+
These flag registers which must be preserved if `preserves_flags` is set:
527+
- x86
528+
- Status flags in `EFLAGS` (CF, PF, AF, ZF, SF, OF).
529+
- Direction flag in `EFLAGS` (DF).
530+
- Floating-point status word (all).
531+
- Floating-point exception flags in `MXCSR` (PE, UE, OE, ZE, DE, IE).
532+
- ARM
533+
- Condition flags in `CPSR` (N, Z, C, V)
534+
- Saturation flag in `CPSR` (Q)
535+
- Greater than or equal flags in `CPSR` (GE).
536+
- Condition flags in `FPSCR` (N, Z, C, V)
537+
- Saturation flag in `FPSCR` (QC)
538+
- Floating-point exception flags in `FPSCR` (IDC, IXC, UFC, OFC, DZC, IOC).
539+
- AArch64
540+
- Condition flags (`NZCV` register).
541+
- Floating-point status (`FPSR` register).
542+
- RISC-V
543+
- Floating-point exception flags in `fcsr` (`fflags`).
544+
545+
> Note: As a general rule, these are the flags which are *not* preserved when performing a function call.
546+
526547
## Mapping to LLVM IR
527548

528549
The direction specification maps to a LLVM constraint specification as follows (using a `reg` operand as an example):
@@ -798,7 +819,7 @@ See the section [above][dsl].
798819
# Unresolved questions
799820
[unresolved-questions]: #unresolved-questions
800821

801-
- What should `preserves_flags` do on architectures that don't have condition flags (e.g. RISC-V)? Do nothing? Compile-time error?
822+
None
802823

803824
# Future possibilities
804825
[future-possibilities]: #future-possibilities
@@ -840,3 +861,9 @@ We could support `mem` as an alternative to specifying a register class which wo
840861
## Shorthand notation for operand names
841862

842863
We should support some sort of shorthand notation for operand names to avoid needing to write `blah = out(reg) blah`? For example, if the expression is just a single identifier, we could implicitly allow that operand to be referred to using that identifier.
864+
865+
## Clobbers for function calls
866+
867+
Sometimes it can be difficult to specify the necessary clobbers for an asm block which performs a function call. In particular, it is difficult for such code to be forward-compatible if the architecture adds new registers in a future revision, which the compiler may use but will be missing from the `asm!` clobber list.
868+
869+
One possible solution to this would be to add a `clobber(<abi>)` operand where `<abi>` is a calling convention such as `"C"` or `"stdcall"`. The compiler would then automatically insert the necessary clobbers for a function call to that ABI.

0 commit comments

Comments
 (0)