mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-04-30 20:00:19 +02:00
Implement reloc shortening, and remove unused functionality
This commit is contained in:
parent
796f263ed8
commit
04d89a7ce2
4 changed files with 79 additions and 103 deletions
|
@ -78,7 +78,6 @@ typedef struct jit_reloc
|
||||||
{
|
{
|
||||||
uint8_t kind;
|
uint8_t kind;
|
||||||
uint8_t inst_start_offset;
|
uint8_t inst_start_offset;
|
||||||
uint16_t flags;
|
|
||||||
uint32_t offset;
|
uint32_t offset;
|
||||||
} jit_reloc_t;
|
} jit_reloc_t;
|
||||||
|
|
||||||
|
|
|
@ -124,11 +124,6 @@ struct jit_state
|
||||||
void (*free)(void*);
|
void (*free)(void*);
|
||||||
};
|
};
|
||||||
|
|
||||||
enum jit_reloc_flags
|
|
||||||
{
|
|
||||||
JIT_RELOC_CAN_SHORTEN = 1<<0
|
|
||||||
};
|
|
||||||
|
|
||||||
#define ASSERT(x) do { if (!(x)) abort(); } while (0)
|
#define ASSERT(x) do { if (!(x)) abort(); } while (0)
|
||||||
#if defined(__GNUC__)
|
#if defined(__GNUC__)
|
||||||
# define UNLIKELY(exprn) __builtin_expect(exprn, 0)
|
# define UNLIKELY(exprn) __builtin_expect(exprn, 0)
|
||||||
|
@ -139,7 +134,8 @@ enum jit_reloc_flags
|
||||||
static jit_bool_t jit_get_cpu(void);
|
static jit_bool_t jit_get_cpu(void);
|
||||||
static jit_bool_t jit_init(jit_state_t *);
|
static jit_bool_t jit_init(jit_state_t *);
|
||||||
static void jit_flush(void *fptr, void *tptr);
|
static void jit_flush(void *fptr, void *tptr);
|
||||||
static void jit_try_shorten(jit_state_t *_jit, jit_reloc_t reloc);
|
static void jit_try_shorten(jit_state_t *_jit, jit_reloc_t reloc,
|
||||||
|
jit_pointer_t addr);
|
||||||
|
|
||||||
jit_bool_t
|
jit_bool_t
|
||||||
init_jit(void)
|
init_jit(void)
|
||||||
|
@ -283,13 +279,12 @@ static inline void emit_u64(jit_state_t *_jit, uint64_t u64) {
|
||||||
|
|
||||||
static inline jit_reloc_t
|
static inline jit_reloc_t
|
||||||
jit_reloc (jit_state_t *_jit, enum jit_reloc_kind kind,
|
jit_reloc (jit_state_t *_jit, enum jit_reloc_kind kind,
|
||||||
uint8_t inst_start_offset, uint16_t flags)
|
uint8_t inst_start_offset)
|
||||||
{
|
{
|
||||||
jit_reloc_t ret;
|
jit_reloc_t ret;
|
||||||
|
|
||||||
ret.kind = kind;
|
ret.kind = kind;
|
||||||
ret.inst_start_offset = inst_start_offset;
|
ret.inst_start_offset = inst_start_offset;
|
||||||
ret.flags = 0;
|
|
||||||
ret.offset = _jit->pc.uc - _jit->start;
|
ret.offset = _jit->pc.uc - _jit->start;
|
||||||
|
|
||||||
switch (kind)
|
switch (kind)
|
||||||
|
@ -331,6 +326,7 @@ jit_patch_there(jit_state_t* _jit, jit_reloc_t reloc, jit_pointer_t addr)
|
||||||
if (_jit->overflow)
|
if (_jit->overflow)
|
||||||
return;
|
return;
|
||||||
union jit_pc loc;
|
union jit_pc loc;
|
||||||
|
uint8_t *end;
|
||||||
loc.uc = _jit->start + reloc.offset;
|
loc.uc = _jit->start + reloc.offset;
|
||||||
ptrdiff_t diff;
|
ptrdiff_t diff;
|
||||||
|
|
||||||
|
@ -341,38 +337,37 @@ jit_patch_there(jit_state_t* _jit, jit_reloc_t reloc, jit_pointer_t addr)
|
||||||
*loc.ui = (uintptr_t)addr;
|
*loc.ui = (uintptr_t)addr;
|
||||||
else
|
else
|
||||||
*loc.ul = (uintptr_t)addr;
|
*loc.ul = (uintptr_t)addr;
|
||||||
if (loc.uc + sizeof(diff) == _jit->pc.uc &&
|
end = loc.uc + sizeof(diff);
|
||||||
(reloc.flags & JIT_RELOC_CAN_SHORTEN))
|
|
||||||
jit_try_shorten (_jit, reloc);
|
|
||||||
break;
|
break;
|
||||||
case JIT_RELOC_REL8:
|
case JIT_RELOC_REL8:
|
||||||
diff = ((uint8_t*)addr) - (loc.uc + 1);
|
diff = ((uint8_t*)addr) - (loc.uc + 1);
|
||||||
ASSERT (INT8_MIN <= diff && diff <= INT8_MAX);
|
ASSERT (INT8_MIN <= diff && diff <= INT8_MAX);
|
||||||
*loc.uc = diff;
|
*loc.uc = diff;
|
||||||
|
end = loc.uc + 1;
|
||||||
break;
|
break;
|
||||||
case JIT_RELOC_REL16:
|
case JIT_RELOC_REL16:
|
||||||
diff = ((uint8_t*)addr) - (loc.uc + 2);
|
diff = ((uint8_t*)addr) - (loc.uc + 2);
|
||||||
ASSERT (INT16_MIN <= diff && diff <= INT16_MAX);
|
ASSERT (INT16_MIN <= diff && diff <= INT16_MAX);
|
||||||
*loc.us = diff;
|
*loc.us = diff;
|
||||||
if ((loc.uc + 1) == _jit->pc.uc && (reloc.flags & JIT_RELOC_CAN_SHORTEN))
|
end = loc.uc + 2;
|
||||||
jit_try_shorten (_jit, reloc);
|
|
||||||
break;
|
break;
|
||||||
case JIT_RELOC_REL32:
|
case JIT_RELOC_REL32:
|
||||||
diff = ((uint8_t*)addr) - (loc.uc + 4);
|
diff = ((uint8_t*)addr) - (loc.uc + 4);
|
||||||
ASSERT (INT32_MIN <= diff && diff <= INT32_MAX);
|
ASSERT (INT32_MIN <= diff && diff <= INT32_MAX);
|
||||||
*loc.ui = diff;
|
*loc.ui = diff;
|
||||||
if ((loc.ui + 1) == _jit->pc.ui && (reloc.flags & JIT_RELOC_CAN_SHORTEN))
|
end = loc.uc + 4;
|
||||||
jit_try_shorten (_jit, reloc);
|
|
||||||
break;
|
break;
|
||||||
case JIT_RELOC_REL64:
|
case JIT_RELOC_REL64:
|
||||||
diff = ((uint8_t*)addr) - (loc.uc + 8);
|
diff = ((uint8_t*)addr) - (loc.uc + 8);
|
||||||
*loc.ul = diff;
|
*loc.ul = diff;
|
||||||
if ((loc.ul + 1) == _jit->pc.ul && (reloc.flags & JIT_RELOC_CAN_SHORTEN))
|
end = loc.uc + 8;
|
||||||
jit_try_shorten (_jit, reloc);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
abort ();
|
abort ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (end == _jit->pc.uc)
|
||||||
|
jit_try_shorten (_jit, reloc, addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(__i386__) || defined(__x86_64__)
|
#if defined(__i386__) || defined(__x86_64__)
|
||||||
|
|
|
@ -403,7 +403,7 @@ mov_addr(jit_state_t *_jit, int32_t r0)
|
||||||
rex(_jit, 0, WIDE, _NOREG, _NOREG, r0);
|
rex(_jit, 0, WIDE, _NOREG, _NOREG, r0);
|
||||||
ic(_jit, 0xb8 | r7(r0));
|
ic(_jit, 0xb8 | r7(r0));
|
||||||
ptrdiff_t inst_start = _jit->pc.uc - pc_start;
|
ptrdiff_t inst_start = _jit->pc.uc - pc_start;
|
||||||
return jit_reloc(_jit, JIT_RELOC_ABSOLUTE, inst_start, 0);
|
return jit_reloc(_jit, JIT_RELOC_ABSOLUTE, inst_start);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -659,15 +659,6 @@ testi(jit_state_t *_jit, int32_t r0, jit_word_t i0)
|
||||||
ii(_jit, i0);
|
ii(_jit, i0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
cc(jit_state_t *_jit, int32_t code, int32_t r0)
|
|
||||||
{
|
|
||||||
rex(_jit, 0, 0, _NOREG, _NOREG, r0);
|
|
||||||
ic(_jit, 0x0f);
|
|
||||||
ic(_jit, 0x90 | code);
|
|
||||||
mrm(_jit, 0x03, 0x00, r7(r0));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
negr(jit_state_t *_jit, int32_t r0, int32_t r1)
|
negr(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||||
{
|
{
|
||||||
|
@ -1465,69 +1456,6 @@ xori(jit_state_t *_jit, int32_t r0, int32_t r1, jit_word_t i0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
cr(jit_state_t *_jit, int32_t code, int32_t r0, int32_t r1, int32_t r2)
|
|
||||||
{
|
|
||||||
if (reg8_p(r0)) {
|
|
||||||
jit_bool_t same = r0 == r1 || r0 == r2;
|
|
||||||
if (!same)
|
|
||||||
ixorr(_jit, r0, r0);
|
|
||||||
icmpr(_jit, r1, r2);
|
|
||||||
if (same)
|
|
||||||
imovi(_jit, r0, 0);
|
|
||||||
cc(_jit, code, r0);
|
|
||||||
} else {
|
|
||||||
jit_gpr_t reg = get_temp_gpr(_jit);
|
|
||||||
ixorr(_jit, jit_gpr_regno(reg), jit_gpr_regno(reg));
|
|
||||||
icmpr(_jit, r1, r2);
|
|
||||||
cc(_jit, code, jit_gpr_regno(reg));
|
|
||||||
movr(_jit, r0, jit_gpr_regno(reg));
|
|
||||||
unget_temp_gpr(_jit);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
ci(jit_state_t *_jit, int32_t code, int32_t r0, int32_t r1, jit_word_t i0)
|
|
||||||
{
|
|
||||||
if (reg8_p(r0)) {
|
|
||||||
jit_bool_t same = r0 == r1;
|
|
||||||
if (!same)
|
|
||||||
ixorr(_jit, r0, r0);
|
|
||||||
icmpi(_jit, r1, i0);
|
|
||||||
if (same)
|
|
||||||
imovi(_jit, r0, 0);
|
|
||||||
cc(_jit, code, r0);
|
|
||||||
} else {
|
|
||||||
jit_gpr_t reg = get_temp_gpr(_jit);
|
|
||||||
ixorr(_jit, jit_gpr_regno(reg), jit_gpr_regno(reg));
|
|
||||||
icmpi(_jit, r1, i0);
|
|
||||||
cc(_jit, code, jit_gpr_regno(reg));
|
|
||||||
movr(_jit, r0, jit_gpr_regno(reg));
|
|
||||||
unget_temp_gpr(_jit);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
ci0(jit_state_t *_jit, int32_t code, int32_t r0, int32_t r1)
|
|
||||||
{
|
|
||||||
if (reg8_p(r0)) {
|
|
||||||
jit_bool_t same = r0 == r1;
|
|
||||||
if (!same)
|
|
||||||
ixorr(_jit, r0, r0);
|
|
||||||
testr(_jit, r1, r1);
|
|
||||||
if (same)
|
|
||||||
imovi(_jit, r0, 0);
|
|
||||||
cc(_jit, code, r0);
|
|
||||||
} else {
|
|
||||||
jit_gpr_t reg = get_temp_gpr(_jit);
|
|
||||||
ixorr(_jit, jit_gpr_regno(reg), jit_gpr_regno(reg));
|
|
||||||
testr(_jit, r1, r1);
|
|
||||||
cc(_jit, code, jit_gpr_regno(reg));
|
|
||||||
movr(_jit, r0, jit_gpr_regno(reg));
|
|
||||||
unget_temp_gpr(_jit);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
extr_c(jit_state_t *_jit, int32_t r0, int32_t r1)
|
extr_c(jit_state_t *_jit, int32_t r0, int32_t r1)
|
||||||
{
|
{
|
||||||
|
@ -2255,7 +2183,7 @@ static jit_reloc_t
|
||||||
jccs(jit_state_t *_jit, int32_t code)
|
jccs(jit_state_t *_jit, int32_t code)
|
||||||
{
|
{
|
||||||
ic(_jit, 0x70 | code);
|
ic(_jit, 0x70 | code);
|
||||||
return jit_reloc(_jit, JIT_RELOC_REL8, 1, 0);
|
return jit_reloc(_jit, JIT_RELOC_REL8, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static jit_reloc_t
|
static jit_reloc_t
|
||||||
|
@ -2263,7 +2191,26 @@ jcc(jit_state_t *_jit, int32_t code)
|
||||||
{
|
{
|
||||||
ic(_jit, 0x0f);
|
ic(_jit, 0x0f);
|
||||||
ic(_jit, 0x80 | code);
|
ic(_jit, 0x80 | code);
|
||||||
return jit_reloc(_jit, JIT_RELOC_REL32, 2, 0);
|
return jit_reloc(_jit, JIT_RELOC_REL32, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
jcci(jit_state_t *_jit, int32_t code, jit_word_t i0)
|
||||||
|
{
|
||||||
|
ptrdiff_t rel8 = i0 - (_jit->pc.w + 1 + 1);
|
||||||
|
ptrdiff_t rel32 = i0 - (_jit->pc.w + 2 + 4);
|
||||||
|
if (INT8_MIN <= rel8 && rel8 <= INT8_MAX)
|
||||||
|
{
|
||||||
|
ic(_jit, 0x70 | code);
|
||||||
|
ic(_jit, rel8);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ASSERT(INT32_MIN <= rel32 && rel32 <= INT32_MAX);
|
||||||
|
ic(_jit, 0x0f);
|
||||||
|
ic(_jit, 0x80 | code);
|
||||||
|
ii(_jit, rel32);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DEFINE_JUMPS(cc, CC, code) \
|
#define DEFINE_JUMPS(cc, CC, code) \
|
||||||
|
@ -2666,8 +2613,14 @@ jmpr(jit_state_t *_jit, int32_t r0)
|
||||||
static void
|
static void
|
||||||
jmpi(jit_state_t *_jit, jit_word_t i0)
|
jmpi(jit_state_t *_jit, jit_word_t i0)
|
||||||
{
|
{
|
||||||
|
ptrdiff_t rel8 = i0 - (_jit->pc.w + 1 + 1);
|
||||||
ptrdiff_t rel32 = i0 - (_jit->pc.w + 1 + 4);
|
ptrdiff_t rel32 = i0 - (_jit->pc.w + 1 + 4);
|
||||||
if (INT32_MIN <= rel32 && rel32 <= INT32_MAX)
|
if (INT8_MIN <= rel8 && rel8 <= INT8_MAX)
|
||||||
|
{
|
||||||
|
ic(_jit, 0xeb);
|
||||||
|
ic(_jit, rel8);
|
||||||
|
}
|
||||||
|
else if (INT32_MIN <= rel32 && rel32 <= INT32_MAX)
|
||||||
{
|
{
|
||||||
ic(_jit, 0xe9);
|
ic(_jit, 0xe9);
|
||||||
ii(_jit, rel32);
|
ii(_jit, rel32);
|
||||||
|
@ -2685,14 +2638,7 @@ static jit_reloc_t
|
||||||
jmp(jit_state_t *_jit)
|
jmp(jit_state_t *_jit)
|
||||||
{
|
{
|
||||||
ic(_jit, 0xe9);
|
ic(_jit, 0xe9);
|
||||||
return jit_reloc(_jit, JIT_RELOC_REL32, 1, 0);
|
return jit_reloc(_jit, JIT_RELOC_REL32, 1);
|
||||||
}
|
|
||||||
|
|
||||||
static jit_reloc_t
|
|
||||||
jmpsi(jit_state_t *_jit)
|
|
||||||
{
|
|
||||||
ic(_jit, 0xeb);
|
|
||||||
return jit_reloc(_jit, JIT_RELOC_REL8, 1, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|
|
@ -351,6 +351,42 @@ jit_flush(void *fptr, void *tptr)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
jit_try_shorten(jit_state_t *_jit, jit_reloc_t reloc)
|
jit_try_shorten(jit_state_t *_jit, jit_reloc_t reloc, jit_pointer_t addr)
|
||||||
{
|
{
|
||||||
|
uint8_t *loc = _jit->start + reloc.offset;
|
||||||
|
uint8_t *start = loc - reloc.inst_start_offset;
|
||||||
|
jit_imm_t i0 = (jit_imm_t)addr;
|
||||||
|
|
||||||
|
switch (reloc.kind)
|
||||||
|
{
|
||||||
|
case JIT_RELOC_ABSOLUTE: {
|
||||||
|
_jit->pc.uc = start;
|
||||||
|
ASSERT((loc[-1] & ~7) == 0xb8); // MOVI
|
||||||
|
int32_t r0 = loc[-1] & 7;
|
||||||
|
if (start != loc - 1) {
|
||||||
|
ASSERT(start == loc - 2);
|
||||||
|
r0 |= (loc[-2] & 1) << 3;
|
||||||
|
}
|
||||||
|
return movi(_jit, r0, i0);
|
||||||
|
}
|
||||||
|
case JIT_RELOC_REL8:
|
||||||
|
ASSERT((loc[-1] & ~0xf) == 0x70 || loc[-1] == 0xeb); // JCCSI or JMPSI
|
||||||
|
/* Nothing useful to do. */
|
||||||
|
return;
|
||||||
|
case JIT_RELOC_REL16:
|
||||||
|
/* We don't emit these. */
|
||||||
|
abort ();
|
||||||
|
case JIT_RELOC_REL32:
|
||||||
|
_jit->pc.uc = start;
|
||||||
|
if (start[0] == 0xe9) { // JMP
|
||||||
|
return jmpi(_jit, i0);
|
||||||
|
}
|
||||||
|
ASSERT(start[0] == 0x0f); // JCC
|
||||||
|
return jcci(_jit, start[1] & ~0x80, i0);
|
||||||
|
case JIT_RELOC_REL64:
|
||||||
|
/* We don't emit these. */
|
||||||
|
abort ();
|
||||||
|
default:
|
||||||
|
abort ();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue