This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[PATCH] bfd: xtensa: fix callx relaxation
- From: Max Filippov <jcmvbkbc at gmail dot com>
- To: binutils at sourceware dot org
- Cc: Sterling Augustine <augustine dot sterling at gmail dot com>, Eric Tsai <erictsai at cadence dot com>, linux-xtensa at linux-xtensa dot org, Max Filippov <jcmvbkbc at gmail dot com>
- Date: Tue, 19 Feb 2019 19:50:11 -0800
- Subject: [PATCH] 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-19 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/elf32-xtensa.c | 55 +++++++++++++++++++++++++++++++++
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 +
6 files changed, 91 insertions(+)
create mode 100644 ld/testsuite/ld-xtensa/call_overflow.d
create mode 100644 ld/testsuite/ld-xtensa/call_overflow1.s
create mode 100644 ld/testsuite/ld-xtensa/call_overflow2.s
create mode 100644 ld/testsuite/ld-xtensa/call_overflow3.s
diff --git a/bfd/elf32-xtensa.c b/bfd/elf32-xtensa.c
index edd9a0d6d835..c3df3d6db756 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/testsuite/ld-xtensa/call_overflow.d b/ld/testsuite/ld-xtensa/call_overflow.d
new file mode 100644
index 000000000000..95728488567f
--- /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 000000000000..8b032892e20f
--- /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 000000000000..588b3d9fa4aa
--- /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 000000000000..33f59d8bc0bb
--- /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 e8befa9c530f..91b23142b126 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"
--
2.11.0