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:
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 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,
|
||||
|
|
|
@ -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[])
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue