[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