1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-05-08 22:50:27 +02:00
guile/check/carg.c
pcpa c8b6c36971 Implement the jit_arg_register_p predicate.
* include/lightning.h, lib/jit_aarch64.c,
	lib/jit_alpha.c, lib/jit_arm-vfp.c, lib/jit_arm.c,
	lib/jit_hppa.c,	lib/jit_ia64.c, lib/jit_mips.c,
	lib/jit_ppc.c, lib/jit_s390.c, lib/jit_sparc.c,
	lib/jit_x86.c: Add the new jit_arg_register_p predicate.
	The predicate is expected to be used to know if an
	argument is in a register, what would need special
	handling if code that can overwrite non callee save
	registers is executed.

	* check/carg.c: New test case to check consistency and
	expected usage of jit_arg_register_p.

	* check/Makefile.am: Update for new test case.
2015-01-18 11:24:25 -02:00

538 lines
12 KiB
C

#include <lightning.h>
#include <stdio.h>
/* Simple test for arguments handling, that also shows how to use
* arguments to store values.
* Register arguments, if available, are very fast, but are also
* very volatile on some ports, because some ports will do C calls
* to implement division, remainder, sometimes multiplication, or
* some float operations.
* Arguments in registers should be fetched in the prolog of the
* function, and if they must be saved, they should be saved in
* the prolog.
* The predicate macro "jit_arg_register_p(arg)" allows knowing if
* an argument lives in a register, where it is known for being a very
* fast to read/write temporary storage.
*/
#define W jit_word_t
#define F jit_float32_t
#define D jit_float64_t
jit_state_t *_jit;
void
cw(W a1, W a2, W a3, W a4, W a5, W a6, W a7, W a8,
W a9, W a10, W a11, W a12, W a13, W a14, W a15, W a16)
{
if ( a1 != 1 || a2 != 2 || a3 != 3 || a4 != 4 ||
a5 != 5 || a6 != 6 || a7 != 7 || a8 != 8 ||
a9 != 9 || a10 != 10 || a11 != 11 || a12 != 12 ||
a13 != 13 || a14 != 14 || a15 != 15 || a16 != 16)
abort();
}
void
cf(F a1, F a2, F a3, F a4, F a5, F a6, F a7, F a8,
F a9, F a10, F a11, F a12, F a13, F a14, F a15, F a16)
{
if ( a1 != 1 || a2 != 2 || a3 != 3 || a4 != 4 ||
a5 != 5 || a6 != 6 || a7 != 7 || a8 != 8 ||
a9 != 9 || a10 != 10 || a11 != 11 || a12 != 12 ||
a13 != 13 || a14 != 14 || a15 != 15 || a16 != 16)
abort();
}
void
cd(D a1, D a2, D a3, D a4, D a5, D a6, D a7, D a8,
D a9, D a10, D a11, D a12, D a13, D a14, D a15, D a16)
{
if ( a1 != 1 || a2 != 2 || a3 != 3 || a4 != 4 ||
a5 != 5 || a6 != 6 || a7 != 7 || a8 != 8 ||
a9 != 9 || a10 != 10 || a11 != 11 || a12 != 12 ||
a13 != 13 || a14 != 14 || a15 != 15 || a16 != 16)
abort();
}
int
main(int argc, char *argv[])
{
void (*code)(void);
jit_node_t *jmp, *pass;
jit_node_t *jw, *jf, *jd;
jit_int32_t s1, s2, s3, s4, s5, s6, s7, s8,
s9, s10, s11, s12, s13, s14, s15, s16;
jit_node_t *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8,
*a9, *a10, *a11, *a12, *a13, *a14, *a15, *a16;
init_jit(argv[0]);
_jit = jit_new_state();
/* jump to "main" label */
jmp = jit_jmpi();
/* Create jit function that
* o Receives 16 word arguments
* o Save in the stack any register argument. Also force register
* arguments to be clobbered to properly make the test
* o Calls a C function that receives 16 word arguments, with
* values different from the ones received by this function
* o Reload from stack any register argument
* o Validated all arguments were not modified in the known
* cases it could have been clobbered
*/
jw = jit_label();
jit_name("jw");
jit_note(__FILE__, __LINE__);
jit_prolog();
a1 = jit_arg();
a2 = jit_arg();
a3 = jit_arg();
a4 = jit_arg();
a5 = jit_arg();
a6 = jit_arg();
a7 = jit_arg();
a8 = jit_arg();
a9 = jit_arg();
a10 = jit_arg();
a11 = jit_arg();
a12 = jit_arg();
a13 = jit_arg();
a14 = jit_arg();
a15 = jit_arg();
a16 = jit_arg();
#define SAVE_ARG(N) \
do { \
if (jit_arg_register_p(a##N)) { \
s##N = jit_allocai(sizeof(W)); \
jit_getarg(JIT_R0, a##N); \
jit_stxi(s##N, JIT_FP, JIT_R0); \
jit_putargi(-1, a##N); \
} \
} while (0)
SAVE_ARG(1);
SAVE_ARG(2);
SAVE_ARG(3);
SAVE_ARG(4);
SAVE_ARG(5);
SAVE_ARG(6);
SAVE_ARG(7);
SAVE_ARG(8);
SAVE_ARG(9);
SAVE_ARG(10);
SAVE_ARG(11);
SAVE_ARG(12);
SAVE_ARG(13);
SAVE_ARG(14);
SAVE_ARG(15);
SAVE_ARG(16);
#undef SAVE_ARG
jit_prepare();
{
jit_pushargi(1);
jit_pushargi(2);
jit_pushargi(3);
jit_pushargi(4);
jit_pushargi(5);
jit_pushargi(6);
jit_pushargi(7);
jit_pushargi(8);
jit_pushargi(9);
jit_pushargi(10);
jit_pushargi(11);
jit_pushargi(12);
jit_pushargi(13);
jit_pushargi(14);
jit_pushargi(15);
jit_pushargi(16);
}
jit_finishi(cw);
#define LOAD_ARG(N) \
do { \
if (jit_arg_register_p(a##N)) { \
jit_ldxi(JIT_R0, JIT_FP, s##N); \
jit_putargr(JIT_R0, a##N); \
} \
} while (0)
LOAD_ARG(1);
LOAD_ARG(2);
LOAD_ARG(3);
LOAD_ARG(4);
LOAD_ARG(5);
LOAD_ARG(6);
LOAD_ARG(7);
LOAD_ARG(8);
LOAD_ARG(9);
LOAD_ARG(10);
LOAD_ARG(11);
LOAD_ARG(12);
LOAD_ARG(13);
LOAD_ARG(14);
LOAD_ARG(15);
LOAD_ARG(16);
#undef LOAD_ARG
pass = jit_forward();
#define CHECK_ARG(N) \
do { \
jit_getarg(JIT_R0, a##N); \
jit_patch_at(jit_beqi(JIT_R0, 17 - N), pass); \
} while (0)
CHECK_ARG(1);
CHECK_ARG(2);
CHECK_ARG(3);
CHECK_ARG(4);
CHECK_ARG(5);
CHECK_ARG(6);
CHECK_ARG(7);
CHECK_ARG(8);
CHECK_ARG(9);
CHECK_ARG(10);
CHECK_ARG(11);
CHECK_ARG(12);
CHECK_ARG(13);
CHECK_ARG(14);
CHECK_ARG(15);
CHECK_ARG(16);
#undef CHECK_ARG
jit_calli(abort);
jit_link(pass);
jit_ret();
jit_epilog();
/* Create jit function that
* o Receives 16 float arguments
* o Save in the stack any register argument. Also force register
* arguments to be clobbered to properly make the test
* o Calls a C function that receives 16 float arguments, with
* values different from the ones received by this function
* o Reload from stack any register argument
* o Validated all arguments were not modified in the known
* cases it could have been clobbered
*/
jf = jit_label();
jit_name("jf");
jit_note(__FILE__, __LINE__);
jit_prolog();
a1 = jit_arg_f();
a2 = jit_arg_f();
a3 = jit_arg_f();
a4 = jit_arg_f();
a5 = jit_arg_f();
a6 = jit_arg_f();
a7 = jit_arg_f();
a8 = jit_arg_f();
a9 = jit_arg_f();
a10 = jit_arg_f();
a11 = jit_arg_f();
a12 = jit_arg_f();
a13 = jit_arg_f();
a14 = jit_arg_f();
a15 = jit_arg_f();
a16 = jit_arg_f();
#define SAVE_ARG(N) \
do { \
if (jit_arg_register_p(a##N)) { \
s##N = jit_allocai(sizeof(F)); \
jit_getarg_f(JIT_F0, a##N); \
jit_stxi_f(s##N, JIT_FP, JIT_F0); \
jit_putargi_f(-1, a##N); \
} \
} while (0)
SAVE_ARG(1);
SAVE_ARG(2);
SAVE_ARG(3);
SAVE_ARG(4);
SAVE_ARG(5);
SAVE_ARG(6);
SAVE_ARG(7);
SAVE_ARG(8);
SAVE_ARG(9);
SAVE_ARG(10);
SAVE_ARG(11);
SAVE_ARG(12);
SAVE_ARG(13);
SAVE_ARG(14);
SAVE_ARG(15);
SAVE_ARG(16);
#undef SAVE_ARG
jit_prepare();
{
jit_pushargi_f(1);
jit_pushargi_f(2);
jit_pushargi_f(3);
jit_pushargi_f(4);
jit_pushargi_f(5);
jit_pushargi_f(6);
jit_pushargi_f(7);
jit_pushargi_f(8);
jit_pushargi_f(9);
jit_pushargi_f(10);
jit_pushargi_f(11);
jit_pushargi_f(12);
jit_pushargi_f(13);
jit_pushargi_f(14);
jit_pushargi_f(15);
jit_pushargi_f(16);
}
jit_finishi(cf);
#define LOAD_ARG(N) \
do { \
if (jit_arg_register_p(a##N)) { \
jit_ldxi_f(JIT_F0, JIT_FP, s##N); \
jit_putargr_f(JIT_F0, a##N); \
} \
} while (0)
LOAD_ARG(1);
LOAD_ARG(2);
LOAD_ARG(3);
LOAD_ARG(4);
LOAD_ARG(5);
LOAD_ARG(6);
LOAD_ARG(7);
LOAD_ARG(8);
LOAD_ARG(9);
LOAD_ARG(10);
LOAD_ARG(11);
LOAD_ARG(12);
LOAD_ARG(13);
LOAD_ARG(14);
LOAD_ARG(15);
LOAD_ARG(16);
#undef LOAD_ARG
pass = jit_forward();
#define CHECK_ARG(N) \
do { \
jit_getarg_f(JIT_F0, a##N); \
jit_patch_at(jit_beqi_f(JIT_F0, 17 - N), pass); \
} while (0)
CHECK_ARG(1);
CHECK_ARG(2);
CHECK_ARG(3);
CHECK_ARG(4);
CHECK_ARG(5);
CHECK_ARG(6);
CHECK_ARG(7);
CHECK_ARG(8);
CHECK_ARG(9);
CHECK_ARG(10);
CHECK_ARG(11);
CHECK_ARG(12);
CHECK_ARG(13);
CHECK_ARG(14);
CHECK_ARG(15);
CHECK_ARG(16);
#undef CHECK_ARG
jit_calli(abort);
jit_link(pass);
jit_ret();
jit_epilog();
/* Create jit function that
* o Receives 16 double arguments
* o Save in the stack any register argument. Also force register
* arguments to be clobbered to properly make the test
* o Calls a C function that receives 16 double arguments, with
* values different from the ones received by this function
* o Reload from stack any register argument
* o Validated all arguments were not modified in the known
* cases it could have been clobbered
*/
jd = jit_label();
jit_name("jd");
jit_note(__FILE__, __LINE__);
jit_prolog();
a1 = jit_arg_d();
a2 = jit_arg_d();
a3 = jit_arg_d();
a4 = jit_arg_d();
a5 = jit_arg_d();
a6 = jit_arg_d();
a7 = jit_arg_d();
a8 = jit_arg_d();
a9 = jit_arg_d();
a10 = jit_arg_d();
a11 = jit_arg_d();
a12 = jit_arg_d();
a13 = jit_arg_d();
a14 = jit_arg_d();
a15 = jit_arg_d();
a16 = jit_arg_d();
#define SAVE_ARG(N) \
do { \
if (jit_arg_register_p(a##N)) { \
s##N = jit_allocai(sizeof(D)); \
jit_getarg_d(JIT_F0, a##N); \
jit_stxi_d(s##N, JIT_FP, JIT_F0); \
jit_putargi_d(-1, a##N); \
} \
} while (0)
SAVE_ARG(1);
SAVE_ARG(2);
SAVE_ARG(3);
SAVE_ARG(4);
SAVE_ARG(5);
SAVE_ARG(6);
SAVE_ARG(7);
SAVE_ARG(8);
SAVE_ARG(9);
SAVE_ARG(10);
SAVE_ARG(11);
SAVE_ARG(12);
SAVE_ARG(13);
SAVE_ARG(14);
SAVE_ARG(15);
SAVE_ARG(16);
#undef SAVE_ARG
jit_prepare();
{
jit_pushargi_d(1);
jit_pushargi_d(2);
jit_pushargi_d(3);
jit_pushargi_d(4);
jit_pushargi_d(5);
jit_pushargi_d(6);
jit_pushargi_d(7);
jit_pushargi_d(8);
jit_pushargi_d(9);
jit_pushargi_d(10);
jit_pushargi_d(11);
jit_pushargi_d(12);
jit_pushargi_d(13);
jit_pushargi_d(14);
jit_pushargi_d(15);
jit_pushargi_d(16);
}
jit_finishi(cd);
#define LOAD_ARG(N) \
do { \
if (jit_arg_register_p(a##N)) { \
jit_ldxi_d(JIT_F0, JIT_FP, s##N); \
jit_putargr_d(JIT_F0, a##N); \
} \
} while (0)
LOAD_ARG(1);
LOAD_ARG(2);
LOAD_ARG(3);
LOAD_ARG(4);
LOAD_ARG(5);
LOAD_ARG(6);
LOAD_ARG(7);
LOAD_ARG(8);
LOAD_ARG(9);
LOAD_ARG(10);
LOAD_ARG(11);
LOAD_ARG(12);
LOAD_ARG(13);
LOAD_ARG(14);
LOAD_ARG(15);
LOAD_ARG(16);
#undef LOAD_ARG
pass = jit_forward();
#define CHECK_ARG(N) \
do { \
jit_getarg_d(JIT_F0, a##N); \
jit_patch_at(jit_beqi_d(JIT_F0, 17 - N), pass); \
} while (0)
CHECK_ARG(1);
CHECK_ARG(2);
CHECK_ARG(3);
CHECK_ARG(4);
CHECK_ARG(5);
CHECK_ARG(6);
CHECK_ARG(7);
CHECK_ARG(8);
CHECK_ARG(9);
CHECK_ARG(10);
CHECK_ARG(11);
CHECK_ARG(12);
CHECK_ARG(13);
CHECK_ARG(14);
CHECK_ARG(15);
CHECK_ARG(16);
#undef CHECK_ARG
jit_calli(abort);
jit_link(pass);
jit_ret();
jit_epilog();
/* Create a jit function that calls the 3 previous ones.
* o First call the function that receives 16 word arguments
* o Then call the function that receives 16 float arguments
* o Finally call the function that receives 16 double arguments
*/
jit_patch(jmp);
jit_name("main");
jit_note(__FILE__, __LINE__);
jit_prolog();
jit_prepare();
{
jit_pushargi(16);
jit_pushargi(15);
jit_pushargi(14);
jit_pushargi(13);
jit_pushargi(12);
jit_pushargi(11);
jit_pushargi(10);
jit_pushargi(9);
jit_pushargi(8);
jit_pushargi(7);
jit_pushargi(6);
jit_pushargi(5);
jit_pushargi(4);
jit_pushargi(3);
jit_pushargi(2);
jit_pushargi(1);
}
jit_patch_at(jit_finishi(NULL), jw);
jit_prepare();
{
jit_pushargi_f(16);
jit_pushargi_f(15);
jit_pushargi_f(14);
jit_pushargi_f(13);
jit_pushargi_f(12);
jit_pushargi_f(11);
jit_pushargi_f(10);
jit_pushargi_f(9);
jit_pushargi_f(8);
jit_pushargi_f(7);
jit_pushargi_f(6);
jit_pushargi_f(5);
jit_pushargi_f(4);
jit_pushargi_f(3);
jit_pushargi_f(2);
jit_pushargi_f(1);
}
jit_patch_at(jit_finishi(NULL), jf);
jit_prepare();
{
jit_pushargi_d(16);
jit_pushargi_d(15);
jit_pushargi_d(14);
jit_pushargi_d(13);
jit_pushargi_d(12);
jit_pushargi_d(11);
jit_pushargi_d(10);
jit_pushargi_d(9);
jit_pushargi_d(8);
jit_pushargi_d(7);
jit_pushargi_d(6);
jit_pushargi_d(5);
jit_pushargi_d(4);
jit_pushargi_d(3);
jit_pushargi_d(2);
jit_pushargi_d(1);
}
jit_patch_at(jit_finishi(NULL), jd);
jit_ret();
jit_epilog();
code = jit_emit();
jit_clear_state();
(*code)();
jit_destroy_state();
finish_jit();
return (0);
}