[rustc_public] Enhance PassMode API#159359
Conversation
Replace the opaque representation of `PassMode::Cast` with a structured `CastTarget` type that exposes the register layout used by the platform ABI. Add `Uniform`, `Reg`, and `RegKind` types so tools can inspect how arguments are mapped to registers. Add `CastTarget::size()` and `Uniform::reg_count()` helpers. Add a test covering cast on args, returns, mixed register kinds, multiple arguments, and register exhaustion causing stack spill.
Expose argument ABI attributes through a structured type instead of opaque debug strings. ArgAttributes provides accessors for the extension mode (zero/sign-extend) and pointee alignment, which are needed by tools doing their own code generation. This removes all uses of Opaque from the abi module.
|
r? @makai410 rustbot has assigned @makai410. Use Why was this reviewer chosen?The reviewer was selected based on:
|
There was a problem hiding this comment.
This file has incorrect statements such as
/// The `abi` defines how this data is passed between functions.
pub abi: ValueAbi,
See #132246 for more on why this is wrong.
I would honestly rather you not "enhance" anything here and set almost this entire file on fire here because it's just going to make me actually rewriting this harder. We could make more accurate information available in the future, but it's unclear why anyone would benefit from the current information because they lack the full context to interpret it.
There was a problem hiding this comment.
I appreciate the context. Having to reverse engineer the compiler is not an easy task, so please do point out any inaccuracies. Most of the comments here I wrote based on the comments from rustc_target and from analyzing the generated FnAbi for different function signatures.
There was a problem hiding this comment.
I dearly sympathize because my task of figuring out what the hell is going on involves reverse-engineering LLVM. 🙃
At some point I just sort of started assuming everything I am reading is probably wrong, unfortunately.
There was a problem hiding this comment.
My question here is mostly: What question is someone trying to answer that they think this information would be of use to them? If they're trying to do a basic ABI equality check then smuggling the data around opaquely with mostly no transformation and exposing a PartialEq impl that interrogates the innards seems more useful.
There was a problem hiding this comment.
To elaborate: The rustc_target and rustc_abi crates were mostly written ages ago by people who are not easy to ask questions of anymore, in a single-backend context, where x86-64 was our only tier 1 target. It was then incrementally edited, including by people such as myself, in ways that were "good enough", and our unclear understandings documented as truth because no one was around anymore who completely knew exactly what was going on and we could usefully discuss things with. "cg_ssa" (rustc_codegen_ssa) was introduced as an incomplete abstraction layer over LLVMIR, and to the extent it has abstracted anything, it has made everything in rustc_abi and rustc_target wronger.
That is why asking questions about things below FnAbi is probably not a good idea, unless it's about a fundamental like Size or Align. Obviously those have to be correct. And we've... tried to make LayoutData... vaguely intelligible.
There was a problem hiding this comment.
In the Rust ABI there are things that can't be represented as a valid C signature. For example there are cases where we use more return registers than the platform C ABI allows, but LLVM supports representing it anyway.
There was a problem hiding this comment.
Thanks for the context. To summarize where I think we are: this PR adds information that is currently missing from rustc_public — the structure of PassMode::Cast, argument attributes, and corrected documentation. The data itself is not incorrect; it accurately reflects the compiler's calling convention decisions.
Users may still need to do further processing depending on their use case (as cg_ssa does today), and the Rust ABI can produce things that don't map cleanly to a C signature. The data shouldn't be taken at face value as "this is exactly what happens on the wire" — but it is the correct input for tools that need to reason about argument layout and pass modes.
There was a problem hiding this comment.
The use case is tools that build their own backends or analyzers on top of MIR and need to generate compatible call sequences or how the code interacts via FFI without depending on LLVM.
Do these need to be compatible with the Rust ABI that the LLVM backend happens to use or is it only about C FFI and can they chose to use an arbitrary ABI for extern "Rust"?
There was a problem hiding this comment.
That's a good question. From a usability perspective, I'd prefer that the API was complete in a way that allows users to interact with things like a pre-compiled rust std. The ideal goal is to enable users to build rich Rust tooling, not to tell users what they can or cannot do.
That said, from a maintenance point of view, I think it makes sense to start small if the cost is too high or impractical, and expand wherever we can once there's demand.
So being able to reason about C FFI interaction and implement an arbitrary ABI for extern "Rust" is a reasonable first step.
There was a problem hiding this comment.
For C FFI depending on how exactly your backend works, lowering the Layout rather than FnAbi may work better. Especially if you are emitting to a C shaped IR with actual support for C types as arguments. FnAbi is designed for LLVM IR and works fine for Cranelift IR too given how similar Cranelift IR is to LLVM IR. It happens to work for gccjit, but I'm not sure if it is actually correct when cross-language LTO. I haven't checked, but I wouldn't be surprised if GCC keeps the full C types and expects other frontends to produce the exact same types, which using FnAbi definitively won't do. For LLVM shaped backends it does make sense to use FnAbi, but the function signature handling has to be fairly closely modeled after LLVM.
|
What is the purpose of the information here? It honestly is mostly not information that can be used correctly by people who aren't willing to just look directly at the LLVMIR and emitted assembly, which will actually tell them what is going on. |
|
Like, all of the annotations that we emit do not have a precise relationship with what LLVM does, because LLVM... interprets... various IR patterns differently, often in a way that depends on which machine backend you are using, specifics of the exact target in question, and even the position of the argument (well before you run out of registers, mind!). That is, to put it simply: |
This comment has been minimized.
This comment has been minimized.
59b3ad1 to
ae8aeeb
Compare
BREAKING CHANGE: `ValueAbi` is renamed to `ValueRepr` and the `LayoutShape::abi` field is renamed to `LayoutShape::value_repr`. The old name was misleading: this type does not describe how values are passed in function calls (that is `PassMode`), it is a hint for how backends should represent values (as scalars, vectors, or aggregates). This aligns with the internal rename from `Abi` to `BackendRepr`. Also fixes several doc comments that incorrectly claimed layout fields define calling behavior.
ae8aeeb to
f340101
Compare
This change is split into two different commits: