bfd: xtensa: fix callx relaxation
authorMax Filippov <jcmvbkbc@gmail.com>
Sat, 16 Feb 2019 00:43:23 +0000 (16:43 -0800)
committerMax Filippov <jcmvbkbc@gmail.com>
Wed, 20 Feb 2019 10:51:01 +0000 (02:51 -0800)
Big section alignment requirements between source and destination of a
long call can result in making call range bigger than what's reachable
by the call opcode. Add biggest section alignment of sections between
the call site and call destination to the call distance when making
long call relaxation decision.

2019-02-20  Eric Tsai  <erictsai@cadence.com>
bfd/
* elf32-xtensa.c (is_resolvable_asm_expansion): Scan output
sections between the call site and call destination and adjust
call distance by the largest alignment.

ld/
* testsuite/ld-xtensa/call_overflow.d: New test definition.
* testsuite/ld-xtensa/call_overflow1.s: New test source.
* testsuite/ld-xtensa/call_overflow2.s: New test source.
* testsuite/ld-xtensa/call_overflow3.s: New test source.
* testsuite/ld-xtensa/xtensa.exp: Add call_overflow test.

bfd/ChangeLog
bfd/elf32-xtensa.c
ld/ChangeLog
ld/testsuite/ld-xtensa/call_overflow.d [new file with mode: 0644]
ld/testsuite/ld-xtensa/call_overflow1.s [new file with mode: 0644]
ld/testsuite/ld-xtensa/call_overflow2.s [new file with mode: 0644]
ld/testsuite/ld-xtensa/call_overflow3.s [new file with mode: 0644]
ld/testsuite/ld-xtensa/xtensa.exp

index c10f1a4f2be9f65bff5b446be663689aaac2d46f..ce088c96cdab1e82dc670bd0f24c2c763f2aece8 100644 (file)
@@ -1,3 +1,9 @@
+2019-02-20  Eric Tsai  <erictsai@cadence.com>
+
+       * elf32-xtensa.c (is_resolvable_asm_expansion): Scan output
+       sections between the call site and call destination and adjust
+       call distance by the largest alignment.
+
 2019-02-20  Alan Hayward  <alan.hayward@arm.com>
 
        * elf-bfd.h (elfcore_write_aarch_pauth): Add declaration.
index edd9a0d6d8354c2414d00abb1b0fa315ba0cdb36..c3df3d6db756eaeafb49bfb7a1439b73d77162b2 100644 (file)
@@ -7195,6 +7195,11 @@ is_resolvable_asm_expansion (bfd *abfd,
                             bfd_boolean *is_reachable_p)
 {
   asection *target_sec;
+  asection *s;
+  bfd_vma first_vma;
+  bfd_vma last_vma;
+  unsigned int first_align;
+  unsigned int adjust;
   bfd_vma target_offset;
   r_reloc r_rel;
   xtensa_opcode opcode, direct_call_opcode;
@@ -7283,6 +7288,56 @@ is_resolvable_asm_expansion (bfd *abfd,
                      + target_sec->output_offset + target_offset);
     }
 
+  /* Adjust addresses with alignments for the worst case to see if call insn
+     can fit.  Don't relax l32r + callx to call if the target can be out of
+     range due to alignment.
+     Caller and target addresses are highest and lowest address.
+     Search all sections between caller and target, looking for max alignment.
+     The adjustment is max alignment bytes.  If the alignment at the lowest
+     address is less than the adjustment, apply the adjustment to highest
+     address.  */
+
+  /* Start from lowest address.
+     Lowest address aligmnet is from input section.
+     Initial alignment (adjust) is from input section.  */
+  if (dest_address > self_address)
+    {
+      s = sec->output_section;
+      last_vma = dest_address;
+      first_align = sec->alignment_power;
+      adjust = target_sec->alignment_power;
+    }
+  else
+    {
+      s = target_sec->output_section;
+      last_vma = self_address;
+      first_align = target_sec->alignment_power;
+      adjust = sec->alignment_power;
+    }
+
+  first_vma = s->vma;
+
+  /* Find the largest alignment in output section list.  */
+  for (; s && s->vma >= first_vma && s->vma <= last_vma ; s = s->next)
+    {
+      if (s->alignment_power > adjust)
+       adjust = s->alignment_power;
+    }
+
+  if (adjust > first_align)
+    {
+      /* Alignment may enlarge the range, adjust highest address.  */
+      adjust = 1 << adjust;
+      if (dest_address > self_address)
+       {
+         dest_address += adjust;
+       }
+      else
+       {
+         self_address += adjust;
+       }
+    }
+
   *is_reachable_p = pcrel_reloc_fits (direct_call_opcode, 0,
                                      self_address, dest_address);
 
index 508858f2afa5c02c6607440a2e9acdde95db4829..0e00e41b920986a6edbdc60a96165eca35ae4800 100644 (file)
@@ -1,3 +1,11 @@
+2019-02-20  Eric Tsai  <erictsai@cadence.com>
+
+       * testsuite/ld-xtensa/call_overflow.d: New test definition.
+       * testsuite/ld-xtensa/call_overflow1.s: New test source.
+       * testsuite/ld-xtensa/call_overflow2.s: New test source.
+       * testsuite/ld-xtensa/call_overflow3.s: New test source.
+       * testsuite/ld-xtensa/xtensa.exp: Add call_overflow test.
+
 2019-02-14  Thomas Schwinge  <thomas@codesourcery.com>
 
        * testsuite/ld-elf/elf.exp: Remove Hurd XFAILs.
diff --git a/ld/testsuite/ld-xtensa/call_overflow.d b/ld/testsuite/ld-xtensa/call_overflow.d
new file mode 100644 (file)
index 0000000..9572848
--- /dev/null
@@ -0,0 +1,7 @@
+#source: call_overflow1.s
+#source: call_overflow2.s
+#source: call_overflow3.s
+#as: --longcalls
+#ld:
+#objdump: -d
+#...
diff --git a/ld/testsuite/ld-xtensa/call_overflow1.s b/ld/testsuite/ld-xtensa/call_overflow1.s
new file mode 100644 (file)
index 0000000..8b03289
--- /dev/null
@@ -0,0 +1,9 @@
+       .text
+       .global _start
+       .align 4
+_start:
+       call8   a
+       .rep    2051
+       nop.n
+       nop.n
+       .endr
diff --git a/ld/testsuite/ld-xtensa/call_overflow2.s b/ld/testsuite/ld-xtensa/call_overflow2.s
new file mode 100644 (file)
index 0000000..c3f36fa
--- /dev/null
@@ -0,0 +1,14 @@
+       .text
+       .global a
+       .align  4
+a:
+       j       a
+
+       .align  4
+x:
+       call8   b
+#29
+       .rep    131070
+       nop.n
+       nop.n
+       .endr
diff --git a/ld/testsuite/ld-xtensa/call_overflow3.s b/ld/testsuite/ld-xtensa/call_overflow3.s
new file mode 100644 (file)
index 0000000..33f59d8
--- /dev/null
@@ -0,0 +1,5 @@
+       .text
+       .align 32
+       .global b
+b:
+       j       b
index e8befa9c530fa5b363af6a89fc96cd041f66181c..91b23142b126dac7244813b16fbc0038a2e4f669 100644 (file)
@@ -23,6 +23,7 @@ if { !([istarget "xtensa*-*-*"]) } {
     return
 }
 
+run_dump_test "call_overflow"
 run_dump_test "coalesce"
 run_dump_test "diff_overflow"
 run_dump_test "lcall"