On Mon, Jun 30, 2025 at 11:10 AM Fractal Fir <fractalfir...@gmail.com> wrote:
>
> Hi!
>
> I am one of the folk currently working on `rustc_codegen_gcc`, and I thought 
> that I will provide some more context.
>
> > So I looked into this further, it is not rust that specifies sret but
> rather rust transformation into llvm code generation that does that.
>
> > So you need to explain what exactly what you need.
>
> The problem here is as follows:
>
> The Rust ABI is specified in terms of "PassMode"s. The `PassMode::Indirect` 
> should *always* correspond to LLVM's `sret` attribute when applied to a 
> return value.
>
> The Rust frontend is free to use `sret` however it pleases. It can choose to 
> use it in cases where C would not, or not use it where C would.
>
> As an example:
>
> ```rust
> #[repr(C)] // Same layout as in C
> struct Foo {
>     a: u128,
> }
>
> #[unsafe(no_mangle)]
> // Function with the Rust ABI:
> extern "Rust" fn rust_func() -> Foo {
>     Foo { a: 1 }
> }
> ```
>
> This struct will be passed via `sret` by Rust:
> ```arm
> rust_func:
>         mov     w9, #1
>         stp     x9, xzr, [x8]
>         ret
> ```
>
> However, GCC(following the C ABI) will pass the struct in a register:
>
> ```c
> struct Foo{
>     __uint128_t a
> };
> struct Foo c_func(){
>     struct Foo res = {1};
>     return res;
> }
> ```
>
> ```arm
> c_func:
>         mov     x0, 1
>         mov     x1, 0
>         ret
> ```
>
> We need some way to force GCC to pass the return value in `sret`, to match 
> the Rust ABI. Otherwise, we will get subtle ABI bugs.

So to force GCC to the struct type in memory, you need to have
TREE_ADDRESSABLE set on the RECORD_TYPE.
I partly mentioned this but it looks like you missed that part.

So in this case it looks like you need 2 different RECORD_TYPEs, one
which has TREE_ADDRESSABLE set on it and one without it.
You can use VIEW_CONVERT_EXPR to "convert" between the 2 as needed.
You use the one with TREE_ADDRESSABLE not set for the C
arguments/return types and then use the rest otherwise.

CALL_EXPR_RETURN_SLOT_OPT is a separate (though related) issue.

I hope this helps. And the C++ front-end uses TREE_ADDRESSABLE for
non-pod (for ABI reasons) in a similar way.

Thanks,
Andrew Pinski


>
>
> We need to do so both on the calle and the caller side. I believe 
> `CALL_EXPR_RETURN_SLOT_OPT` is applied on the caller side only, which is 
> insufficient for our purposes.
>
> Is there something we could use to achieve this effect?
>
> If no, I'd be willing to work on adding such an attribute. Do you have a 
> rough idea about where I should start?
>
> Thank you for taking the time to help us with this issue!

>
>
>
> On Mon, 30 Jun 2025 at 19:31, Antoni Boucher <boua...@zoho.com> wrote:
>>
>> 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.
>> >>>       >
>> >>>
>> >>
>>

Reply via email to