gas: xtensa: fix incorrect code generated with auto litpools
authorMax Filippov <jcmvbkbc@gmail.com>
Mon, 10 Apr 2017 12:12:52 +0000 (13:12 +0100)
committerNick Clifton <nickc@redhat.com>
Mon, 10 Apr 2017 12:12:52 +0000 (13:12 +0100)
* config/tc-xtensa.c (xtensa_maybe_create_literal_pool_frag):
Initialize lps->frag_count with auto_litpool_limit.
(xg_promote_candidate_litpool): New function.
(xtensa_move_literals): Extract candidate litpool promotion code
into separate function. Call it for all possible found
candidates.
(xtensa_switch_to_literal_fragment): Drop 'recursive' flag and
call to xtensa_mark_literal_pool_location that it guards.
Replace it with call to xtensa_maybe_create_literal_pool_frag.
Initialize pool_location with created literal pool candidate.
* testsuite/gas/xtensa/all.exp: Add new tests.
* testsuite/gas/xtensa/auto-litpools-first1.d: New test results.
* testsuite/gas/xtensa/auto-litpools-first1.s: New test.
* testsuite/gas/xtensa/auto-litpools-first2.d: New test results.
* testsuite/gas/xtensa/auto-litpools-first2.s: New test.
* testsuite/gas/xtensa/auto-litpools.d: Fix offsets changed due
to additional jump instruction.

gas/ChangeLog
gas/config/tc-xtensa.c
gas/testsuite/gas/xtensa/all.exp
gas/testsuite/gas/xtensa/auto-litpools-first1.d [new file with mode: 0644]
gas/testsuite/gas/xtensa/auto-litpools-first1.s [new file with mode: 0644]
gas/testsuite/gas/xtensa/auto-litpools-first2.d [new file with mode: 0644]
gas/testsuite/gas/xtensa/auto-litpools-first2.s [new file with mode: 0644]
gas/testsuite/gas/xtensa/auto-litpools.d

index ff9fca3ed5c7c51c727461b330d9fe40d503f2bc..f7a8628ce394ceb627608b1bdd9fa2a9f6aca129 100644 (file)
@@ -1,3 +1,23 @@
+2017-04-10  Max Filippov  <jcmvbkbc@gmail.com>
+
+       * config/tc-xtensa.c (xtensa_maybe_create_literal_pool_frag):
+       Initialize lps->frag_count with auto_litpool_limit.
+       (xg_promote_candidate_litpool): New function.
+       (xtensa_move_literals): Extract candidate litpool promotion code
+       into separate function. Call it for all possible found
+       candidates.
+       (xtensa_switch_to_literal_fragment): Drop 'recursive' flag and
+       call to xtensa_mark_literal_pool_location that it guards.
+       Replace it with call to xtensa_maybe_create_literal_pool_frag.
+       Initialize pool_location with created literal pool candidate.
+       * testsuite/gas/xtensa/all.exp: Add new tests.
+       * testsuite/gas/xtensa/auto-litpools-first1.d: New test results.
+       * testsuite/gas/xtensa/auto-litpools-first1.s: New test.
+       * testsuite/gas/xtensa/auto-litpools-first2.d: New test results.
+       * testsuite/gas/xtensa/auto-litpools-first2.s: New test.
+       * testsuite/gas/xtensa/auto-litpools.d: Fix offsets changed due
+       to additional jump instruction.
+
 2017-04-07  Alan Modra  <amodra@gmail.com>
 
        * testsuite/gas/ppc/altivec2.s: Delete E6500 vector insns.
index c45c70d5123ed540a00ee420e2bee9de589125e5..e1efaae88c512cf5e0a0fb8de5f1ec711f55171c 100644 (file)
@@ -7547,6 +7547,10 @@ xtensa_maybe_create_literal_pool_frag (bfd_boolean create,
       lps->seg = now_seg;
       lps->frag_list.next = &lps->frag_list;
       lps->frag_list.prev = &lps->frag_list;
+      /* Put candidate literal pool at the beginning of every section,
+         so that even when section starts with literal load there's a
+        literal pool available.  */
+      lps->frag_count = auto_litpool_limit;
     }
 
   lps->frag_count++;
@@ -11034,6 +11038,30 @@ xtensa_move_seg_list_to_beginning (seg_list *head)
 
 static void mark_literal_frags (seg_list *);
 
+static void
+xg_promote_candidate_litpool (struct litpool_seg *lps,
+                             struct litpool_frag *lp)
+{
+  fragS *poolbeg;
+  fragS *poolend;
+  symbolS *lsym;
+  char label[10 + 2 * sizeof (fragS *)];
+
+  poolbeg = lp->fragP;
+  lp->priority = 1;
+  poolbeg->fr_subtype = RELAX_LITERAL_POOL_BEGIN;
+  poolend = poolbeg->fr_next;
+  gas_assert (poolend->fr_type == rs_machine_dependent &&
+             poolend->fr_subtype == RELAX_LITERAL_POOL_END);
+  /* Create a local symbol pointing to the
+     end of the pool.  */
+  sprintf (label, ".L0_LT_%p", poolbeg);
+  lsym = (symbolS *)local_symbol_make (label, lps->seg,
+                                      0, poolend);
+  poolbeg->fr_symbol = lsym;
+  /* Rest is done in xtensa_relax_frag.  */
+}
+
 static void
 xtensa_move_literals (void)
 {
@@ -11121,27 +11149,17 @@ xtensa_move_literals (void)
                                      /* This is still a "candidate" but the next one
                                         will be too far away, so revert to the nearest
                                         one, convert it and add the jump around.  */
-                                     fragS *poolbeg;
-                                     fragS *poolend;
-                                     symbolS *lsym;
-                                     char label[10 + 2 * sizeof (fragS *)];
                                      lp = lpf->prev;
-                                     poolbeg = lp->fragP;
-                                     lp->priority = 1;
-                                     poolbeg->fr_subtype = RELAX_LITERAL_POOL_BEGIN;
-                                     poolend = poolbeg->fr_next;
-                                     gas_assert (poolend->fr_type == rs_machine_dependent &&
-                                                 poolend->fr_subtype == RELAX_LITERAL_POOL_END);
-                                     /* Create a local symbol pointing to the
-                                        end of the pool.  */
-                                     sprintf (label, ".L0_LT_%p", poolbeg);
-                                     lsym = (symbolS *)local_symbol_make (label, lps->seg,
-                                                                          0, poolend);
-                                     poolbeg->fr_symbol = lsym;
-                                     /* Rest is done in xtensa_relax_frag.  */
+                                     break;
                                    }
                                }
                            }
+
+                         /* Convert candidate and add the jump around.  */
+                         if (lp->fragP->fr_subtype ==
+                             RELAX_LITERAL_POOL_CANDIDATE_BEGIN)
+                           xg_promote_candidate_litpool (lps, lp);
+
                          if (! litfrag->tc_frag_data.literal_frag)
                            {
                              /* Take earliest use of this literal to avoid
@@ -11413,7 +11431,6 @@ xtensa_switch_to_literal_fragment (emit_state *result)
 static void
 xtensa_switch_to_non_abs_literal_fragment (emit_state *result)
 {
-  static bfd_boolean recursive = FALSE;
   fragS *pool_location = get_literal_pool_location (now_seg);
   segT lit_seg;
   bfd_boolean is_init =
@@ -11423,23 +11440,14 @@ xtensa_switch_to_non_abs_literal_fragment (emit_state *result)
 
   if (pool_location == NULL
       && !use_literal_section
-      && !recursive
       && !is_init && ! is_fini)
     {
       if (!auto_litpools)
        {
          as_bad (_("literal pool location required for text-section-literals; specify with .literal_position"));
        }
-
-      /* When we mark a literal pool location, we want to put a frag in
-        the literal pool that points to it.  But to do that, we want to
-        switch_to_literal_fragment.  But literal sections don't have
-        literal pools, so their location is always null, so we would
-        recurse forever.  This is kind of hacky, but it works.  */
-
-      recursive = TRUE;
-      xtensa_mark_literal_pool_location ();
-      recursive = FALSE;
+      xtensa_maybe_create_literal_pool_frag (TRUE, TRUE);
+      pool_location = get_literal_pool_location (now_seg);
     }
 
   lit_seg = cache_literal_section (FALSE);
index 98041b5e4b9380397fcf69ab1788abff1103b1d1..1ab382700a3f597c2559c3f65c25c35b05ccf7ee 100644 (file)
@@ -101,6 +101,8 @@ if [istarget xtensa*-*-*] then {
     run_dump_test "trampoline"
     run_dump_test "first_frag_align"
     run_dump_test "auto-litpools"
+    run_dump_test "auto-litpools-first1"
+    run_dump_test "auto-litpools-first2"
     run_dump_test "loc"
     run_dump_test "init-fini-literals"
 }
diff --git a/gas/testsuite/gas/xtensa/auto-litpools-first1.d b/gas/testsuite/gas/xtensa/auto-litpools-first1.d
new file mode 100644 (file)
index 0000000..322cdc5
--- /dev/null
@@ -0,0 +1,12 @@
+#as: --auto-litpools
+#objdump: -ds
+#name: auto-litpools-first1 (check that literal pool is created when source starts with literal)
+
+.*: +file format .*xtensa.*
+#...
+Contents of section .text:
+ 0000 ........ 20170331 .*
+#...
+00000000 <f>:
+.*0:.*j.8 .*
+#...
diff --git a/gas/testsuite/gas/xtensa/auto-litpools-first1.s b/gas/testsuite/gas/xtensa/auto-litpools-first1.s
new file mode 100644 (file)
index 0000000..7ac0bf8
--- /dev/null
@@ -0,0 +1,3 @@
+f:
+       .literal .L0, 0x20170331
+       l32r    a2, .L0
diff --git a/gas/testsuite/gas/xtensa/auto-litpools-first2.d b/gas/testsuite/gas/xtensa/auto-litpools-first2.d
new file mode 100644 (file)
index 0000000..a6b798e
--- /dev/null
@@ -0,0 +1,15 @@
+#as: --auto-litpools
+#objdump: -ds
+#name: auto-litpools-first2 (check that literal pool with jump around is created for generated literal)
+
+.*: +file format .*xtensa.*
+#...
+Contents of section .text:
+ 0000 ........ ........ 20170331 .*
+#...
+00000000 <f>:
+   0:.*addi.*a1.*
+   3:.*j.*c.*
+#...
+   c:.*l32r.*a2, 8.*
+#...
diff --git a/gas/testsuite/gas/xtensa/auto-litpools-first2.s b/gas/testsuite/gas/xtensa/auto-litpools-first2.s
new file mode 100644 (file)
index 0000000..c097dac
--- /dev/null
@@ -0,0 +1,3 @@
+f:
+       addi    a1, a1, -16
+       movi    a2, 0x20170331
index 4d1a690b085f70a49e3ad1eba392b3005a6293e3..fc6f5cbbc308e65c8954a0112ce5ca7ae6e41fce 100644 (file)
@@ -4,9 +4,9 @@
 
 .*: +file format .*xtensa.*
 #...
-.*4:.*l32r.a2, 0 .*
+.*8:.*l32r.a2, 4 .*
 #...
-.*3e437:.*j.3e440 .*
+.*3e43b:.*j.3e444 .*
 #...
-.*40750:.*l32r.a2, 3e43c .*
+.*40754:.*l32r.a2, 3e440 .*
 #...