From fd1188b7846d0160488da4f4335de8543b8ff9fa Mon Sep 17 00:00:00 2001 From: bstrie <865233+bstrie@users.noreply.github.com> Date: Mon, 31 Jan 2022 16:08:11 -0500 Subject: [PATCH 1/9] Add documentation for the `naked` function attribute --- src/attributes/codegen.md | 86 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 85 insertions(+), 1 deletion(-) diff --git a/src/attributes/codegen.md b/src/attributes/codegen.md index 297d6436f..8677ec074 100644 --- a/src/attributes/codegen.md +++ b/src/attributes/codegen.md @@ -51,6 +51,80 @@ r[attributes.codegen.cold] The *`cold` [attribute]* suggests that the attributed function is unlikely to be called. +## The `naked` attribute + +The *`naked` [attribute]* may be applied to a function in order to prevent the compiler +from emitting a function prologue. + +### Requirements + +Any function marked with the `naked` attribute must meet the following requirements; +failure to do so will result in a compiler error. + +* The [function body] must consist of exactly one [`asm!`] macro invocation, + which may be enclosed within an [unsafe block]. + * This `asm!` invocation must not contain any [operands] + except for `const` and `sym` operands. + * This `asm!` invocation must specify the `noreturn` [option], + and must not specify any other options except for `att_syntax`. +* The function must not be marked with the [`inline`] attribute. + +### Recommendations + +Any function marked with the `naked` attribute should adhere to the following recommendations; +failure to do so will result in a compiler warning. + +* The function should feature an [extern function qualifier] that is not `extern "Rust"`. +* All arguments and return types of the function should be [FFI-safe]. + +### Effects + +Marking a function with the `naked` attribute has the following effects: + +* The compiler will not generate a prologue for this function. + Within the function, all registers will remain precisely as they were set up + by its caller. +* The compiler will suppress the [`unused_variables`] lint for this function. + +### Notes + +* The [rules for inline assembly] ordinarily consider it undefined behavior to + refer to registers not specified as input operands, or to modify + registers not specified as output operands. + The reason for this is because ordinarily an `asm!` invocation cannot guarantee + the state of the registers surrounding the assembly block. + However, in naked functions the state of the registers is guaranteed + by adherence to the specified calling convention. + Therefore, it is not undefined behavior for the `asm!` invocation in a naked function + to refer to registers without specifying them as operands. +* A naked function that makes use of registers in a way that does not conform + to the specified calling convention imposes additional safety invariants on its caller, + and therefore must be marked as an [unsafe function]. +* Implementations may assume that naked functions never unwind. + Unwinding through a naked function is undefined behavior. +* The semantics of naked functions require implementations to set up the call stack + according to the specified calling convention before executing a naked function, + even in contexts where setting up the call stack would ordinarily be unnecessary, + such as when the function is inlined. + An implementation can fulfill this requirement by guaranteeing that naked functions + are never inlined. + However, implementations are not currently required to guarantee that naked functions + are never inlined. + In the future it may become a requirement for implementations to guarantee that + naked functions are never inlined; + users must not rely on any observable behavior that may result from inlining. +* Although implementations are prohibited from generating code for a naked function that + contains any instructions that precede the naked function's `asm!` block, + under some circumstances, implementations may generate code that contains instructions + *after* a naked function's `asm!` block. + In the future it may become a requirement for implementations to guarantee + the absence of any instructions following a naked function's `asm!` block; + users must not rely on the presence of any trailing instructions. + If a user of the `naked` attribute relies on the absence of trailing instructions + for correctness, for the time being it is the user's responsibility to ensure that + the instructions truly are absent, + for example by passing any necessary code generation flags to the compiler. + ## The `no_builtins` attribute r[attributes.codegen.no_builtins] @@ -469,14 +543,24 @@ trait object whose methods are attributed. [`-C target-feature`]: ../../rustc/codegen-options/index.html#target-feature [`is_x86_feature_detected`]: ../../std/arch/macro.is_x86_feature_detected.html [`is_aarch64_feature_detected`]: ../../std/arch/macro.is_aarch64_feature_detected.html +[`naked_asm!`]: ../inline-assembly.md +[`inline`]: #the-inline-attribute [`target_feature` conditional compilation option]: ../conditional-compilation.md#target_feature +[`unused_variables`]: ../../rustc/lints/listing/warn-by-default.html#unused-variables [attribute]: ../attributes.md [attributes]: ../attributes.md +[extern function qualifier]: ../items/functions.md#extern-function-qualifier +[FFI-safe]: ../../rustc/lints/listing/warn-by-default.html#improper-ctypes-definitions +[function body]: ../items/functions.md#function-body [functions]: ../items/functions.md +[operands]: ../inline-assembly.md#operand-type +[option]: ../inline-assembly.md#options +[rules for inline assembly]: ../inline-assembly.md#rules-for-inline-assembly [target architecture]: ../conditional-compilation.md#target_arch [trait]: ../items/traits.md [undefined behavior]: ../behavior-considered-undefined.md -[unsafe function]: ../unsafe-keyword.md +[unsafe block]: ../unsafe-blocks.md +[unsafe function]: ../unsafe-functions.md [rust-abi]: ../items/external-blocks.md#abi [`Location`]: core::panic::Location From 01a416581c2620f01125f15d69d06ff90d6bb019 Mon Sep 17 00:00:00 2001 From: bstrie <865233+bstrie@users.noreply.github.com> Date: Wed, 2 Feb 2022 16:05:07 -0500 Subject: [PATCH 2/9] Add `naked` to the attribute index --- src/attributes.md | 2 + src/attributes/codegen.md | 115 +++++++++++++++----------------------- 2 files changed, 46 insertions(+), 71 deletions(-) diff --git a/src/attributes.md b/src/attributes.md index f537e4cd2..9aad3c68b 100644 --- a/src/attributes.md +++ b/src/attributes.md @@ -291,6 +291,7 @@ The following is an index of all built-in attributes. - Code generation - [`inline`] --- Hint to inline code. - [`cold`] --- Hint that a function is unlikely to be called. + - [`naked`] - Prevent the compiler from emitting a function prologue. - [`no_builtins`] --- Disables use of certain built-in functions. - [`target_feature`] --- Configure platform-specific code generation. - [`track_caller`] --- Pass the parent call location to `std::panic::Location::caller()`. @@ -367,6 +368,7 @@ The following is an index of all built-in attributes. [`macro_export`]: macros-by-example.md#path-based-scope [`macro_use`]: macros-by-example.md#the-macro_use-attribute [`must_use`]: attributes/diagnostics.md#the-must_use-attribute +[`naked`]: attributes/codegen.md#the-naked-attribute [`no_builtins`]: attributes/codegen.md#the-no_builtins-attribute [`no_implicit_prelude`]: names/preludes.md#the-no_implicit_prelude-attribute [`no_link`]: items/extern-crates.md#the-no_link-attribute diff --git a/src/attributes/codegen.md b/src/attributes/codegen.md index 8677ec074..ae7f0e645 100644 --- a/src/attributes/codegen.md +++ b/src/attributes/codegen.md @@ -53,77 +53,49 @@ be called. ## The `naked` attribute -The *`naked` [attribute]* may be applied to a function in order to prevent the compiler -from emitting a function prologue. - -### Requirements - -Any function marked with the `naked` attribute must meet the following requirements; -failure to do so will result in a compiler error. - -* The [function body] must consist of exactly one [`asm!`] macro invocation, - which may be enclosed within an [unsafe block]. - * This `asm!` invocation must not contain any [operands] - except for `const` and `sym` operands. - * This `asm!` invocation must specify the `noreturn` [option], - and must not specify any other options except for `att_syntax`. -* The function must not be marked with the [`inline`] attribute. - -### Recommendations - -Any function marked with the `naked` attribute should adhere to the following recommendations; -failure to do so will result in a compiler warning. - -* The function should feature an [extern function qualifier] that is not `extern "Rust"`. -* All arguments and return types of the function should be [FFI-safe]. - -### Effects - -Marking a function with the `naked` attribute has the following effects: - -* The compiler will not generate a prologue for this function. - Within the function, all registers will remain precisely as they were set up - by its caller. -* The compiler will suppress the [`unused_variables`] lint for this function. - -### Notes - -* The [rules for inline assembly] ordinarily consider it undefined behavior to - refer to registers not specified as input operands, or to modify - registers not specified as output operands. - The reason for this is because ordinarily an `asm!` invocation cannot guarantee - the state of the registers surrounding the assembly block. - However, in naked functions the state of the registers is guaranteed - by adherence to the specified calling convention. - Therefore, it is not undefined behavior for the `asm!` invocation in a naked function - to refer to registers without specifying them as operands. -* A naked function that makes use of registers in a way that does not conform - to the specified calling convention imposes additional safety invariants on its caller, - and therefore must be marked as an [unsafe function]. -* Implementations may assume that naked functions never unwind. - Unwinding through a naked function is undefined behavior. -* The semantics of naked functions require implementations to set up the call stack - according to the specified calling convention before executing a naked function, - even in contexts where setting up the call stack would ordinarily be unnecessary, - such as when the function is inlined. - An implementation can fulfill this requirement by guaranteeing that naked functions - are never inlined. - However, implementations are not currently required to guarantee that naked functions - are never inlined. - In the future it may become a requirement for implementations to guarantee that - naked functions are never inlined; - users must not rely on any observable behavior that may result from inlining. -* Although implementations are prohibited from generating code for a naked function that - contains any instructions that precede the naked function's `asm!` block, - under some circumstances, implementations may generate code that contains instructions - *after* a naked function's `asm!` block. - In the future it may become a requirement for implementations to guarantee - the absence of any instructions following a naked function's `asm!` block; - users must not rely on the presence of any trailing instructions. - If a user of the `naked` attribute relies on the absence of trailing instructions - for correctness, for the time being it is the user's responsibility to ensure that - the instructions truly are absent, - for example by passing any necessary code generation flags to the compiler. +r[attributes.codegen.naked] + +r[attributes.codegen.naked.intro] +The *`naked` [attribute]* prevents the compiler from emitting a function prologue and +epilogue for the attributed function. + +r[attributes.codegen.naked.body] +The [function body] must consist of exactly one [`naked_asm!`] macro invocation, which +may be enclosed within an [unsafe block]. + +r[attributes.codegen.naked.prologue-epilogue] +No function prologue or epilogue are generated for the attributed function: the contents +of the `naked_asm!` invocation make up the full body of a naked function. + +r[attributes.codegen.naked.call-stack] +The caller must set up the call stack acording to the specified calling convention before +executing a naked function, even in contexts where setting up the call stack would ordinarily +be unnecessary, such as when the function is inlined. + +An implementation can fulfill this requirement by guaranteeing that naked functions +are never inlined. However, implementations are not currently required to guarantee that +naked functions are never inlined. + +In the future it may become a requirement for implementations to guarantee that +naked functions are never inlined; users must not rely on any observable behavior +that may result from inlining. according to the specified calling convention before +executing a naked function, + +r[attributes.codegen.naked.unsafe-function] +A naked function that makes use of registers in a way that does not conform +to the specified calling convention imposes additional safety invariants on its caller, +and therefore must be marked as an [unsafe function]. + +> ***Note***: a `naked_asm!` invocation may refer to registers that were not specified as operands. +> for standard `asm!` this is undefined behavior, but `inline_asm!` may rely on the state of registers +> as specified by the calling convention. + +r[attributes.codegen.naked.unused-variables] +The [`unused_variables`] lint is suppressed within naked functions. + +r[attributes.codegen.naked.no-unwind] +Implementations may assume that naked functions never unwind. +Unwinding through a naked function is undefined behavior. ## The `no_builtins` attribute @@ -545,6 +517,7 @@ trait object whose methods are attributed. [`is_aarch64_feature_detected`]: ../../std/arch/macro.is_aarch64_feature_detected.html [`naked_asm!`]: ../inline-assembly.md [`inline`]: #the-inline-attribute +[`track_caller`]: #the-track-caller-attribute [`target_feature` conditional compilation option]: ../conditional-compilation.md#target_feature [`unused_variables`]: ../../rustc/lints/listing/warn-by-default.html#unused-variables [attribute]: ../attributes.md From 19d44ba2e11a2e7231350daa6cbef883f3f792b3 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sun, 1 Dec 2024 16:19:30 +0100 Subject: [PATCH 3/9] document `naked_asm!` --- src/attributes/codegen.md | 8 ++---- src/inline-assembly.md | 59 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 57 insertions(+), 10 deletions(-) diff --git a/src/attributes/codegen.md b/src/attributes/codegen.md index ae7f0e645..9aa162198 100644 --- a/src/attributes/codegen.md +++ b/src/attributes/codegen.md @@ -68,7 +68,7 @@ No function prologue or epilogue are generated for the attributed function: the of the `naked_asm!` invocation make up the full body of a naked function. r[attributes.codegen.naked.call-stack] -The caller must set up the call stack acording to the specified calling convention before +The caller must set up the call stack according to the specified calling convention before executing a naked function, even in contexts where setting up the call stack would ordinarily be unnecessary, such as when the function is inlined. @@ -87,16 +87,12 @@ to the specified calling convention imposes additional safety invariants on its and therefore must be marked as an [unsafe function]. > ***Note***: a `naked_asm!` invocation may refer to registers that were not specified as operands. -> for standard `asm!` this is undefined behavior, but `inline_asm!` may rely on the state of registers +> for standard `asm!` this is undefined behavior, but `naked_asm!` may rely on the state of registers > as specified by the calling convention. r[attributes.codegen.naked.unused-variables] The [`unused_variables`] lint is suppressed within naked functions. -r[attributes.codegen.naked.no-unwind] -Implementations may assume that naked functions never unwind. -Unwinding through a naked function is undefined behavior. - ## The `no_builtins` attribute r[attributes.codegen.no_builtins] diff --git a/src/inline-assembly.md b/src/inline-assembly.md index a6cdb1ed8..3e59ad450 100644 --- a/src/inline-assembly.md +++ b/src/inline-assembly.md @@ -3,10 +3,11 @@ r[asm] r[asm.intro] -Support for inline assembly is provided via the [`asm!`] and [`global_asm!`] macros. +Support for inline assembly is provided via the [`asm!`], [`naked_asm!`] and [`global_asm!`] macros. It can be used to embed handwritten assembly in the assembly output generated by the compiler. [`asm!`]: core::arch::asm +[`naked_asm!`]: core::arch::naked_asm [`global_asm!`]: core::arch::global_asm r[asm.stable-targets] @@ -61,6 +62,7 @@ option := "pure" / "nomem" / "readonly" / "preserves_flags" / "noreturn" / "nost options := "options(" option *("," option) [","] ")" operand := reg_operand / clobber_abi / options asm := "asm!(" format_string *("," format_string) *("," operand) [","] ")" +naked_asm := "asm!(" format_string *("," format_string) *("," operand) [","] ")" global_asm := "global_asm!(" format_string *("," format_string) *("," operand) [","] ")" ``` @@ -69,13 +71,17 @@ global_asm := "global_asm!(" format_string *("," format_string) *("," operand) [ r[asm.scope] r[asm.scope.intro] -Inline assembly can be used in one of two ways. +Inline assembly can be used in one of three ways. r[asm.scope.asm] With the `asm!` macro, the assembly code is emitted in a function scope and integrated into the compiler-generated assembly code of a function. This assembly code must obey [strict rules](#rules-for-inline-assembly) to avoid undefined behavior. Note that in some cases the compiler may choose to emit the assembly code as a separate function and generate a call to it. +r[asm.scope.naked_asm] +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). + r[asm.scope.global_asm] With the `global_asm!` macro, the assembly code is emitted in a global scope, outside a function. 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 After the `asm!` has executed, outputs are written to in left to right order. This is significant if two outputs point to the same place: that place will contain the value of the rightmost output. +r[asm.operand-type.naked_asm-restriction] +Because `naked_asm!` defines a whole function body, it can only use `sym` and `const` operands. + r[asm.operand-type.global_asm-restriction] -Since `global_asm!` exists outside a function, it can only use `sym` and `const` operands. +Because `global_asm!` exists outside a function, it can only use `sym` and `const` operands. ## Register operands @@ -578,9 +587,13 @@ r[asm.options.checks.pure] r[asm.options.checks.noreturn] - It is a compile-time error to specify `noreturn` on an asm block with outputs. +r[asm.options.naked_asm-restriction] +`global_asm!` only supports the `att_syntax` and `raw` options. +The remaining options are not meaningful because the inline assembly defines the whole function body. + r[asm.options.global_asm-restriction] `global_asm!` only supports the `att_syntax` and `raw` options. -The remaining options are not meaningful for global-scope inline assembly +The remaining options are not meaningful for global-scope inline assembly. ## Rules for inline assembly @@ -693,6 +706,44 @@ r[asm.rules.x86-prefix-restriction] r[asm.rules.preserves_flags] > **Note**: As a general rule, the flags covered by `preserves_flags` are those which are *not* preserved when performing a function call. +## Rules for naked inline assembly + +r[asm.naked-rules] + +r[asm.naked-rules.intro] +To avoid undefined behavior, these rules must be followed when using function-scope inline assembly in naked functions (`naked_asm!`): + +r[asm.naked-rules.reg-not-input] +- 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. + - 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). + +r[asm.naked-rules.reg-not-output] +- Any callee-saved registers must have the same value upon exiting the asm block as they had on entry, otherwise behavior is undefined. + - Caller-saved registes may be used freely, even if they are not used for the return value. + +r[asm.naked-rules.unwind] +- Behavior is undefined if execution unwinds out of an asm block. + - This also applies if the assembly code calls a function which then unwinds. + +r[asm.naked-rules.noreturn] +- Behavior is undefined if execution falls through to the end of the asm block. + +r[asm.naked-rules.mem-same-as-ffi] +- The set of memory locations that assembly code is allowed to read and write are the same as those allowed for an FFI function. + - Refer to the unsafe code guidelines for the exact rules. + - These rules do not apply to memory which is private to the asm code, such as stack space allocated within the asm block. + +r[asm.naked-rules.black-box] +- The compiler cannot assume that the instructions in the asm are the ones that will actually end up executed. + - 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. + - Runtime code patching is allowed, via target-specific mechanisms. + - 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. + +r[asm.naked-rules.not-exactly-once] +- You cannot assume that an `naked_asm!` block will appear exactly once in the output binary. + 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. + ### Correctness and Validity r[asm.validity] From 3cda6540a6041c8bb5fab68c1aa1d052456ff0f1 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sun, 1 Dec 2024 16:44:09 +0100 Subject: [PATCH 4/9] mention incompatible attributes --- src/attributes/codegen.md | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/attributes/codegen.md b/src/attributes/codegen.md index 9aa162198..998b94170 100644 --- a/src/attributes/codegen.md +++ b/src/attributes/codegen.md @@ -86,13 +86,18 @@ A naked function that makes use of registers in a way that does not conform to the specified calling convention imposes additional safety invariants on its caller, and therefore must be marked as an [unsafe function]. -> ***Note***: a `naked_asm!` invocation may refer to registers that were not specified as operands. -> for standard `asm!` this is undefined behavior, but `naked_asm!` may rely on the state of registers -> as specified by the calling convention. - r[attributes.codegen.naked.unused-variables] The [`unused_variables`] lint is suppressed within naked functions. +r[attributes.codegen.naked.inline] +A naked function cannot be attributed by the [`inline`](#the-inline-attribute) attribute. + +r[attributes.codegen.naked.track_caller] +A naked function cannot be attributed by the [`track_caller`](#the-track_caller-attribute) attribute. + +r[attributes.codegen.naked.testing] +A naked function cannot be attributed by [the testing attributes](../testing.md). + ## The `no_builtins` attribute r[attributes.codegen.no_builtins] From 17751560eb6b9bc1a7cf72d2b67f0d42970542ca Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sun, 1 Dec 2024 16:54:55 +0100 Subject: [PATCH 5/9] remove unused links --- src/attributes/codegen.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/attributes/codegen.md b/src/attributes/codegen.md index 998b94170..d6b1baa52 100644 --- a/src/attributes/codegen.md +++ b/src/attributes/codegen.md @@ -523,12 +523,9 @@ trait object whose methods are attributed. [`unused_variables`]: ../../rustc/lints/listing/warn-by-default.html#unused-variables [attribute]: ../attributes.md [attributes]: ../attributes.md -[extern function qualifier]: ../items/functions.md#extern-function-qualifier [FFI-safe]: ../../rustc/lints/listing/warn-by-default.html#improper-ctypes-definitions [function body]: ../items/functions.md#function-body [functions]: ../items/functions.md -[operands]: ../inline-assembly.md#operand-type -[option]: ../inline-assembly.md#options [rules for inline assembly]: ../inline-assembly.md#rules-for-inline-assembly [target architecture]: ../conditional-compilation.md#target_arch [trait]: ../items/traits.md From 23be8ef0f85f912e1db1655f6ecbb3a4daebb505 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sun, 1 Dec 2024 19:31:27 +0100 Subject: [PATCH 6/9] changes after code review also maybe make links work? --- src/attributes/codegen.md | 17 +++++------------ src/inline-assembly.md | 17 ++++------------- 2 files changed, 9 insertions(+), 25 deletions(-) diff --git a/src/attributes/codegen.md b/src/attributes/codegen.md index d6b1baa52..dddf568d3 100644 --- a/src/attributes/codegen.md +++ b/src/attributes/codegen.md @@ -68,18 +68,11 @@ No function prologue or epilogue are generated for the attributed function: the of the `naked_asm!` invocation make up the full body of a naked function. r[attributes.codegen.naked.call-stack] -The caller must set up the call stack according to the specified calling convention before -executing a naked function, even in contexts where setting up the call stack would ordinarily -be unnecessary, such as when the function is inlined. +The asm code will have a valid call stack and register state on entry as per the signature and calling convention of the function. -An implementation can fulfill this requirement by guaranteeing that naked functions -are never inlined. However, implementations are not currently required to guarantee that -naked functions are never inlined. - -In the future it may become a requirement for implementations to guarantee that -naked functions are never inlined; users must not rely on any observable behavior -that may result from inlining. according to the specified calling convention before -executing a naked function, +r[attributes.codegen.naked.no-duplication] +The asm code may not be duplicated by the compiler. +This property is important for naked functions that define symbols in the assembly code. r[attributes.codegen.naked.unsafe-function] A naked function that makes use of registers in a way that does not conform @@ -96,7 +89,7 @@ r[attributes.codegen.naked.track_caller] A naked function cannot be attributed by the [`track_caller`](#the-track_caller-attribute) attribute. r[attributes.codegen.naked.testing] -A naked function cannot be attributed by [the testing attributes](../testing.md). +A naked function cannot be attributed by [the testing attributes](attributes/testing.md). ## The `no_builtins` attribute diff --git a/src/inline-assembly.md b/src/inline-assembly.md index 3e59ad450..b3be061e9 100644 --- a/src/inline-assembly.md +++ b/src/inline-assembly.md @@ -80,7 +80,7 @@ Note that in some cases the compiler may choose to emit the assembly code as a s r[asm.scope.naked_asm] 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). +The `naked_asm!` macro is only allowed in [naked functions](attributes/codegen.md#the-naked-attribute). r[asm.scope.global_asm] With the `global_asm!` macro, the assembly code is emitted in a global scope, outside a function. @@ -588,7 +588,7 @@ r[asm.options.checks.noreturn] - It is a compile-time error to specify `noreturn` on an asm block with outputs. r[asm.options.naked_asm-restriction] -`global_asm!` only supports the `att_syntax` and `raw` options. +`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. r[asm.options.global_asm-restriction] @@ -719,7 +719,7 @@ r[asm.naked-rules.reg-not-input] 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). r[asm.naked-rules.reg-not-output] -- Any callee-saved registers must have the same value upon exiting the asm block as they had on entry, otherwise behavior is undefined. +- Any callee-saved registers must have the same value upon return as they had on entry, otherwise behavior is undefined. - Caller-saved registes may be used freely, even if they are not used for the return value. r[asm.naked-rules.unwind] @@ -728,22 +728,13 @@ r[asm.naked-rules.unwind] r[asm.naked-rules.noreturn] - Behavior is undefined if execution falls through to the end of the asm block. + - the assembly code is expected to contain a return instruction or to diverge r[asm.naked-rules.mem-same-as-ffi] - The set of memory locations that assembly code is allowed to read and write are the same as those allowed for an FFI function. - Refer to the unsafe code guidelines for the exact rules. - These rules do not apply to memory which is private to the asm code, such as stack space allocated within the asm block. -r[asm.naked-rules.black-box] -- The compiler cannot assume that the instructions in the asm are the ones that will actually end up executed. - - 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. - - Runtime code patching is allowed, via target-specific mechanisms. - - 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. - -r[asm.naked-rules.not-exactly-once] -- You cannot assume that an `naked_asm!` block will appear exactly once in the output binary. - 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. - ### Correctness and Validity r[asm.validity] From a9301726f3b729a70b0d4969429f967ce842ddef Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sun, 1 Dec 2024 21:23:26 +0100 Subject: [PATCH 7/9] fix link --- src/attributes/codegen.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/attributes/codegen.md b/src/attributes/codegen.md index dddf568d3..6790f1754 100644 --- a/src/attributes/codegen.md +++ b/src/attributes/codegen.md @@ -89,7 +89,7 @@ r[attributes.codegen.naked.track_caller] A naked function cannot be attributed by the [`track_caller`](#the-track_caller-attribute) attribute. r[attributes.codegen.naked.testing] -A naked function cannot be attributed by [the testing attributes](attributes/testing.md). +A naked function cannot be attributed by [the testing attributes](testing.md). ## The `no_builtins` attribute From 959b8f17d6bc10a41e6122c36fceb86a4b0f6708 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Mon, 2 Dec 2024 10:02:23 +0100 Subject: [PATCH 8/9] add rule on black box/code patching --- src/inline-assembly.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/inline-assembly.md b/src/inline-assembly.md index b3be061e9..5ffaffa43 100644 --- a/src/inline-assembly.md +++ b/src/inline-assembly.md @@ -735,6 +735,11 @@ r[asm.naked-rules.mem-same-as-ffi] - Refer to the unsafe code guidelines for the exact rules. - These rules do not apply to memory which is private to the asm code, such as stack space allocated within the asm block. +r[asm.rules.black-box] +- The compiler cannot assume that the instructions in the asm are the ones that will actually end up executed. + - 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. + - Runtime code patching is allowed, via target-specific mechanisms. + ### Correctness and Validity r[asm.validity] From 5deb3b5ad05bcf62e2ba9b5c5b9f49ec3e8f6731 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Mon, 2 Dec 2024 10:31:56 +0100 Subject: [PATCH 9/9] fix rule name Co-authored-by: bjorn3 <17426603+bjorn3@users.noreply.github.com> --- src/inline-assembly.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/inline-assembly.md b/src/inline-assembly.md index 5ffaffa43..572419772 100644 --- a/src/inline-assembly.md +++ b/src/inline-assembly.md @@ -735,7 +735,7 @@ r[asm.naked-rules.mem-same-as-ffi] - Refer to the unsafe code guidelines for the exact rules. - These rules do not apply to memory which is private to the asm code, such as stack space allocated within the asm block. -r[asm.rules.black-box] +r[asm.naked-rules.black-box] - The compiler cannot assume that the instructions in the asm are the ones that will actually end up executed. - 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. - Runtime code patching is allowed, via target-specific mechanisms.