mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-22 11:31:05 +08:00
x86-64: Add vector vararg ABI tests
We can scan stack for return address to get vector arguments passed on stack. Tested on Linux/x86-64 and Linux/x32. * gcc.target/x86_64/abi/test_varargs-m128.c: New file. * gcc.target/x86_64/abi/avx/test_varargs-m256.c: Likewise. * gcc.target/x86_64/abi/avx512f/test_varargs-m512.c: Likewise. From-SVN: r271329
This commit is contained in:
parent
45641b316a
commit
2a380e2ed0
@ -1,3 +1,9 @@
|
||||
2019-05-17 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
* gcc.target/x86_64/abi/test_varargs-m128.c: New file.
|
||||
* gcc.target/x86_64/abi/avx/test_varargs-m256.c: Likewise.
|
||||
* gcc.target/x86_64/abi/avx512f/test_varargs-m512.c: Likewise.
|
||||
|
||||
2019-05-17 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
PR target/90497
|
||||
|
104
gcc/testsuite/gcc.target/x86_64/abi/avx/test_varargs-m256.c
Normal file
104
gcc/testsuite/gcc.target/x86_64/abi/avx/test_varargs-m256.c
Normal file
@ -0,0 +1,104 @@
|
||||
/* Test variable number of 256-bit vector arguments passed to functions. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include "avx-check.h"
|
||||
#include "args.h"
|
||||
|
||||
struct IntegerRegisters iregs;
|
||||
struct FloatRegisters fregs;
|
||||
|
||||
/* This struct holds values for argument checking. */
|
||||
struct
|
||||
{
|
||||
YMM_T i0, i1, i2, i3, i4, i5, i6, i7, i8, i9;
|
||||
} values;
|
||||
|
||||
char *pass;
|
||||
int failed = 0;
|
||||
|
||||
#undef assert
|
||||
#define assert(c) do { \
|
||||
if (!(c)) {failed++; printf ("failed %s\n", pass); } \
|
||||
} while (0)
|
||||
|
||||
#define compare(X1,X2,T) do { \
|
||||
assert (memcmp (&X1, &X2, sizeof (T)) == 0); \
|
||||
} while (0)
|
||||
|
||||
void
|
||||
fun_check_passing_m256_varargs (__m256 i0, __m256 i1, __m256 i2,
|
||||
__m256 i3, ...)
|
||||
{
|
||||
/* Check argument values. */
|
||||
void **fp = __builtin_frame_address (0);
|
||||
void *ra = __builtin_return_address (0);
|
||||
__m256 *argp;
|
||||
|
||||
compare (values.i0, i0, __m256);
|
||||
compare (values.i1, i1, __m256);
|
||||
compare (values.i2, i2, __m256);
|
||||
compare (values.i3, i3, __m256);
|
||||
|
||||
/* Get the pointer to the return address on stack. */
|
||||
while (*fp != ra)
|
||||
fp++;
|
||||
|
||||
/* Skip the return address stack slot. */
|
||||
argp = (__m256 *) (((char *) fp) + 8);
|
||||
|
||||
/* Check __m256 arguments passed on stack. */
|
||||
compare (values.i4, argp[0], __m256);
|
||||
compare (values.i5, argp[1], __m256);
|
||||
compare (values.i6, argp[2], __m256);
|
||||
compare (values.i7, argp[3], __m256);
|
||||
compare (values.i8, argp[4], __m256);
|
||||
compare (values.i9, argp[5], __m256);
|
||||
|
||||
/* Check register contents. */
|
||||
compare (fregs.ymm0, ymm_regs[0], __m256);
|
||||
compare (fregs.ymm1, ymm_regs[1], __m256);
|
||||
compare (fregs.ymm2, ymm_regs[2], __m256);
|
||||
compare (fregs.ymm3, ymm_regs[3], __m256);
|
||||
}
|
||||
|
||||
#define def_check_int_passing_varargs(_i0, _i1, _i2, _i3, _i4, _i5, \
|
||||
_i6, _i7, _i8, _i9, \
|
||||
_func, TYPE) \
|
||||
values.i0.TYPE[0] = _i0; \
|
||||
values.i1.TYPE[0] = _i1; \
|
||||
values.i2.TYPE[0] = _i2; \
|
||||
values.i3.TYPE[0] = _i3; \
|
||||
values.i4.TYPE[0] = _i4; \
|
||||
values.i5.TYPE[0] = _i5; \
|
||||
values.i6.TYPE[0] = _i6; \
|
||||
values.i7.TYPE[0] = _i7; \
|
||||
values.i8.TYPE[0] = _i8; \
|
||||
values.i9.TYPE[0] = _i9; \
|
||||
clear_struct_registers; \
|
||||
fregs.F0.TYPE[0] = _i0; \
|
||||
fregs.F1.TYPE[0] = _i1; \
|
||||
fregs.F2.TYPE[0] = _i2; \
|
||||
fregs.F3.TYPE[0] = _i3; \
|
||||
WRAP_CALL(_func) (_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, _i9);
|
||||
|
||||
void
|
||||
test_m256_varargs (void)
|
||||
{
|
||||
__m256 x[10];
|
||||
int i;
|
||||
for (i = 0; i < 10; i++)
|
||||
x[i] = (__m256){32+i, 0, 0, 0, 0, 0, 0, 0};
|
||||
pass = "m256-varargs";
|
||||
def_check_int_passing_varargs (x[0], x[1], x[2], x[3], x[4], x[5],
|
||||
x[6], x[7], x[8], x[9],
|
||||
fun_check_passing_m256_varargs,
|
||||
_m256);
|
||||
}
|
||||
|
||||
void
|
||||
avx_test (void)
|
||||
{
|
||||
test_m256_varargs ();
|
||||
if (failed)
|
||||
abort ();
|
||||
}
|
104
gcc/testsuite/gcc.target/x86_64/abi/avx512f/test_varargs-m512.c
Normal file
104
gcc/testsuite/gcc.target/x86_64/abi/avx512f/test_varargs-m512.c
Normal file
@ -0,0 +1,104 @@
|
||||
/* Test variable number of 512-bit vector arguments passed to functions. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include "avx512f-check.h"
|
||||
#include "args.h"
|
||||
|
||||
struct IntegerRegisters iregs;
|
||||
struct FloatRegisters fregs;
|
||||
|
||||
/* This struct holds values for argument checking. */
|
||||
struct
|
||||
{
|
||||
ZMM_T i0, i1, i2, i3, i4, i5, i6, i7, i8, i9;
|
||||
} values;
|
||||
|
||||
char *pass;
|
||||
int failed = 0;
|
||||
|
||||
#undef assert
|
||||
#define assert(c) do { \
|
||||
if (!(c)) {failed++; printf ("failed %s\n", pass); } \
|
||||
} while (0)
|
||||
|
||||
#define compare(X1,X2,T) do { \
|
||||
assert (memcmp (&X1, &X2, sizeof (T)) == 0); \
|
||||
} while (0)
|
||||
|
||||
void
|
||||
fun_check_passing_m512_varargs (__m512 i0, __m512 i1, __m512 i2,
|
||||
__m512 i3, ...)
|
||||
{
|
||||
/* Check argument values. */
|
||||
void **fp = __builtin_frame_address (0);
|
||||
void *ra = __builtin_return_address (0);
|
||||
__m512 *argp;
|
||||
|
||||
compare (values.i0, i0, __m512);
|
||||
compare (values.i1, i1, __m512);
|
||||
compare (values.i2, i2, __m512);
|
||||
compare (values.i3, i3, __m512);
|
||||
|
||||
/* Get the pointer to the return address on stack. */
|
||||
while (*fp != ra)
|
||||
fp++;
|
||||
|
||||
/* Skip the return address stack slot. */
|
||||
argp = (__m512 *)(((char *) fp) + 8);
|
||||
|
||||
/* Check __m512 arguments passed on stack. */
|
||||
compare (values.i4, argp[0], __m512);
|
||||
compare (values.i5, argp[1], __m512);
|
||||
compare (values.i6, argp[2], __m512);
|
||||
compare (values.i7, argp[3], __m512);
|
||||
compare (values.i8, argp[4], __m512);
|
||||
compare (values.i9, argp[5], __m512);
|
||||
|
||||
/* Check register contents. */
|
||||
compare (fregs.zmm0, zmm_regs[0], __m512);
|
||||
compare (fregs.zmm1, zmm_regs[1], __m512);
|
||||
compare (fregs.zmm2, zmm_regs[2], __m512);
|
||||
compare (fregs.zmm3, zmm_regs[3], __m512);
|
||||
}
|
||||
|
||||
#define def_check_int_passing_varargs(_i0, _i1, _i2, _i3, _i4, _i5, \
|
||||
_i6, _i7, _i8, _i9, \
|
||||
_func, TYPE) \
|
||||
values.i0.TYPE[0] = _i0; \
|
||||
values.i1.TYPE[0] = _i1; \
|
||||
values.i2.TYPE[0] = _i2; \
|
||||
values.i3.TYPE[0] = _i3; \
|
||||
values.i4.TYPE[0] = _i4; \
|
||||
values.i5.TYPE[0] = _i5; \
|
||||
values.i6.TYPE[0] = _i6; \
|
||||
values.i7.TYPE[0] = _i7; \
|
||||
values.i8.TYPE[0] = _i8; \
|
||||
values.i9.TYPE[0] = _i9; \
|
||||
clear_struct_registers; \
|
||||
fregs.F0.TYPE[0] = _i0; \
|
||||
fregs.F1.TYPE[0] = _i1; \
|
||||
fregs.F2.TYPE[0] = _i2; \
|
||||
fregs.F3.TYPE[0] = _i3; \
|
||||
WRAP_CALL(_func) (_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, _i9);
|
||||
|
||||
void
|
||||
test_m512_varargs (void)
|
||||
{
|
||||
__m512 x[10];
|
||||
int i;
|
||||
for (i = 0; i < 10; i++)
|
||||
x[i] = (__m512){32+i, 0, 0, 0, 0, 0, 0, 0};
|
||||
pass = "m512-varargs";
|
||||
def_check_int_passing_varargs (x[0], x[1], x[2], x[3], x[4], x[5],
|
||||
x[6], x[7], x[8], x[9],
|
||||
fun_check_passing_m512_varargs,
|
||||
_m512);
|
||||
}
|
||||
|
||||
void
|
||||
avx512f_test (void)
|
||||
{
|
||||
test_m512_varargs ();
|
||||
if (failed)
|
||||
abort ();
|
||||
}
|
110
gcc/testsuite/gcc.target/x86_64/abi/test_varargs-m128.c
Normal file
110
gcc/testsuite/gcc.target/x86_64/abi/test_varargs-m128.c
Normal file
@ -0,0 +1,110 @@
|
||||
/* Test variable number of 128-bit vector arguments passed to functions. */
|
||||
|
||||
#include <stdio.h>
|
||||
#include "defines.h"
|
||||
#include "macros.h"
|
||||
#include "args.h"
|
||||
|
||||
struct IntegerRegisters iregs;
|
||||
struct FloatRegisters fregs;
|
||||
|
||||
/* This struct holds values for argument checking. */
|
||||
struct
|
||||
{
|
||||
XMM_T i0, i1, i2, i3, i4, i5, i6, i7, i8, i9;
|
||||
} values;
|
||||
|
||||
char *pass;
|
||||
int failed = 0;
|
||||
|
||||
#undef assert
|
||||
#define assert(c) do { \
|
||||
if (!(c)) {failed++; printf ("failed %s\n", pass); } \
|
||||
} while (0)
|
||||
|
||||
#define compare(X1,X2,T) do { \
|
||||
assert (memcmp (&X1, &X2, sizeof (T)) == 0); \
|
||||
} while (0)
|
||||
|
||||
void
|
||||
fun_check_passing_m128_varargs (__m128 i0, __m128 i1, __m128 i2,
|
||||
__m128 i3, ...)
|
||||
{
|
||||
/* Check argument values. */
|
||||
void **fp = __builtin_frame_address (0);
|
||||
void *ra = __builtin_return_address (0);
|
||||
__m128 *argp;
|
||||
|
||||
compare (values.i0, i0, __m128);
|
||||
compare (values.i1, i1, __m128);
|
||||
compare (values.i2, i2, __m128);
|
||||
compare (values.i3, i3, __m128);
|
||||
|
||||
/* Get the pointer to the return address on stack. */
|
||||
while (*fp != ra)
|
||||
fp++;
|
||||
|
||||
/* Skip the return address stack slot. */
|
||||
argp = (__m128 *) (((char *) fp) + 8);
|
||||
|
||||
/* Check __m128 arguments passed on stack. */
|
||||
compare (values.i8, argp[0], __m128);
|
||||
compare (values.i9, argp[1], __m128);
|
||||
|
||||
/* Check register contents. */
|
||||
compare (fregs.xmm0, xmm_regs[0], __m128);
|
||||
compare (fregs.xmm1, xmm_regs[1], __m128);
|
||||
compare (fregs.xmm2, xmm_regs[2], __m128);
|
||||
compare (fregs.xmm3, xmm_regs[3], __m128);
|
||||
compare (fregs.xmm4, xmm_regs[4], __m128);
|
||||
compare (fregs.xmm5, xmm_regs[5], __m128);
|
||||
compare (fregs.xmm6, xmm_regs[6], __m128);
|
||||
compare (fregs.xmm7, xmm_regs[7], __m128);
|
||||
}
|
||||
|
||||
#define def_check_int_passing_varargs(_i0, _i1, _i2, _i3, _i4, _i5, \
|
||||
_i6, _i7, _i8, _i9, \
|
||||
_func, TYPE) \
|
||||
values.i0.TYPE[0] = _i0; \
|
||||
values.i1.TYPE[0] = _i1; \
|
||||
values.i2.TYPE[0] = _i2; \
|
||||
values.i3.TYPE[0] = _i3; \
|
||||
values.i4.TYPE[0] = _i4; \
|
||||
values.i5.TYPE[0] = _i5; \
|
||||
values.i6.TYPE[0] = _i6; \
|
||||
values.i7.TYPE[0] = _i7; \
|
||||
values.i8.TYPE[0] = _i8; \
|
||||
values.i9.TYPE[0] = _i9; \
|
||||
clear_float_registers; \
|
||||
fregs.F0.TYPE[0] = _i0; \
|
||||
fregs.F1.TYPE[0] = _i1; \
|
||||
fregs.F2.TYPE[0] = _i2; \
|
||||
fregs.F3.TYPE[0] = _i3; \
|
||||
fregs.F4.TYPE[0] = _i4; \
|
||||
fregs.F5.TYPE[0] = _i5; \
|
||||
fregs.F6.TYPE[0] = _i6; \
|
||||
fregs.F7.TYPE[0] = _i7; \
|
||||
WRAP_CALL(_func) (_i0, _i1, _i2, _i3, _i4, _i5, _i6, _i7, _i8, _i9);
|
||||
|
||||
void
|
||||
test_m128_varargs (void)
|
||||
{
|
||||
__m128 x[10];
|
||||
int i;
|
||||
for (i = 0; i < 10; i++)
|
||||
x[i] = (__m128){32+i, 0, 0, 0};
|
||||
pass = "m128-varargs";
|
||||
def_check_int_passing_varargs (x[0], x[1], x[2], x[3], x[4], x[5],
|
||||
x[6], x[7], x[8], x[9],
|
||||
fun_check_passing_m128_varargs,
|
||||
_m128);
|
||||
}
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
test_m128_varargs ();
|
||||
if (failed)
|
||||
abort ();
|
||||
return 0;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user