guile-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Guile-commits] 10/14: Always emit veneers for non-bl jumps to ARM code


From: Andy Wingo
Subject: [Guile-commits] 10/14: Always emit veneers for non-bl jumps to ARM code
Date: Fri, 12 Jun 2020 10:18:44 -0400 (EDT)

wingo pushed a commit to branch master
in repository guile.

commit 11b9d3744e963a121270712199bbfa7edb70d245
Author: Icecream95 <ixn@keemail.me>
AuthorDate: Thu Apr 9 22:10:15 2020 +1200

    Always emit veneers for non-bl jumps to ARM code
    
    It is unlikely for any ARM code to be close enough to not have needed
    a veneer, but it is possible, especially if running in a program with
    another JIT library.
---
 lightening/aarch64.c    |  4 ++--
 lightening/arm-cpu.c    | 26 ++++++++++++++++++--------
 lightening/lightening.c |  9 +++++----
 3 files changed, 25 insertions(+), 14 deletions(-)

diff --git a/lightening/aarch64.c b/lightening/aarch64.c
index b605cc5..2b3ed4d 100644
--- a/lightening/aarch64.c
+++ b/lightening/aarch64.c
@@ -90,9 +90,9 @@ DEFINE_ENCODER(size, 2, 22, unsigned, uint32_t)
   {                                                                     \
     return read_signed_bitfield(*loc, kind##_width, kind##_shift);      \
   }                                                                     \
-  static int offset_in_##name##_range(ptrdiff_t diff) maybe_unused;     \
+  static int offset_in_##name##_range(ptrdiff_t diff, int flags) maybe_unused; 
\
   static int                                                            \
-  offset_in_##name##_range(ptrdiff_t diff)                              \
+  offset_in_##name##_range(ptrdiff_t diff, int flags)                   \
   {                                                                     \
     return in_signed_range(diff, kind##_width);                         \
   }                                                                     \
diff --git a/lightening/arm-cpu.c b/lightening/arm-cpu.c
index 192c705..1bb7394 100644
--- a/lightening/arm-cpu.c
+++ b/lightening/arm-cpu.c
@@ -186,6 +186,8 @@
 
 #define _NOREG (jit_gpr_regno(_PC))
 
+#define JIT_RELOC_B JIT_RELOC_FLAG_0
+
 static void
 emit_wide_thumb(jit_state_t *_jit, uint32_t inst)
 {
@@ -265,9 +267,12 @@ write_wide_thumb(uint32_t *loc, uint32_t v)
 }
 
 static int
-offset_in_jmp_range(int32_t offset)
+offset_in_jmp_range(int32_t offset, int flags)
 {
-  return -0x1000000 <= offset && offset <= 0xffffff;
+  if (!(offset & 1) && flags | JIT_RELOC_B)
+    return 0;
+  else
+    return -0x1000000 <= offset && offset <= 0xffffff;
 }
 
 static int32_t
@@ -295,7 +300,7 @@ static const uint32_t thumb_jump_mask = 0xf800d000;
 static uint32_t
 encode_thumb_jump(int32_t v)
 {
-  ASSERT(offset_in_jmp_range(v));
+  ASSERT(offset_in_jmp_range(v, 0));
   v >>= 1;
   uint32_t s  = !!(v & 0x800000);
   uint32_t i1 = !!(v & 0x400000);
@@ -339,8 +344,10 @@ emit_thumb_jump(jit_state_t *_jit, uint32_t inst)
   while (1) {
     uint8_t *pc_base = _jit->pc.uc + 4;
     int32_t off = (uint8_t*)jit_address(_jit) - pc_base;
-    jit_reloc_t ret =
-      jit_reloc (_jit, JIT_RELOC_JMP_WITH_VENEER, 0, _jit->pc.uc, pc_base, 0);
+    enum jit_reloc_kind kind = JIT_RELOC_JMP_WITH_VENEER;
+    if (inst == THUMB2_B)
+      kind |= JIT_RELOC_B;
+    jit_reloc_t ret = jit_reloc (_jit, kind, 0, _jit->pc.uc, pc_base, 0);
     uint8_t thumb_jump_width = 24;
     if (add_pending_literal(_jit, ret, thumb_jump_width - 1)) {
       emit_wide_thumb(_jit, patch_thumb_jump(inst, off));
@@ -350,9 +357,12 @@ emit_thumb_jump(jit_state_t *_jit, uint32_t inst)
 }
 
 static int
-offset_in_jcc_range(int32_t v)
+offset_in_jcc_range(int32_t v, int flags)
 {
-  return -0x100000 <= v && v <= 0xfffff;
+  if (!(v & 1))
+    return 0;
+  else
+    return -0x100000 <= v && v <= 0xfffff;
 }
 
 static int32_t
@@ -378,7 +388,7 @@ static const uint32_t thumb_cc_jump_mask = 0xfbc0d000;
 static uint32_t
 encode_thumb_cc_jump(int32_t v)
 {
-  ASSERT(offset_in_jcc_range(v));
+  ASSERT(offset_in_jcc_range(v, 0));
   v >>= 1;
   uint32_t s  = !!(v & 0x80000);
   uint32_t j2 = !!(v & 0x40000);
diff --git a/lightening/lightening.c b/lightening/lightening.c
index 92e40c4..6620788 100644
--- a/lightening/lightening.c
+++ b/lightening/lightening.c
@@ -105,11 +105,11 @@ enum guard_pool { GUARD_NEEDED, NO_GUARD_NEEDED };
 static void emit_literal_pool(jit_state_t *_jit, enum guard_pool guard);
 
 static int32_t read_jmp_offset(uint32_t *loc);
-static int offset_in_jmp_range(ptrdiff_t offset);
+static int offset_in_jmp_range(ptrdiff_t offset, int flags);
 static void patch_jmp_offset(uint32_t *loc, ptrdiff_t offset);
 static void patch_veneer_jmp_offset(uint32_t *loc, ptrdiff_t offset);
 static int32_t read_jcc_offset(uint32_t *loc);
-static int offset_in_jcc_range(ptrdiff_t offset);
+static int offset_in_jcc_range(ptrdiff_t offset, int flags);
 static void patch_jcc_offset(uint32_t *loc, ptrdiff_t offset);
 static void patch_veneer_jcc_offset(uint32_t *loc, ptrdiff_t offset);
 static void patch_veneer(uint32_t *loc, jit_pointer_t addr);
@@ -380,6 +380,7 @@ jit_patch_there(jit_state_t* _jit, jit_reloc_t reloc, 
jit_pointer_t addr)
   ptrdiff_t diff = (uint8_t*)addr - pc_base;
   ASSERT((diff & ((1 << reloc.rsh) - 1)) == 0);
   diff >>= reloc.rsh;
+  int flags = reloc.kind & ~JIT_RELOC_MASK;
 
   switch (reloc.kind & JIT_RELOC_MASK)
     {
@@ -406,7 +407,7 @@ jit_patch_there(jit_state_t* _jit, jit_reloc_t reloc, 
jit_pointer_t addr)
       uint8_t *target = pc_base + (voff << reloc.rsh);
       if (target == loc.uc) {
         // PC still in range to reify direct branch.
-        if (offset_in_jmp_range(diff)) {
+        if (offset_in_jmp_range(diff, flags)) {
           // Target also in range: reify direct branch.
           patch_jmp_offset(loc.ui, diff);
           remove_pending_literal(_jit, reloc);
@@ -425,7 +426,7 @@ jit_patch_there(jit_state_t* _jit, jit_reloc_t reloc, 
jit_pointer_t addr)
       int32_t voff = read_jcc_offset(loc.ui);
       uint8_t *target = pc_base + (voff << reloc.rsh);
       if (target == loc.uc) {
-        if (offset_in_jcc_range(diff)) {
+        if (offset_in_jcc_range(diff, flags)) {
           patch_jcc_offset(loc.ui, diff);
           remove_pending_literal(_jit, reloc);
         } else {



reply via email to

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