guile-commits
[Top][All Lists]
Advanced

[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);
+}



reply via email to

[Prev in Thread] Current Thread [Next in Thread]