linux-mm.kvack.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/4] Inline helpers into Rust without full LTO
@ 2025-12-02 20:27 Alice Ryhl
  2025-12-02 20:27 ` [PATCH 1/4] vmalloc: export vrealloc_node_align_noprof Alice Ryhl
                   ` (3 more replies)
  0 siblings, 4 replies; 20+ messages in thread
From: Alice Ryhl @ 2025-12-02 20:27 UTC (permalink / raw)
  To: Miguel Ojeda
  Cc: Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
	Andreas Hindborg, Trevor Gross, Danilo Krummrich,
	Alexandre Courbot, Will Deacon, Peter Zijlstra, Mark Rutland,
	Nathan Chancellor, Nick Desaulniers, Bill Wendling, Justin Stitt,
	Nicolas Schier, Andrew Morton, Uladzislau Rezki, rust-for-linux,
	linux-kernel, llvm, linux-kbuild, linux-mm, nouveau, Alice Ryhl,
	Matthew Maurer

Currently the only way for Rust code to call a static inline function is
to go through a helper in rust/helpers/. This introduces performance
costs due to additional function calls and also clutters backtraces and
flame graphs with helper symbols.

To get rid of these helper symbols, provide functionality to inline
helpers into Rust using llvm-link. This option complements full LTO, by
being much cheaper and avoiding incompatibility with BTF.

I ran a microbenchmark showing the benefit of this. All the benchmark
does is call refcount_inc() in a loop. This was chosen since refcounting
is quite hot in Binder. The results are that Rust spends 6.35 ns per
call vs 5.73 ns per call in C. When enabling this option, the two
languages become equally fast, and disassembly confirms the exact same
machine code is used (in particular there is no call to
rust_helper_refcount_inc). Benchmarking Binder also results in an
improvement from this change.

This patch is complementary to:
https://lore.kernel.org/all/20251202-define-rust-helper-v1-0-a2e13cbc17a6@google.com/

Signed-off-by: Alice Ryhl <aliceryhl@google.com>
---
Alice Ryhl (1):
      vmalloc: export vrealloc_node_align_noprof

Gary Guo (3):
      rust: helpers: #define __rust_helper
      kbuild: rust: add `CONFIG_RUSTC_CLANG_LLVM_COMPATIBLE`
      build: rust: provide an option to inline C helpers into Rust

 Makefile                                  |  4 +++-
 init/Kconfig                              | 15 +++++++++++++++
 lib/Kconfig.debug                         | 15 +++++++++++++++
 mm/vmalloc.c                              |  1 +
 rust/Makefile                             | 26 ++++++++++++++++++++++----
 rust/exports.c                            |  5 ++++-
 rust/helpers/atomic.c                     |  5 -----
 rust/helpers/helpers.c                    | 31 +++++++++++++++++++++++++++++++
 scripts/Makefile.build                    |  5 ++++-
 scripts/atomic/gen-rust-atomic-helpers.sh |  5 -----
 10 files changed, 95 insertions(+), 17 deletions(-)
---
base-commit: 54e3eae855629702c566bd2e130d9f40e7f35bde
change-id: 20251202-inline-helpers-996f4db65e18

Best regards,
-- 
Alice Ryhl <aliceryhl@google.com>



^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH 1/4] vmalloc: export vrealloc_node_align_noprof
  2025-12-02 20:27 [PATCH 0/4] Inline helpers into Rust without full LTO Alice Ryhl
@ 2025-12-02 20:27 ` Alice Ryhl
  2025-12-02 20:27 ` [PATCH 2/4] rust: helpers: #define __rust_helper Alice Ryhl
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 20+ messages in thread
From: Alice Ryhl @ 2025-12-02 20:27 UTC (permalink / raw)
  To: Miguel Ojeda
  Cc: Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
	Andreas Hindborg, Trevor Gross, Danilo Krummrich,
	Alexandre Courbot, Will Deacon, Peter Zijlstra, Mark Rutland,
	Nathan Chancellor, Nick Desaulniers, Bill Wendling, Justin Stitt,
	Nicolas Schier, Andrew Morton, Uladzislau Rezki, rust-for-linux,
	linux-kernel, llvm, linux-kbuild, linux-mm, nouveau, Alice Ryhl

This symbol is used from the Nova driver, so it needs to be exported to
avoid a build failure when building Nova as a module.

ERROR: modpost: "vrealloc_node_align_noprof" [drivers/gpu/nova-core/nova_core.ko] undefined!
ERROR: modpost: "vrealloc_node_align_noprof" [samples/rust/rust_dma.ko] undefined!

This error is only triggered if inlining of helpers into Rust is
enabled.

Signed-off-by: Alice Ryhl <aliceryhl@google.com>
---
 mm/vmalloc.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index 798b2ed21e46059f341ed0d46c7fe56bbe357b22..e086d00f04d61ebd481cb84e3dfea51d8a2ffc57 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -4200,6 +4200,7 @@ void *vrealloc_node_align_noprof(const void *p, size_t size, unsigned long align
 
 	return n;
 }
+EXPORT_SYMBOL(vrealloc_node_align_noprof);
 
 #if defined(CONFIG_64BIT) && defined(CONFIG_ZONE_DMA32)
 #define GFP_VMALLOC32 (GFP_DMA32 | GFP_KERNEL)

-- 
2.52.0.158.g65b55ccf14-goog



^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH 2/4] rust: helpers: #define __rust_helper
  2025-12-02 20:27 [PATCH 0/4] Inline helpers into Rust without full LTO Alice Ryhl
  2025-12-02 20:27 ` [PATCH 1/4] vmalloc: export vrealloc_node_align_noprof Alice Ryhl
@ 2025-12-02 20:27 ` Alice Ryhl
  2025-12-02 20:27 ` [PATCH 3/4] kbuild: rust: add `CONFIG_RUSTC_CLANG_LLVM_COMPATIBLE` Alice Ryhl
  2025-12-02 20:27 ` [PATCH 4/4] build: rust: provide an option to inline C helpers into Rust Alice Ryhl
  3 siblings, 0 replies; 20+ messages in thread
From: Alice Ryhl @ 2025-12-02 20:27 UTC (permalink / raw)
  To: Miguel Ojeda
  Cc: Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
	Andreas Hindborg, Trevor Gross, Danilo Krummrich,
	Alexandre Courbot, Will Deacon, Peter Zijlstra, Mark Rutland,
	Nathan Chancellor, Nick Desaulniers, Bill Wendling, Justin Stitt,
	Nicolas Schier, Andrew Morton, Uladzislau Rezki, rust-for-linux,
	linux-kernel, llvm, linux-kbuild, linux-mm, nouveau, Alice Ryhl

From: Gary Guo <gary@garyguo.net>

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.

The actual additions of __rust_helper can happen in separate patches. A
"flag day" change is not required since missing annotations do not lead
to anything worse than missing inlining.

Signed-off-by: Gary Guo <gary@garyguo.net>
Signed-off-by: Alice Ryhl <aliceryhl@google.com>
---
 rust/helpers/atomic.c                     |  5 -----
 rust/helpers/helpers.c                    | 31 +++++++++++++++++++++++++++++++
 scripts/atomic/gen-rust-atomic-helpers.sh |  5 -----
 3 files changed, 31 insertions(+), 10 deletions(-)

diff --git a/rust/helpers/atomic.c b/rust/helpers/atomic.c
index cf06b7ef9a1c559e8d7bdfc2bcd2aeb8951c29d1..a48605628ed73ac32aae2e6280481407a670e88f 100644
--- a/rust/helpers/atomic.c
+++ b/rust/helpers/atomic.c
@@ -11,11 +11,6 @@
 
 #include <linux/atomic.h>
 
-// TODO: Remove this after INLINE_HELPERS support is added.
-#ifndef __rust_helper
-#define __rust_helper
-#endif
-
 __rust_helper int
 rust_helper_atomic_read(const atomic_t *v)
 {
diff --git a/rust/helpers/helpers.c b/rust/helpers/helpers.c
index 551da6c9b5064c324d6f62bafcec672c6c6f5bee..d0e2f1f9b449b2248cfbddcee1e8bf9becc8a2f9 100644
--- a/rust/helpers/helpers.c
+++ b/rust/helpers/helpers.c
@@ -7,6 +7,37 @@
  * 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 "auxiliary.c"
 #include "barrier.c"
diff --git a/scripts/atomic/gen-rust-atomic-helpers.sh b/scripts/atomic/gen-rust-atomic-helpers.sh
index 45b1e100ed7c63108ee6cb07e48a17668f860d47..a3732153af29f415e397e17cab6e75cb5d7efafc 100755
--- a/scripts/atomic/gen-rust-atomic-helpers.sh
+++ b/scripts/atomic/gen-rust-atomic-helpers.sh
@@ -47,11 +47,6 @@ cat << EOF
 
 #include <linux/atomic.h>
 
-// TODO: Remove this after INLINE_HELPERS support is added.
-#ifndef __rust_helper
-#define __rust_helper
-#endif
-
 EOF
 
 grep '^[a-z]' "$1" | while read name meta args; do

-- 
2.52.0.158.g65b55ccf14-goog



^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH 3/4] kbuild: rust: add `CONFIG_RUSTC_CLANG_LLVM_COMPATIBLE`
  2025-12-02 20:27 [PATCH 0/4] Inline helpers into Rust without full LTO Alice Ryhl
  2025-12-02 20:27 ` [PATCH 1/4] vmalloc: export vrealloc_node_align_noprof Alice Ryhl
  2025-12-02 20:27 ` [PATCH 2/4] rust: helpers: #define __rust_helper Alice Ryhl
@ 2025-12-02 20:27 ` Alice Ryhl
  2025-12-02 20:27 ` [PATCH 4/4] build: rust: provide an option to inline C helpers into Rust Alice Ryhl
  3 siblings, 0 replies; 20+ messages in thread
From: Alice Ryhl @ 2025-12-02 20:27 UTC (permalink / raw)
  To: Miguel Ojeda
  Cc: Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
	Andreas Hindborg, Trevor Gross, Danilo Krummrich,
	Alexandre Courbot, Will Deacon, Peter Zijlstra, Mark Rutland,
	Nathan Chancellor, Nick Desaulniers, Bill Wendling, Justin Stitt,
	Nicolas Schier, Andrew Morton, Uladzislau Rezki, rust-for-linux,
	linux-kernel, llvm, linux-kbuild, linux-mm, nouveau, Alice Ryhl,
	Matthew Maurer

From: Gary Guo <gary@garyguo.net>

This config detects if Rust and Clang have matching LLVM major version.
All IR or bitcode operations (e.g. LTO) rely on LLVM major version to be
matching, otherwise it may generate errors, or worse, miscompile silently
due to change of IR semantics.

It's usually suggested to use the exact same LLVM version, but this can
be difficult to guarantee. Rust's suggestion [1] is also major-version only,
so I think this check is sufficient for the kernel.

Link: https://doc.rust-lang.org/rustc/linker-plugin-lto.html [1]
Reviewed-by: Andreas Hindborg <a.hindborg@kernel.org>
Signed-off-by: Gary Guo <gary@garyguo.net>
Signed-off-by: Matthew Maurer <mmaurer@google.com>
Signed-off-by: Alice Ryhl <aliceryhl@google.com>
---
 init/Kconfig | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/init/Kconfig b/init/Kconfig
index cab3ad28ca49e7ac930207c9cde8d431d55dc7af..d35d0ddee573d09997087a0f99dee7c7c9a66ae3 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -82,6 +82,21 @@ config RUSTC_LLVM_VERSION
 	int
 	default $(rustc-llvm-version)
 
+config RUSTC_LLVM_MAJOR_VERSION
+	int
+	default $(shell,expr $(rustc-llvm-version) / 10000)
+
+config RUSTC_CLANG_LLVM_COMPATIBLE
+	bool
+	default y if CC_IS_CLANG && RUSTC_LLVM_MAJOR_VERSION = $(shell,expr $(cc-version) / 10000)
+	help
+	  This indicates whether Rust and Clang use LLVM of the same major
+	  version.
+
+	  Operations involving handling LLVM IR or bitcode (e.g. cross-language
+	  LTO) requires the same LLVM major version to work properly. For best
+	  compatibility it is recommended that the exact same LLVM is used.
+
 config CC_CAN_LINK
 	bool
 	default $(success,$(srctree)/scripts/cc-can-link.sh $(CC) $(CLANG_FLAGS) $(USERCFLAGS) $(USERLDFLAGS) $(m64-flag)) if 64BIT

-- 
2.52.0.158.g65b55ccf14-goog



^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCH 4/4] build: rust: provide an option to inline C helpers into Rust
  2025-12-02 20:27 [PATCH 0/4] Inline helpers into Rust without full LTO Alice Ryhl
                   ` (2 preceding siblings ...)
  2025-12-02 20:27 ` [PATCH 3/4] kbuild: rust: add `CONFIG_RUSTC_CLANG_LLVM_COMPATIBLE` Alice Ryhl
@ 2025-12-02 20:27 ` Alice Ryhl
  2025-12-03  0:40   ` Matthew Maurer
                     ` (3 more replies)
  3 siblings, 4 replies; 20+ messages in thread
From: Alice Ryhl @ 2025-12-02 20:27 UTC (permalink / raw)
  To: Miguel Ojeda
  Cc: Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
	Andreas Hindborg, Trevor Gross, Danilo Krummrich,
	Alexandre Courbot, Will Deacon, Peter Zijlstra, Mark Rutland,
	Nathan Chancellor, Nick Desaulniers, Bill Wendling, Justin Stitt,
	Nicolas Schier, Andrew Morton, Uladzislau Rezki, rust-for-linux,
	linux-kernel, llvm, linux-kbuild, linux-mm, nouveau, Alice Ryhl,
	Matthew Maurer

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.
* The LLVM IR is compiled to bitcode (This is step is not necessary, but
  is a performance optimisation to prevent LLVM from always have to
  reparse the same IR).
* When a Rust crate is compiled, instead of generating an object file, we
  ask LLVM bitcode to be 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.

The --internalize flag tells llvm-link to treat all symbols in
helpers.bc using `internal` linkage. 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 suppress the warning.

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>
---
 Makefile               |  4 +++-
 lib/Kconfig.debug      | 15 +++++++++++++++
 rust/Makefile          | 26 ++++++++++++++++++++++----
 rust/exports.c         |  5 ++++-
 scripts/Makefile.build |  5 ++++-
 5 files changed, 48 insertions(+), 7 deletions(-)

diff --git a/Makefile b/Makefile
index 96ddbaae7e12de71bcfabef4639de3a13a6e4815..5834bfd568548d1bee34b328dccce5d60f85526f 100644
--- a/Makefile
+++ b/Makefile
@@ -517,6 +517,8 @@ 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)
+LLVM_AS		= $(LLVM_PREFIX)llvm-as$(LLVM_SUFFIX)
 else
 CC		= $(CROSS_COMPILE)gcc
 LD		= $(CROSS_COMPILE)ld
@@ -625,7 +627,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 LLVM_AS
 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 3034e294d50df55c4003c5fa5df442f59e711bd8..e63c5eb57b049aff988419ccd12dfd99d59f5080 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -3427,6 +3427,21 @@ config RUST_KERNEL_DOCTESTS
 
 	  If unsure, say N.
 
+config RUST_INLINE_HELPERS
+    bool "Inline C helpers into Rust crates (EXPERIMENTAL)"
+    depends on RUST && RUSTC_CLANG_LLVM_COMPATIBLE
+    depends on EXPERT
+    help
+        Links C helpers into Rust crates through LLVM IR.
+
+        If this option is enabled, instead of generating object files directly,
+        rustc is asked to produce LLVM IR, which is then linked together with
+        the LLVM IR of C helpers, before object file is generated.
+
+        This requires a matching LLVM version for Clang and rustc.
+
+        If unsure, say N.
+
 endmenu # "Rust"
 
 endmenu # Kernel hacking
diff --git a/rust/Makefile b/rust/Makefile
index d7d19c21b671dea10242b1772a8bcf0bf5dcc1cd..2344e2662ce29280582215954132c09f63cd8c9d 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
+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
@@ -468,6 +472,13 @@ $(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 $< -emit-llvm -o $@
+
+$(obj)/helpers/helpers.bc: $(obj)/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 $@
@@ -547,11 +558,13 @@ 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.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_objtool)
 
@@ -678,4 +691,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 d0ee33a487be95f8ba9a5c964ebecfbebc6c4bf8..04eaf2b4fbca2245f904a6dc7875cb3275aa7df6 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -343,7 +343,10 @@ 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.bc -o $(patsubst %.o,%.m.bc,$@); \
+		$(CC) $(CLANG_FLAGS) $(KBUILD_CFLAGS) -Wno-override-module -c $(patsubst %.o,%.m.bc,$@) -o $@) \
+	$(cmd_objtool)
 
 define rule_rustc_o_rs
 	$(call cmd_and_fixdep,rustc_o_rs)

-- 
2.52.0.158.g65b55ccf14-goog



^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 4/4] build: rust: provide an option to inline C helpers into Rust
  2025-12-02 20:27 ` [PATCH 4/4] build: rust: provide an option to inline C helpers into Rust Alice Ryhl
@ 2025-12-03  0:40   ` Matthew Maurer
  2025-12-03 18:09   ` Gary Guo
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 20+ messages in thread
From: Matthew Maurer @ 2025-12-03  0:40 UTC (permalink / raw)
  To: Alice Ryhl
  Cc: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
	Benno Lossin, Andreas Hindborg, Trevor Gross, Danilo Krummrich,
	Alexandre Courbot, Will Deacon, Peter Zijlstra, Mark Rutland,
	Nathan Chancellor, Nick Desaulniers, Bill Wendling, Justin Stitt,
	Nicolas Schier, Andrew Morton, Uladzislau Rezki, rust-for-linux,
	linux-kernel, llvm, linux-kbuild, linux-mm, nouveau

On Tue, Dec 2, 2025 at 12:28 PM Alice Ryhl <aliceryhl@google.com> 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.
> * The LLVM IR is compiled to bitcode (This is step is not necessary, but
>   is a performance optimisation to prevent LLVM from always have to
>   reparse the same IR).
> * When a Rust crate is compiled, instead of generating an object file, we
>   ask LLVM bitcode to be 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.
>
> The --internalize flag tells llvm-link to treat all symbols in
> helpers.bc using `internal` linkage. This matches the behavior of
> `clang` on `static inline` functions, and avoids exporting the symbol
> from the object file.

I've filed a PR with LLVM [1] to clarify that this is the intended
operation of the tool.

[1]: https://github.com/llvm/llvm-project/pull/170397

>
> 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 suppress the warning.
>
> 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>
> ---
>  Makefile               |  4 +++-
>  lib/Kconfig.debug      | 15 +++++++++++++++
>  rust/Makefile          | 26 ++++++++++++++++++++++----
>  rust/exports.c         |  5 ++++-
>  scripts/Makefile.build |  5 ++++-
>  5 files changed, 48 insertions(+), 7 deletions(-)
>
> diff --git a/Makefile b/Makefile
> index 96ddbaae7e12de71bcfabef4639de3a13a6e4815..5834bfd568548d1bee34b328dccce5d60f85526f 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -517,6 +517,8 @@ 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)
> +LLVM_AS                = $(LLVM_PREFIX)llvm-as$(LLVM_SUFFIX)
>  else
>  CC             = $(CROSS_COMPILE)gcc
>  LD             = $(CROSS_COMPILE)ld
> @@ -625,7 +627,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 LLVM_AS
>  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 3034e294d50df55c4003c5fa5df442f59e711bd8..e63c5eb57b049aff988419ccd12dfd99d59f5080 100644
> --- a/lib/Kconfig.debug
> +++ b/lib/Kconfig.debug
> @@ -3427,6 +3427,21 @@ config RUST_KERNEL_DOCTESTS
>
>           If unsure, say N.
>
> +config RUST_INLINE_HELPERS
> +    bool "Inline C helpers into Rust crates (EXPERIMENTAL)"
> +    depends on RUST && RUSTC_CLANG_LLVM_COMPATIBLE
> +    depends on EXPERT
> +    help
> +        Links C helpers into Rust crates through LLVM IR.
> +
> +        If this option is enabled, instead of generating object files directly,
> +        rustc is asked to produce LLVM IR, which is then linked together with
> +        the LLVM IR of C helpers, before object file is generated.
> +
> +        This requires a matching LLVM version for Clang and rustc.
> +
> +        If unsure, say N.
> +
>  endmenu # "Rust"
>
>  endmenu # Kernel hacking
> diff --git a/rust/Makefile b/rust/Makefile
> index d7d19c21b671dea10242b1772a8bcf0bf5dcc1cd..2344e2662ce29280582215954132c09f63cd8c9d 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
> +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
> @@ -468,6 +472,13 @@ $(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 $< -emit-llvm -o $@
> +
> +$(obj)/helpers/helpers.bc: $(obj)/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 $@
> @@ -547,11 +558,13 @@ 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.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_objtool)
>
> @@ -678,4 +691,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 d0ee33a487be95f8ba9a5c964ebecfbebc6c4bf8..04eaf2b4fbca2245f904a6dc7875cb3275aa7df6 100644
> --- a/scripts/Makefile.build
> +++ b/scripts/Makefile.build
> @@ -343,7 +343,10 @@ 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.bc -o $(patsubst %.o,%.m.bc,$@); \
> +               $(CC) $(CLANG_FLAGS) $(KBUILD_CFLAGS) -Wno-override-module -c $(patsubst %.o,%.m.bc,$@) -o $@) \
> +       $(cmd_objtool)
>
>  define rule_rustc_o_rs
>         $(call cmd_and_fixdep,rustc_o_rs)
>
> --
> 2.52.0.158.g65b55ccf14-goog
>


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 4/4] build: rust: provide an option to inline C helpers into Rust
  2025-12-02 20:27 ` [PATCH 4/4] build: rust: provide an option to inline C helpers into Rust Alice Ryhl
  2025-12-03  0:40   ` Matthew Maurer
@ 2025-12-03 18:09   ` Gary Guo
  2025-12-03 21:25   ` Nathan Chancellor
  2025-12-04 10:07   ` Peter Zijlstra
  3 siblings, 0 replies; 20+ messages in thread
From: Gary Guo @ 2025-12-03 18:09 UTC (permalink / raw)
  To: Alice Ryhl
  Cc: Miguel Ojeda, Boqun Feng,  Björn Roy Baron, Benno Lossin,
	Andreas Hindborg, Trevor Gross, Danilo Krummrich,
	Alexandre Courbot, Will Deacon, Peter Zijlstra, Mark Rutland,
	Nathan Chancellor, Nick Desaulniers, Bill Wendling, Justin Stitt,
	Nicolas Schier, Andrew Morton, Uladzislau Rezki, rust-for-linux,
	linux-kernel, llvm, linux-kbuild, linux-mm, nouveau,
	Matthew Maurer

On Tue, 02 Dec 2025 20:27:59 +0000
Alice Ryhl <aliceryhl@google.com> 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.
> * The LLVM IR is compiled to bitcode (This is step is not necessary, but
>   is a performance optimisation to prevent LLVM from always have to
>   reparse the same IR).
> * When a Rust crate is compiled, instead of generating an object file, we
>   ask LLVM bitcode to be 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.
> 
> The --internalize flag tells llvm-link to treat all symbols in
> helpers.bc using `internal` linkage. This matches the behavior of
> `clang` on `static inline` functions, and avoids exporting the symbol
> from the object file.

Huge shout-out to Matthew for discovering this option, this makes thing
so much nicer and it feels way less hacky and more reliable now.

> 
> 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.

Again this is a much nicer way to workaround the issue than changing
the language name in the DWARF info using text replacement that I come
up with :)

> 
> We have an intended triple mismatch of `aarch64-unknown-none` vs
> `aarch64-unknown-linux-gnu`, so we suppress the warning.
> 
> 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>
> ---
>  Makefile               |  4 +++-
>  lib/Kconfig.debug      | 15 +++++++++++++++
>  rust/Makefile          | 26 ++++++++++++++++++++++----
>  rust/exports.c         |  5 ++++-
>  scripts/Makefile.build |  5 ++++-
>  5 files changed, 48 insertions(+), 7 deletions(-)
> 
> diff --git a/Makefile b/Makefile
> index 96ddbaae7e12de71bcfabef4639de3a13a6e4815..5834bfd568548d1bee34b328dccce5d60f85526f 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -517,6 +517,8 @@ 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)
> +LLVM_AS		= $(LLVM_PREFIX)llvm-as$(LLVM_SUFFIX)

I think this is no longer needed as we only use LLVM BC now without
having to round-trip between LLVM IR.

>  else
>  CC		= $(CROSS_COMPILE)gcc
>  LD		= $(CROSS_COMPILE)ld
> @@ -625,7 +627,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 LLVM_AS
>  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

Best,
Gary


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 4/4] build: rust: provide an option to inline C helpers into Rust
  2025-12-02 20:27 ` [PATCH 4/4] build: rust: provide an option to inline C helpers into Rust Alice Ryhl
  2025-12-03  0:40   ` Matthew Maurer
  2025-12-03 18:09   ` Gary Guo
@ 2025-12-03 21:25   ` Nathan Chancellor
  2025-12-03 23:25     ` Matthew Maurer
  2025-12-04  9:46     ` Alice Ryhl
  2025-12-04 10:07   ` Peter Zijlstra
  3 siblings, 2 replies; 20+ messages in thread
From: Nathan Chancellor @ 2025-12-03 21:25 UTC (permalink / raw)
  To: Alice Ryhl
  Cc: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
	Benno Lossin, Andreas Hindborg, Trevor Gross, Danilo Krummrich,
	Alexandre Courbot, Will Deacon, Peter Zijlstra, Mark Rutland,
	Nick Desaulniers, Bill Wendling, Justin Stitt, Nicolas Schier,
	Andrew Morton, Uladzislau Rezki, rust-for-linux, linux-kernel,
	llvm, linux-kbuild, linux-mm, nouveau, Matthew Maurer

Hi Alice,

On Tue, Dec 02, 2025 at 08:27:59PM +0000, Alice Ryhl wrote:
...
> diff --git a/Makefile b/Makefile
> index 96ddbaae7e12de71bcfabef4639de3a13a6e4815..5834bfd568548d1bee34b328dccce5d60f85526f 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -517,6 +517,8 @@ 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)
> +LLVM_AS		= $(LLVM_PREFIX)llvm-as$(LLVM_SUFFIX)

Please keep the binutils alphabetized (i.e, put LLVM_LINK between AR and
NM).

Other than that, this seems fine from a Kbuild perspective (but I did
not look too hard).

>  else
>  CC		= $(CROSS_COMPILE)gcc
>  LD		= $(CROSS_COMPILE)ld
> @@ -625,7 +627,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 LLVM_AS
>  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 3034e294d50df55c4003c5fa5df442f59e711bd8..e63c5eb57b049aff988419ccd12dfd99d59f5080 100644
> --- a/lib/Kconfig.debug
> +++ b/lib/Kconfig.debug
> @@ -3427,6 +3427,21 @@ config RUST_KERNEL_DOCTESTS
>  
>  	  If unsure, say N.
>  
> +config RUST_INLINE_HELPERS
> +    bool "Inline C helpers into Rust crates (EXPERIMENTAL)"
> +    depends on RUST && RUSTC_CLANG_LLVM_COMPATIBLE
> +    depends on EXPERT
> +    help
> +        Links C helpers into Rust crates through LLVM IR.
> +
> +        If this option is enabled, instead of generating object files directly,
> +        rustc is asked to produce LLVM IR, which is then linked together with
> +        the LLVM IR of C helpers, before object file is generated.
> +
> +        This requires a matching LLVM version for Clang and rustc.
> +
> +        If unsure, say N.
> +

I am just curious, why would someone want (or not) to do this? This help
text does not really indicate the point of the option, just what it
does. Is it just the standard tradeoffs with inlining (potential
improvements in performance due to better optimization opportunities
versus text size increase and icache pressure) or something else?

Cheers,
Nathan


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 4/4] build: rust: provide an option to inline C helpers into Rust
  2025-12-03 21:25   ` Nathan Chancellor
@ 2025-12-03 23:25     ` Matthew Maurer
  2025-12-04  9:46     ` Alice Ryhl
  1 sibling, 0 replies; 20+ messages in thread
From: Matthew Maurer @ 2025-12-03 23:25 UTC (permalink / raw)
  To: Nathan Chancellor
  Cc: Alice Ryhl, Miguel Ojeda, Boqun Feng, Gary Guo,
	Björn Roy Baron, Benno Lossin, Andreas Hindborg,
	Trevor Gross, Danilo Krummrich, Alexandre Courbot, Will Deacon,
	Peter Zijlstra, Mark Rutland, Nick Desaulniers, Bill Wendling,
	Justin Stitt, Nicolas Schier, Andrew Morton, Uladzislau Rezki,
	rust-for-linux, linux-kernel, llvm, linux-kbuild, linux-mm,
	nouveau

> I am just curious, why would someone want (or not) to do this? This help
> text does not really indicate the point of the option, just what it
> does. Is it just the standard tradeoffs with inlining (potential
> improvements in performance due to better optimization opportunities
> versus text size increase and icache pressure) or something else?

The main situations where someone would want this off are:
* Not using `clang` (should already be covered in config logic)
* Out of tree module build without the whole kernel build tree (the
`.bc` file produced here would need to be shipped to your out-of-tree
module build environment - it essentially becomes like a header file
for purposes of building an out-of-tree / DKMS Rust module)
* Don't have matching `rustc` and `clang` LLVM (kind of covered in
config logic - if anyone is using a non-release version of LLVM, the
config may indicate them as compatible incorrectly).
* Requires out-of-tree / DKMS Rust modules to build with the same LLVM
revision as the kernel was built with - may be a packaging concern

While the usual inlining tradeoffs apply, all of these functions have
been explicitly marked `static inline`, which indicates those
tradeoffs have already been thought through.

I think that if we had a reliable signal of "`clang` and `rustc` use
compatible bitcode", turning this on by default would be reasonable.
As-is, we have a mostly-reliable signal, so defaulting it to off seems
reasonable so that people don't get surprise miscompilations if they
use a `clang` or `rustc` which are not using precisely a
release-boundary LLVM version. People who know their toolchain story
for x-lang is squared away can turn it on.

>
> Cheers,
> Nathan


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 4/4] build: rust: provide an option to inline C helpers into Rust
  2025-12-03 21:25   ` Nathan Chancellor
  2025-12-03 23:25     ` Matthew Maurer
@ 2025-12-04  9:46     ` Alice Ryhl
  1 sibling, 0 replies; 20+ messages in thread
From: Alice Ryhl @ 2025-12-04  9:46 UTC (permalink / raw)
  To: Nathan Chancellor
  Cc: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
	Benno Lossin, Andreas Hindborg, Trevor Gross, Danilo Krummrich,
	Alexandre Courbot, Will Deacon, Peter Zijlstra, Mark Rutland,
	Nick Desaulniers, Bill Wendling, Justin Stitt, Nicolas Schier,
	Andrew Morton, Uladzislau Rezki, rust-for-linux, linux-kernel,
	llvm, linux-kbuild, linux-mm, nouveau, Matthew Maurer

On Wed, Dec 03, 2025 at 02:25:58PM -0700, Nathan Chancellor wrote:
> Hi Alice,
> 
> On Tue, Dec 02, 2025 at 08:27:59PM +0000, Alice Ryhl wrote:
> ...
> > diff --git a/Makefile b/Makefile
> > index 96ddbaae7e12de71bcfabef4639de3a13a6e4815..5834bfd568548d1bee34b328dccce5d60f85526f 100644
> > --- a/Makefile
> > +++ b/Makefile
> > @@ -517,6 +517,8 @@ 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)
> > +LLVM_AS		= $(LLVM_PREFIX)llvm-as$(LLVM_SUFFIX)
> 
> Please keep the binutils alphabetized (i.e, put LLVM_LINK between AR and
> NM).
> 
> Other than that, this seems fine from a Kbuild perspective (but I did
> not look too hard).

Sure will reorder.

> >  else
> >  CC		= $(CROSS_COMPILE)gcc
> >  LD		= $(CROSS_COMPILE)ld
> > @@ -625,7 +627,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 LLVM_AS
> >  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 3034e294d50df55c4003c5fa5df442f59e711bd8..e63c5eb57b049aff988419ccd12dfd99d59f5080 100644
> > --- a/lib/Kconfig.debug
> > +++ b/lib/Kconfig.debug
> > @@ -3427,6 +3427,21 @@ config RUST_KERNEL_DOCTESTS
> >  
> >  	  If unsure, say N.
> >  
> > +config RUST_INLINE_HELPERS
> > +    bool "Inline C helpers into Rust crates (EXPERIMENTAL)"
> > +    depends on RUST && RUSTC_CLANG_LLVM_COMPATIBLE
> > +    depends on EXPERT
> > +    help
> > +        Links C helpers into Rust crates through LLVM IR.
> > +
> > +        If this option is enabled, instead of generating object files directly,
> > +        rustc is asked to produce LLVM IR, which is then linked together with
> > +        the LLVM IR of C helpers, before object file is generated.
> > +
> > +        This requires a matching LLVM version for Clang and rustc.
> > +
> > +        If unsure, say N.
> > +
> 
> I am just curious, why would someone want (or not) to do this? This help
> text does not really indicate the point of the option, just what it
> does. Is it just the standard tradeoffs with inlining (potential
> improvements in performance due to better optimization opportunities
> versus text size increase and icache pressure) or something else?

Basically you probably want this on if you can enable it, but
RUSTC_CLANG_LLVM_COMPATIBLE is actually a pretty harsh requirement. If
you just install rustc and clang, it's likely they wont be sufficiently
compatible for LTO to take place.

I'll expand on this in the help text.

Alice


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 4/4] build: rust: provide an option to inline C helpers into Rust
  2025-12-02 20:27 ` [PATCH 4/4] build: rust: provide an option to inline C helpers into Rust Alice Ryhl
                     ` (2 preceding siblings ...)
  2025-12-03 21:25   ` Nathan Chancellor
@ 2025-12-04 10:07   ` Peter Zijlstra
  2025-12-04 10:23     ` Alice Ryhl
  3 siblings, 1 reply; 20+ messages in thread
From: Peter Zijlstra @ 2025-12-04 10:07 UTC (permalink / raw)
  To: Alice Ryhl
  Cc: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
	Benno Lossin, Andreas Hindborg, Trevor Gross, Danilo Krummrich,
	Alexandre Courbot, Will Deacon, Mark Rutland, Nathan Chancellor,
	Nick Desaulniers, Bill Wendling, Justin Stitt, Nicolas Schier,
	Andrew Morton, Uladzislau Rezki, rust-for-linux, linux-kernel,
	llvm, linux-kbuild, linux-mm, nouveau, Matthew Maurer

On Tue, Dec 02, 2025 at 08:27:59PM +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.
> * The LLVM IR is compiled to bitcode (This is step is not necessary, but
>   is a performance optimisation to prevent LLVM from always have to
>   reparse the same IR).
> * When a Rust crate is compiled, instead of generating an object file, we
>   ask LLVM bitcode to be 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.
> 
> The --internalize flag tells llvm-link to treat all symbols in
> helpers.bc using `internal` linkage. 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 suppress the warning.

So if I understand this correctly, it will consume the helpers twice,
once for bindgen to generate the rust ffi glue, and then a second time
to 'compile' to IR.

Then the IR is 'linked' into the rust translation units allowing the
actual inlining to take place once 'LTO' runs.

And while this works, this still has the downside of requiring those
rust helper files and using bindgen.

The other day [*] I proposed extending Rust such that it would be able
to consume a clang precompiled header directly, this would allow doing
away with most of all this. No more helpers and no more bindgen.

Would that not be a much saner approach to all this?


[*] https://lkml.kernel.org/r/20251124163315.GL4068168@noisy.programming.kicks-ass.net


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 4/4] build: rust: provide an option to inline C helpers into Rust
  2025-12-04 10:07   ` Peter Zijlstra
@ 2025-12-04 10:23     ` Alice Ryhl
  2025-12-04 11:11       ` Peter Zijlstra
  0 siblings, 1 reply; 20+ messages in thread
From: Alice Ryhl @ 2025-12-04 10:23 UTC (permalink / raw)
  To: Peter Zijlstra, Josh Triplett
  Cc: Miguel Ojeda, Boqun Feng, Gary Guo, Björn Roy Baron,
	Benno Lossin, Andreas Hindborg, Trevor Gross, Danilo Krummrich,
	Alexandre Courbot, Will Deacon, Mark Rutland, Nathan Chancellor,
	Nick Desaulniers, Bill Wendling, Justin Stitt, Nicolas Schier,
	Andrew Morton, Uladzislau Rezki, rust-for-linux, linux-kernel,
	llvm, linux-kbuild, linux-mm, nouveau, Matthew Maurer

On Thu, Dec 04, 2025 at 11:07:25AM +0100, Peter Zijlstra wrote:
> On Tue, Dec 02, 2025 at 08:27:59PM +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.
> > * The LLVM IR is compiled to bitcode (This is step is not necessary, but
> >   is a performance optimisation to prevent LLVM from always have to
> >   reparse the same IR).
> > * When a Rust crate is compiled, instead of generating an object file, we
> >   ask LLVM bitcode to be 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.
> > 
> > The --internalize flag tells llvm-link to treat all symbols in
> > helpers.bc using `internal` linkage. 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 suppress the warning.
> 
> So if I understand this correctly, it will consume the helpers twice,
> once for bindgen to generate the rust ffi glue, and then a second time
> to 'compile' to IR.
> 
> Then the IR is 'linked' into the rust translation units allowing the
> actual inlining to take place once 'LTO' runs.
> 
> And while this works, this still has the downside of requiring those
> rust helper files and using bindgen.

That's right.

> The other day [*] I proposed extending Rust such that it would be able
> to consume a clang precompiled header directly, this would allow doing
> away with most of all this. No more helpers and no more bindgen.
> 
> Would that not be a much saner approach to all this?
> 
> [*] https://lkml.kernel.org/r/20251124163315.GL4068168@noisy.programming.kicks-ass.net

I have actually discussed similar ideas in the past with Josh Triplett,
so you are not the only one who thinks it is a good idea. Unfortunately,
the road to get there is long.

Another option to get rid of the helpers is that bindgen is working on a
--wrap-static-fns flag, which would generate the helpers for us.
However, that route would still require this patch for them to be
inlined.

One detail that makes the precompiled clang header really tricky is
that IMO we should not require RUSTC_CLANG_LLVM_COMPATIBLE for the
build. With bindgen, you just need bindgen and clang to match LLVMs.
That's easy since bindgen loads a dylib from your clang install. But if
you build this logic into rustc, then you need to be really careful to
get rustc and clang from the same source, and that same source must use
the same LLVM to build both.

Alice


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 4/4] build: rust: provide an option to inline C helpers into Rust
  2025-12-04 10:23     ` Alice Ryhl
@ 2025-12-04 11:11       ` Peter Zijlstra
  2025-12-04 11:57         ` Miguel Ojeda
  0 siblings, 1 reply; 20+ messages in thread
From: Peter Zijlstra @ 2025-12-04 11:11 UTC (permalink / raw)
  To: Alice Ryhl
  Cc: Josh Triplett, Miguel Ojeda, Boqun Feng, Gary Guo,
	Björn Roy Baron, Benno Lossin, Andreas Hindborg,
	Trevor Gross, Danilo Krummrich, Alexandre Courbot, Will Deacon,
	Mark Rutland, Nathan Chancellor, Nick Desaulniers, Bill Wendling,
	Justin Stitt, Nicolas Schier, Andrew Morton, Uladzislau Rezki,
	rust-for-linux, linux-kernel, llvm, linux-kbuild, linux-mm,
	nouveau, Matthew Maurer

On Thu, Dec 04, 2025 at 10:23:17AM +0000, Alice Ryhl wrote:

> > The other day [*] I proposed extending Rust such that it would be able
> > to consume a clang precompiled header directly, this would allow doing
> > away with most of all this. No more helpers and no more bindgen.
> > 
> > Would that not be a much saner approach to all this?
> > 
> > [*] https://lkml.kernel.org/r/20251124163315.GL4068168@noisy.programming.kicks-ass.net
> 
> I have actually discussed similar ideas in the past with Josh Triplett,
> so you are not the only one who thinks it is a good idea. Unfortunately,
> the road to get there is long.

Right. Earlier I also proposed using libclang to parse the C header and
inject that. This might be a little simpler, in that..

> Another option to get rid of the helpers is that bindgen is working on a
> --wrap-static-fns flag, which would generate the helpers for us.
> However, that route would still require this patch for them to be
> inlined.
> 
> One detail that makes the precompiled clang header really tricky is
> that IMO we should not require RUSTC_CLANG_LLVM_COMPATIBLE for the
> build. With bindgen, you just need bindgen and clang to match LLVMs.
> That's easy since bindgen loads a dylib from your clang install. But if
> you build this logic into rustc, then you need to be really careful to
> get rustc and clang from the same source, and that same source must use
> the same LLVM to build both.

... if you build rustc against libclang they are necessarily from the
same LLVM build.

But that might be more tricky in that you might need ways to specify C
specific build flags.

Anyway, good to know people are in fact pondering this, because IMO the
whole interoperability thing with C is quite terrible.


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 4/4] build: rust: provide an option to inline C helpers into Rust
  2025-12-04 11:11       ` Peter Zijlstra
@ 2025-12-04 11:57         ` Miguel Ojeda
  2025-12-04 12:39           ` Peter Zijlstra
  2025-12-04 12:49           ` Emilio Cobos Álvarez
  0 siblings, 2 replies; 20+ messages in thread
From: Miguel Ojeda @ 2025-12-04 11:57 UTC (permalink / raw)
  To: Peter Zijlstra, Antoni Boucher, Emilio Cobos Álvarez,
	Arthur Cohen, Gary Guo
  Cc: Alice Ryhl, Josh Triplett, Miguel Ojeda, Boqun Feng,
	Björn Roy Baron, Benno Lossin, Andreas Hindborg,
	Trevor Gross, Danilo Krummrich, Alexandre Courbot, Will Deacon,
	Mark Rutland, Nathan Chancellor, Nick Desaulniers, Bill Wendling,
	Justin Stitt, Nicolas Schier, Andrew Morton, Uladzislau Rezki,
	rust-for-linux, linux-kernel, llvm, linux-kbuild, linux-mm,
	nouveau, Matthew Maurer

On Thu, Dec 4, 2025 at 12:11 PM Peter Zijlstra <peterz@infradead.org> wrote:
>
> Right. Earlier I also proposed using libclang to parse the C header and
> inject that. This might be a little simpler, in that..

Yeah, that would be closer to the `bindgen` route in that `libclang`
gets already involved.

> ... if you build rustc against libclang they are necessarily from the
> same LLVM build.

So currently there are 3 "LLVMs" that get involved:

  - The one Clang uses (in LLVM=1 builds).
  - The one `rustc` uses (the LLVM backend).
  - The one `bindgen` uses (via libclang).

If that is all done within `rustc` (so no `bindgen`), then there may
still be `rustc` vs. Clang mismatches, which are harder to resolve in
the Rust side at least (it is easier to pick another Clang version to
match).

For those using builds from distros, that shouldn't be a problem.
Others using external `rustc` builds, e.g. from `rustup` (e.g. for
testing different Rust versions) it would be harder.

But I mean, anything approach that gets us into a better position is
welcome and I think requiring people to match LLVM everywhere should
be easier now that distributions are starting to enable Rust (even
Debian).

We have been talking about this since the very beginning of the
project -- e.g. I remember Wedson and I talking to Josh et al. about
improving the situation here (in particular, talking about integrating
a solution into `rustc` directly) long before Rust was merged into the
kernel. Even on things like a `rustc cc` or `cImport` like Zig (but
Zig moved on the other direction since then), which I recall Gary
having opinions about too.

There is also the question about GCC. A deeper integration into
`rustc` would ideally need to have a way (perhaps depending on the
backend picked?) to support GCC builds properly (to read the header
and flags as expected, as you mention).

And finally there is the question of what GCC Rust would do in such a
case. Things have substantially changed on the GCC Rust in the last
years, and they are now closer to build the kernel, thus I think their
side of things is getting important to consider too.

Cc'ing Emilio (`bindgen`), Antoni (GCC backend) and Arthur (GCC Rust)
so that they are in the loop -- context at:

    https://lore.kernel.org/rust-for-linux/20251204111124.GJ2528459@noisy.programming.kicks-ass.net/

Cheers,
Miguel


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 4/4] build: rust: provide an option to inline C helpers into Rust
  2025-12-04 11:57         ` Miguel Ojeda
@ 2025-12-04 12:39           ` Peter Zijlstra
  2025-12-04 13:03             ` Alice Ryhl
  2025-12-04 12:49           ` Emilio Cobos Álvarez
  1 sibling, 1 reply; 20+ messages in thread
From: Peter Zijlstra @ 2025-12-04 12:39 UTC (permalink / raw)
  To: Miguel Ojeda
  Cc: Antoni Boucher, Emilio Cobos Álvarez, Arthur Cohen,
	Gary Guo, Alice Ryhl, Josh Triplett, Miguel Ojeda, Boqun Feng,
	Björn Roy Baron, Benno Lossin, Andreas Hindborg,
	Trevor Gross, Danilo Krummrich, Alexandre Courbot, Will Deacon,
	Mark Rutland, Nathan Chancellor, Nick Desaulniers, Bill Wendling,
	Justin Stitt, Nicolas Schier, Andrew Morton, Uladzislau Rezki,
	rust-for-linux, linux-kernel, llvm, linux-kbuild, linux-mm,
	nouveau, Matthew Maurer

On Thu, Dec 04, 2025 at 12:57:31PM +0100, Miguel Ojeda wrote:
> On Thu, Dec 4, 2025 at 12:11 PM Peter Zijlstra <peterz@infradead.org> wrote:
> >
> > Right. Earlier I also proposed using libclang to parse the C header and
> > inject that. This might be a little simpler, in that..
> 
> Yeah, that would be closer to the `bindgen` route in that `libclang`
> gets already involved.
> 
> > ... if you build rustc against libclang they are necessarily from the
> > same LLVM build.
> 
> So currently there are 3 "LLVMs" that get involved:
> 
>   - The one Clang uses (in LLVM=1 builds).

Well, being on Debian, I'm more likely to be using LLVM=-22 (or whatever
actual version is required, 22 just being the latest shipped by Debian
at this point in time).

>   - The one `rustc` uses (the LLVM backend).
>   - The one `bindgen` uses (via libclang).

These are not necessarily the same? That is, is not bindgen part of the
rustc project and so would be built against the same LLVM?

> If that is all done within `rustc` (so no `bindgen`), then there may
> still be `rustc` vs. Clang mismatches, which are harder to resolve in
> the Rust side at least (it is easier to pick another Clang version to
> match).
> 
> For those using builds from distros, that shouldn't be a problem.
> Others using external `rustc` builds, e.g. from `rustup` (e.g. for
> testing different Rust versions) it would be harder.

Make rust part of LLVM and get them all built and distributed
together... such that LLVM=-23 will get me a coherent set of tools.

/me runs like crazeh ;-)

> There is also the question about GCC. A deeper integration into
> `rustc` would ideally need to have a way (perhaps depending on the
> backend picked?) to support GCC builds properly (to read the header
> and flags as expected, as you mention).

Right, so the backend that spits out C could obviously just pass through
any C headers. But otherwise, inlining C headers (and inline functions)
would be something that is independent of the C files. At the end of the
day all that really matters is the architecture C ABI.

That is, if rustc inlines a C function from a header, it doesn't matter
it used libclang to do so, even if the C files are then compiled with
GCC.

> And finally there is the question of what GCC Rust would do in such a
> case. Things have substantially changed on the GCC Rust in the last
> years, and they are now closer to build the kernel, thus I think their
> side of things is getting important to consider too.
> 
> Cc'ing Emilio (`bindgen`), Antoni (GCC backend) and Arthur (GCC Rust)
> so that they are in the loop -- context at:

Right, so clearly GCC has the capability to parse C headers :-) So I
would imagine their Rust front-end would be able to hand off C headers
and get back IR much like LLVM based projects can using libclang.




^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 4/4] build: rust: provide an option to inline C helpers into Rust
  2025-12-04 11:57         ` Miguel Ojeda
  2025-12-04 12:39           ` Peter Zijlstra
@ 2025-12-04 12:49           ` Emilio Cobos Álvarez
  2025-12-04 13:15             ` Alice Ryhl
  1 sibling, 1 reply; 20+ messages in thread
From: Emilio Cobos Álvarez @ 2025-12-04 12:49 UTC (permalink / raw)
  To: Miguel Ojeda, Peter Zijlstra, Antoni Boucher, Arthur Cohen, Gary Guo
  Cc: Alice Ryhl, Josh Triplett, Miguel Ojeda, Boqun Feng,
	Björn Roy Baron, Benno Lossin, Andreas Hindborg,
	Trevor Gross, Danilo Krummrich, Alexandre Courbot, Will Deacon,
	Mark Rutland, Nathan Chancellor, Nick Desaulniers, Bill Wendling,
	Justin Stitt, Nicolas Schier, Andrew Morton, Uladzislau Rezki,
	rust-for-linux, linux-kernel, llvm, linux-kbuild, linux-mm,
	nouveau, Matthew Maurer

On 12/4/25 12:57 PM, Miguel Ojeda wrote:
> On Thu, Dec 4, 2025 at 12:11 PM Peter Zijlstra <peterz@infradead.org> wrote:
>>
>> Right. Earlier I also proposed using libclang to parse the C header and
>> inject that. This might be a little simpler, in that..
> 
> Yeah, that would be closer to the `bindgen` route in that `libclang`
> gets already involved.

Yeah, so... there are existing tools (c2rust [0] being the actively 
maintained one IIUC) that in theory could do something like that 
(translate the bodies of the functions from C to Rust so that rustc 
could consume them directly rather than via LLVM LTO).

I think the intended use case is more "translate a whole C project into 
rust", but it could be interesting to test how well / poorly it performs 
with the kernel helpers / with a single header translated to Rust.

I personally haven't tried it because for work I need to deal with C++, 
which means that automatic translation to Rust is a lot harder / 
probably impossible in general. So for Firefox we end up relying on 
bindgen + cross-language LTO for this kind of thing, and it works well 
for us.

If I'm understanding correctly, it seems the kernel needs this extra bit 
of help (__always_inline) to push LLVM to inline C functions into rust, 
which is a bit unfortunate... But this approach seems sensible to me, 
for now at least.

FWIW Bindgen recently gained an option to generate inline functions [1], 
which could help avoid at least the bindgen ifdef in the patch series?

Anyways, it might be interesting to give c2rust a go on the kernel 
helpers if nobody has done so, and see how well / poorly it works in 
practice? Of course probably introducing a new dependency would be kind 
of a pain, but could be a good data point for pushing into adding 
something like it built into rustc...

Thanks,
  -- Emilio

[0]: https://github.com/immunant/c2rust
[1]: 
https://docs.rs/bindgen/latest/bindgen/struct.Builder.html#method.generate_inline_functions


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 4/4] build: rust: provide an option to inline C helpers into Rust
  2025-12-04 12:39           ` Peter Zijlstra
@ 2025-12-04 13:03             ` Alice Ryhl
  0 siblings, 0 replies; 20+ messages in thread
From: Alice Ryhl @ 2025-12-04 13:03 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Miguel Ojeda, Antoni Boucher, Emilio Cobos Álvarez,
	Arthur Cohen, Gary Guo, Josh Triplett, Miguel Ojeda, Boqun Feng,
	Björn Roy Baron, Benno Lossin, Andreas Hindborg,
	Trevor Gross, Danilo Krummrich, Alexandre Courbot, Will Deacon,
	Mark Rutland, Nathan Chancellor, Nick Desaulniers, Bill Wendling,
	Justin Stitt, Nicolas Schier, Andrew Morton, Uladzislau Rezki,
	rust-for-linux, linux-kernel, llvm, linux-kbuild, linux-mm,
	nouveau, Matthew Maurer

On Thu, Dec 04, 2025 at 01:39:06PM +0100, Peter Zijlstra wrote:
> On Thu, Dec 04, 2025 at 12:57:31PM +0100, Miguel Ojeda wrote:
> > On Thu, Dec 4, 2025 at 12:11 PM Peter Zijlstra <peterz@infradead.org> wrote:
> > >
> > > Right. Earlier I also proposed using libclang to parse the C header and
> > > inject that. This might be a little simpler, in that..
> > 
> > Yeah, that would be closer to the `bindgen` route in that `libclang`
> > gets already involved.
> > 
> > > ... if you build rustc against libclang they are necessarily from the
> > > same LLVM build.
> > 
> > So currently there are 3 "LLVMs" that get involved:
> > 
> >   - The one Clang uses (in LLVM=1 builds).
> 
> Well, being on Debian, I'm more likely to be using LLVM=-22 (or whatever
> actual version is required, 22 just being the latest shipped by Debian
> at this point in time).
> 
> >   - The one `rustc` uses (the LLVM backend).
> >   - The one `bindgen` uses (via libclang).
> 
> These are not necessarily the same? That is, is not bindgen part of the
> rustc project and so would be built against the same LLVM?

Rustc and bindgen are both part of the Rust project, but they're two
different repos:
https://github.com/rust-lang/rust
https://github.com/rust-lang/rust-bindgen

Generally you need to ensure that bindgen matches clang. This ensures
that bindgen and clang agree on the interpretation of C headers.

> > If that is all done within `rustc` (so no `bindgen`), then there may
> > still be `rustc` vs. Clang mismatches, which are harder to resolve in
> > the Rust side at least (it is easier to pick another Clang version to
> > match).
> > 
> > For those using builds from distros, that shouldn't be a problem.
> > Others using external `rustc` builds, e.g. from `rustup` (e.g. for
> > testing different Rust versions) it would be harder.
> 
> Make rust part of LLVM and get them all built and distributed
> together... such that LLVM=-23 will get me a coherent set of tools.
> 
> /me runs like crazeh ;-)

Maybe clang itself should have an option to emit Rust headers, taking
over the role of bindgen?

/me runs like crazeh ;-)

Alice


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 4/4] build: rust: provide an option to inline C helpers into Rust
  2025-12-04 12:49           ` Emilio Cobos Álvarez
@ 2025-12-04 13:15             ` Alice Ryhl
  2025-12-04 14:27               ` Peter Zijlstra
  0 siblings, 1 reply; 20+ messages in thread
From: Alice Ryhl @ 2025-12-04 13:15 UTC (permalink / raw)
  To: Emilio Cobos Álvarez
  Cc: Miguel Ojeda, Peter Zijlstra, Antoni Boucher, Arthur Cohen,
	Gary Guo, Josh Triplett, Miguel Ojeda, Boqun Feng,
	Björn Roy Baron, Benno Lossin, Andreas Hindborg,
	Trevor Gross, Danilo Krummrich, Alexandre Courbot, Will Deacon,
	Mark Rutland, Nathan Chancellor, Nick Desaulniers, Bill Wendling,
	Justin Stitt, Nicolas Schier, Andrew Morton, Uladzislau Rezki,
	rust-for-linux, linux-kernel, llvm, linux-kbuild, linux-mm,
	nouveau, Matthew Maurer

On Thu, Dec 04, 2025 at 01:49:28PM +0100, Emilio Cobos Álvarez wrote:
> On 12/4/25 12:57 PM, Miguel Ojeda wrote:
> > On Thu, Dec 4, 2025 at 12:11 PM Peter Zijlstra <peterz@infradead.org> wrote:
> > > 
> > > Right. Earlier I also proposed using libclang to parse the C header and
> > > inject that. This might be a little simpler, in that..
> > 
> > Yeah, that would be closer to the `bindgen` route in that `libclang`
> > gets already involved.
> 
> Yeah, so... there are existing tools (c2rust [0] being the actively
> maintained one IIUC) that in theory could do something like that (translate
> the bodies of the functions from C to Rust so that rustc could consume them
> directly rather than via LLVM LTO).
> 
> I think the intended use case is more "translate a whole C project into
> rust", but it could be interesting to test how well / poorly it performs
> with the kernel helpers / with a single header translated to Rust.
> 
> I personally haven't tried it because for work I need to deal with C++,
> which means that automatic translation to Rust is a lot harder / probably
> impossible in general. So for Firefox we end up relying on bindgen +
> cross-language LTO for this kind of thing, and it works well for us.
> 
> If I'm understanding correctly, it seems the kernel needs this extra bit of
> help (__always_inline) to push LLVM to inline C functions into rust, which
> is a bit unfortunate... But this approach seems sensible to me, for now at
> least.
> 
> FWIW Bindgen recently gained an option to generate inline functions [1],
> which could help avoid at least the bindgen ifdef in the patch series?
> 
> Anyways, it might be interesting to give c2rust a go on the kernel helpers
> if nobody has done so, and see how well / poorly it works in practice? Of
> course probably introducing a new dependency would be kind of a pain, but
> could be a good data point for pushing into adding something like it built
> into rustc...

I already tried c2rust as an alternative to this patch. It works okay
for many functions, but it's missing support for some features such as
asm goto, though this is fixable. But a larger issue is that some things
simply do not translate to Rust right now. For example:

* Atomics use the Ir operand.
* static_branch uses the i operand.

neither of which translate directly to Rust.

Alice


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 4/4] build: rust: provide an option to inline C helpers into Rust
  2025-12-04 13:15             ` Alice Ryhl
@ 2025-12-04 14:27               ` Peter Zijlstra
  2025-12-04 19:29                 ` Matthew Maurer
  0 siblings, 1 reply; 20+ messages in thread
From: Peter Zijlstra @ 2025-12-04 14:27 UTC (permalink / raw)
  To: Alice Ryhl
  Cc: Emilio Cobos Álvarez, Miguel Ojeda, Antoni Boucher,
	Arthur Cohen, Gary Guo, Josh Triplett, Miguel Ojeda, Boqun Feng,
	Björn Roy Baron, Benno Lossin, Andreas Hindborg,
	Trevor Gross, Danilo Krummrich, Alexandre Courbot, Will Deacon,
	Mark Rutland, Nathan Chancellor, Nick Desaulniers, Bill Wendling,
	Justin Stitt, Nicolas Schier, Andrew Morton, Uladzislau Rezki,
	rust-for-linux, linux-kernel, llvm, linux-kbuild, linux-mm,
	nouveau, Matthew Maurer

On Thu, Dec 04, 2025 at 01:15:34PM +0000, Alice Ryhl wrote:
> On Thu, Dec 04, 2025 at 01:49:28PM +0100, Emilio Cobos Álvarez wrote:
> > On 12/4/25 12:57 PM, Miguel Ojeda wrote:
> > > On Thu, Dec 4, 2025 at 12:11 PM Peter Zijlstra <peterz@infradead.org> wrote:
> > > > 
> > > > Right. Earlier I also proposed using libclang to parse the C header and
> > > > inject that. This might be a little simpler, in that..
> > > 
> > > Yeah, that would be closer to the `bindgen` route in that `libclang`
> > > gets already involved.
> > 
> > Yeah, so... there are existing tools (c2rust [0] being the actively
> > maintained one IIUC) that in theory could do something like that (translate
> > the bodies of the functions from C to Rust so that rustc could consume them
> > directly rather than via LLVM LTO).
> > 
> > I think the intended use case is more "translate a whole C project into
> > rust", but it could be interesting to test how well / poorly it performs
> > with the kernel helpers / with a single header translated to Rust.
> > 
> > I personally haven't tried it because for work I need to deal with C++,
> > which means that automatic translation to Rust is a lot harder / probably
> > impossible in general. So for Firefox we end up relying on bindgen +
> > cross-language LTO for this kind of thing, and it works well for us.
> > 
> > If I'm understanding correctly, it seems the kernel needs this extra bit of
> > help (__always_inline) to push LLVM to inline C functions into rust, which
> > is a bit unfortunate... But this approach seems sensible to me, for now at
> > least.
> > 
> > FWIW Bindgen recently gained an option to generate inline functions [1],
> > which could help avoid at least the bindgen ifdef in the patch series?
> > 
> > Anyways, it might be interesting to give c2rust a go on the kernel helpers
> > if nobody has done so, and see how well / poorly it works in practice? Of
> > course probably introducing a new dependency would be kind of a pain, but
> > could be a good data point for pushing into adding something like it built
> > into rustc...
> 
> I already tried c2rust as an alternative to this patch. It works okay
> for many functions, but it's missing support for some features such as
> asm goto, though this is fixable. But a larger issue is that some things
> simply do not translate to Rust right now. For example:
> 
> * Atomics use the Ir operand.
> * static_branch uses the i operand.
> 
> neither of which translate directly to Rust.

Right this. AFAIK Rust simply does not have feature parity with inline
asm. Them having picked a wildly different syntax for inline asm didn't
help either of course. But Rust is Rust, must have terrible syntax :-)


^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCH 4/4] build: rust: provide an option to inline C helpers into Rust
  2025-12-04 14:27               ` Peter Zijlstra
@ 2025-12-04 19:29                 ` Matthew Maurer
  0 siblings, 0 replies; 20+ messages in thread
From: Matthew Maurer @ 2025-12-04 19:29 UTC (permalink / raw)
  To: Peter Zijlstra
  Cc: Alice Ryhl, Emilio Cobos Álvarez, Miguel Ojeda,
	Antoni Boucher, Arthur Cohen, Gary Guo, Josh Triplett,
	Miguel Ojeda, Boqun Feng, Björn Roy Baron, Benno Lossin,
	Andreas Hindborg, Trevor Gross, Danilo Krummrich,
	Alexandre Courbot, Will Deacon, Mark Rutland, Nathan Chancellor,
	Nick Desaulniers, Bill Wendling, Justin Stitt, Nicolas Schier,
	Andrew Morton, Uladzislau Rezki, rust-for-linux, linux-kernel,
	llvm, linux-kbuild, linux-mm, nouveau

On Thu, Dec 4, 2025 at 6:27 AM Peter Zijlstra <peterz@infradead.org> wrote:
>
> On Thu, Dec 04, 2025 at 01:15:34PM +0000, Alice Ryhl wrote:
> > On Thu, Dec 04, 2025 at 01:49:28PM +0100, Emilio Cobos Álvarez wrote:
> > > On 12/4/25 12:57 PM, Miguel Ojeda wrote:
> > > > On Thu, Dec 4, 2025 at 12:11 PM Peter Zijlstra <peterz@infradead.org> wrote:
> > > > >
> > > > > Right. Earlier I also proposed using libclang to parse the C header and
> > > > > inject that. This might be a little simpler, in that..
> > > >
> > > > Yeah, that would be closer to the `bindgen` route in that `libclang`
> > > > gets already involved.
> > >
> > > Yeah, so... there are existing tools (c2rust [0] being the actively
> > > maintained one IIUC) that in theory could do something like that (translate
> > > the bodies of the functions from C to Rust so that rustc could consume them
> > > directly rather than via LLVM LTO).
> > >
> > > I think the intended use case is more "translate a whole C project into
> > > rust", but it could be interesting to test how well / poorly it performs
> > > with the kernel helpers / with a single header translated to Rust.
> > >
> > > I personally haven't tried it because for work I need to deal with C++,
> > > which means that automatic translation to Rust is a lot harder / probably
> > > impossible in general. So for Firefox we end up relying on bindgen +
> > > cross-language LTO for this kind of thing, and it works well for us.
> > >
> > > If I'm understanding correctly, it seems the kernel needs this extra bit of
> > > help (__always_inline) to push LLVM to inline C functions into rust, which
> > > is a bit unfortunate... But this approach seems sensible to me, for now at
> > > least.
> > >
> > > FWIW Bindgen recently gained an option to generate inline functions [1],
> > > which could help avoid at least the bindgen ifdef in the patch series?
> > >
> > > Anyways, it might be interesting to give c2rust a go on the kernel helpers
> > > if nobody has done so, and see how well / poorly it works in practice? Of
> > > course probably introducing a new dependency would be kind of a pain, but
> > > could be a good data point for pushing into adding something like it built
> > > into rustc...
> >
> > I already tried c2rust as an alternative to this patch. It works okay
> > for many functions, but it's missing support for some features such as
> > asm goto, though this is fixable. But a larger issue is that some things
> > simply do not translate to Rust right now. For example:
> >
> > * Atomics use the Ir operand.
> > * static_branch uses the i operand.
> >
> > neither of which translate directly to Rust.

I took a shot at `c2rust` as well, the summary was that `c2rust` was missing:
* Asm goto support
* __builtin_types_compatible_p
* Deduced types
* __count
* _Generic

I was adding hacky implementations along the way to see if things
could be made to work, but the %l and %i missing in Rust itself that
Alice pointed out were not things that could really be worked around.

I also think that the bitcode-based approach is more future proof -
the kernel may pick up new C features that `c2rust` hasn't yet learned
about. If `clang` is in charge of generating the bitcode for the
to-be-inlined helpers, we don't risk any desync in terms of what
features are supported either by `c2rust` or by `rustc` relative to
what's in use by the rest of the kernel.

>
> Right this. AFAIK Rust simply does not have feature parity with inline
> asm. Them having picked a wildly different syntax for inline asm didn't
> help either of course. But Rust is Rust, must have terrible syntax :-)


^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2025-12-04 19:29 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-12-02 20:27 [PATCH 0/4] Inline helpers into Rust without full LTO Alice Ryhl
2025-12-02 20:27 ` [PATCH 1/4] vmalloc: export vrealloc_node_align_noprof Alice Ryhl
2025-12-02 20:27 ` [PATCH 2/4] rust: helpers: #define __rust_helper Alice Ryhl
2025-12-02 20:27 ` [PATCH 3/4] kbuild: rust: add `CONFIG_RUSTC_CLANG_LLVM_COMPATIBLE` Alice Ryhl
2025-12-02 20:27 ` [PATCH 4/4] build: rust: provide an option to inline C helpers into Rust Alice Ryhl
2025-12-03  0:40   ` Matthew Maurer
2025-12-03 18:09   ` Gary Guo
2025-12-03 21:25   ` Nathan Chancellor
2025-12-03 23:25     ` Matthew Maurer
2025-12-04  9:46     ` Alice Ryhl
2025-12-04 10:07   ` Peter Zijlstra
2025-12-04 10:23     ` Alice Ryhl
2025-12-04 11:11       ` Peter Zijlstra
2025-12-04 11:57         ` Miguel Ojeda
2025-12-04 12:39           ` Peter Zijlstra
2025-12-04 13:03             ` Alice Ryhl
2025-12-04 12:49           ` Emilio Cobos Álvarez
2025-12-04 13:15             ` Alice Ryhl
2025-12-04 14:27               ` Peter Zijlstra
2025-12-04 19:29                 ` Matthew Maurer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox