[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
- [Tinycc-devel] SSE calling convention bug,
Shachaf Ben-Kiki <=