tinycc-devel
[Top][All Lists]
Advanced

[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
> 
> 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]