From: Nathan Chancellor <nathan@kernel.org>
To: Alice Ryhl <aliceryhl@google.com>
Cc: "Miguel Ojeda" <ojeda@kernel.org>,
"Boqun Feng" <boqun.feng@gmail.com>,
"Gary Guo" <gary@garyguo.net>,
"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
"Benno Lossin" <lossin@kernel.org>,
"Andreas Hindborg" <a.hindborg@kernel.org>,
"Trevor Gross" <tmgross@umich.edu>,
"Danilo Krummrich" <dakr@kernel.org>,
"Alexandre Courbot" <acourbot@nvidia.com>,
"Will Deacon" <will@kernel.org>,
"Peter Zijlstra" <peterz@infradead.org>,
"Mark Rutland" <mark.rutland@arm.com>,
"Nick Desaulniers" <nick.desaulniers+lkml@gmail.com>,
"Bill Wendling" <morbo@google.com>,
"Justin Stitt" <justinstitt@google.com>,
"Nicolas Schier" <nicolas.schier@linux.dev>,
"Andrew Morton" <akpm@linux-foundation.org>,
"Uladzislau Rezki" <urezki@gmail.com>,
rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org,
llvm@lists.linux.dev, linux-kbuild@vger.kernel.org,
linux-mm@kvack.org, "Matthew Maurer" <mmaurer@google.com>
Subject: Re: [PATCH v2 3/3] build: rust: provide an option to inline C helpers into Rust
Date: Fri, 13 Mar 2026 17:34:50 -0700 [thread overview]
Message-ID: <20260314003450.GC534169@ax162> (raw)
In-Reply-To: <20260203-inline-helpers-v2-3-beb8547a03c9@google.com>
On Tue, Feb 03, 2026 at 11:34:10AM +0000, Alice Ryhl wrote:
> From: Gary Guo <gary@garyguo.net>
>
> A new experimental Kconfig option, `RUST_INLINE_HELPERS` is added to
> allow C helpers (which were created to allow Rust to call into
> inline/macro C functions without having to re-implement the logic in
> Rust) to be inlined into Rust crates without performing global LTO.
>
> If the option is enabled, the following is performed:
> * For helpers, instead of compiling them to an object file to be linked
> into vmlinux, they're compiled to LLVM IR bitcode. Two versions are
> generated: one for built-in code (`helpers.bc`) and one for modules
> (`helpers_module.bc`, with -DMODULE defined). This ensures that C
> macros/inlines that behave differently for modules (e.g. static calls)
> function correctly when inlined.
> * When a Rust crate or object is compiled, instead of generating an
> object file, LLVM bitcode is generated.
> * llvm-link is invoked with --internalize to combine the helper bitcode
> with the crate bitcode. This step is similar to LTO, but this is much
> faster since it only needs to inline the helpers.
> * clang is invoked to turn the combined bitcode into a final object file.
> * Since clang may produce LLVM bitcode when LTO is enabled, and objtool
> requires ELF input, $(cmd_ld_single) is invoked to ensure the object
> is converted to ELF before objtool runs.
>
> The --internalize flag tells llvm-link to treat all symbols in
> helpers.bc using `internal` linkage [1]. This matches the behavior of
> `clang` on `static inline` functions, and avoids exporting the symbol
> from the object file.
>
> To ensure that RUST_INLINE_HELPERS is not incompatible with BTF, we pass
> the -g0 flag when building helpers. See commit 5daa0c35a1f0 ("rust:
> Disallow BTF generation with Rust + LTO") for details.
>
> We have an intended triple mismatch of `aarch64-unknown-none` vs
> `aarch64-unknown-linux-gnu`, so we pass --suppress-warnings to llvm-link
> to suppress it.
>
> We add $(cmd_ld_single) before $(cmd_objtool). Otherwise objtool fails
> to parse the resulting files as Elf when CONFIG_LTO is enabled.
You mention this as the last bullet point above, so this paragraph can
probably be dropped.
> I considered adding some sort of check that KBUILD_MODNAME is not
> present in helpers_module.bc, but this is actually not so easy to carry
> out because .bc files store strings in a weird binary format, so you
> cannot just grep it for a string to check whether it ended up using
> KBUILD_MODNAME anywhere.
>
> Link: https://github.com/llvm/llvm-project/pull/170397 [1]
> Co-developed-by: Boqun Feng <boqun.feng@gmail.com>
> Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
> Co-developed-by: Matthew Maurer <mmaurer@google.com>
> Signed-off-by: Matthew Maurer <mmaurer@google.com>
> Signed-off-by: Gary Guo <gary@garyguo.net>
> Co-developed-by: Alice Ryhl <aliceryhl@google.com>
> Signed-off-by: Alice Ryhl <aliceryhl@google.com>
Reviewed-by: Nathan Chancellor <nathan@kernel.org>
Tested-by: Nathan Chancellor <nathan@kernel.org>
> ---
> Makefile | 3 ++-
> lib/Kconfig.debug | 15 +++++++++++++++
> rust/Makefile | 29 +++++++++++++++++++++++++----
> rust/exports.c | 5 ++++-
> scripts/Makefile.build | 7 ++++++-
> 5 files changed, 52 insertions(+), 7 deletions(-)
>
> diff --git a/Makefile b/Makefile
> index c97f06ee0dda1c922aa23bd5249052591d528eb6..155db03cf489d931eefdb4bd7e3b93e5aa3ea2d6 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -519,6 +519,7 @@ OBJCOPY = $(LLVM_PREFIX)llvm-objcopy$(LLVM_SUFFIX)
> OBJDUMP = $(LLVM_PREFIX)llvm-objdump$(LLVM_SUFFIX)
> READELF = $(LLVM_PREFIX)llvm-readelf$(LLVM_SUFFIX)
> STRIP = $(LLVM_PREFIX)llvm-strip$(LLVM_SUFFIX)
> +LLVM_LINK = $(LLVM_PREFIX)llvm-link$(LLVM_SUFFIX)
I don't have a strong preference but this could be alphabetized among
the binutils variables.
> else
> CC = $(CROSS_COMPILE)gcc
> LD = $(CROSS_COMPILE)ld
> @@ -627,7 +628,7 @@ export RUSTC_BOOTSTRAP := 1
> export CLIPPY_CONF_DIR := $(srctree)
>
> export ARCH SRCARCH CONFIG_SHELL BASH HOSTCC KBUILD_HOSTCFLAGS CROSS_COMPILE LD CC HOSTPKG_CONFIG
> -export RUSTC RUSTDOC RUSTFMT RUSTC_OR_CLIPPY_QUIET RUSTC_OR_CLIPPY BINDGEN
> +export RUSTC RUSTDOC RUSTFMT RUSTC_OR_CLIPPY_QUIET RUSTC_OR_CLIPPY BINDGEN LLVM_LINK
> export HOSTRUSTC KBUILD_HOSTRUSTFLAGS
> export CPP AR NM STRIP OBJCOPY OBJDUMP READELF PAHOLE RESOLVE_BTFIDS LEX YACC AWK INSTALLKERNEL
> export PERL PYTHON3 CHECK CHECKFLAGS MAKE UTS_MACHINE HOSTCXX
> diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
> index 7570a694d54e6170ae6738634218b37e38a4b76a..c44c08b49f3a3c2e06fca42adeb9e04304e7a869 100644
> --- a/lib/Kconfig.debug
> +++ b/lib/Kconfig.debug
> @@ -3551,6 +3551,21 @@ config RUST_KERNEL_DOCTESTS
>
> If unsure, say N.
>
> +config RUST_INLINE_HELPERS
> + bool "Inline C helpers into Rust code"
> + depends on RUST && RUSTC_CLANG_LLVM_COMPATIBLE
> + depends on EXPERT
> + help
> + Inlines C helpers into Rust code using Link Time Optimization.
> +
> + If this option is enabled, C helper functions declared in
> + rust/helpers/ are inlined into Rust code, which is helpful for
> + performance of Rust code. This requires a matching LLVM version for
> + Clang and rustc.
> +
> + If you are sure that you're using Clang and rustc with matching LLVM
> + versions, say Y. Otherwise say N.
> +
> endmenu # "Rust"
>
> endmenu # Kernel hacking
> diff --git a/rust/Makefile b/rust/Makefile
> index 63464bd2c1e9734cd6e659f7ee3db58bf995d6dd..a6839f2d39feefcfea497384ae202a7c6b475942 100644
> --- a/rust/Makefile
> +++ b/rust/Makefile
> @@ -6,15 +6,19 @@ rustdoc_output := $(objtree)/Documentation/output/rust/rustdoc
> obj-$(CONFIG_RUST) += core.o compiler_builtins.o ffi.o
> always-$(CONFIG_RUST) += exports_core_generated.h
>
> +ifdef CONFIG_RUST_INLINE_HELPERS
> +always-$(CONFIG_RUST) += helpers/helpers.bc helpers/helpers_module.bc
> +else
> +obj-$(CONFIG_RUST) += helpers/helpers.o
> +always-$(CONFIG_RUST) += exports_helpers_generated.h
> +endif
> # Missing prototypes are expected in the helpers since these are exported
> # for Rust only, thus there is no header nor prototypes.
> -obj-$(CONFIG_RUST) += helpers/helpers.o
> CFLAGS_REMOVE_helpers/helpers.o = -Wmissing-prototypes -Wmissing-declarations
>
> always-$(CONFIG_RUST) += bindings/bindings_generated.rs bindings/bindings_helpers_generated.rs
> obj-$(CONFIG_RUST) += bindings.o pin_init.o kernel.o
> -always-$(CONFIG_RUST) += exports_helpers_generated.h \
> - exports_bindings_generated.h exports_kernel_generated.h
> +always-$(CONFIG_RUST) += exports_bindings_generated.h exports_kernel_generated.h
>
> always-$(CONFIG_RUST) += uapi/uapi_generated.rs
> obj-$(CONFIG_RUST) += uapi.o
> @@ -480,6 +484,14 @@ $(obj)/bindings/bindings_helpers_generated.rs: private bindgen_target_extra = ;
> $(obj)/bindings/bindings_helpers_generated.rs: $(src)/helpers/helpers.c FORCE
> $(call if_changed_dep,bindgen)
>
> +quiet_cmd_rust_helper = HELPER $@
> + cmd_rust_helper = \
> + $(CC) $(filter-out $(CFLAGS_REMOVE_helpers/helpers.o), $(c_flags)) \
> + -c -g0 $< $(if $(filter %_module.bc,$@),-DMODULE) -emit-llvm -o $@
> +
> +$(obj)/helpers/helpers.bc $(obj)/helpers/helpers_module.bc: $(src)/helpers/helpers.c FORCE
> + +$(call if_changed_dep,rust_helper)
> +
> rust_exports = $(NM) -p --defined-only $(1) | awk '$$2~/(T|R|D|B)/ && $$3!~/__(pfx|cfi|odr_asan)/ { printf $(2),$$3 }'
>
> quiet_cmd_exports = EXPORTS $@
> @@ -561,12 +573,16 @@ quiet_cmd_rustc_library = $(if $(skip_clippy),RUSTC,$(RUSTC_OR_CLIPPY_QUIET)) L
> OBJTREE=$(abspath $(objtree)) \
> $(if $(skip_clippy),$(RUSTC),$(RUSTC_OR_CLIPPY)) \
> $(filter-out $(skip_flags),$(rust_flags)) $(rustc_target_flags) \
> - --emit=dep-info=$(depfile) --emit=obj=$@ \
> + --emit=dep-info=$(depfile) --emit=$(if $(link_helper),llvm-bc=$(patsubst %.o,%.bc,$@),obj=$@) \
> --emit=metadata=$(dir $@)$(patsubst %.o,lib%.rmeta,$(notdir $@)) \
> --crate-type rlib -L$(objtree)/$(obj) \
> --crate-name $(patsubst %.o,%,$(notdir $@)) $< \
> --sysroot=/dev/null \
> + $(if $(link_helper),;$(LLVM_LINK) --internalize --suppress-warnings $(patsubst %.o,%.bc,$@) \
> + $(obj)/helpers/helpers$(if $(part-of-module),_module).bc -o $(patsubst %.o,%.m.bc,$@); \
> + $(CC) $(CLANG_FLAGS) $(KBUILD_CFLAGS) -Wno-override-module -c $(patsubst %.o,%.m.bc,$@) -o $@) \
> $(if $(rustc_objcopy),;$(OBJCOPY) $(rustc_objcopy) $@) \
> + $(cmd_ld_single) \
> $(cmd_objtool)
>
> rust-analyzer:
> @@ -696,4 +712,9 @@ $(obj)/kernel.o: $(obj)/kernel/generated_arch_warn_asm.rs $(obj)/kernel/generate
> endif
> endif
>
> +ifdef CONFIG_RUST_INLINE_HELPERS
> +$(obj)/kernel.o: private link_helper = 1
> +$(obj)/kernel.o: $(obj)/helpers/helpers.bc
> +endif
> +
> endif # CONFIG_RUST
> diff --git a/rust/exports.c b/rust/exports.c
> index 587f0e776aba52854080f15aa91094b55996c072..1b52460b0f4eeef6df9081abb9b7e054a28c3c21 100644
> --- a/rust/exports.c
> +++ b/rust/exports.c
> @@ -16,10 +16,13 @@
> #define EXPORT_SYMBOL_RUST_GPL(sym) extern int sym; EXPORT_SYMBOL_GPL(sym)
>
> #include "exports_core_generated.h"
> -#include "exports_helpers_generated.h"
> #include "exports_bindings_generated.h"
> #include "exports_kernel_generated.h"
>
> +#ifndef CONFIG_RUST_INLINE_HELPERS
> +#include "exports_helpers_generated.h"
> +#endif
> +
> // For modules using `rust/build_error.rs`.
> #ifdef CONFIG_RUST_BUILD_ASSERT_ALLOW
> EXPORT_SYMBOL_RUST_GPL(rust_build_error);
> diff --git a/scripts/Makefile.build b/scripts/Makefile.build
> index 0c838c467c764e14a51ad132444544373e90a84c..7176d997ecab7c3ffd1e00400a8a79a8309485e1 100644
> --- a/scripts/Makefile.build
> +++ b/scripts/Makefile.build
> @@ -343,7 +343,12 @@ rust_common_cmd = \
> # would not match each other.
>
> quiet_cmd_rustc_o_rs = $(RUSTC_OR_CLIPPY_QUIET) $(quiet_modtag) $@
> - cmd_rustc_o_rs = $(rust_common_cmd) --emit=obj=$@ $< $(cmd_objtool)
> + cmd_rustc_o_rs = $(rust_common_cmd) --emit=$(if $(CONFIG_RUST_INLINE_HELPERS),llvm-bc=$(patsubst %.o,%.bc,$@),obj=$@) $< \
> + $(if $(CONFIG_RUST_INLINE_HELPERS),;$(LLVM_LINK) --internalize --suppress-warnings $(patsubst %.o,%.bc,$@) \
> + $(objtree)/rust/helpers/helpers$(if $(part-of-module),_module).bc -o $(patsubst %.o,%.m.bc,$@); \
> + $(CC) $(CLANG_FLAGS) $(KBUILD_CFLAGS) -Wno-override-module -c $(patsubst %.o,%.m.bc,$@) -o $@) \
> + $(cmd_ld_single) \
> + $(cmd_objtool)
>
> define rule_rustc_o_rs
> $(call cmd_and_fixdep,rustc_o_rs)
>
> --
> 2.53.0.rc1.225.gd81095ad13-goog
>
next prev parent reply other threads:[~2026-03-14 0:34 UTC|newest]
Thread overview: 57+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-02-03 11:34 [PATCH v2 0/3] Inline helpers into Rust without full LTO Alice Ryhl
2026-02-03 11:34 ` [PATCH v2 1/3] kbuild: rust: add `CONFIG_RUSTC_CLANG_LLVM_COMPATIBLE` Alice Ryhl
2026-02-03 11:49 ` Will Deacon
2026-02-03 12:02 ` Alice Ryhl
2026-03-05 10:12 ` Nicolas Schier
2026-03-05 10:51 ` Alice Ryhl
2026-03-14 0:26 ` Nathan Chancellor
2026-02-03 11:34 ` [PATCH v2 2/3] rust: helpers: #define __rust_helper Alice Ryhl
2026-03-14 0:28 ` Nathan Chancellor
2026-02-03 11:34 ` [PATCH v2 3/3] build: rust: provide an option to inline C helpers into Rust Alice Ryhl
2026-03-06 17:32 ` Alice Ryhl
2026-03-14 0:40 ` Nathan Chancellor
2026-03-14 11:22 ` Alice Ryhl
2026-03-16 21:34 ` Nathan Chancellor
2026-03-17 8:02 ` Miguel Ojeda
2026-03-14 0:34 ` Nathan Chancellor [this message]
2026-03-17 8:25 ` [PATCH v2 0/3] Inline helpers into Rust without full LTO Andreas Hindborg
2026-03-22 19:21 ` Miguel Ojeda
2026-03-22 19:38 ` Miguel Ojeda
2026-03-23 13:54 ` Mark Brown
2026-03-23 14:53 ` Miguel Ojeda
2026-03-22 19:46 ` Miguel Ojeda
2026-03-23 8:49 ` Marek Szyprowski
2026-03-25 1:58 ` Miguel Ojeda
2026-03-26 21:12 ` Arnd Bergmann
2026-03-27 8:02 ` Miguel Ojeda
2026-03-27 8:16 ` Marek Szyprowski
2026-03-23 0:03 ` Miguel Ojeda
2026-03-23 3:04 ` Andrew Lunn
2026-03-23 3:24 ` Miguel Ojeda
2026-03-23 12:54 ` Andrew Lunn
2026-03-23 13:13 ` Gary Guo
2026-03-23 13:28 ` Andrew Lunn
2026-03-23 13:34 ` Miguel Ojeda
2026-03-23 14:39 ` Alice Ryhl
2026-03-23 13:14 ` Miguel Ojeda
2026-03-23 10:03 ` Russell King (Oracle)
2026-03-23 13:26 ` Miguel Ojeda
2026-03-26 10:10 ` Alice Ryhl
2026-03-26 13:47 ` Miguel Ojeda
2026-03-26 14:31 ` Christian Schrefl
2026-03-26 15:18 ` Russell King (Oracle)
2026-03-26 17:30 ` Miguel Ojeda
2026-03-30 21:09 ` Christian Schrefl
2026-03-31 11:44 ` Arnd Bergmann
2026-03-26 21:33 ` Arnd Bergmann
2026-03-27 7:56 ` Geert Uytterhoeven
2026-03-27 9:02 ` Arnd Bergmann
2026-03-27 13:41 ` Arnd Bergmann
2026-03-30 12:03 ` Geert Uytterhoeven
2026-03-30 12:13 ` Arnd Bergmann
2026-03-30 12:17 ` Geert Uytterhoeven
2026-03-26 17:31 ` Miguel Ojeda
2026-03-26 2:42 ` Nathan Chancellor
2026-03-26 17:13 ` Miguel Ojeda
2026-03-26 5:34 ` David Gow
2026-03-29 17:33 ` Miguel Ojeda
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260314003450.GC534169@ax162 \
--to=nathan@kernel.org \
--cc=a.hindborg@kernel.org \
--cc=acourbot@nvidia.com \
--cc=akpm@linux-foundation.org \
--cc=aliceryhl@google.com \
--cc=bjorn3_gh@protonmail.com \
--cc=boqun.feng@gmail.com \
--cc=dakr@kernel.org \
--cc=gary@garyguo.net \
--cc=justinstitt@google.com \
--cc=linux-kbuild@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=llvm@lists.linux.dev \
--cc=lossin@kernel.org \
--cc=mark.rutland@arm.com \
--cc=mmaurer@google.com \
--cc=morbo@google.com \
--cc=nick.desaulniers+lkml@gmail.com \
--cc=nicolas.schier@linux.dev \
--cc=ojeda@kernel.org \
--cc=peterz@infradead.org \
--cc=rust-for-linux@vger.kernel.org \
--cc=tmgross@umich.edu \
--cc=urezki@gmail.com \
--cc=will@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.