mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-06-01 01:40:21 +02:00
Add facility to enter and leave JIT ABI
This allows us to save and restore callee-save temporaries, i.e. RBP on 32-bit x86. Otherwise it's a disaster shuffling stack arguments using temporaries.
This commit is contained in:
parent
9906cd5f84
commit
42bc762d26
8 changed files with 113 additions and 85 deletions
|
@ -228,6 +228,11 @@ JIT_API void jit_move_operands (jit_state_t *_jit, jit_operand_t *dst,
|
||||||
JIT_API size_t jit_align_stack (jit_state_t *_jit, size_t expand);
|
JIT_API size_t jit_align_stack (jit_state_t *_jit, size_t expand);
|
||||||
JIT_API void jit_shrink_stack (jit_state_t *_jit, size_t diff);
|
JIT_API void jit_shrink_stack (jit_state_t *_jit, size_t diff);
|
||||||
|
|
||||||
|
JIT_API size_t jit_enter_jit_abi (jit_state_t *_jit,
|
||||||
|
size_t v, size_t vf, size_t frame_size);
|
||||||
|
JIT_API void jit_leave_jit_abi (jit_state_t *_jit,
|
||||||
|
size_t v, size_t vf, size_t frame_size);
|
||||||
|
|
||||||
/* Note that all functions that take jit_operand_t args[] use the args
|
/* Note that all functions that take jit_operand_t args[] use the args
|
||||||
as scratch space while shuffling values into position. */
|
as scratch space while shuffling values into position. */
|
||||||
JIT_API void jit_calli(jit_state_t *, jit_pointer_t f,
|
JIT_API void jit_calli(jit_state_t *, jit_pointer_t f,
|
||||||
|
|
|
@ -863,6 +863,104 @@ jit_shrink_stack(jit_state_t *_jit, size_t diff)
|
||||||
_jit->frame_size -= diff;
|
_jit->frame_size -= diff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const jit_gpr_t V[] = {
|
||||||
|
#ifdef JIT_VTMP
|
||||||
|
JIT_VTMP ,
|
||||||
|
#endif
|
||||||
|
JIT_V0, JIT_V1, JIT_V2
|
||||||
|
#ifdef JIT_V3
|
||||||
|
, JIT_V3
|
||||||
|
#endif
|
||||||
|
#ifdef JIT_V4
|
||||||
|
, JIT_V4
|
||||||
|
#endif
|
||||||
|
#ifdef JIT_V5
|
||||||
|
, JIT_V5
|
||||||
|
#endif
|
||||||
|
#ifdef JIT_V6
|
||||||
|
, JIT_V6
|
||||||
|
#endif
|
||||||
|
#ifdef JIT_V7
|
||||||
|
, JIT_V7
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
static const jit_fpr_t VF[] = {
|
||||||
|
#ifdef JIT_VFTMP
|
||||||
|
JIT_VFTMP ,
|
||||||
|
#endif
|
||||||
|
#ifdef JIT_VF0
|
||||||
|
JIT_VF0
|
||||||
|
#endif
|
||||||
|
#ifdef JIT_VF1
|
||||||
|
, JIT_VF1
|
||||||
|
#endif
|
||||||
|
#ifdef JIT_VF2
|
||||||
|
, JIT_VF2
|
||||||
|
#endif
|
||||||
|
#ifdef JIT_VF3
|
||||||
|
, JIT_VF3
|
||||||
|
#endif
|
||||||
|
#ifdef JIT_VF4
|
||||||
|
, JIT_VF4
|
||||||
|
#endif
|
||||||
|
#ifdef JIT_VF5
|
||||||
|
, JIT_VF5
|
||||||
|
#endif
|
||||||
|
#ifdef JIT_VF6
|
||||||
|
, JIT_VF6
|
||||||
|
#endif
|
||||||
|
#ifdef JIT_VF7
|
||||||
|
, JIT_VF7
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
static const size_t v_count = sizeof(V) / sizeof(V[0]);
|
||||||
|
static const size_t vf_count = sizeof(VF) / sizeof(VF[0]);
|
||||||
|
|
||||||
|
size_t
|
||||||
|
jit_enter_jit_abi(jit_state_t *_jit, size_t v, size_t vf, size_t frame_size)
|
||||||
|
{
|
||||||
|
#ifdef JIT_VTMP
|
||||||
|
v++;
|
||||||
|
#endif
|
||||||
|
#ifdef JIT_VFTMP
|
||||||
|
vf++;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ASSERT(v <= v_count);
|
||||||
|
ASSERT(vf <= vf_count);
|
||||||
|
|
||||||
|
/* Save values of callee-save registers. */
|
||||||
|
for (size_t i = 0; i < v; i++)
|
||||||
|
jit_pushr (_jit, V[i]);
|
||||||
|
for (size_t i = 0; i < vf; i++)
|
||||||
|
jit_pushr_d (_jit, VF[i]);
|
||||||
|
|
||||||
|
return jit_align_stack(_jit, frame_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
jit_leave_jit_abi(jit_state_t *_jit, size_t v, size_t vf, size_t frame_size)
|
||||||
|
{
|
||||||
|
#ifdef JIT_VTMP
|
||||||
|
v++;
|
||||||
|
#endif
|
||||||
|
#ifdef JIT_VFTMP
|
||||||
|
vf++;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
jit_shrink_stack(_jit, frame_size);
|
||||||
|
|
||||||
|
/* Restore callee-save registers. */
|
||||||
|
for (size_t i = 0; i < vf; i++)
|
||||||
|
jit_popr_d (_jit, VF[vf_count - i - 1]);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < v; i++)
|
||||||
|
jit_popr (_jit, V[v_count - i - 1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Precondition: stack is already aligned.
|
// Precondition: stack is already aligned.
|
||||||
static size_t
|
static size_t
|
||||||
prepare_call_args(jit_state_t *_jit, size_t argc, jit_operand_t args[])
|
prepare_call_args(jit_state_t *_jit, size_t argc, jit_operand_t args[])
|
||||||
|
|
|
@ -273,8 +273,7 @@ get_temp_gpr(jit_state_t *_jit)
|
||||||
#ifdef JIT_RTMP
|
#ifdef JIT_RTMP
|
||||||
return JIT_RTMP;
|
return JIT_RTMP;
|
||||||
#else
|
#else
|
||||||
pushr(_jit, _RBP_REGNO);
|
return JIT_VTMP;
|
||||||
return _RBP;
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -283,9 +282,6 @@ unget_temp_gpr(jit_state_t *_jit)
|
||||||
{
|
{
|
||||||
ASSERT(_jit->temp_gpr_saved);
|
ASSERT(_jit->temp_gpr_saved);
|
||||||
_jit->temp_gpr_saved = 0;
|
_jit->temp_gpr_saved = 0;
|
||||||
#ifndef JIT_RTMP
|
|
||||||
popr(_jit, _RBP_REGNO);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
@ -133,6 +133,7 @@ jit_fpr_is_callee_save (jit_fpr_t reg)
|
||||||
# define JIT_V0 _RBX
|
# define JIT_V0 _RBX
|
||||||
# define JIT_V1 _RSI
|
# define JIT_V1 _RSI
|
||||||
# define JIT_V2 _RDI
|
# define JIT_V2 _RDI
|
||||||
|
# define JIT_VTMP _RBP
|
||||||
# define JIT_F0 _XMM0
|
# define JIT_F0 _XMM0
|
||||||
# define JIT_F1 _XMM1
|
# define JIT_F1 _XMM1
|
||||||
# define JIT_F2 _XMM2
|
# define JIT_F2 _XMM2
|
||||||
|
|
|
@ -1,26 +1,10 @@
|
||||||
#include "test.h"
|
#include "test.h"
|
||||||
|
|
||||||
static void
|
|
||||||
maybe_save(jit_state_t *j, jit_gpr_t reg)
|
|
||||||
{
|
|
||||||
if (jit_gpr_is_callee_save (reg))
|
|
||||||
jit_pushr(j, reg);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
maybe_restore(jit_state_t *j, jit_gpr_t reg)
|
|
||||||
{
|
|
||||||
if (jit_gpr_is_callee_save (reg))
|
|
||||||
jit_popr(j, reg);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
run_test(jit_state_t *j, uint8_t *arena_base, size_t arena_size)
|
run_test(jit_state_t *j, uint8_t *arena_base, size_t arena_size)
|
||||||
{
|
{
|
||||||
jit_begin(j, arena_base, arena_size);
|
jit_begin(j, arena_base, arena_size);
|
||||||
maybe_save(j, JIT_V0);
|
size_t align = jit_enter_jit_abi(j, 3, 0, 0);
|
||||||
maybe_save(j, JIT_V1);
|
|
||||||
maybe_save(j, JIT_V2);
|
|
||||||
|
|
||||||
jit_operand_t args[] =
|
jit_operand_t args[] =
|
||||||
{ jit_operand_gpr (JIT_OPERAND_ABI_POINTER, JIT_R0),
|
{ jit_operand_gpr (JIT_OPERAND_ABI_POINTER, JIT_R0),
|
||||||
|
@ -33,9 +17,7 @@ run_test(jit_state_t *j, uint8_t *arena_base, size_t arena_size)
|
||||||
jit_str(j, JIT_R0, JIT_V1);
|
jit_str(j, JIT_R0, JIT_V1);
|
||||||
jit_str(j, JIT_R1, JIT_V2);
|
jit_str(j, JIT_R1, JIT_V2);
|
||||||
|
|
||||||
maybe_restore(j, JIT_V2);
|
jit_leave_jit_abi(j, 3, 0, align);
|
||||||
maybe_restore(j, JIT_V1);
|
|
||||||
maybe_restore(j, JIT_V0);
|
|
||||||
|
|
||||||
jit_ret(j);
|
jit_ret(j);
|
||||||
|
|
||||||
|
|
|
@ -1,27 +1,11 @@
|
||||||
#include "test.h"
|
#include "test.h"
|
||||||
|
|
||||||
static void
|
|
||||||
maybe_save(jit_state_t *j, jit_gpr_t reg)
|
|
||||||
{
|
|
||||||
if (jit_gpr_is_callee_save (reg))
|
|
||||||
jit_pushr(j, reg);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
maybe_restore(jit_state_t *j, jit_gpr_t reg)
|
|
||||||
{
|
|
||||||
if (jit_gpr_is_callee_save (reg))
|
|
||||||
jit_popr(j, reg);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
run_test(jit_state_t *j, uint8_t *arena_base, size_t arena_size)
|
run_test(jit_state_t *j, uint8_t *arena_base, size_t arena_size)
|
||||||
{
|
{
|
||||||
jit_begin(j, arena_base, arena_size);
|
jit_begin(j, arena_base, arena_size);
|
||||||
|
|
||||||
maybe_save(j, JIT_V0);
|
size_t align = jit_enter_jit_abi(j, 3, 0, 0);
|
||||||
maybe_save(j, JIT_V1);
|
|
||||||
maybe_save(j, JIT_V2);
|
|
||||||
|
|
||||||
jit_operand_t args[] =
|
jit_operand_t args[] =
|
||||||
{ jit_operand_gpr (JIT_OPERAND_ABI_POINTER, JIT_R0),
|
{ jit_operand_gpr (JIT_OPERAND_ABI_POINTER, JIT_R0),
|
||||||
|
@ -34,9 +18,7 @@ run_test(jit_state_t *j, uint8_t *arena_base, size_t arena_size)
|
||||||
jit_str(j, JIT_R0, JIT_V1);
|
jit_str(j, JIT_R0, JIT_V1);
|
||||||
jit_str(j, JIT_R1, JIT_V2);
|
jit_str(j, JIT_R1, JIT_V2);
|
||||||
|
|
||||||
maybe_restore(j, JIT_V2);
|
jit_leave_jit_abi(j, 3, 0, align);
|
||||||
maybe_restore(j, JIT_V1);
|
|
||||||
maybe_restore(j, JIT_V0);
|
|
||||||
|
|
||||||
jit_ret(j);
|
jit_ret(j);
|
||||||
|
|
||||||
|
|
|
@ -1,27 +1,11 @@
|
||||||
#include "test.h"
|
#include "test.h"
|
||||||
|
|
||||||
static void
|
|
||||||
maybe_save(jit_state_t *j, jit_gpr_t reg)
|
|
||||||
{
|
|
||||||
if (jit_gpr_is_callee_save (reg))
|
|
||||||
jit_pushr(j, reg);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
maybe_restore(jit_state_t *j, jit_gpr_t reg)
|
|
||||||
{
|
|
||||||
if (jit_gpr_is_callee_save (reg))
|
|
||||||
jit_popr(j, reg);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
run_test(jit_state_t *j, uint8_t *arena_base, size_t arena_size)
|
run_test(jit_state_t *j, uint8_t *arena_base, size_t arena_size)
|
||||||
{
|
{
|
||||||
jit_begin(j, arena_base, arena_size);
|
jit_begin(j, arena_base, arena_size);
|
||||||
|
|
||||||
maybe_save(j, JIT_V0);
|
size_t align = jit_enter_jit_abi(j, 3, 0, 0);
|
||||||
maybe_save(j, JIT_V1);
|
|
||||||
maybe_save(j, JIT_V2);
|
|
||||||
|
|
||||||
jit_operand_t args[] =
|
jit_operand_t args[] =
|
||||||
{ jit_operand_gpr (JIT_OPERAND_ABI_POINTER, JIT_R0),
|
{ jit_operand_gpr (JIT_OPERAND_ABI_POINTER, JIT_R0),
|
||||||
|
@ -34,9 +18,7 @@ run_test(jit_state_t *j, uint8_t *arena_base, size_t arena_size)
|
||||||
jit_str(j, JIT_R0, JIT_V1);
|
jit_str(j, JIT_R0, JIT_V1);
|
||||||
jit_str(j, JIT_R1, JIT_V2);
|
jit_str(j, JIT_R1, JIT_V2);
|
||||||
|
|
||||||
maybe_restore(j, JIT_V2);
|
jit_leave_jit_abi(j, 3, 0, align);
|
||||||
maybe_restore(j, JIT_V1);
|
|
||||||
maybe_restore(j, JIT_V0);
|
|
||||||
|
|
||||||
jit_ret(j);
|
jit_ret(j);
|
||||||
|
|
||||||
|
|
|
@ -1,27 +1,11 @@
|
||||||
#include "test.h"
|
#include "test.h"
|
||||||
|
|
||||||
static void
|
|
||||||
maybe_save(jit_state_t *j, jit_gpr_t reg)
|
|
||||||
{
|
|
||||||
if (jit_gpr_is_callee_save (reg))
|
|
||||||
jit_pushr(j, reg);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
maybe_restore(jit_state_t *j, jit_gpr_t reg)
|
|
||||||
{
|
|
||||||
if (jit_gpr_is_callee_save (reg))
|
|
||||||
jit_popr(j, reg);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
run_test(jit_state_t *j, uint8_t *arena_base, size_t arena_size)
|
run_test(jit_state_t *j, uint8_t *arena_base, size_t arena_size)
|
||||||
{
|
{
|
||||||
jit_begin(j, arena_base, arena_size);
|
jit_begin(j, arena_base, arena_size);
|
||||||
|
|
||||||
maybe_save(j, JIT_V0);
|
size_t align = jit_enter_jit_abi(j, 3, 0, 0);
|
||||||
maybe_save(j, JIT_V1);
|
|
||||||
maybe_save(j, JIT_V2);
|
|
||||||
|
|
||||||
jit_operand_t args[] =
|
jit_operand_t args[] =
|
||||||
{ jit_operand_gpr (JIT_OPERAND_ABI_POINTER, JIT_R0),
|
{ jit_operand_gpr (JIT_OPERAND_ABI_POINTER, JIT_R0),
|
||||||
|
@ -34,9 +18,7 @@ run_test(jit_state_t *j, uint8_t *arena_base, size_t arena_size)
|
||||||
jit_str(j, JIT_R0, JIT_V1);
|
jit_str(j, JIT_R0, JIT_V1);
|
||||||
jit_str(j, JIT_R1, JIT_V2);
|
jit_str(j, JIT_R1, JIT_V2);
|
||||||
|
|
||||||
maybe_restore(j, JIT_V2);
|
jit_leave_jit_abi(j, 3, 0, align);
|
||||||
maybe_restore(j, JIT_V1);
|
|
||||||
maybe_restore(j, JIT_V0);
|
|
||||||
|
|
||||||
jit_ret(j);
|
jit_ret(j);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue