Add BTF relocation builtins - #161107
Add BTF relocation builtins#161107vadorovsky wants to merge 7 commits into
Conversation
|
Some changes occurred to MIR optimizations cc @rust-lang/wg-mir-opt This PR changes MIR cc @oli-obk, @RalfJung, @JakobDegen, @vakaras Some changes occurred to constck cc @fee1-dead
cc @Amanieu, @folkertdev, @sayantn This PR changes rustc_public cc @oli-obk, @celinval, @ouz-a, @makai410 Some changes occurred to the CTFE machinery Some changes occurred in compiler/rustc_passes/src/check_attr.rs cc @jdonszelmann, @JonathanBrouwer
cc @bjorn3 Some changes occurred in match checking cc @Nadrieril Some changes occurred in compiler/rustc_attr_parsing cc @jdonszelmann, @JonathanBrouwer Some changes occurred in compiler/rustc_attr_ir cc @jdonszelmann, @JonathanBrouwer Some changes occurred in cc @BoxyUwU The parser was modified, potentially altering the grammar of (stable) Rust cc @fmease Some changes occurred to the CTFE / Miri interpreter cc @rust-lang/miri |
This comment has been minimized.
This comment has been minimized.
Sorry, I will trim this PR only to the builtins. They can be still tested with minicore and a macro embedded in test. And I'm going to leave the core_arch change for later. |
7de4ec2 to
869a54b
Compare
This comment has been minimized.
This comment has been minimized.
|
Now CI fails on |
869a54b to
b42b869
Compare
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
| Reborrow(Ty<'tcx>, Mutability, Place<'tcx>), | ||
|
|
||
| /// Queries BTF metadata for a statically resolved field path. | ||
| BtfFieldInfo { base_ty: Ty<'tcx>, path: Box<[BtfFieldStep<'tcx>]>, kind: BtfFieldInfoKind }, |
There was a problem hiding this comment.
This is a very unusual MIR construct, to put it quite mildly. Please add a bit more detail. What is this "metadata" that is being queried and how is it returned? What are the validity conditions? When is this operation UB (if ever)?
We usually work very hard to keep target-specific things away from this core part of the compiler, so seeing BTF-specific things here is somewhat alarming.
There was a problem hiding this comment.
Also, please write comments in this part in the compiler assuming that the reader never heard of BTF or BPF before. So, always include a link for such acronyms.
There was a problem hiding this comment.
We usually work very hard to keep target-specific things away from this core part of the compiler, so seeing BTF-specific things here is somewhat alarming.
I hear you. Given that the other field relocation mechanisms (like Swift ABI reslence, Objective-C ivars etc.) could potentially reuse this construct, I will try to come up with some neutral name. Would that be satisfactory for you?
There was a problem hiding this comment.
That's not where I was going. :) I am not asking for overeager generalization, we can always rename stuff later if it becomes more generally useful.
What I was going for with the second paragraph in my comment is: does this have to be a primitive MIR statement? Why is there no less invasive way to do this?
There was a problem hiding this comment.
Can this for example be an intrinsic (core::intrinsics::btf_field_info(...))?
There was a problem hiding this comment.
Can this for example be an intrinsic (
core::intrinsics::btf_field_info(...))?
Given @RalfJung's comment below #161107 (comment) about not using the numeric values for relocation kinds, I think we could introduce more intrinsics:
btf_preserve_access_index, which could lower to thepreserve_access_indexintrinsics in backends (both LLVM and GCC).
And then three intrinsics for each kind of field info we want to support, so we don't have to use the numeric values in MIR:
btf_preserve_field_byte_offsetbtf_preserve_field_byte_sizebtf_preserve_field_exists
Each builtin macro (btf_field_byte_offset, btf_field_byte_size, btf_field_exists) would use btf_preserve_access_index intrinsic and an appropriate field info intrinsic (e.g. btf_preserve_field_byte_offset).
I will try to wrap it up this solution today and push it. How does it sound to you?
There was a problem hiding this comment.
This should be addressed now, see the new AST/MIR/HIR commit: ca2966b
There was a problem hiding this comment.
So, what is the representation that you chose now?
It seems there are new built-in macros, and intrinsics that don't show up in intrinsics/mod.rs, that have magic arguments that must be constants. That's... all quite strange to be honest. In particular the part where these intrinsics can only be generated by magic macros, that's unprecedented and will probably confuse people working on the compiler. And intrinsics whose arguments must be const are something we have repeatedly rejected in the past (with three exceptions that are grandfathered in and that need special ad-hoc hacks) as it breaks the abstraction of intrinsics being mostly like functions.
I'm sorry I don't have the time to actually work out a good design with you here. The best process for that is probably an MCP, since you're apparently doing something that's fundamentally different from any construct Rust has ever represented in the past. The MCP should also explain why the existing approaches we use for the entire rest of the language don't work here.
| Self::ByteOffset => 0, | ||
| Self::ByteSize => 1, | ||
| Self::Exists => 2, |
There was a problem hiding this comment.
Where do these constants come from? Can rustc just do whatever it wants here or are these magic constants defined by some outside protocol?
There was a problem hiding this comment.
They are defined by LLVM in https://github.com/llvm/llvm-project/blob/llvmorg-23.1.1/llvm/include/llvm/DebugInfo/BTF/BTF.h#L280-L296
I added only these 3 variants, because they are sufficient for basic field relocations to work. I was thinking about following up with the rest of relocation types later.
There was a problem hiding this comment.
We should definitely not have any values defined by LLVM in rustc_middle. This is backend-agonstic code. LLVM-specific consts can only be used in the LLVM backend.
There was a problem hiding this comment.
Sorry, I wasn't exactly right in my last comment - these values are not limited to LLVM, they're honored in Linux kernel headers as well:
https://elixir.bootlin.com/linux/v7.2.5/source/include/uapi/linux/bpf.h#L7616
And they are used in the binary relocation records that are present in BPF object files. So I think these variant IDs can be treated as universal for BPF, not LLVM-specific.
That said, I can try avoiding to use them in MIR.
There was a problem hiding this comment.
I kicked these IDs out of MIR and moved them to LLVM backend, see: c2024a7#diff-158a197387680f1912d11d2963f81632218de6857a971be95eebb964d90b4736R290-R305
| } | ||
|
|
||
| BtfFieldInfo { .. } => { | ||
| throw_unsup_format!("BTF field relocation queries cannot be interpreted"); |
There was a problem hiding this comment.
FWIW Miri will probably eventually want to support these, so for stabilization we need to consider what to do. But for now this is fine.
There was a problem hiding this comment.
This change is removed now.
b42b869 to
3dea160
Compare
This comment has been minimized.
This comment has been minimized.
2a1be29 to
0278cb1
Compare
This comment has been minimized.
This comment has been minimized.
45b4a1a to
75f7f08
Compare
|
This PR was rebased onto a different main commit. Here's a range-diff highlighting what actually changed. Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers. |
This comment has been minimized.
This comment has been minimized.
75f7f08 to
6d7a2f8
Compare
This comment has been minimized.
This comment has been minimized.
6d7a2f8 to
af06f13
Compare
This comment has been minimized.
This comment has been minimized.
af06f13 to
22a067e
Compare
|
cc @rust-lang/clippy |
Impossible without making CI in this PR red. The clippy change lives in its own commit 22a067e and can be applied in the clippy repository after this PR is merged. |
This comment has been minimized.
This comment has been minimized.
|
cc @rust-lang/rustfmt |
Same here. |
| // The `{}` is for better error messages | ||
| {builtin # offset_of($Container, $($fields)+)} |
There was a problem hiding this comment.
| // The `{}` is for better error messages | |
| {builtin # offset_of($Container, $($fields)+)} | |
| const { builtin # offset_of($Container, $($fields)+) } |
builtin # offset(…) is never legal at runtime & the comment is outdated. You seem to have copy/pasted the core definition of macro offset_of from before Nov 18, 2025 for some reason (more than 10 months ago) (a version prior to RUST-148151).
There was a problem hiding this comment.
You seem to have copy/pasted the core definition of macro offset_of from before Nov 18, 2025 for some reason (more than 10 months ago) (a version prior to RUST-148151).
Yes, sorry, I've been working on this for around a year. I noticed the change of offset_of in the MIR and THIR, but I missed the macro change. Should be fixed now.
This comment has been minimized.
This comment has been minimized.
Register the unstable `btf_relocations` feature and add the `#[btf_relocatable]` built-in attribute for structs and unions, that can be used only on BPF architecture. Preserve the attribute in crate metadata, add UI coverage for feature gating and attribute target validation.
Reject field projection and `offset_off!` usage on `#[btf_relocatable]` types.
Add builtin macros for requesting BTF field information from the Rust compiler's frontend perspective: * `btf_field_byte_offset` * `btf_field_byte_size` * `btf_field_exists` Parse them as `BtfFieldInfo` expressions that carry the kind of requested information (offset, size, exists), base type and the field path. This mechanism supports nested field accesses in one query. Add internal compiler intrinsics and corresponding methods in the `BuilderMethods` trait named: * `btf_preserve_access_index` * `btf_preserve_field_byte_offset` * `btf_preserve_field_byte_size` * `btf_preserve_field_exists` Lower the builtin macros to calls to these intrinsics. Backends without BTF relocation support report an error. Support in backends will be added in follow-up changes. This change does not expose the functionality to the users. A user-facing API will also be added in a follow-up change.
Expose wrappers for the `llvm.preserve.struct.access.index` and
`llvm.preserve.union.access.index` intrinsics.
Lower backend-neutral BTF field paths by mapping Rust field indices to
LLVM aggregate indices and emitting the corresponding intrinsic calls
(`llvm.preserve.{struct,union}.access.index`). Pass the resulting field
pointer to `llvm.bpf.preserve.field.info`.
Test the `btf_field_exists`, `btf_field_byte_offset` and `btf_field_byte_size` builtins and make sure they emit correct LLVM intrinsic calls.
Previous changes introduced `BtfFieldInfo` expression variant in the AST and HIR for BTF CO-RE relocation. Add support for it to clippy.
Previous changes introduced `BtfFieldInfo` expression variant in the AST and HIR for BTF CO-RE relocation. Add support for it to rustfmt.
a2aef57 to
8315d32
Compare
View all comments
Add experimental Rust support for Compile Once, Run Everywhere (CO-RE) relocations based on the BPF Type Format (BTF). The entire feature is specific to the BPF architecture and cannot be used elsewhere. The feature introduces a
#[btf_relocatable]attribute for structs and unions whose field layout must be queried through BTF-aware operations, and adds BTF-aware bultins:btf_field_existsbtf_field_byte_offsetbtf_field_byte_sizeThis PR does not yet expose these builtins to the users, the
core_archAPI will be added as a follow-up change.The user-facing feature is gated by
#![feature(btf_relocations)].See individual commits for details.
Created with the help of an LLM, initially used to analyze the existing MIR, codegen SSA and LLVM backend code, to help identifying which parts of code need modification. Afterwards, the code and commit messages were written by hand, then reviewed by an LLM.
Tracking issue: #160616
RFC: rust-lang/rfcs#3966
r? @traviscross @nagisa