Skip to content

Commit 19d44ba

Browse files
committed
document naked_asm!
1 parent 01a4165 commit 19d44ba

File tree

2 files changed

+57
-10
lines changed

2 files changed

+57
-10
lines changed

src/attributes/codegen.md

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

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

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

8989
> ***Note***: a `naked_asm!` invocation may refer to registers that were not specified as operands.
90-
> for standard `asm!` this is undefined behavior, but `inline_asm!` may rely on the state of registers
90+
> for standard `asm!` this is undefined behavior, but `naked_asm!` may rely on the state of registers
9191
> as specified by the calling convention.
9292
9393
r[attributes.codegen.naked.unused-variables]
9494
The [`unused_variables`] lint is suppressed within naked functions.
9595

96-
r[attributes.codegen.naked.no-unwind]
97-
Implementations may assume that naked functions never unwind.
98-
Unwinding through a naked function is undefined behavior.
99-
10096
## The `no_builtins` attribute
10197

10298
r[attributes.codegen.no_builtins]

src/inline-assembly.md

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@
33
r[asm]
44

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

99
[`asm!`]: core::arch::asm
10+
[`naked_asm!`]: core::arch::naked_asm
1011
[`global_asm!`]: core::arch::global_asm
1112

1213
r[asm.stable-targets]
@@ -61,6 +62,7 @@ option := "pure" / "nomem" / "readonly" / "preserves_flags" / "noreturn" / "nost
6162
options := "options(" option *("," option) [","] ")"
6263
operand := reg_operand / clobber_abi / options
6364
asm := "asm!(" format_string *("," format_string) *("," operand) [","] ")"
65+
naked_asm := "asm!(" format_string *("," format_string) *("," operand) [","] ")"
6466
global_asm := "global_asm!(" format_string *("," format_string) *("," operand) [","] ")"
6567
```
6668

@@ -69,13 +71,17 @@ global_asm := "global_asm!(" format_string *("," format_string) *("," operand) [
6971
r[asm.scope]
7072

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

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

81+
r[asm.scope.naked_asm]
82+
With the `naked_asm!` macro, the assembly code is emitted in a function scope and constitutes the full assembly code of a function.
83+
The `naked_asm!` macro is only allowed in [naked functions](../attributes/codegen.md#the-naked-attribute).
84+
7985
r[asm.scope.global_asm]
8086
With the `global_asm!` macro, the assembly code is emitted in a global scope, outside a function.
8187
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.
@@ -185,8 +191,11 @@ Operand expressions are evaluated from left to right, just like function call ar
185191
After the `asm!` has executed, outputs are written to in left to right order.
186192
This is significant if two outputs point to the same place: that place will contain the value of the rightmost output.
187193

194+
r[asm.operand-type.naked_asm-restriction]
195+
Because `naked_asm!` defines a whole function body, it can only use `sym` and `const` operands.
196+
188197
r[asm.operand-type.global_asm-restriction]
189-
Since `global_asm!` exists outside a function, it can only use `sym` and `const` operands.
198+
Because `global_asm!` exists outside a function, it can only use `sym` and `const` operands.
190199

191200
## Register operands
192201

@@ -578,9 +587,13 @@ r[asm.options.checks.pure]
578587
r[asm.options.checks.noreturn]
579588
- It is a compile-time error to specify `noreturn` on an asm block with outputs.
580589

590+
r[asm.options.naked_asm-restriction]
591+
`global_asm!` only supports the `att_syntax` and `raw` options.
592+
The remaining options are not meaningful because the inline assembly defines the whole function body.
593+
581594
r[asm.options.global_asm-restriction]
582595
`global_asm!` only supports the `att_syntax` and `raw` options.
583-
The remaining options are not meaningful for global-scope inline assembly
596+
The remaining options are not meaningful for global-scope inline assembly.
584597

585598
## Rules for inline assembly
586599

@@ -693,6 +706,44 @@ r[asm.rules.x86-prefix-restriction]
693706
r[asm.rules.preserves_flags]
694707
> **Note**: As a general rule, the flags covered by `preserves_flags` are those which are *not* preserved when performing a function call.
695708
709+
## Rules for naked inline assembly
710+
711+
r[asm.naked-rules]
712+
713+
r[asm.naked-rules.intro]
714+
To avoid undefined behavior, these rules must be followed when using function-scope inline assembly in naked functions (`naked_asm!`):
715+
716+
r[asm.naked-rules.reg-not-input]
717+
- 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.
718+
- 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.
719+
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).
720+
721+
r[asm.naked-rules.reg-not-output]
722+
- Any callee-saved registers must have the same value upon exiting the asm block as they had on entry, otherwise behavior is undefined.
723+
- Caller-saved registes may be used freely, even if they are not used for the return value.
724+
725+
r[asm.naked-rules.unwind]
726+
- Behavior is undefined if execution unwinds out of an asm block.
727+
- This also applies if the assembly code calls a function which then unwinds.
728+
729+
r[asm.naked-rules.noreturn]
730+
- Behavior is undefined if execution falls through to the end of the asm block.
731+
732+
r[asm.naked-rules.mem-same-as-ffi]
733+
- The set of memory locations that assembly code is allowed to read and write are the same as those allowed for an FFI function.
734+
- Refer to the unsafe code guidelines for the exact rules.
735+
- These rules do not apply to memory which is private to the asm code, such as stack space allocated within the asm block.
736+
737+
r[asm.naked-rules.black-box]
738+
- The compiler cannot assume that the instructions in the asm are the ones that will actually end up executed.
739+
- 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.
740+
- Runtime code patching is allowed, via target-specific mechanisms.
741+
- 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.
742+
743+
r[asm.naked-rules.not-exactly-once]
744+
- You cannot assume that an `naked_asm!` block will appear exactly once in the output binary.
745+
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.
746+
696747
### Correctness and Validity
697748

698749
r[asm.validity]

0 commit comments

Comments
 (0)