[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Tinycc-devel] Possible issue in Win64 tcc with returning a struct?
From: |
Christophe Staïesse |
Subject: |
Re: [Tinycc-devel] Possible issue in Win64 tcc with returning a struct? |
Date: |
Wed, 17 Jun 2015 16:58:46 +0200 |
Hi Allan,
Your C is not so bad :-) It's well a compiler bug that affects version 0.9.26
and the master.
Here is a disassembly of function() (Intel syntax) compiled with 0.9.26:
struct test_struct function (void)
{
0: 55 push rbp
1: 48 89 e5 mov rbp,rsp
4: 48 81 ec 30 00 00 00 sub rsp,0x30
b: 48 89 4d 10 mov QWORD PTR [rbp+0x10],rcx [1]
struct test_struct bar;
bar.member = 'A';
f: b8 41 00 00 00 mov eax,0x41
14: 88 45 ff mov BYTE PTR [rbp-0x1],al
return bar;
17: 48 8b 45 00 mov rax,QWORD PTR [rbp+0x0] [2]
1b: 48 89 45 f0 mov QWORD PTR [rbp-0x10],rax
1f: b8 01 00 00 00 mov eax,0x1
24: 49 89 c0 mov r8,rax
27: 48 8d 55 ff lea rdx,[rbp-0x1]
2b: 48 8b 4d f0 mov rcx,QWORD PTR [rbp-0x10]
2f: e8 fc ff ff ff call 30 <function+0x30>
34: e9 00 00 00 00 jmp 39 <function+0x39>
39: c9 leave
3a: c3 ret
3b: 00 01 add BYTE PTR [rcx],al
3d: 04 02 add al,0x2
3f: 05 04 03 01 50 add eax,0x50010304
0000000000000044 <main>:
}
There are several problems:
1) In the prolog of function(), at [1], the address of the return struct is
saved outside the local stack frame. The address of the first (hypothetical)
stack parameter was passed instead. Solved by allocating a temporary variable.
2) At [2], this address is retrieved from another location. Solved by providing
the offset to this variable to the compiler through func_vc.
Here is a patch for 0.9.26 that should solve these two problems. I didn't
tested it though.
@@ -739,9 +740,10 @@ void gfunc_prolog(CType *func_type)
implicit pointer parameter */
func_vt = sym->type;
if ((func_vt.t & VT_BTYPE) == VT_STRUCT) {
- gen_modrm64(0x89, arg_regs[reg_param_index], VT_LOCAL, NULL, addr);
+ loc -= PTR_SIZE;
+ gen_modrm64(0x89, arg_regs[reg_param_index], VT_LOCAL, NULL, loc);
reg_param_index++;
- addr += PTR_SIZE;
+ func_vc = loc;
}
/* define parameters */
There are more bugs to fix and I must say, for what I saw of the 0.9.26
version, that the code seems to be in a bad shape and I won't recommend to use
the 64-bit version.
Christophe.
On Thu, 11 Jun 2015 03:27:05 +0100
Allan Crossman <address@hidden> wrote:
> Hi -
>
> My C is quite bad, so it's possible the fault lies in me rather than
> tcc. However, the following code seems OK to me but produces an
> unexpected result in the 64-bit version of tcc 0.9.26 for Windows:
>
> #include <stdio.h>
>
> struct test_struct {
> char member;
> };
>
> struct test_struct function (void)
> {
> struct test_struct bar;
> bar.member = 'A';
> return bar;
> }
>
> int main (void)
> {
> struct test_struct foo;
> foo = function();
> printf("Result: '%c' (should be 'A')\n", foo.member);
> return 0;
> }
>
> The struct returned from the function seems to be zeroed for some
> reason. This code works OK in the 32-bit version, however. If I've made
> some stupid error perhaps you can tell me.
>
> Thanks,
> Allan Crossman
>
>