[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Guile-commits] 06/09: Add support for emitting inline data and table sw
From: |
Andy Wingo |
Subject: |
[Guile-commits] 06/09: Add support for emitting inline data and table switches |
Date: |
Thu, 30 Jul 2020 07:26:45 -0400 (EDT) |
wingo pushed a commit to branch master
in repository guile.
commit 91c1591e411d9ff3f0242d4157782190980adcf1
Author: Andy Wingo <wingo@igalia.com>
AuthorDate: Mon Jul 27 21:55:00 2020 +0200
Add support for emitting inline data and table switches
* lightening.h:
* lightening/lightening.c (jit_begin_data, jit_end_data)
(jit_emit_u8, jit_emit_u16, jit_emit_u32, jit_emit_u64): Add new raw
data-emitting primitives, bracketed by begin/end so that we can flush
constant pools first, if needed.
* lightening/lightening.c (struct jit_state): Add new emitting_data
flag.
(jit_begin, jit_reset, jit_end): Handle the new flag.
(emit_abs_reloc): Move here, from x86.c.
* lightening/x86.c (emit_abs_reloc): Remove.
(jit_try_shorten): Don't shorten if loc == start; could be raw data.
* tests/jmp_table.c: New test.
---
lightening.h | 11 +++++-
lightening/lightening.c | 90 +++++++++++++++++++++++++++++++++++++++++++++----
lightening/x86.c | 16 +++------
tests/jmp_table.c | 61 +++++++++++++++++++++++++++++++++
4 files changed, 158 insertions(+), 20 deletions(-)
diff --git a/lightening.h b/lightening.h
index 4749723..020c479 100644
--- a/lightening.h
+++ b/lightening.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2019 Free Software Foundation, Inc.
+ * Copyright (C) 2012-2020 Free Software Foundation, Inc.
*
* This file is part of GNU lightning.
*
@@ -661,4 +661,13 @@ FOR_EACH_INSTRUCTION(DECLARE_INSTRUCTION)
# define jit_truncr_f(j,u,v) jit_truncr_f_l(j,u,v)
#endif
+void jit_begin_data(jit_state_t *);
+void jit_end_data(jit_state_t *);
+void jit_emit_u8(jit_state_t *, uint8_t);
+void jit_emit_u16(jit_state_t *, uint16_t);
+void jit_emit_u32(jit_state_t *, uint32_t);
+void jit_emit_u64(jit_state_t *, uint64_t);
+void jit_emit_ptr(jit_state_t *, void *);
+jit_reloc_t jit_emit_addr(jit_state_t *);
+
#endif /* _jit_h */
diff --git a/lightening/lightening.c b/lightening/lightening.c
index 6948a81..775b2b6 100644
--- a/lightening/lightening.c
+++ b/lightening/lightening.c
@@ -74,6 +74,7 @@ struct jit_state
uint8_t temp_gpr_saved;
uint8_t temp_fpr_saved;
uint8_t overflow;
+ uint8_t emitting_data;
int frame_size; // Used to know when to align stack.
#ifdef JIT_NEEDS_LITERAL_POOL
struct jit_literal_pool *pool;
@@ -171,7 +172,8 @@ jit_pointer_t
jit_address(jit_state_t *_jit)
{
ASSERT (_jit->start);
- return jit_address_to_function_pointer (_jit->pc.uc);
+ jit_pointer_t ret = _jit->pc.uc;
+ return _jit->emitting_data ? ret : jit_address_to_function_pointer (ret);
}
void
@@ -183,6 +185,7 @@ jit_begin(jit_state_t *_jit, uint8_t* buf, size_t length)
_jit->limit = buf + length;
_jit->overflow = 0;
_jit->frame_size = 0;
+ _jit->emitting_data = 0;
#if JIT_NEEDS_LITERAL_POOL
ASSERT(_jit->pool->size == 0);
_jit->pool->deadline = length;
@@ -203,6 +206,7 @@ jit_reset(jit_state_t *_jit)
_jit->pc.uc = _jit->start = _jit->limit = NULL;
_jit->overflow = 0;
_jit->frame_size = 0;
+ _jit->emitting_data = 0;
#ifdef JIT_NEEDS_LITERAL_POOL
reset_literal_pool(_jit, _jit->pool);
#endif
@@ -228,9 +232,10 @@ jit_end(jit_state_t *_jit, size_t *length)
uint8_t *start = _jit->start;
uint8_t *end = _jit->pc.uc;
- ASSERT (start);
- ASSERT (start <= end);
- ASSERT (end <= _jit->limit);
+ ASSERT(start);
+ ASSERT(start <= end);
+ ASSERT(end <= _jit->limit);
+ ASSERT(!_jit->emitting_data);
jit_flush (start, end);
@@ -343,9 +348,9 @@ static inline void emit_u64(jit_state_t *_jit, uint64_t
u64) {
}
static inline jit_reloc_t
-jit_reloc (jit_state_t *_jit, enum jit_reloc_kind kind,
- uint8_t inst_start_offset, uint8_t *loc, uint8_t *pc_base,
- uint8_t rsh)
+jit_reloc(jit_state_t *_jit, enum jit_reloc_kind kind,
+ uint8_t inst_start_offset, uint8_t *loc, uint8_t *pc_base,
+ uint8_t rsh)
{
jit_reloc_t ret;
@@ -362,6 +367,17 @@ jit_reloc (jit_state_t *_jit, enum jit_reloc_kind kind,
return ret;
}
+static inline jit_reloc_t
+emit_abs_reloc (jit_state_t *_jit, uint8_t inst_start)
+{
+ uint8_t *loc = _jit->pc.uc;
+ if (sizeof(intptr_t) == 4)
+ emit_u32 (_jit, 0);
+ else
+ emit_u64 (_jit, 0);
+ return jit_reloc(_jit, JIT_RELOC_ABSOLUTE, inst_start, loc, _jit->pc.uc, 0);
+}
+
void
jit_patch_here(jit_state_t *_jit, jit_reloc_t reloc)
{
@@ -467,6 +483,66 @@ jit_patch_there(jit_state_t* _jit, jit_reloc_t reloc,
jit_pointer_t addr)
jit_try_shorten (_jit, reloc, addr);
}
+void
+jit_begin_data(jit_state_t *j)
+{
+#ifdef JIT_NEEDS_LITERAL_POOL
+ if (j->pool->size)
+ emit_literal_pool(j, NO_GUARD_NEEDED);
+ ASSERT(j->overflow || j->pool->size == 0);
+#endif
+
+ ASSERT(!j->emitting_data);
+ j->emitting_data = 1;
+}
+
+void
+jit_end_data(jit_state_t *j)
+{
+#ifdef JIT_NEEDS_LITERAL_POOL
+ ASSERT(j->overflow || j->pool->size == 0);
+#endif
+
+ ASSERT(j->emitting_data);
+ j->emitting_data = 0;
+}
+
+void
+jit_emit_u8(jit_state_t *j, uint8_t u8)
+{
+ ASSERT(j->emitting_data);
+ emit_u8(j, u8);
+}
+
+void
+jit_emit_u16(jit_state_t *j, uint16_t u16)
+{
+ ASSERT(j->emitting_data);
+ emit_u16(j, u16);
+}
+
+void
+jit_emit_u32(jit_state_t *j, uint32_t u32)
+{
+ ASSERT(j->emitting_data);
+ emit_u32(j, u32);
+}
+
+void
+jit_emit_u64(jit_state_t *j, uint64_t u64)
+{
+ ASSERT(j->emitting_data);
+ emit_u64(j, u64);
+}
+
+jit_reloc_t
+jit_emit_addr(jit_state_t *j)
+{
+ ASSERT(j->emitting_data);
+ uint8_t inst_start = 0;
+ return emit_abs_reloc(j, inst_start);
+}
+
#if defined(__i386__) || defined(__x86_64__)
# include "x86.c"
#elif defined(__mips__)
diff --git a/lightening/x86.c b/lightening/x86.c
index bdd26e1..5d75eb0 100644
--- a/lightening/x86.c
+++ b/lightening/x86.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2019 Free Software Foundation, Inc.
+ * Copyright (C) 2012-2020 Free Software Foundation, Inc.
*
* This file is part of GNU lightning.
*
@@ -76,17 +76,6 @@ emit_rel32_reloc (jit_state_t *_jit, uint8_t inst_start)
return jit_reloc(_jit, JIT_RELOC_REL32, inst_start, loc, _jit->pc.uc, 0);
}
-static inline jit_reloc_t
-emit_abs_reloc (jit_state_t *_jit, uint8_t inst_start)
-{
- uint8_t *loc = _jit->pc.uc;
- if (sizeof(intptr_t) == 4)
- emit_u32 (_jit, 0);
- else
- emit_u64 (_jit, 0);
- return jit_reloc(_jit, JIT_RELOC_ABSOLUTE, inst_start, loc, _jit->pc.uc, 0);
-}
-
#include "x86-cpu.c"
#include "x86-sse.c"
@@ -375,6 +364,9 @@ jit_try_shorten(jit_state_t *_jit, jit_reloc_t reloc,
jit_pointer_t addr)
uint8_t *start = loc - reloc.inst_start_offset;
jit_imm_t i0 = (jit_imm_t)addr;
+ if (loc == start)
+ return;
+
switch (reloc.kind)
{
case JIT_RELOC_ABSOLUTE: {
diff --git a/tests/jmp_table.c b/tests/jmp_table.c
new file mode 100644
index 0000000..6d86b65
--- /dev/null
+++ b/tests/jmp_table.c
@@ -0,0 +1,61 @@
+#include "test.h"
+
+#define NTARGETS ((size_t) 4)
+
+static void
+run_test(jit_state_t *j, uint8_t *arena_base, size_t arena_size)
+{
+ jit_begin(j, arena_base, arena_size);
+ size_t align = jit_enter_jit_abi(j, 0, 0, 0);
+ jit_load_args_1(j, jit_operand_gpr (JIT_OPERAND_ABI_POINTER, JIT_R0));
+
+ jit_reloc_t default_target = jit_bgei_u(j, JIT_R0, NTARGETS);
+
+ // FIXME: need ldxr with word stride, then can eliminate lshi.
+ jit_lshi(j, JIT_R0, JIT_R0, sizeof(intptr_t) == 4 ? 2 : 3);
+ jit_reloc_t table = jit_mov_addr(j, JIT_R1);
+ jit_ldxr(j, JIT_R1, JIT_R1, JIT_R0);
+ jit_jmpr(j, JIT_R1);
+
+ jit_begin_data (j);
+ jit_align(j, sizeof(intptr_t));
+ jit_patch_here(j, table);
+ jit_reloc_t targets[NTARGETS];
+ jit_reloc_t tails[NTARGETS];
+ for (size_t i = 0; i < NTARGETS; i++) {
+ targets[i] = jit_emit_addr(j);
+ }
+ jit_end_data (j);
+
+ for (size_t i = 0; i < NTARGETS; i++) {
+ jit_patch_here(j, targets[i]);
+ jit_movi(j, JIT_R0, i * i);
+ tails[i] = jit_jmp(j);
+ }
+
+ jit_patch_here(j, default_target);
+ jit_movi(j, JIT_R0, 42);
+ for (int i = 0; i < NTARGETS; i++) {
+ jit_patch_here(j, tails[i]);
+ }
+ jit_leave_jit_abi(j, 0, 0, align);
+ jit_retr(j, JIT_R0);
+
+ jit_word_t (*f)(jit_word_t) = jit_end(j, NULL);
+
+ for (int i = -2; i < ((int) NTARGETS) + 2; i++) {
+ if (i < 0) {
+ ASSERT(f(i) == 42);
+ } else if (i < NTARGETS) {
+ ASSERT(f(i) == i * i);
+ } else {
+ ASSERT(f(i) == 42);
+ }
+ }
+}
+
+int
+main (int argc, char *argv[])
+{
+ return main_helper(argc, argv, run_test);
+}
- [Guile-commits] branch master updated (5e1748f -> 5342eb5), Andy Wingo, 2020/07/30
- [Guile-commits] 01/09: Add jtable instruction, Andy Wingo, 2020/07/30
- [Guile-commits] 02/09: Fix patch_veneer on aarch64, Andy Wingo, 2020/07/30
- [Guile-commits] 04/09: Ensure tail caller and callee in jmpi test have compatible ABI, Andy Wingo, 2020/07/30
- [Guile-commits] 03/09: Merge branch 'fix-aarch64-veneers' into 'master', Andy Wingo, 2020/07/30
- [Guile-commits] 06/09: Add support for emitting inline data and table switches,
Andy Wingo <=
- [Guile-commits] 07/09: Merge branch 'table-switch' into 'master', Andy Wingo, 2020/07/30
- [Guile-commits] 05/09: Merge branch 'fix-tail-call-test' into 'master', Andy Wingo, 2020/07/30
- [Guile-commits] 08/09: Merge https://gitlab.com/wingo/lightening master branch, Andy Wingo, 2020/07/30
- [Guile-commits] 09/09: Add JIT implementation for jtable, Andy Wingo, 2020/07/30