Skip to content

Commit 1384941

Browse files
committed
document naked_asm!
1 parent 128be8d commit 1384941

File tree

2 files changed

+56
-6
lines changed

2 files changed

+56
-6
lines changed

src/attributes/codegen.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ No function prologue or epilogue are generated for the attributed function: the
6767
of the `naked_asm!` invocation make up the full body of a naked function.
6868

6969
r[attributes.codegen.naked.call-stack]
70-
The caller must set up the call stack acording to the specified calling convention before
70+
The caller must set up the call stack according to the specified calling convention before
7171
executing a naked function, even in contexts where setting up the call stack would ordinarily
7272
be unnecessary, such as when the function is inlined.
7373

@@ -86,7 +86,7 @@ to the specified calling convention imposes additional safety invariants on its
8686
and therefore must be marked as an [unsafe function].
8787

8888
> ***Note***: a `naked_asm!` invocation may refer to registers that were not specified as operands.
89-
> for standard `asm!` this is undefined behavior, but `inline_asm!` may rely on the state of registers
89+
> for standard `asm!` this is undefined behavior, but `naked_asm!` may rely on the state of registers
9090
> as specified by the calling convention.
9191
9292
r[attributes.codegen.naked.unused-variables]

src/inline-assembly.md

Lines changed: 54 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@ r[asm]
22
# Inline assembly
33

44
r[asm.intro]
5-
Support for inline assembly is provided via the [`asm!`] and [`global_asm!`] macros.
5+
Support for inline assembly is provided via the [`asm!`], [`naked_asm!`] and [`global_asm!`] macros.
66
It can be used to embed handwritten assembly in the assembly output generated by the compiler.
77

88
[`asm!`]: core::arch::asm
9+
[`naked_asm!`]: core::arch::naked_asm
910
[`global_asm!`]: core::arch::global_asm
1011

1112
r[asm.stable-targets]
@@ -60,20 +61,25 @@ option := "pure" / "nomem" / "readonly" / "preserves_flags" / "noreturn" / "nost
6061
options := "options(" option *("," option) [","] ")"
6162
operand := reg_operand / clobber_abi / options
6263
asm := "asm!(" format_string *("," format_string) *("," operand) [","] ")"
64+
naked_asm := "asm!(" format_string *("," format_string) *("," operand) [","] ")"
6365
global_asm := "global_asm!(" format_string *("," format_string) *("," operand) [","] ")"
6466
```
6567

6668
r[asm.scope]
6769
## Scope
6870

6971
r[asm.scope.intro]
70-
Inline assembly can be used in one of two ways.
72+
Inline assembly can be used in one of three ways.
7173

7274
r[asm.scope.asm]
7375
With the `asm!` macro, the assembly code is emitted in a function scope and integrated into the compiler-generated assembly code of a function.
7476
This assembly code must obey [strict rules](#rules-for-inline-assembly) to avoid undefined behavior.
7577
Note that in some cases the compiler may choose to emit the assembly code as a separate function and generate a call to it.
7678

79+
r[asm.scope.naked_asm]
80+
With the `naked_asm!` macro, the assembly code is emitted in a function scope and constitutes the full assembly code of a function.
81+
The `naked_asm!` macro is only allowed in [naked functions](../attributes/codegen.md#the-naked-attribute).
82+
7783
r[asm.scope.global_asm]
7884
With the `global_asm!` macro, the assembly code is emitted in a global scope, outside a function.
7985
This can be used to hand-write entire functions using assembly code, and generally provides much more freedom to use arbitrary registers and assembler directives.
@@ -181,8 +187,11 @@ Operand expressions are evaluated from left to right, just like function call ar
181187
After the `asm!` has executed, outputs are written to in left to right order.
182188
This is significant if two outputs point to the same place: that place will contain the value of the rightmost output.
183189

190+
r[asm.operand-type.naked_asm-restriction]
191+
Because `naked_asm!` defines a whole function body, it can only use `sym` and `const` operands.
192+
184193
r[asm.operand-type.global_asm-restriction]
185-
Since `global_asm!` exists outside a function, it can only use `sym` and `const` operands.
194+
Because `global_asm!` exists outside a function, it can only use `sym` and `const` operands.
186195

187196
r[asm.register-operands]
188197
## Register operands
@@ -571,9 +580,13 @@ r[asm.options.checks.pure]
571580
r[asm.options.checks.noreturn]
572581
- It is a compile-time error to specify `noreturn` on an asm block with outputs.
573582

583+
r[asm.options.naked_asm-restriction]
584+
`global_asm!` only supports the `att_syntax` and `raw` options.
585+
The remaining options are not meaningful because the inline assembly defines the whole function body.
586+
574587
r[asm.options.global_asm-restriction]
575588
`global_asm!` only supports the `att_syntax` and `raw` options.
576-
The remaining options are not meaningful for global-scope inline assembly
589+
The remaining options are not meaningful for global-scope inline assembly.
577590

578591
r[asm.rules]
579592
## Rules for inline assembly
@@ -685,6 +698,43 @@ r[asm.rules.x86-prefix-restriction]
685698
r[asm.rules.preserves_flags]
686699
> **Note**: As a general rule, the flags covered by `preserves_flags` are those which are *not* preserved when performing a function call.
687700
701+
r[asm.naked-rules]
702+
## Rules for naked inline assembly
703+
704+
r[asm.naked-rules.intro]
705+
To avoid undefined behavior, these rules must be followed when using function-scope inline assembly in naked functions (`naked_asm!`):
706+
707+
r[asm.naked-rules.reg-not-input]
708+
- Any registers not used for function inputs according to the calling convention and function signature will contain an undefined value on entry to the asm block.
709+
- An "undefined value" in the context of inline assembly means that the register can (non-deterministically) have any one of the possible values allowed by the architecture.
710+
Notably it is not the same as an LLVM `undef` which can have a different value every time you read it (since such a concept does not exist in assembly code).
711+
712+
r[asm.naked-rules.reg-not-output]
713+
- Any callee-saved registers must have the same value upon exiting the asm block as they had on entry, otherwise behavior is undefined.
714+
- Caller-saved registes may be used freely, even if they are not used for the return value.
715+
716+
r[asm.naked-rules.unwind]
717+
- Behavior is undefined if execution unwinds out of an asm block.
718+
- This also applies if the assembly code calls a function which then unwinds.
719+
720+
r[asm.naked-rules.noreturn]
721+
- Behavior is undefined if execution falls through to the end of the asm block.
722+
723+
r[asm.naked-rules.mem-same-as-ffi]
724+
- The set of memory locations that assembly code is allowed to read and write are the same as those allowed for an FFI function.
725+
- Refer to the unsafe code guidelines for the exact rules.
726+
- These rules do not apply to memory which is private to the asm code, such as stack space allocated within the asm block.
727+
728+
r[asm.naked-rules.black-box]
729+
- The compiler cannot assume that the instructions in the asm are the ones that will actually end up executed.
730+
- This effectively means that the compiler must treat the `naked_asm!` as a black box and only take the interface specification into account, not the instructions themselves.
731+
- Runtime code patching is allowed, via target-specific mechanisms.
732+
- However there is no guarantee that each `naked_asm!` directly corresponds to a single instance of instructions in the object file: the compiler is free to duplicate or deduplicate `naked_asm!` blocks.
733+
734+
r[asm.naked-rules.not-exactly-once]
735+
- You cannot assume that an `naked_asm!` block will appear exactly once in the output binary.
736+
The compiler is allowed to instantiate multiple copies of the `naked_asm!` block, for example when the function containing it is inlined in multiple places.
737+
688738
r[asm.validity]
689739
### Correctness and Validity
690740

0 commit comments

Comments
 (0)