tinycc-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Tinycc-devel] SSE calling convention bug


From: Shachaf Ben-Kiki
Subject: [Tinycc-devel] SSE calling convention bug
Date: Sat, 26 Oct 2019 03:58:38 -0700

Hello,

I ran into a bug in the SSE function call code in x86_64-gen.c. It's
in the following lines, in gfunc_call:

                if (sse_reg) { /* avoid redundant movaps %xmm0, %xmm0 */
                    /* movaps %xmm0, %xmmN */
                    o(0x280f);
                    o(0xc0 + (sse_reg << 3));
                    /* movaps %xmm1, %xmmN */
                    o(0x280f);
                    o(0xc1 + ((sse_reg+1) << 3));
                }

When sse_reg is %xmm1, this generates

    0f 28 c8                movaps %xmm0,%xmm1
    0f 28 d1                movaps %xmm1,%xmm2

Such that the first mov overwrites xmm1 before the second mov uses it.
Since the registers are used in reverse order and only one or two at a
time, I think swapping the order of the movs should be sufficient to
fix it.

Here's a test case:

#include <stdio.h>

struct Point {
  float x;
  float y;
};

struct Rect {
  struct Point top_left;
  struct Point size;
};

float foo(struct Point p, struct Rect r) {
  return r.size.x;
}

int main(int argc, char **argv) {
  struct Point p = {1, 2};
  struct Rect r = {{3, 4}, {5, 6}};
  printf("%f\n", foo(p, r));
  return 0;
}

This program should print 5, but it prints 3 in tcc.

Is this the right place to post this? I can post it elsewhere, or send
a patch (it took a while to track this down but I think the fix should
be easy).

Thanks,
    Shachaf



reply via email to

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