* dwarf2dbg.c (struct line_entry): Replace frag and frag_ofs
authorRichard Henderson <rth@redhat.com>
Tue, 20 Sep 2005 18:24:48 +0000 (18:24 +0000)
committerRichard Henderson <rth@redhat.com>
Tue, 20 Sep 2005 18:24:48 +0000 (18:24 +0000)
        with label.
        (dwarf2_loc_mark_labels): New.
        (dwarf2_gen_line_info_1): Split out of ...
        (dwarf2_gen_line_info): ... here.  Create the temp symbol here.
        (dwarf2_emit_label): New.
        (dwarf2_directive_loc_mark_labels): New.
        (out_set_addr): Take a symbol instead of frag+ofs.
        (relax_inc_line_addr): Likewise.
        (emit_inc_line_addr): Assert delta non-negative.
        (process_entries): Remove dead code.  Update to work with temp
        symbols instead of frag+ofs.
        * dwarf2dbg.h (dwarf2_directive_loc_mark_labels): Declare.
        (dwarf2_emit_label, dwarf2_loc_mark_labels): Declare.
        * config/obj-elf.c (elf_pseudo_tab): Add loc_mark_labels.
        * config/obj-elf.h (obj_frob_label): New.
        * config/tc-alpha.c (alpha_define_label): Call dwarf2_emit_label.
        * config/tc-arm.c, config/tc-hppa.c, config/tc-m68k.c,
        config/tc-mips.c, config/tc-ppc.c, config/tc-sh.c, config/tc-xtensa.c:
        Similarly in the respective tc_frob_label implementation functions.
        * config/tc-i386.c (md_pseudo_table): Move file and loc to
        non-elf section; add loc_mark_labels.
        * config/tc-ia64.c (struct label_fix): Add dw2_mark_labels.
        (ia64_flush_insns): Check for marked labels; emit line entry if so.
        (emit_one_bundle): Similarly.
        (ia64_frob_label): Record marked labels.
        * config/tc-m68hc11.h (tc_frob_label): Remove.
        * config/tc-ms1.c (md_pseudo_table): Remove file and loc.
        * config/tc-sh.h (tc_frob_label): Pass sym to sh_frob_label.
        * config/tc-sh64.h (tc_frob_label): Likewise.
        * doc/as.texinfo (LNS directives): Docuement .loc_mark_blocks.

20 files changed:
gas/ChangeLog
gas/config/obj-elf.c
gas/config/obj-elf.h
gas/config/tc-alpha.c
gas/config/tc-arm.c
gas/config/tc-hppa.c
gas/config/tc-i386.c
gas/config/tc-ia64.c
gas/config/tc-m68hc11.h
gas/config/tc-m68k.c
gas/config/tc-mips.c
gas/config/tc-ms1.c
gas/config/tc-ppc.c
gas/config/tc-sh.c
gas/config/tc-sh.h
gas/config/tc-sh64.h
gas/config/tc-xtensa.c
gas/doc/as.texinfo
gas/dwarf2dbg.c
gas/dwarf2dbg.h

index 2018e20bfc2a825d036ed13fa2d16387d73bc7a1..c4848424930f7e3f57ed9842c6eed32759e5fbb6 100644 (file)
@@ -1,3 +1,37 @@
+2005-09-20  Richard Henderson  <rth@redhat.com>
+
+       * dwarf2dbg.c (struct line_entry): Replace frag and frag_ofs
+       with label.
+       (dwarf2_loc_mark_labels): New.
+       (dwarf2_gen_line_info_1): Split out of ...
+       (dwarf2_gen_line_info): ... here.  Create the temp symbol here.
+       (dwarf2_emit_label): New.
+       (dwarf2_directive_loc_mark_labels): New.
+       (out_set_addr): Take a symbol instead of frag+ofs.
+       (relax_inc_line_addr): Likewise.
+       (emit_inc_line_addr): Assert delta non-negative.
+       (process_entries): Remove dead code.  Update to work with temp
+       symbols instead of frag+ofs.
+       * dwarf2dbg.h (dwarf2_directive_loc_mark_labels): Declare.
+       (dwarf2_emit_label, dwarf2_loc_mark_labels): Declare.
+       * config/obj-elf.c (elf_pseudo_tab): Add loc_mark_labels.
+       * config/obj-elf.h (obj_frob_label): New.
+       * config/tc-alpha.c (alpha_define_label): Call dwarf2_emit_label.
+       * config/tc-arm.c, config/tc-hppa.c, config/tc-m68k.c,
+       config/tc-mips.c, config/tc-ppc.c, config/tc-sh.c, config/tc-xtensa.c:
+       Similarly in the respective tc_frob_label implementation functions.
+       * config/tc-i386.c (md_pseudo_table): Move file and loc to
+       non-elf section; add loc_mark_labels.
+       * config/tc-ia64.c (struct label_fix): Add dw2_mark_labels.
+       (ia64_flush_insns): Check for marked labels; emit line entry if so.
+       (emit_one_bundle): Similarly.
+       (ia64_frob_label): Record marked labels.
+       * config/tc-m68hc11.h (tc_frob_label): Remove.
+       * config/tc-ms1.c (md_pseudo_table): Remove file and loc.
+       * config/tc-sh.h (tc_frob_label): Pass sym to sh_frob_label.
+       * config/tc-sh64.h (tc_frob_label): Likewise.
+       * doc/as.texinfo (LNS directives): Docuement .loc_mark_blocks.
+
 2005-09-20  Alan Modra  <amodra@bigpond.net.au>
 
        * read.c (pseudo_set): Set segment of expression syms to expr_section.
index 43e0c97a0d2174ae927d7c5ce23a303051fee9fd..f922149cae0d918e6a33e9df0d441c1752d1a8e2 100644 (file)
@@ -115,6 +115,7 @@ static const pseudo_typeS elf_pseudo_table[] =
   /* These are used for dwarf2.  */
   { "file", (void (*) (int)) dwarf2_directive_file, 0 },
   { "loc",  dwarf2_directive_loc,  0 },
+  { "loc_mark_labels", dwarf2_directive_loc_mark_labels, 0 },
 
   /* We need to trap the section changing calls to handle .previous.  */
   {"data", obj_elf_data, 0},
index 629fc00fcff14d61da117eda61f035ffdb43c434..7ff9ef09aa3cb8e560c97c677e69a721477b04bc 100644 (file)
@@ -156,6 +156,13 @@ extern void elf_frob_file_before_adjust (void);
 #endif
 extern void elf_frob_file_after_relocs (void);
 
+/* If the target doesn't have special processing for labels, take care of
+   dwarf2 output at the object file level.  */
+#ifndef tc_frob_label
+#include "dwarf2dbg.h"
+#define obj_frob_label  dwarf2_emit_label
+#endif
+
 #ifndef obj_app_file
 #define obj_app_file elf_file_symbol
 #endif
index 2eb0adfd3b18d528afd6652d7b150963d7801f42..8d923529c1d2046c5ce0446bb8154b56463f0a0c 100644 (file)
@@ -5464,6 +5464,9 @@ void
 alpha_define_label (symbolS *sym)
 {
   alpha_insn_label = sym;
+#ifdef OBJ_ELF
+  dwarf2_emit_label (sym);
+#endif
 }
 
 /* Return true if we must always emit a reloc for a type and false if
index c11e149b45969039e8bc7f9c38fb1debca6bf9a1..8d327eb0cf2ae702397c169d072af02a24f5ed5e 100644 (file)
@@ -8092,6 +8092,10 @@ arm_frob_label (symbolS * sym)
 
       label_is_thumb_function_name = FALSE;
     }
+
+#ifdef OBJ_ELF
+  dwarf2_emit_label (sym);
+#endif
 }
 
 int
index 75f6dbb361ee4dd22152f300d6239dc04610aae1..1c1b4e45eba5c48b901fa46cecec39c57b3e0d2c 100644 (file)
@@ -1287,6 +1287,10 @@ pa_define_label (symbol)
 
       label_symbols_rootp = label_chain;
     }
+
+#ifdef OBJ_ELF
+  dwarf2_emit_label (symbol);
+#endif
 }
 
 /* Removes a label definition for the current space.
index b562b765e3ff2a950081960033158373d77ba9c7..3820b19abec224b2a03c9b88fa1b69a4b9c842ba 100644 (file)
@@ -469,10 +469,12 @@ const pseudo_typeS md_pseudo_table[] =
   {"code64", set_code_flag, CODE_64BIT},
   {"intel_syntax", set_intel_syntax, 1},
   {"att_syntax", set_intel_syntax, 0},
-  {"file", (void (*) PARAMS ((int))) dwarf2_directive_file, 0},
-  {"loc", dwarf2_directive_loc, 0},
 #if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
   {"largecomm", handle_large_common, 0},
+#else
+  {"file", (void (*) PARAMS ((int))) dwarf2_directive_file, 0},
+  {"loc", dwarf2_directive_loc, 0},
+  {"loc_mark_labels", dwarf2_directive_loc_mark_labels, 0},
 #endif
 #ifdef TE_PE
   {"secrel32", pe_directive_secrel, 0},
index 81e5cd56a0abec0006c3b5c047dd43915c7ba7d1..5875551c78d8f265a510e179f936a226cbdeda5d 100644 (file)
@@ -159,6 +159,7 @@ struct label_fix
 {
   struct label_fix *next;
   struct symbol *sym;
+  bfd_boolean dw2_mark_labels;
 };
 
 /* This is the endianness of the current section.  */
@@ -1083,6 +1084,7 @@ ia64_flush_insns ()
   segT saved_seg;
   subsegT saved_subseg;
   unw_rec_list *ptr;
+  bfd_boolean mark;
 
   if (!md.last_text_seg)
     return;
@@ -1096,18 +1098,23 @@ ia64_flush_insns ()
     emit_one_bundle ();                /* force out queued instructions */
 
   /* In case there are labels following the last instruction, resolve
-     those now:  */
+     those now.  */
+  mark = FALSE;
   for (lfix = CURR_SLOT.label_fixups; lfix; lfix = lfix->next)
     {
-      S_SET_VALUE (lfix->sym, frag_now_fix ());
-      symbol_set_frag (lfix->sym, frag_now);
+      symbol_set_value_now (lfix->sym);
+      mark |= lfix->dw2_mark_labels;
     }
-  CURR_SLOT.label_fixups = 0;
-  for (lfix = CURR_SLOT.tag_fixups; lfix; lfix = lfix->next)
+  if (mark)
     {
-      S_SET_VALUE (lfix->sym, frag_now_fix ());
-      symbol_set_frag (lfix->sym, frag_now);
+      dwarf2_where (&CURR_SLOT.debug_line);
+      CURR_SLOT.debug_line.flags |= DWARF2_FLAG_BASIC_BLOCK;
+      dwarf2_gen_line_info (frag_now_fix (), &CURR_SLOT.debug_line);
     }
+  CURR_SLOT.label_fixups = 0;
+
+  for (lfix = CURR_SLOT.tag_fixups; lfix; lfix = lfix->next)
+    symbol_set_value_now (lfix->sym);
   CURR_SLOT.tag_fixups = 0;
 
   /* In case there are unwind directives following the last instruction,
@@ -6647,6 +6654,7 @@ emit_one_bundle ()
   int n, i, j, first, curr, last_slot;
   bfd_vma t0 = 0, t1 = 0;
   struct label_fix *lfix;
+  bfd_boolean mark_label;
   struct insn_fix *ifix;
   char mnemonic[16];
   fixS *fix;
@@ -6967,11 +6975,30 @@ emit_one_bundle ()
       if (insn_unit != required_unit)
        continue;               /* Try next slot.  */
 
-      if (debug_type == DEBUG_DWARF2 || md.slot[curr].loc_directive_seen)
+      /* Now is a good time to fix up the labels for this insn.  */
+      mark_label = FALSE;
+      for (lfix = md.slot[curr].label_fixups; lfix; lfix = lfix->next)
+       {
+         S_SET_VALUE (lfix->sym, frag_now_fix () - 16);
+         symbol_set_frag (lfix->sym, frag_now);
+         mark_label |= lfix->dw2_mark_labels;
+       }
+      for (lfix = md.slot[curr].tag_fixups; lfix; lfix = lfix->next)
+       {
+         S_SET_VALUE (lfix->sym, frag_now_fix () - 16 + i);
+         symbol_set_frag (lfix->sym, frag_now);
+       }
+
+      if (debug_type == DEBUG_DWARF2
+         || md.slot[curr].loc_directive_seen
+         || mark_label)
        {
          bfd_vma addr = frag_now->fr_address + frag_now_fix () - 16 + i;
 
          md.slot[curr].loc_directive_seen = 0;
+         if (mark_label)
+           md.slot[curr].debug_line.flags |= DWARF2_FLAG_BASIC_BLOCK;
+
          dwarf2_gen_line_info (addr, &md.slot[curr].debug_line);
        }
 
@@ -7000,19 +7027,6 @@ emit_one_bundle ()
       --md.num_slots_in_use;
       last_slot = i;
 
-      /* now is a good time to fix up the labels for this insn:  */
-      for (lfix = md.slot[curr].label_fixups; lfix; lfix = lfix->next)
-       {
-         S_SET_VALUE (lfix->sym, frag_now_fix () - 16);
-         symbol_set_frag (lfix->sym, frag_now);
-       }
-      /* and fix up the tags also.  */
-      for (lfix = md.slot[curr].tag_fixups; lfix; lfix = lfix->next)
-       {
-         S_SET_VALUE (lfix->sym, frag_now_fix () - 16 + i);
-         symbol_set_frag (lfix->sym, frag_now);
-       }
-
       for (j = 0; j < md.slot[curr].num_fixups; ++j)
        {
          ifix = md.slot[curr].fixup + j;
@@ -7904,6 +7918,7 @@ ia64_frob_label (sym)
       fix = obstack_alloc (&notes, sizeof (*fix));
       fix->sym = sym;
       fix->next = CURR_SLOT.tag_fixups;
+      fix->dw2_mark_labels = FALSE;
       CURR_SLOT.tag_fixups = fix;
 
       return;
@@ -7915,6 +7930,7 @@ ia64_frob_label (sym)
       fix = obstack_alloc (&notes, sizeof (*fix));
       fix->sym = sym;
       fix->next = CURR_SLOT.label_fixups;
+      fix->dw2_mark_labels = dwarf2_loc_mark_labels;
       CURR_SLOT.label_fixups = fix;
 
       /* Keep track of how many code entry points we've seen.  */
index a1a42b80f67521fa212cd82439a8bab8f05642b9..70d7d9e7f21d824e18792974e82e738ef470162b 100644 (file)
@@ -101,9 +101,6 @@ extern int tc_m68hc11_force_relocation (struct fix *);
 extern int tc_m68hc11_fix_adjustable (struct fix *);
 
 #define md_operand(x)
-#define tc_frob_label(sym) do {\
-  S_SET_VALUE (sym, (valueT) frag_now_fix ()); \
-} while (0)
 
 #define elf_tc_final_processing        m68hc11_elf_final_processing
 extern void m68hc11_elf_final_processing (void);
index 8862a7fadbeac8f086a58458f669f50e1625a80e..761cdd458a308e5a479cdb311f436cc72ea67c92 100644 (file)
@@ -4394,6 +4394,10 @@ m68k_frob_label (symbolS *sym)
   n->text = 0;
   labels = n;
   current_label = n;
+
+#ifdef OBJ_ELF
+  dwarf2_emit_label (sym);
+#endif
 }
 
 /* This is called when a value that is not an instruction is emitted.  */
index b4b76f018b56675f835eea6d695081f0f077eade..2ce3415073b5932ac05b82750b983b7a050d1c90 100644 (file)
@@ -13594,6 +13594,10 @@ mips_define_label (symbolS *sym)
   l->label = sym;
   l->next = insn_labels;
   insn_labels = l;
+
+#ifdef OBJ_ELF
+  dwarf2_emit_label (sym);
+#endif
 }
 \f
 #if defined (OBJ_ELF) || defined (OBJ_MAYBE_ELF)
index 3c604740be96f2e1c4044a8b7128e91a6fa7a652..e459bc843196f7412ec7a49af0146645c69e2d7a 100644 (file)
@@ -63,8 +63,6 @@ const char FLT_CHARS[]            = "dD";
 const pseudo_typeS md_pseudo_table[] =
 {
     { "word",   cons,                   4 }, 
-    { "file",  (void (*) (int)) dwarf2_directive_file, 0 },
-    { "loc",   dwarf2_directive_loc,   0 },
     { NULL,    NULL,                   0 }
 };
 
index c7ad970672443ee9547c5ed92bb0af278080dfc0..2de8a8b85cb3b19455335456f86d703913551b93 100644 (file)
@@ -4840,6 +4840,10 @@ ppc_frob_label (sym)
                     &symbol_rootP, &symbol_lastP);
       symbol_get_tc (ppc_current_csect)->within = sym;
     }
+
+#ifdef OBJ_ELF
+  dwarf2_emit_label (sym);
+#endif
 }
 
 /* This variable is set by ppc_frob_symbol if any absolute symbols are
index b61793ded5d609b9e11b1ea170b831143048cf49..555842b5fbde58a679181e3def1e4c56b805b09e 100644 (file)
@@ -2876,7 +2876,7 @@ md_assemble (char *str)
    emits a BFD_RELOC_SH_LABEL reloc if necessary.  */
 
 void
-sh_frob_label (void)
+sh_frob_label (symbolS *sym)
 {
   static fragS *last_label_frag;
   static int last_label_offset;
@@ -2895,6 +2895,8 @@ sh_frob_label (void)
          last_label_offset = offset;
        }
     }
+
+  dwarf2_emit_label (sym);
 }
 
 /* This routine is called when the assembler is about to output some
index c0adaa1dace445540ef055215b547d55f8b6cc6f..69b82b229dbbad0f5d069b4cf0a263b9e4b88c01 100644 (file)
@@ -103,8 +103,8 @@ struct sh_segment_info_type
 
 /* We call a routine to emit a reloc for a label, so that the linker
    can align loads and stores without crossing a label.  */
-extern void sh_frob_label (void);
-#define tc_frob_label(sym) sh_frob_label ()
+extern void sh_frob_label (symbolS *);
+#define tc_frob_label(sym) sh_frob_label (sym)
 
 /* We call a routine to flush pending output in order to output a DATA
    reloc when required.  */
index cbb37791c9b8473354415feebc7e2e768e0de120..8af9b95fe94e5f7e9fece4c10eee2bedc09d8246 100644 (file)
@@ -144,7 +144,7 @@ extern void sh64_frob_label (symbolS *);
 
 #undef  tc_frob_label
 #define tc_frob_label(sym) \
-  do { sh_frob_label (); sh64_frob_label (sym); } while (0)
+  do { sh_frob_label (sym); sh64_frob_label (sym); } while (0)
 
 #define tc_symbol_new_hook(s) sh64_frob_label (s)
 
index a93f57eaf8e69f406c2c48cfd0c4a547f4d5a62e..c93a4dfafe90e6d28137b8c81493f8bf0aeb4165 100644 (file)
@@ -5054,7 +5054,7 @@ xtensa_frob_label (symbolS *sym)
 
       xtensa_set_frag_assembly_state (frag_now);
       xtensa_move_labels (frag_now, 0, TRUE);
-  }
+    }
 
   /* No target aligning in the absolute section.  */
   if (now_seg != absolute_section
@@ -5083,6 +5083,8 @@ xtensa_frob_label (symbolS *sym)
   /* Loops only go forward, so they can be identified here.  */
   if (symbol_get_tc (sym)->is_loop_target)
     symbol_get_frag (sym)->tc_frag_data.is_loop_target = TRUE;
+
+  dwarf2_emit_label (sym);
 }
 
 
index 86827d5116e923504352d8be05bdacd3a9838c43..63cc5d135fa9f87c6754b69f2c522bd41653760f 100644 (file)
@@ -4103,6 +4103,15 @@ either 0 or 1.
 @item isa @var{value}
 This directive will set the @code{isa} register in the @code{.debug_line}
 state machine to @var{value}, which must be an unsigned integer.
+
+@section @code{.loc_mark_blocks @var{enable}}
+@cindex @code{loc_mark_blocks} directive
+The @code{.loc_mark_blocks} directive makes the assembler emit an entry
+to the @code{.debug_line} line number matrix with the @code{basic_block}
+register in the state machine set whenever a code label is seen.
+The @var{enable} argument should be either 1 or 0, to enable or disable
+this function respectively.
+
 @end table
 
 @node Data
index 43600803bec3a041cb8f560e2953761dbac17144..be59eba5db72ad637a691703468f2965e32412c9 100644 (file)
 
 struct line_entry {
   struct line_entry *next;
-  fragS *frag;
-  addressT frag_ofs;
+  symbolS *label;
   struct dwarf2_line_info loc;
 };
 
@@ -147,6 +146,10 @@ static unsigned int dirs_allocated;
    doing work when there's nothing to do.  */
 static bfd_boolean loc_directive_seen;
 
+/* TRUE when we're supposed to set the basic block mark whenever a
+   label is seen.  */
+bfd_boolean dwarf2_loc_mark_labels;
+
 /* Current location as indicated by the most recent .loc directive.  */
 static struct dwarf2_line_info current = {
   1, 1, 0, 0,
@@ -167,12 +170,11 @@ static void out_four (int);
 static void out_abbrev (int, int);
 static void out_uleb128 (addressT);
 static offsetT get_frag_fix (fragS *);
-static void out_set_addr (segT, fragS *, addressT);
+static void out_set_addr (symbolS *);
 static int size_inc_line_addr (int, addressT);
 static void emit_inc_line_addr (int, addressT, char *, int);
 static void out_inc_line_addr (int, addressT);
-static void relax_inc_line_addr (int, segT, fragS *, addressT,
-                                fragS *, addressT);
+static void relax_inc_line_addr (int, symbolS *, symbolS *);
 static void process_entries (segT, struct line_entry *);
 static void out_file_list (void);
 static void out_debug_line (segT);
@@ -247,16 +249,34 @@ get_line_subseg (segT seg, subsegT subseg)
   return ss;
 }
 
+/* Record an entry for LOC occurring at LABEL.  */
+
+static void
+dwarf2_gen_line_info_1 (symbolS *label, struct dwarf2_line_info *loc)
+{
+  struct line_subseg *ss;
+  struct line_entry *e;
+
+  e = (struct line_entry *) xmalloc (sizeof (*e));
+  e->next = NULL;
+  e->label = label;
+  e->loc = *loc;
+
+  ss = get_line_subseg (now_seg, now_subseg);
+  *ss->ptail = e;
+  ss->ptail = &e->next;
+}
+
 /* Record an entry for LOC occurring at OFS within the current fragment.  */
 
 void
 dwarf2_gen_line_info (addressT ofs, struct dwarf2_line_info *loc)
 {
-  struct line_subseg *ss;
-  struct line_entry *e;
   static unsigned int line = -1;
   static unsigned int filenum = -1;
 
+  symbolS *sym;
+
   /* Early out for as-yet incomplete location information.  */
   if (loc->filenum == 0 || loc->line == 0)
     return;
@@ -272,15 +292,8 @@ dwarf2_gen_line_info (addressT ofs, struct dwarf2_line_info *loc)
   line = loc->line;
   filenum = loc->filenum;
 
-  e = (struct line_entry *) xmalloc (sizeof (*e));
-  e->next = NULL;
-  e->frag = frag_now;
-  e->frag_ofs = ofs;
-  e->loc = *loc;
-
-  ss = get_line_subseg (now_seg, now_subseg);
-  *ss->ptail = e;
-  ss->ptail = &e->next;
+  sym = symbol_temp_new (now_seg, ofs, frag_now);
+  dwarf2_gen_line_info_1 (sym, loc);
 }
 
 /* Returns the current source information.  If .file directives have
@@ -349,6 +362,38 @@ dwarf2_emit_insn (int size)
                     | DWARF2_FLAG_EPILOGUE_BEGIN);
 }
 
+/* Called for each (preferably code) label.  If dwarf2_loc_mark_labels
+   is enabled, emit a basic block marker.  */
+
+void
+dwarf2_emit_label (symbolS *label)
+{
+  struct dwarf2_line_info loc;
+
+  if (!dwarf2_loc_mark_labels)
+    return;
+  if (S_GET_SEGMENT (label) != now_seg)
+    return;
+  if (!(bfd_get_section_flags (stdoutput, now_seg) & SEC_CODE))
+    return;
+  
+  if (debug_type == DEBUG_DWARF2)
+    dwarf2_where (&loc);
+  else
+    {
+      loc = current;
+      loc_directive_seen = FALSE;
+    }
+
+  loc.flags |= DWARF2_FLAG_BASIC_BLOCK;
+
+  current.flags &= ~(DWARF2_FLAG_BASIC_BLOCK
+                    | DWARF2_FLAG_PROLOGUE_END
+                    | DWARF2_FLAG_EPILOGUE_BEGIN);
+
+  dwarf2_gen_line_info_1 (label, &loc);
+}
+
 /* Get a .debug_line file number for FILENAME.  If NUM is nonzero,
    allocate it on that file table slot, otherwise return the first
    empty one.  */
@@ -603,6 +648,23 @@ dwarf2_directive_loc (int dummy ATTRIBUTE_UNUSED)
   demand_empty_rest_of_line ();
   loc_directive_seen = TRUE;
 }
+
+void
+dwarf2_directive_loc_mark_labels (int dummy ATTRIBUTE_UNUSED)
+{
+  offsetT value = get_absolute_expression ();
+
+  if (value != 0 && value != 1)
+    {
+      as_bad (_("expected 0 or 1"));
+      ignore_rest_of_line ();
+    }
+  else
+    {
+      dwarf2_loc_mark_labels = value != 0;
+      demand_empty_rest_of_line ();
+    }
+}
 \f
 static struct frag *
 first_frag_for_seg (segT seg)
@@ -702,12 +764,9 @@ get_frag_fix (fragS *frag)
 /* Set an absolute address (may result in a relocation entry).  */
 
 static void
-out_set_addr (segT seg, fragS *frag, addressT ofs)
+out_set_addr (symbolS *sym)
 {
   expressionS expr;
-  symbolS *sym;
-
-  sym = symbol_temp_new (seg, ofs, frag);
 
   out_opcode (DW_LNS_extended_op);
   out_uleb128 (sizeof_address + 1);
@@ -811,6 +870,10 @@ emit_inc_line_addr (int line_delta, addressT addr_delta, char *p, int len)
   int need_copy = 0;
   char *end = p + len;
 
+  /* Line number sequences cannot go backward in addresses.  This means
+     we've incorrectly ordered the statements in the sequence.  */
+  assert ((offsetT) addr_delta >= 0);
+
   /* Scale the address delta by the minimum instruction length.  */
   scale_addr_delta (&addr_delta);
 
@@ -906,17 +969,11 @@ out_inc_line_addr (int line_delta, addressT addr_delta)
    increments between fragments of the target segment.  */
 
 static void
-relax_inc_line_addr (int line_delta, segT seg,
-                    fragS *to_frag, addressT to_ofs,
-                    fragS *from_frag, addressT from_ofs)
+relax_inc_line_addr (int line_delta, symbolS *to_sym, symbolS *from_sym)
 {
-  symbolS *to_sym, *from_sym;
   expressionS expr;
   int max_chars;
 
-  to_sym = symbol_temp_new (seg, to_ofs, to_frag);
-  from_sym = symbol_temp_new (seg, from_ofs, from_frag);
-
   expr.X_op = O_subtract;
   expr.X_add_symbol = to_sym;
   expr.X_op_symbol = from_sym;
@@ -999,22 +1056,20 @@ process_entries (segT seg, struct line_entry *e)
   unsigned column = 0;
   unsigned isa = 0;
   unsigned flags = DWARF2_LINE_DEFAULT_IS_STMT ? DWARF2_FLAG_IS_STMT : 0;
-  fragS *frag = NULL;
-  fragS *last_frag;
-  addressT frag_ofs = 0;
-  addressT last_frag_ofs;
+  fragS *last_frag = NULL, *frag;
+  addressT last_frag_ofs = 0, frag_ofs;
+  symbolS *last_lab, *lab;
   struct line_entry *next;
 
   while (e)
     {
-      int changed = 0;
+      int line_delta;
 
       if (filenum != e->loc.filenum)
        {
          filenum = e->loc.filenum;
          out_opcode (DW_LNS_set_file);
          out_uleb128 (filenum);
-         changed = 1;
        }
 
       if (column != e->loc.column)
@@ -1022,7 +1077,6 @@ process_entries (segT seg, struct line_entry *e)
          column = e->loc.column;
          out_opcode (DW_LNS_set_column);
          out_uleb128 (column);
-         changed = 1;
        }
 
       if (isa != e->loc.isa)
@@ -1030,62 +1084,46 @@ process_entries (segT seg, struct line_entry *e)
          isa = e->loc.isa;
          out_opcode (DW_LNS_set_isa);
          out_uleb128 (isa);
-         changed = 1;
        }
 
       if ((e->loc.flags ^ flags) & DWARF2_FLAG_IS_STMT)
        {
          flags = e->loc.flags;
          out_opcode (DW_LNS_negate_stmt);
-         changed = 1;
        }
 
       if (e->loc.flags & DWARF2_FLAG_BASIC_BLOCK)
-       {
-         out_opcode (DW_LNS_set_basic_block);
-         changed = 1;
-       }
+       out_opcode (DW_LNS_set_basic_block);
 
       if (e->loc.flags & DWARF2_FLAG_PROLOGUE_END)
-       {
-         out_opcode (DW_LNS_set_prologue_end);
-         changed = 1;
-       }
+       out_opcode (DW_LNS_set_prologue_end);
 
       if (e->loc.flags & DWARF2_FLAG_EPILOGUE_BEGIN)
-       {
-         out_opcode (DW_LNS_set_epilogue_begin);
-         changed = 1;
-       }
+       out_opcode (DW_LNS_set_epilogue_begin);
 
       /* Don't try to optimize away redundant entries; gdb wants two
         entries for a function where the code starts on the same line as
         the {, and there's no way to identify that case here.  Trust gcc
         to optimize appropriately.  */
-      if (1 /* line != e->loc.line || changed */)
-       {
-         int line_delta = e->loc.line - line;
-         if (frag == NULL)
-           {
-             out_set_addr (seg, e->frag, e->frag_ofs);
-             out_inc_line_addr (line_delta, 0);
-           }
-         else if (frag == e->frag)
-           out_inc_line_addr (line_delta, e->frag_ofs - frag_ofs);
-         else
-           relax_inc_line_addr (line_delta, seg, e->frag, e->frag_ofs,
-                                frag, frag_ofs);
+      line_delta = e->loc.line - line;
+      lab = e->label;
+      frag = symbol_get_frag (lab);
+      frag_ofs = S_GET_VALUE (lab);
 
-         frag = e->frag;
-         frag_ofs = e->frag_ofs;
-         line = e->loc.line;
-       }
-      else if (frag == NULL)
+      if (last_frag == NULL)
        {
-         out_set_addr (seg, e->frag, e->frag_ofs);
-         frag = e->frag;
-         frag_ofs = e->frag_ofs;
+         out_set_addr (lab);
+         out_inc_line_addr (line_delta, 0);
        }
+      else if (frag == last_frag)
+       out_inc_line_addr (line_delta, frag_ofs - last_frag_ofs);
+      else
+       relax_inc_line_addr (line_delta, lab, last_lab);
+
+      line = e->loc.line;
+      last_lab = lab;
+      last_frag = frag;
+      last_frag_ofs = frag_ofs;
 
       next = e->next;
       free (e);
@@ -1093,13 +1131,15 @@ process_entries (segT seg, struct line_entry *e)
     }
 
   /* Emit a DW_LNE_end_sequence for the end of the section.  */
-  last_frag = last_frag_for_seg (seg);
-  last_frag_ofs = get_frag_fix (last_frag);
+  frag = last_frag_for_seg (seg);
+  frag_ofs = get_frag_fix (frag);
   if (frag == last_frag)
-    out_inc_line_addr (INT_MAX, last_frag_ofs - frag_ofs);
+    out_inc_line_addr (INT_MAX, frag_ofs - last_frag_ofs);
   else
-    relax_inc_line_addr (INT_MAX, seg, last_frag, last_frag_ofs,
-                        frag, frag_ofs);
+    {
+      lab = symbol_temp_new (seg, frag_ofs, frag);
+      relax_inc_line_addr (INT_MAX, lab, last_lab);
+    }
 }
 
 /* Emit the directory and file tables for .debug_line.  */
index 6e80021927db083c886ff9bd7a2445eb10f5976b..cd1d17b2031fcf24103830e6aff117635a5acb60 100644 (file)
@@ -49,6 +49,9 @@ extern char *dwarf2_directive_file (int dummy);
    used.  */
 extern void dwarf2_directive_loc (int dummy);
 
+/* Implements the .loc_mark_labels {0,1} directive.  */
+extern void dwarf2_directive_loc_mark_labels (int dummy);
+
 /* Returns the current source information.  If .file directives have
    been encountered, the info for the corresponding source file is
    returned.  Otherwise, the info for the assembly source file is
@@ -69,6 +72,14 @@ 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);
 
+/* Should be called for each code label.  */
+extern void dwarf2_emit_label (symbolS *);
+
+/* True when we're supposed to set the basic block mark whenever a label
+   is seen.  Unless the target is doing Something Weird, just call 
+   dwarf2_emit_label.  */
+bfd_boolean dwarf2_loc_mark_labels;
+
 extern void dwarf2_finish (void);
 
 extern int dwarf2dbg_estimate_size_before_relax (fragS *);