Reading execise

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

Reading execise

Valeriy Savchenko via cfe-dev
<https://docs.microsoft.com/en-us/cpp/build/x64-calling-convention#return-values>

| To return a user-defined type by value in RAX, it must have a length
| of 1, 2, 4, 8, 16, 32, or 64 bits. [...] Otherwise, the caller must
| allocate memory for the return value and pass a pointer to it as the
| first argument. The remaining arguments are then shifted one argument
| to the right. The same pointer must be returned by the callee in RAX.

--- incompatible.c ---
__attribute__((ms_abi))
__uint128_t buggy(__uint128_t a, __uint128_t b, __uint128_t c) {
    return a + b * c;
}
--- EOF ---

clang -mno-sse -o- -O3 -S -target amd64-pc-windows incompatible.c

buggy:                                  # @buggy
# %bb.0:
        movq    (%rdx), %r9             # OUCH: before it was destroyed,
                                        #       r9 held the address of c
        movq    (%r8), %rax
        movq    8(%rdx), %r10
        imulq   %rax, %r10
        mulq    %r9                     # OUCH: the source says b * c,
                                        #       NOT a * <something>
        imulq   8(%r8), %r9             # OUCH: idem
        addq    %r10, %rdx
        addq    %r9, %rdx
        addq    (%rcx), %rax            # OUCH: rcx holds the address of
                                        #       the return value!
                                        # OUCH: rax does NOT point to the
                                        #       return value!
        adcq    8(%rcx), %rdx           # OUCH: rcx holds the address of
                                        #       the return value!
        retq


Stefan
_______________________________________________
cfe-dev mailing list
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: Reading execise

Valeriy Savchenko via cfe-dev
On Fri, Sep 18, 2020 at 1:19 PM Stefan Kanthak via cfe-dev <[hidden email]> wrote:
<https://docs.microsoft.com/en-us/cpp/build/x64-calling-convention#return-values>

| To return a user-defined type by value in RAX, it must have a length
| of 1, 2, 4, 8, 16, 32, or 64 bits. [...] Otherwise, the caller must
| allocate memory for the return value and pass a pointer to it as the
| first argument. The remaining arguments are then shifted one argument
| to the right. The same pointer must be returned by the callee in RAX.
Is there a particular reason for starting a new thread?

Statements have been made in https://lists.llvm.org/pipermail/cfe-dev/2020-September/066811.html to clarify the relationship between __[u]int128_t and the MS ABI.
 

--- incompatible.c ---
__attribute__((ms_abi))
__uint128_t buggy(__uint128_t a, __uint128_t b, __uint128_t c) {
    return a + b * c;
}
--- EOF ---

clang -mno-sse -o- -O3 -S -target amd64-pc-windows incompatible.c

buggy:                                  # @buggy
# %bb.0:
        movq    (%rdx), %r9             # OUCH: before it was destroyed,
                                        #       r9 held the address of c
It might help to provide the source code for a caller of this function and the associated assembly of the caller to demonstrate such a mismatch.
 
        movq    (%r8), %rax
        movq    8(%rdx), %r10
        imulq   %rax, %r10
        mulq    %r9                     # OUCH: the source says b * c,
                                        #       NOT a * <something>
        imulq   8(%r8), %r9             # OUCH: idem
        addq    %r10, %rdx
        addq    %r9, %rdx
        addq    (%rcx), %rax            # OUCH: rcx holds the address of
                                        #       the return value!
                                        # OUCH: rax does NOT point to the
                                        #       return value!
        adcq    8(%rcx), %rdx           # OUCH: rcx holds the address of
                                        #       the return value!
        retq


Stefan
_______________________________________________
cfe-dev mailing list
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev

_______________________________________________
cfe-dev mailing list
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
Reply | Threaded
Open this post in threaded view
|

Re: Reading execise

Valeriy Savchenko via cfe-dev
In reply to this post by Valeriy Savchenko via cfe-dev
In fact, I did not.  You simply aren't understanding what is going on.  The problem here is either you don't understand what others have been telling you, or are being intentionally dense.

__int128_t and __uint128_t are both typedefs for __int128 and __uint128.  That doesn't change anything.   This isn't some big 'gotcha' moment here, its simply you not understanding what is going on in your example.

So I'll state this simply:  The 128-bit integer types are integers.  Integers are defined by the compiler, not by the user.  Thus, the rule you quote about "user-defined types" is a hilariously misguided attempt to prove a non-existent-point.

-----Original Message-----
From: Stefan Kanthak <[hidden email]>
Sent: Friday, September 18, 2020 12:17 PM
To: Keane, Erich <[hidden email]>
Subject: Re: [cfe-dev] Reading execise

"Keane, Erich" <[hidden email]> wrote:

You just failed the reading exercise, twice!


> __int128 / __uint128 are NOT "user-defined types".

Ouch: the source "incompatible.c" uses the type __uint128_t, with a _t at it's end!

>  They are compiler defined types, so that rules doesn't apply.

Neither Clang nor MSVC have __uint128_t or __int128_t defined.

Is CAREFUL reading really SOOOO hard?

Stefan

> -----Original Message-----
> From: cfe-dev <[hidden email]> On Behalf Of Stefan
> Kanthak via cfe-dev
> Sent: Wednesday, September 16, 2020 3:44 PM
> To: [hidden email]
> Subject: [cfe-dev] Reading execise
>
> <https://docs.microsoft.com/en-us/cpp/build/x64-calling-convention#ret
> urn-values>
>
> | To return a user-defined type by value in RAX, it must have a length
> | of 1, 2, 4, 8, 16, 32, or 64 bits. [...] Otherwise, the caller must
> | allocate memory for the return value and pass a pointer to it as the
> | first argument. The remaining arguments are then shifted one
> | argument to the right. The same pointer must be returned by the callee in RAX.
>
> --- incompatible.c ---
> __attribute__((ms_abi))
> __uint128_t buggy(__uint128_t a, __uint128_t b, __uint128_t c) {
>    return a + b * c;
> }
> --- EOF ---
>
> clang -mno-sse -o- -O3 -S -target amd64-pc-windows incompatible.c
>
> buggy:                                  # @buggy
> # %bb.0:
>        movq    (%rdx), %r9             # OUCH: before it was destroyed,
>                                        #       r9 held the address of c
>        movq    (%r8), %rax
>        movq    8(%rdx), %r10
>        imulq   %rax, %r10
>        mulq    %r9                     # OUCH: the source says b * c,
>                                        #       NOT a * <something>
>        imulq   8(%r8), %r9             # OUCH: idem
>        addq    %r10, %rdx
>        addq    %r9, %rdx
>        addq    (%rcx), %rax            # OUCH: rcx holds the address of
>                                        #       the return value!
>                                        # OUCH: rax does NOT point to the
>                                        #       return value!
>        adcq    8(%rcx), %rdx           # OUCH: rcx holds the address of
>                                        #       the return value!
>        retq
>
>
> Stefan
_______________________________________________
cfe-dev mailing list
[hidden email]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev