gas/
authorRichard Sandiford <rdsandiford@googlemail.com>
Fri, 14 Jun 2013 13:30:28 +0000 (13:30 +0000)
committerRichard Sandiford <rdsandiford@googlemail.com>
Fri, 14 Jun 2013 13:30:28 +0000 (13:30 +0000)
* dwarf2dbg.h (dwarf2_move_insn): Declare.
* dwarf2dbg.c (line_subseg): Add pmove_tail.
(get_line_subseg): Add create_p argument.  Initialize pmove_tail.
(dwarf2_gen_line_info_1): Update call accordingly.
(dwarf2_move_insn): New function.
* config/tc-mips.c (append_insn): Use dwarf2_move_insn.

gas/testsuite/
* gas/mips/loc-swap-3.d, gas/mips/loc-swap-3.s: New test.
* gas/mips/mips.exp: Run it.

gas/ChangeLog
gas/config/tc-mips.c
gas/dwarf2dbg.c
gas/dwarf2dbg.h
gas/testsuite/ChangeLog
gas/testsuite/gas/mips/loc-swap-3.d [new file with mode: 0644]
gas/testsuite/gas/mips/loc-swap-3.s [new file with mode: 0644]
gas/testsuite/gas/mips/mips.exp

index dbe82bb..fb59e46 100644 (file)
@@ -1,5 +1,14 @@
 2013-06-14  Richard Sandiford  <rsandifo@linux.vnet.ibm.com>
 
+       * dwarf2dbg.h (dwarf2_move_insn): Declare.
+       * dwarf2dbg.c (line_subseg): Add pmove_tail.
+       (get_line_subseg): Add create_p argument.  Initialize pmove_tail.
+       (dwarf2_gen_line_info_1): Update call accordingly.
+       (dwarf2_move_insn): New function.
+       * config/tc-mips.c (append_insn): Use dwarf2_move_insn.
+
+2013-06-14  Richard Sandiford  <rsandifo@linux.vnet.ibm.com>
+
        Revert:
 
        2011-09-05  Richard Sandiford  <rdsandiford@googlemail.com>
index 468e40f..106f754 100644 (file)
@@ -4373,22 +4373,19 @@ append_insn (struct mips_cl_insn *ip, expressionS *address_expr,
   branch_disp = method == APPEND_SWAP ? insn_length (history) : 0;
 
 #ifdef OBJ_ELF
-  /* The value passed to dwarf2_emit_insn is the distance between
-     the beginning of the current instruction and the address that
-     should be recorded in the debug tables.  This is normally the
-     current address.
-
-     For MIPS16/microMIPS debug info we want to use ISA-encoded
-     addresses, so we use -1 for an address higher by one than the
-     current one.
-
-     If the instruction produced is a branch that we will swap with
-     the preceding instruction, then we add the displacement by which
-     the branch will be moved backwards.  This is more appropriate
-     and for MIPS16/microMIPS code also prevents a debugger from
-     placing a breakpoint in the middle of the branch (and corrupting
-     code if software breakpoints are used).  */
-  dwarf2_emit_insn ((HAVE_CODE_COMPRESSION ? -1 : 0) + branch_disp);
+  dwarf2_emit_insn (0);
+  /* We want MIPS16 and microMIPS debug info to use ISA-encoded addresses,
+     so "move" the instruction address accordingly.
+
+     Also, it doesn't seem appropriate for the assembler to reorder .loc
+     entries.  If this instruction is a branch that we are going to swap
+     with the previous instruction, the two instructions should be
+     treated as a unit, and the debug information for both instructions
+     should refer to the start of the branch sequence.  Using the
+     current position is certainly wrong when swapping a 32-bit branch
+     and a 16-bit delay slot, since the current position would then be
+     in the middle of a branch.  */
+  dwarf2_move_insn ((HAVE_CODE_COMPRESSION ? 1 : 0) - branch_disp);
 #endif
 
   relax32 = (mips_relax_branch
index f5623f6..6d6ee2d 100644 (file)
@@ -169,6 +169,7 @@ struct line_subseg {
   subsegT subseg;
   struct line_entry *head;
   struct line_entry **ptail;
+  struct line_entry **pmove_tail;
 };
 
 struct line_seg {
@@ -238,10 +239,10 @@ generic_dwarf2_emit_offset (symbolS *symbol, unsigned int size)
 }
 #endif
 
-/* Find or create an entry for SEG+SUBSEG in ALL_SEGS.  */
+/* Find or create (if CREATE_P) an entry for SEG+SUBSEG in ALL_SEGS.  */
 
 static struct line_subseg *
-get_line_subseg (segT seg, subsegT subseg)
+get_line_subseg (segT seg, subsegT subseg, bfd_boolean create_p)
 {
   static segT last_seg;
   static subsegT last_subseg;
@@ -256,6 +257,9 @@ get_line_subseg (segT seg, subsegT subseg)
   s = (struct line_seg *) hash_find (all_segs_hash, seg->name);
   if (s == NULL)
     {
+      if (!create_p)
+       return NULL;
+
       s = (struct line_seg *) xmalloc (sizeof (*s));
       s->next = NULL;
       s->seg = seg;
@@ -279,6 +283,7 @@ get_line_subseg (segT seg, subsegT subseg)
   lss->subseg = subseg;
   lss->head = NULL;
   lss->ptail = &lss->head;
+  lss->pmove_tail = &lss->head;
   *pss = lss;
 
  found_subseg:
@@ -302,7 +307,7 @@ dwarf2_gen_line_info_1 (symbolS *label, struct dwarf2_line_info *loc)
   e->label = label;
   e->loc = *loc;
 
-  lss = get_line_subseg (now_seg, now_subseg);
+  lss = get_line_subseg (now_seg, now_subseg, TRUE);
   *lss->ptail = e;
   lss->ptail = &e->next;
 }
@@ -396,6 +401,33 @@ dwarf2_emit_insn (int size)
   dwarf2_consume_line_info ();
 }
 
+/* Move all previously-emitted line entries for the current position by
+   DELTA bytes.  This function cannot be used to move the same entries
+   twice.  */
+
+void
+dwarf2_move_insn (int delta)
+{
+  struct line_subseg *lss;
+  struct line_entry *e;
+  valueT now;
+
+  if (delta == 0)
+    return;
+
+  lss = get_line_subseg (now_seg, now_subseg, FALSE);
+  if (!lss)
+    return;
+
+  now = frag_now_fix ();
+  while ((e = *lss->pmove_tail))
+    {
+      if (S_GET_VALUE (e->label) == now)
+       S_SET_VALUE (e->label, now + delta);
+      lss->pmove_tail = &e->next;
+    }
+}
+
 /* Called after the current line information has been either used with
    dwarf2_gen_line_info or saved with a machine instruction for later use.
    This resets the state of the line number information to reflect that
index 05c7bee..84ef8f6 100644 (file)
@@ -74,6 +74,8 @@ extern void dwarf2_gen_line_info (addressT addr, struct dwarf2_line_info *l);
 /* Must be called for each generated instruction.  */
 extern void dwarf2_emit_insn (int);
 
+void dwarf2_move_insn (int);
+
 /* Reset the state of the line number information to reflect that
    it has been used.  */
 extern void dwarf2_consume_line_info (void);
index 9a11bb1..aa57f27 100644 (file)
@@ -1,3 +1,8 @@
+2013-06-14  Richard Sandiford  <rsandifo@linux.vnet.ibm.com>
+
+       * gas/mips/loc-swap-3.d, gas/mips/loc-swap-3.s: New test.
+       * gas/mips/mips.exp: Run it.
+
 2013-06-13  Chao-ying Fu  <Chao-ying.Fu@imgtec.com>
 
        * gas/mips/micromips@virt.d: New file.
diff --git a/gas/testsuite/gas/mips/loc-swap-3.d b/gas/testsuite/gas/mips/loc-swap-3.d
new file mode 100644 (file)
index 0000000..9fc5e56
--- /dev/null
@@ -0,0 +1,16 @@
+#PROG: readelf
+#readelf: -wl
+#name: MIPS DWARF-2 location information with branch swapping (3)
+#...
+ Line Number Statements:
+.*  Set prologue_end to true
+.*  Extended opcode 2: set Address to 0x[01]
+.*  Copy
+#------------------------------------------------------------------------
+# There used to be a bogus:
+#   Set prologue_end to true
+# here
+#------------------------------------------------------------------------
+.*  Special opcode 6: advance Address by 0 to 0x[01] and Line by 1 to 2
+.*  Advance PC by .*
+.*  Extended opcode 1: End of Sequence
diff --git a/gas/testsuite/gas/mips/loc-swap-3.s b/gas/testsuite/gas/mips/loc-swap-3.s
new file mode 100644 (file)
index 0000000..1e4eb9a
--- /dev/null
@@ -0,0 +1,6 @@
+        .file   1 "test.cpp"
+
+        .text
+        .loc    1 1 0 prologue_end
+        .loc    1 2 0
+        nop
index a0ba481..e00b3f2 100644 (file)
@@ -999,6 +999,7 @@ if { [istarget mips*-*-vxworks*] } {
        run_dump_test_arches "loc-swap-dis" \
                                        [mips_arch_list_all]
        run_dump_test_arches "loc-swap-2" [mips_arch_list_all]
+       run_dump_test_arches "loc-swap-3" [mips_arch_list_all]
     }
 
     if $has_newabi {