1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-05-30 17:00:23 +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:
Andy Wingo 2019-04-26 17:26:03 +02:00
parent 9906cd5f84
commit 42bc762d26
8 changed files with 113 additions and 85 deletions

View file

@ -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 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
as scratch space while shuffling values into position. */
JIT_API void jit_calli(jit_state_t *, jit_pointer_t f,

View file

@ -863,6 +863,104 @@ jit_shrink_stack(jit_state_t *_jit, size_t 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.
static size_t
prepare_call_args(jit_state_t *_jit, size_t argc, jit_operand_t args[])

View file

@ -273,8 +273,7 @@ get_temp_gpr(jit_state_t *_jit)
#ifdef JIT_RTMP
return JIT_RTMP;
#else
pushr(_jit, _RBP_REGNO);
return _RBP;
return JIT_VTMP;
#endif
}
@ -283,9 +282,6 @@ unget_temp_gpr(jit_state_t *_jit)
{
ASSERT(_jit->temp_gpr_saved);
_jit->temp_gpr_saved = 0;
#ifndef JIT_RTMP
popr(_jit, _RBP_REGNO);
#endif
}
static void

View file

@ -133,6 +133,7 @@ jit_fpr_is_callee_save (jit_fpr_t reg)
# define JIT_V0 _RBX
# define JIT_V1 _RSI
# define JIT_V2 _RDI
# define JIT_VTMP _RBP
# define JIT_F0 _XMM0
# define JIT_F1 _XMM1
# define JIT_F2 _XMM2

View file

@ -1,26 +1,10 @@
#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
run_test(jit_state_t *j, uint8_t *arena_base, size_t arena_size)
{
jit_begin(j, arena_base, arena_size);
maybe_save(j, JIT_V0);
maybe_save(j, JIT_V1);
maybe_save(j, JIT_V2);
size_t align = jit_enter_jit_abi(j, 3, 0, 0);
jit_operand_t args[] =
{ 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_R1, JIT_V2);
maybe_restore(j, JIT_V2);
maybe_restore(j, JIT_V1);
maybe_restore(j, JIT_V0);
jit_leave_jit_abi(j, 3, 0, align);
jit_ret(j);

View file

@ -1,27 +1,11 @@
#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
run_test(jit_state_t *j, uint8_t *arena_base, size_t arena_size)
{
jit_begin(j, arena_base, arena_size);
maybe_save(j, JIT_V0);
maybe_save(j, JIT_V1);
maybe_save(j, JIT_V2);
size_t align = jit_enter_jit_abi(j, 3, 0, 0);
jit_operand_t args[] =
{ 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_R1, JIT_V2);
maybe_restore(j, JIT_V2);
maybe_restore(j, JIT_V1);
maybe_restore(j, JIT_V0);
jit_leave_jit_abi(j, 3, 0, align);
jit_ret(j);

View file

@ -1,27 +1,11 @@
#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
run_test(jit_state_t *j, uint8_t *arena_base, size_t arena_size)
{
jit_begin(j, arena_base, arena_size);
maybe_save(j, JIT_V0);
maybe_save(j, JIT_V1);
maybe_save(j, JIT_V2);
size_t align = jit_enter_jit_abi(j, 3, 0, 0);
jit_operand_t args[] =
{ 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_R1, JIT_V2);
maybe_restore(j, JIT_V2);
maybe_restore(j, JIT_V1);
maybe_restore(j, JIT_V0);
jit_leave_jit_abi(j, 3, 0, align);
jit_ret(j);

View file

@ -1,27 +1,11 @@
#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
run_test(jit_state_t *j, uint8_t *arena_base, size_t arena_size)
{
jit_begin(j, arena_base, arena_size);
maybe_save(j, JIT_V0);
maybe_save(j, JIT_V1);
maybe_save(j, JIT_V2);
size_t align = jit_enter_jit_abi(j, 3, 0, 0);
jit_operand_t args[] =
{ 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_R1, JIT_V2);
maybe_restore(j, JIT_V2);
maybe_restore(j, JIT_V1);
maybe_restore(j, JIT_V0);
jit_leave_jit_abi(j, 3, 0, align);
jit_ret(j);