[binutils-gdb] bfd: xtensa: fix callx relaxation

Max Filippov jcmvbkbc@sourceware.org
Wed Feb 20 10:52:00 GMT 2019


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=eed62915fd5b733632af343fbf3d47c7364f8e36

commit eed62915fd5b733632af343fbf3d47c7364f8e36
Author: Max Filippov <jcmvbkbc@gmail.com>
Date:   Fri Feb 15 16:43:23 2019 -0800

    bfd: xtensa: fix callx relaxation
    
    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.

Diff:
---
 bfd/ChangeLog                           |  6 ++++
 bfd/elf32-xtensa.c                      | 55 +++++++++++++++++++++++++++++++++
 ld/ChangeLog                            |  8 +++++
 ld/testsuite/ld-xtensa/call_overflow.d  |  7 +++++
 ld/testsuite/ld-xtensa/call_overflow1.s |  9 ++++++
 ld/testsuite/ld-xtensa/call_overflow2.s | 14 +++++++++
 ld/testsuite/ld-xtensa/call_overflow3.s |  5 +++
 ld/testsuite/ld-xtensa/xtensa.exp       |  1 +
 8 files changed, 105 insertions(+)

diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index c10f1a4..ce088c9 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -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.
diff --git a/bfd/elf32-xtensa.c b/bfd/elf32-xtensa.c
index edd9a0d..c3df3d6 100644
--- a/bfd/elf32-xtensa.c
+++ b/bfd/elf32-xtensa.c
@@ -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);
 
diff --git a/ld/ChangeLog b/ld/ChangeLog
index 508858f..0e00e41 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -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
index 0000000..9572848
--- /dev/null
+++ b/ld/testsuite/ld-xtensa/call_overflow.d
@@ -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
index 0000000..8b03289
--- /dev/null
+++ b/ld/testsuite/ld-xtensa/call_overflow1.s
@@ -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
index 0000000..c3f36fa
--- /dev/null
+++ b/ld/testsuite/ld-xtensa/call_overflow2.s
@@ -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
index 0000000..33f59d8
--- /dev/null
+++ b/ld/testsuite/ld-xtensa/call_overflow3.s
@@ -0,0 +1,5 @@
+	.text
+	.align 32
+	.global b
+b:
+	j	b
diff --git a/ld/testsuite/ld-xtensa/xtensa.exp b/ld/testsuite/ld-xtensa/xtensa.exp
index e8befa9..91b2314 100644
--- a/ld/testsuite/ld-xtensa/xtensa.exp
+++ b/ld/testsuite/ld-xtensa/xtensa.exp
@@ -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"



More information about the Binutils-cvs mailing list