[llvm-dev] About detailed rule of fastcall

jy ban via llvm-dev llvm-dev at lists.llvm.org
Tue Sep 24 03:30:43 PDT 2019


I think clang behaves differently than gcc.

When the first argument is 'struct' and the second argument is 'int', gcc
put the second argument 'int' in register edx, but clang sometimes in edx,
and sometimes in ecx.
    e.g. void __attribute__((fastcall)) test(struct, int)

I tested with follow structures
    typedef struct _sti {  // gcc: edx, clang: edx
        int i;
    } sti;

    typedef struct _sts {  // gcc: edx, clang: ecx
        short s;
    } sts;

    typedef struct __attribute__((__packed__)) _stss {  // gcc: edx, clang:
ecx
        short s1;
        short s2;
    } stss;

    typedef struct _st1 {  // gcc: edx, clang: ecx
        char str[1];
    } st1;
   ~
    typedef struct _st4 {  // gcc: edx, clang: ecx
        char str[4];
    } st4;


2019년 9월 21일 (토) 오전 5:16, Reid Kleckner <rnk at google.com>님이 작성:

> 1. probably for GCC compatibility
> 2. probably the same
> 3. Hard to say, this could be a bug, compare with GCC
> 4. This behavior was implemented in this change:
> https://reviews.llvm.org/rC166538 You can find the logic for this in
> clang today.
>
> I also noticed that fastcall behaves differently when we target MSVC
> compatibility.
>
>
>
> On Fri, Sep 20, 2019 at 3:29 AM jy ban via llvm-dev <
> llvm-dev at lists.llvm.org> wrote:
>
>> Hello.
>> I'm trying to understand how fastcall works.
>>
>> As far as I know, first two integer type arguments are passed in ecx and
>> edx.
>> I tested several test, but the result was different from what I expected
>>
>> #1
>>     typedef struct _data_t {
>>         int d;
>>     } data_t;
>>
>>     void __attribute__((fastcall)) test_suuu(data_t s, unsigned int a,
>> unsigned int b, unsigned int c);
>>
>> unsigned int a is passed in edx, and the rest are passed in stack (in s,
>> b, c order).
>>
>> #2 : order of arguments is diff from #1
>>    void __attribute__((fastcall)) test_usuu(unsigned int a, data_t s,
>> unsigned int b, unsigned int c);
>>
>> unsigned int a is passed in ecx, and the rest are passed in stack (in s,
>> b, c order)
>>
>> #3 : __attribute__((__packed__)) is diff from #1
>>     typedef struct __attribute__((__packed__)) _data_t3 {
>>         int d;
>>     } data_t3;
>>
>>     void __attribute__((fastcall)) test_s3uu(data_t3 s3, unsigned int a,
>> unsigned int b);
>>
>> unsigned int a is passed in ecx, and the rest are passed in stack (in s,
>> b, c order)
>>
>> My questions are as follow
>> - why struct s in first test is passed in edx not ecx?
>> - why unsigned b is in second test is passed in stack not edx?
>> - why 'packed' makes a difference?
>> - where can I find relevant code in llvm?
>>
>> I'm using i586, linux, llvm 5.02
>> Build with "clang++ -std=c++11 -ggdb -O0 -gdwarf-4
>> -fno-omit-frame-pointer -fno-optimize-sibling-calls -o ref_test
>> ref_test.cpp"
>> (All arguments are used in the function so that they are not optimized
>> out)
>> Tested with gdb
>>     (gdb) break* test_suuu
>>     (gdb) x/6wx $esp
>>     (gdb) i r
>> _______________________________________________
>> LLVM Developers mailing list
>> llvm-dev at lists.llvm.org
>> https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20190924/e2b39612/attachment.html>


More information about the llvm-dev mailing list