Hi.
Let me introduce you Fractal Fir who's a student working on
rustc_codegen_gcc for the Google Summer of Code.
He found some ABI issues (one related to sret) in rustc_codegen_gcc and
wanted to join this discussion in order to share more details about what
we want to achieve here.
Thanks.
Le 2025-06-30 à 10 h 51, Andrew Pinski a écrit :
On Mon, Jun 30, 2025 at 7:25 AM Antoni Boucher <boua...@zoho.com> wrote:
Le 2025-06-29 à 19 h 42, Andrew Pinski a écrit :
On Sun, Jun 29, 2025, 4:36 PM Antoni Boucher <boua...@zoho.com
<mailto:boua...@zoho.com>> wrote:
Le 2025-06-29 à 10 h 46, Andrew Pinski a écrit :
>
>
> On Sun, Jun 29, 2025, 7:43 AM Andrew Pinski <pins...@gmail.com
<mailto:pins...@gmail.com>
> <mailto:pins...@gmail.com <mailto:pins...@gmail.com>>> wrote:
>
> On Sun, Jun 29, 2025, 7:36 AM Antoni Boucher via Gcc
> <gcc@gcc.gnu.org <mailto:gcc@gcc.gnu.org>
<mailto:gcc@gcc.gnu.org <mailto:gcc@gcc.gnu.org>>> wrote:
>
> Hi.
> Is there a way in GENERIC to specify that a parameter will be
> passed in
> "sret", or is this solely controlled by the hook
struct_value_rtx?
>
>
> It is only controlled by the hook.
> What exactly are trying to do?
> You could set the return slot optimization bit on the call
> expression if you want the lhs of a call not to be copied and
just
> passed as the address via sret.
I'm trying to follow the Rust ABI for rustc_codegen_gcc: they manually
specify whether a param is "sret".
Not all ABI/targets have a sret specific register. So this is even more
confusing.
>
> That is if you have:
> StructVar = func(...);
>
> You set the return slot optimization bit on the call expr in
generic
> and which will copy that bit to the gimple GIMPLE_CALL and then
> during expand will again copy it back to the generic
call_expr and
> expand will use the target for the address.
>
>
> CALL_EXPR_RETURN_SLOT_OPT is the macro.
Is this a guaranteed optimization? I'm asking because this is for ABI
correctness and I need a solution that will always work.
If not, would there be another way to do this?
Thanks.
Yes it is guaranteed that if the return type is returned via memory
reference to the other function it will use that memory location.
How does this work on the side of the function declaration? Do we need
to set something so that it follows the correct convention?
So there are 2 separate things here.
First there is an ABI of having struct return in memory.
Note if TREE_ADDRESSABLE is set on a struct type, then return value is
always through memory:
```
In ..._TYPE nodes, it means that objects of this type must be fully
addressable. This means that pieces of this object cannot go into
register parameters, for example. If this a function type, this
means that the value must be returned in memory.
```
The ABI part is independent of the CALL_EXPR and dependent on the
FUNCTION_TYPE that is being used and the target.
Second is specifying if you can reuse the memory of the lhs of a
modify_expr with a call_expr when the ABI says the memory is return in
memory.
This is specified via CALL_EXPR_RETURN_SLOT_OPT on the CALL_EXPR.
I am trying to understand how the rustc front-end sets up this. Does
it implement the ABI of each target as that is needed for LLVM?
This is the major difference here as GCC's front-ends normally don't
care much about the ABI except in specific cases (e.g. returns this
and a few others). GCC's front-end don't handle the call argument ABI
at all; rather it is more like you build call_expr which act like
function calls in C (well with the addition of reference types but
those are really just pointers at that point). And the middle-end
(with help from the backend) which implements the full ABI.
The reason why this is done this way is an abstraction layer and
allows new front-ends for backends that are known to it at the time
without additional work (e.g. gfortran adding support for riscv or
aarch64; no changes to the front-end were made). This seems like the
opposite of LLVM where there is no tight coupling of the 2 and there
is no abstraction for most of the ABI call work and each front-end
needs to implement that again.
Hope this helps explain GCC front-end interactions with the GCC's
middle-end better.
Thanks a lot for your help.
Even for things like a->b = func(...)[RSO]. It is even used by the c++
frontend that way.
>
>
>
> Is that what you are looking for?
>
>
> Thanks,
> Andrew
>
> Thanks.
>