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
Copy file name to clipboardExpand all lines: src/attributes/codegen.md
+44
Original file line number
Diff line number
Diff line change
@@ -46,6 +46,42 @@ r[attributes.codegen.cold]
46
46
The *`cold`[attribute]* suggests that the attributed function is unlikely to
47
47
be called.
48
48
49
+
r[attributes.codegen.naked]
50
+
## The `naked` attribute
51
+
52
+
r[attributes.codegen.naked.intro]
53
+
The *`naked`[attribute]* prevents the compiler from emitting a function prologue and epilogue for the attributed function.
54
+
55
+
r[attributes.codegen.naked.body]
56
+
The [function body] must consist of exactly one [`naked_asm!`] macro invocation.
57
+
58
+
r[attributes.codegen.naked.prologue-epilogue]
59
+
No function prologue or epilogue is generated for the attributed function. The assembly code in the `naked_asm!` block constitutes the full body of a naked function.
60
+
61
+
r[attributes.codegen.naked.unsafe-attribute]
62
+
The `naked` attribute is an [unsafe attribute]. Annotating a function with `#[unsafe(naked)]` comes with the safety obligation that the body must respect the function's calling convention, uphold its signature, and either return or diverge (i.e., not fall through past the end of the assembly code).
63
+
64
+
r[attributes.codegen.naked.call-stack]
65
+
The assembly code may assume that the call stack and register state are valid on entry as per the signature and calling convention of the function.
66
+
67
+
r[attributes.codegen.naked.no-duplication]
68
+
The assembly code may not be duplicated by the compiler except when monomorphizing polymorphic functions.
69
+
70
+
> [!NOTE]
71
+
> Guaranteeing when the assembly code may or may not be duplicated is important for naked functions that define symbols.
72
+
73
+
r[attributes.codegen.naked.unused-variables]
74
+
The [`unused_variables`] lint is suppressed within naked functions.
75
+
76
+
r[attributes.codegen.naked.inline]
77
+
The [`inline`](#the-inline-attribute) attribute cannot by applied to a naked function.
78
+
79
+
r[attributes.codegen.naked.track_caller]
80
+
The [`track_caller`](#the-track_caller-attribute) attribute cannot be applied to a naked function.
81
+
82
+
r[attributes.codegen.naked.testing]
83
+
The [testing attributes](testing.md) cannot be applied to a naked function.
84
+
49
85
r[attributes.codegen.no_builtins]
50
86
## The `no_builtins` attribute
51
87
@@ -497,15 +533,23 @@ trait object whose methods are attributed.
With the `naked_asm!` macro, the assembly code is emitted in a function scope and constitutes the full assembly code of a function. The `naked_asm!` macro is only allowed in [naked functions](attributes/codegen.md#the-naked-attribute).
85
+
86
+
```rust
87
+
# #[cfg(target_arch ="x86_64")] {
88
+
# #[unsafe(naked)]
89
+
# extern"C"fnwrapper() {
90
+
core::arch::naked_asm!("/* {} */", const0);
91
+
# }
92
+
# }
93
+
```
94
+
81
95
r[asm.scope.global_asm]
82
96
With the `global_asm!` macro, the assembly code is emitted in a global scope, outside a function.
83
97
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.
@@ -384,8 +398,11 @@ assert_eq!(y, 1);
384
398
# }
385
399
```
386
400
401
+
r[asm.operand-type.naked_asm-restriction]
402
+
Because `naked_asm!` defines a whole function body and the compiler cannot emit any additional code to handle operands, it can only use `sym` and `const` operands.
403
+
387
404
r[asm.operand-type.global_asm-restriction]
388
-
Since`global_asm!` exists outside a function, it can only use `sym` and `const` operands.
405
+
Because`global_asm!` exists outside a function, it can only use `sym` and `const` operands.
# #[cfg(not(target_arch = "x86_64"))] core::compile_error!("Test not supported on this arch");
1207
1224
```
1208
1225
1226
+
r[asm.options.naked_asm-restriction]
1227
+
`naked_asm!` only supports the `att_syntax` and `raw` options. The remaining options are not meaningful because the inline assembly defines the whole function body.
1228
+
1209
1229
r[asm.options.global_asm-restriction]
1210
-
`global_asm!` only supports the `att_syntax` and `raw` options.
1211
-
The remaining options are not meaningful for global-scope inline assembly
1230
+
`global_asm!` only supports the `att_syntax` and `raw` options. The remaining options are not meaningful for global-scope inline assembly.
1212
1231
1213
1232
```rust,compile_fail
1214
1233
# fn main() {}
@@ -1242,7 +1261,6 @@ r[asm.rules.unwind]
1242
1261
1243
1262
r[asm.rules.mem-same-as-ffi]
1244
1263
- The set of memory locations that assembly code is allowed to read and write are the same as those allowed for an FFI function.
1245
-
- Refer to the unsafe code guidelines for the exact rules.
1246
1264
- If the `readonly` option is set, then only memory reads are allowed.
1247
1265
- If the `nomem` option is set then no reads or writes to memory are allowed.
1248
1266
- These rules do not apply to memory which is private to the assembly code, such as stack space allocated within it.
> As a general rule, the flags covered by `preserves_flags` are those which are *not* preserved when performing a function call.
1364
1382
1383
+
r[asm.naked-rules]
1384
+
## Rules for naked inline assembly
1385
+
1386
+
r[asm.naked-rules.intro]
1387
+
To avoid undefined behavior, these rules must be followed when using function-scope inline assembly in naked functions (`naked_asm!`):
1388
+
1389
+
r[asm.naked-rules.reg-not-input]
1390
+
- Any registers not used for function inputs according to the calling convention and function signature will contain an undefined value on entry to the `naked_asm!` block.
1391
+
- 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. 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).
1392
+
1393
+
r[asm.naked-rules.callee-saved-registers]
1394
+
- All callee-saved registers must have the same value upon return as they had on entry.
1395
+
1396
+
r[asm.naked-rules.caller-saved-registers]
1397
+
- Caller-saved registers may be used freely.
1398
+
1399
+
r[asm.naked-rules.noreturn]
1400
+
- Behavior is undefined if execution falls through past the end of the assembly code.
1401
+
- Every path through the assembly code is expected to terminate with a return instruction or to diverge.
1402
+
1403
+
r[asm.naked-rules.mem-same-as-ffi]
1404
+
- The set of memory locations that assembly code is allowed to read and write are the same as those allowed for an FFI function.
1405
+
1406
+
r[asm.naked-rules.black-box]
1407
+
- The compiler cannot assume that the instructions in the `naked_asm!` block are the ones that will actually be executed.
1408
+
- 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.
1409
+
- Runtime code patching is allowed, via target-specific mechanisms.
1410
+
1411
+
r[asm.naked-rules.unwind]
1412
+
- Unwinding out of a `naked_asm!` block is allowed.
1413
+
- For correct behavior, the appropriate assembler directives that emit unwinding metadata must be used.
1414
+
1415
+
```rust
1416
+
# #[cfg(target_arch ="x86_64")] {
1417
+
#[unsafe(naked)]
1418
+
extern"sysv64-unwind"fnunwinding_naked() {
1419
+
core::arch::naked_asm!(
1420
+
// "CFI" here stands for "call frame information".
1421
+
".cfi_startproc",
1422
+
// The CFA (canonical frame address) is the value of `rsp`
1423
+
// before the `call`, i.e. before the return address, `rip`,
1424
+
// was pushed to `rsp`, so it's eight bytes higher in memory
1425
+
// than `rsp` upon function entry (after `rip` has been
1426
+
// pushed).
1427
+
//
1428
+
// This is the default, so we don't have to write it.
1429
+
//".cfi_def_cfa rsp, 8",
1430
+
//
1431
+
// The traditional thing to do is to preserve the base
1432
+
// pointer, so we'll do that.
1433
+
"push rbp",
1434
+
// Since we've now extended the stack downward by 8 bytes in
1435
+
// memory, we need to adjust the offset to the CFA from `rsp`
1436
+
// by another 8 bytes.
1437
+
".cfi_adjust_cfa_offset 8",
1438
+
// We also then annotate where we've stored the caller's value
1439
+
// of `rbp`, relative to the CFA, so that when unwinding into
1440
+
// the caller we can find it, in case we need it to calculate
1441
+
// the caller's CFA relative to it.
1442
+
//
1443
+
// Here, we've stored the caller's `rbp` starting 16 bytes
1444
+
// below the CFA. I.e., starting from the CFA, there's first
1445
+
// the `rip` (which starts 8 bytes below the CFA and continues
1446
+
// up to it), then there's the caller's `rbp` that we just
1447
+
// pushed.
1448
+
".cfi_offset rbp, -16",
1449
+
// As is traditional, we set the base pointer to the value of
1450
+
// the stack pointer. This way, the base pointer stays the
1451
+
// same throughout the function body.
1452
+
"mov rbp, rsp",
1453
+
// We can now track the offset to the CFA from the base
1454
+
// pointer. This means we don't need to make any further
1455
+
// adjustments until the end, as we don't change `rbp`.
1456
+
".cfi_def_cfa_register rbp",
1457
+
// We can now call a function that may panic.
1458
+
"call {f}",
1459
+
// Upon return, we restore `rbp` in preparation for returning
1460
+
// ourselves.
1461
+
"pop rbp",
1462
+
// Now that we've restored `rbp`, we must specify the offset
1463
+
// to the CFA again in terms of `rsp`.
1464
+
".cfi_def_cfa rsp, 8",
1465
+
// Now we can return.
1466
+
"ret",
1467
+
".cfi_endproc",
1468
+
f=symmay_panic,
1469
+
)
1470
+
}
1471
+
1472
+
extern"sysv64-unwind"fnmay_panic() {
1473
+
panic!("unwind");
1474
+
}
1475
+
# }
1476
+
```
1477
+
1478
+
> [!NOTE]
1479
+
>
1480
+
> For more information on the `cfi` assembler directives above, see these resources:
0 commit comments