Skip to content

Commit 214024b

Browse files
committed
document naked_asm!
1 parent 1e1a4d8 commit 214024b

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

@@ -580,9 +589,13 @@ r[asm.options.checks.pure]
580589
r[asm.options.checks.noreturn]
581590
- It is a compile-time error to specify `noreturn` on an asm block with outputs.
582591

592+
r[asm.options.naked_asm-restriction]
593+
`global_asm!` only supports the `att_syntax` and `raw` options.
594+
The remaining options are not meaningful because the inline assembly defines the whole function body.
595+
583596
r[asm.options.global_asm-restriction]
584597
`global_asm!` only supports the `att_syntax` and `raw` options.
585-
The remaining options are not meaningful for global-scope inline assembly
598+
The remaining options are not meaningful for global-scope inline assembly.
586599

587600
## Rules for inline assembly
588601

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

700751
r[asm.validity]

0 commit comments

Comments
 (0)