Re: [PATCH v2 2/3] rust: helpers: #define __rust_helper
From: Nathan Chancellor
Date: Fri Mar 13 2026 - 20:29:02 EST
On Tue, Feb 03, 2026 at 11:34:09AM +0000, Alice Ryhl wrote:
> From: Gary Guo <gary@xxxxxxxxxxx>
>
> Because of LLVM inling checks, it's generally not possible to inline a C
> helper into Rust code, even with LTO:
>
> * LLVM doesn't want to inline functions compiled with
> `-fno-delete-null-pointer-checks` with code compiled without. The C
> CGUs all have this enabled and Rust CGUs don't. Inlining is okay since
> this is one of the hardening features that does not change the ABI,
> and we shouldn't have null pointer dereferences in these helpers.
>
> * LLVM doesn't want to inline functions with different list of builtins. C
> side has `-fno-builtin-wcslen`; `wcslen` is not a Rust builtin, so
> they should be compatible, but LLVM does not perform inlining due to
> attributes mismatch.
>
> * clang and Rust doesn't have the exact target string. Clang generates
> `+cmov,+cx8,+fxsr` but Rust doesn't enable them (in fact, Rust will
> complain if `-Ctarget-feature=+cmov,+cx8,+fxsr` is used). x86-64
> always enable these features, so they are in fact the same target
> string, but LLVM doesn't understand this and so inlining is inhibited.
> This can be bypassed with `--ignore-tti-inline-compatible`, but this
> is a hidden option.
>
> To fix this, we can add __always_inline on every helper, which skips
> these LLVM inlining checks. For this purpose, introduce a new
> __rust_helper macro that needs to be added to every helper.
>
> Most helpers already have __rust_helper specified, but there are a few
> missing. The only consequence of this is that those specific helpers do
> not get inlined.
>
> Signed-off-by: Gary Guo <gary@xxxxxxxxxxx>
> Signed-off-by: Alice Ryhl <aliceryhl@xxxxxxxxxx>
> ---
Reviewed-by: Nathan Chancellor <nathan@xxxxxxxxxx>
Tested-by: Nathan Chancellor <nathan@xxxxxxxxxx>
> rust/helpers/helpers.c | 29 +++++++++++++++++++++++++++++
> 1 file changed, 29 insertions(+)
>
> diff --git a/rust/helpers/helpers.c b/rust/helpers/helpers.c
> index a3c42e51f00a0990bea81ebce6e99bb397ce7533..e05c6e7e4abb7e6a4c4a3a417e35022dac1d9c58 100644
> --- a/rust/helpers/helpers.c
> +++ b/rust/helpers/helpers.c
> @@ -7,7 +7,36 @@
> * Sorted alphabetically.
> */
>
> +#include <linux/compiler_types.h>
> +
> +#ifdef __BINDGEN__
> +// Omit `inline` for bindgen as it ignores inline functions.
> #define __rust_helper
> +#else
> +// The helper functions are all inline functions.
> +//
> +// We use `__always_inline` here to bypass LLVM inlining checks, in case the
> +// helpers are inlined directly into Rust CGUs.
> +//
> +// The LLVM inlining checks are false positives:
> +// * LLVM doesn't want to inline functions compiled with
> +// `-fno-delete-null-pointer-checks` with code compiled without.
> +// The C CGUs all have this enabled and Rust CGUs don't. Inlining is okay
> +// since this is one of the hardening features that does not change the ABI,
> +// and we shouldn't have null pointer dereferences in these helpers.
> +// * LLVM doesn't want to inline functions with different list of builtins. C
> +// side has `-fno-builtin-wcslen`; `wcslen` is not a Rust builtin, so they
> +// should be compatible, but LLVM does not perform inlining due to attributes
> +// mismatch.
> +// * clang and Rust doesn't have the exact target string. Clang generates
> +// `+cmov,+cx8,+fxsr` but Rust doesn't enable them (in fact, Rust will
> +// complain if `-Ctarget-feature=+cmov,+cx8,+fxsr` is used). x86-64 always
> +// enable these features, so they are in fact the same target string, but
> +// LLVM doesn't understand this and so inlining is inhibited. This can be
> +// bypassed with `--ignore-tti-inline-compatible`, but this is a hidden
> +// option.
> +#define __rust_helper __always_inline
> +#endif
>
> #include "atomic.c"
> #include "atomic_ext.c"
>
> --
> 2.53.0.rc1.225.gd81095ad13-goog
>