Mon Jun 8 12:20:30 1998 Alan Modra <alan@spri.levels.unisa.edu.au>
[deliverable/binutils-gdb.git] / gas / subsegs.c
index 0566d0aa3cf90ae0ebaa5d2d059bea153556778a..3280bcd18c070191450dd1eff5d6d8be4f7539cb 100644 (file)
@@ -1,5 +1,6 @@
 /* subsegs.c - subsegments -
-   Copyright (C) 1987, 1990, 1991, 1992 Free Software Foundation, Inc.
+   Copyright (C) 1987, 1990, 1991, 1992, 1993, 1994
+   Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
 
@@ -15,7 +16,7 @@
 
    You should have received a copy of the GNU General Public License
    along with GAS; see the file COPYING.  If not, write to
-   the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+   the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 /*
  * Segments & sub-segments.
@@ -28,6 +29,8 @@
 
 frchainS *frchain_root, *frchain_now;
 
+static struct obstack frchains;
+
 #ifndef BFD_ASSEMBLER
 #ifdef MANY_SEGMENTS
 segment_info_type segment_info[SEG_MAXIMUM_ORDINAL];
@@ -37,7 +40,7 @@ segment_info_type segment_info[SEG_MAXIMUM_ORDINAL];
 frchainS *data0_frchainP, *bss0_frchainP;
 
 #endif /* MANY_SEGMENTS */
-char *const seg_name[] =
+char const *const seg_name[] =
 {
   "absolute",
 #ifdef MANY_SEGMENTS
@@ -56,9 +59,20 @@ char *const seg_name[] =
   "register",
   "",
 };                             /* Used by error reporters, dumpers etc. */
+#else /* BFD_ASSEMBLER */
+
+/* Gas segment information for bfd_abs_section_ptr and
+   bfd_und_section_ptr.  */
+static segment_info_type *abs_seg_info;
+static segment_info_type *und_seg_info;
+
 #endif /* BFD_ASSEMBLER */
 
 static void subseg_set_rest PARAMS ((segT, subsegT));
+
+static fragS dummy_frag;
+
+static frchainS absolute_frchain;
 \f
 void
 subsegs_begin ()
@@ -79,17 +93,17 @@ subsegs_begin ()
   know (SEG_MAXIMUM_ORDINAL == SEG_REGISTER);
 #endif
 
-  obstack_begin (&frags, 5000);
+  obstack_begin (&frchains, chunksize);
+#if __GNUC__ >= 2
+  obstack_alignment_mask (&frchains) = __alignof__ (frchainS) - 1;
+#endif
+
   frchain_root = NULL;
   frchain_now = NULL;          /* Warn new_subseg() that we are booting. */
-  /* Fake up 1st frag.  It won't be used=> is ok if obstack...
-     pads the end of it for alignment. */
-  frag_now = (fragS *) obstack_alloc (&frags, SIZEOF_STRUCT_FRAG);
-  memset (frag_now, SIZEOF_STRUCT_FRAG, 0);
+
+  frag_now = &dummy_frag;
 
 #ifndef BFD_ASSEMBLER
-  /* This 1st frag will not be in any frchain.
-     We simply give subseg_new somewhere to scribble. */
   now_subseg = 42;             /* Lie for 1st call to subseg_new. */
 #ifdef MANY_SEGMENTS
   {
@@ -110,6 +124,11 @@ subsegs_begin ()
 #endif /* ! MANY_SEGMENTS */
 #endif /* ! BFD_ASSEMBLER */
 
+  absolute_frchain.frch_seg = absolute_section;
+  absolute_frchain.frch_subseg = 0;
+  absolute_frchain.fix_root = absolute_frchain.fix_tail = 0;
+  absolute_frchain.frch_frag_now = &zero_address_frag;
+  absolute_frchain.frch_root = absolute_frchain.frch_last = &zero_address_frag;
 }
 \f
 /*
@@ -130,6 +149,9 @@ subseg_change (seg, subseg)
   now_seg = seg;
   now_subseg = subseg;
 
+  if (now_seg == absolute_section)
+    return;
+
 #ifdef BFD_ASSEMBLER
   {
     segment_info_type *seginfo;
@@ -137,13 +159,17 @@ subseg_change (seg, subseg)
     if (! seginfo)
       {
        seginfo = (segment_info_type *) xmalloc (sizeof (*seginfo));
-       if (! seginfo)
-         abort ();
-       seginfo->fix_root = 0;
-       seginfo->fix_tail = 0;
+       memset ((PTR) seginfo, 0, sizeof (*seginfo));
+       seginfo->fix_root = NULL;
+       seginfo->fix_tail = NULL;
        seginfo->bfd_section = seg;
        seginfo->sym = 0;
-       bfd_set_section_userdata (stdoutput, seg, (char *) seginfo);
+       if (seg == bfd_abs_section_ptr)
+         abs_seg_info = seginfo;
+       else if (seg == bfd_und_section_ptr)
+         und_seg_info = seginfo;
+       else
+         bfd_set_section_userdata (stdoutput, seg, (PTR) seginfo);
       }
   }
 #else
@@ -184,26 +210,29 @@ subseg_set_rest (seg, subseg)
   register fragS *former_last_fragP;
   register fragS *new_fragP;
 
-  if (frag_now)                /* If not bootstrapping. */
+  mri_common_symbol = NULL;
+
+  if (frag_now && frchain_now)
+    frchain_now->frch_frag_now = frag_now;
+
+  assert (frchain_now == 0
+         || now_seg == undefined_section
+         || now_seg == absolute_section
+         || frchain_now->frch_last == frag_now);
+
+  subseg_change (seg, (int) subseg);
+
+  if (seg == absolute_section)
     {
-      frag_now->fr_fix = (char*) obstack_next_free (&frags) - frag_now->fr_literal;
-      frag_wane (frag_now);    /* Close off any frag in old subseg. */
+      frchain_now = &absolute_frchain;
+      frag_now = &zero_address_frag;
+      return;
     }
-  /*
-   * It would be nice to keep an obstack for each subsegment, if we swap
-   * subsegments a lot. Hence we would have much fewer frag_wanes().
-   */
-  {
-    obstack_finish (&frags);
-    /*
-     * If we don't do the above, the next object we put on obstack frags
-     * will appear to start at the fr_literal of the current frag.
-     * Also, above ensures that the next object will begin on a
-     * address that is aligned correctly for the engine that runs
-     * this program.
-     */
-  }
-  subseg_change (seg, (int) subseg);
+
+  assert (frchain_now == 0
+         || now_seg == undefined_section
+         || frchain_now->frch_last == frag_now);
+
   /*
    * Attempt to find or make a frchain for that sub seg.
    * Crawl along chain of frchainSs, begins @ frchain_root.
@@ -211,10 +240,10 @@ subseg_set_rest (seg, subseg)
    * position of chain rooted in frchain_root.
    */
   for (frcP = *(lastPP = &frchain_root);
-       frcP && (int) (frcP->frch_seg) <= (int) seg;
+       frcP && frcP->frch_seg <= seg;
        frcP = *(lastPP = &frcP->frch_next))
     {
-      if ((int) (frcP->frch_seg) == (int) seg
+      if (frcP->frch_seg == seg
          && frcP->frch_subseg >= subseg)
        {
          break;
@@ -242,56 +271,40 @@ subseg_set_rest (seg, subseg)
    *
    */
   if (!frcP
-      || ((int) (frcP->frch_seg) > (int) seg
+      || (frcP->frch_seg > seg
          || frcP->frch_subseg > subseg))       /* Kinky logic only works with 2 segments. */
     {
       /*
        * This should be the only code that creates a frchainS.
        */
-      newP = (frchainS *) obstack_alloc (&frags, sizeof (frchainS));
-      memset (newP, sizeof (frchainS), 0);
-      /* This begines on a good boundary because a obstack_done()
-        preceeded it.  It implies an obstack_done(), so we expect
-        the next object allocated to begin on a correct boundary. */
+      extern fragS *frag_alloc ();
+      newP = (frchainS *) obstack_alloc (&frchains, sizeof (frchainS));
+      newP->frch_subseg = subseg;
+      newP->frch_seg = seg;
+#ifdef BFD_ASSEMBLER
+      newP->fix_root = NULL;
+      newP->fix_tail = NULL;
+#endif
+      obstack_begin (&newP->frch_obstack, 5000);
+#if __GNUC__ >= 2
+      obstack_alignment_mask (&newP->frch_obstack) = __alignof__ (fragS) - 1;
+#endif
+      newP->frch_frag_now = frag_alloc (&newP->frch_obstack);
+      newP->frch_frag_now->fr_type = rs_fill;
+
+      newP->frch_root = newP->frch_last = newP->frch_frag_now;
+
       *lastPP = newP;
       newP->frch_next = frcP;  /* perhaps NULL */
-      (frcP = newP)->frch_subseg = subseg;
-      newP->frch_seg = seg;
-      newP->frch_last = NULL;
+      frcP = newP;
     }
   /*
-   * Here with frcP ->ing to the frchainS for subseg.
+   * Here with frcP pointing to the frchainS for subseg.
    */
   frchain_now = frcP;
-  /*
-   * Make a fresh frag for the subsegment.
-   */
-  /* We expect this to happen on a correct boundary since it was
-     proceeded by a obstack_done(). */
-  tmp = obstack_alignment_mask (&frags);       /* JF disable alignment */
-  obstack_alignment_mask (&frags) = 0;
-  frag_now = (fragS *) obstack_alloc (&frags, SIZEOF_STRUCT_FRAG);
-  memset (frag_now, 0, SIZEOF_STRUCT_FRAG);
-  obstack_alignment_mask (&frags) = tmp;
-  /* But we want any more chars to come immediately after the
-     structure we just made. */
-  new_fragP = frag_now;
-  new_fragP->fr_next = NULL;
-  /*
-   * Append new frag to current frchain.
-   */
-  former_last_fragP = frcP->frch_last;
-  if (former_last_fragP)
-    {
-      know (former_last_fragP->fr_next == NULL);
-      know (frchain_now->frch_root);
-      former_last_fragP->fr_next = new_fragP;
-    }
-  else
-    {
-      frcP->frch_root = new_fragP;
-    }
-  frcP->frch_last = new_fragP;
+  frag_now = frcP->frch_frag_now;
+
+  assert (frchain_now->frch_last == frag_now);
 }
 
 /*
@@ -362,13 +375,17 @@ subseg_set (seg, subseg)  /* begin assembly for a new sub-segment */
      register subsegT subseg;
 {
 #ifndef MANY_SEGMENTS
-  know (seg == SEG_DATA || seg == SEG_TEXT || seg == SEG_BSS);
+  know (seg == SEG_DATA
+       || seg == SEG_TEXT
+       || seg == SEG_BSS
+       || seg == SEG_ABSOLUTE);
 #endif
 
   if (seg != now_seg || subseg != now_subseg)
     {                          /* we just changed sub-segments */
       subseg_set_rest (seg, subseg);
     }
+  mri_common_symbol = NULL;
 }
 
 #else /* BFD_ASSEMBLER */
@@ -398,19 +415,25 @@ subseg_get (segname, force_new)
   seginfo = seg_info (secptr);
   if (! seginfo)
     {
-      secptr->output_section = secptr;
+      /* Check whether output_section is set first because secptr may
+         be bfd_abs_section_ptr.  */
+      if (secptr->output_section != secptr)
+       secptr->output_section = secptr;
       seginfo = (segment_info_type *) xmalloc (sizeof (*seginfo));
-      seginfo->fix_root = 0;
-      seginfo->fix_tail = 0;
+      memset ((PTR) seginfo, 0, sizeof (*seginfo));
+      seginfo->fix_root = NULL;
+      seginfo->fix_tail = NULL;
       seginfo->bfd_section = secptr;
-      bfd_set_section_userdata (stdoutput, secptr, (char *) seginfo);
-      seginfo->frchainP = 0;
-      seginfo->lineno_list_head = seginfo->lineno_list_tail = 0;
-      seginfo->sym = 0;
-      seginfo->dot = 0;
-      seginfo->hadone = 0;
-      seginfo->user_stuff = 0;
-      seginfo->stabu.stab_string_size = 0;
+      if (secptr == bfd_abs_section_ptr)
+       abs_seg_info = seginfo;
+      else if (secptr == bfd_und_section_ptr)
+       und_seg_info = seginfo;
+      else
+       bfd_set_section_userdata (stdoutput, secptr, (PTR) seginfo);
+      seginfo->frchainP = NULL;
+      seginfo->lineno_list_head = seginfo->lineno_list_tail = NULL;
+      seginfo->sym = NULL;
+      seginfo->dot = NULL;
     }
   return secptr;
 }
@@ -456,6 +479,25 @@ subseg_set (secptr, subseg)
 {
   if (! (secptr == now_seg && subseg == now_subseg))
     subseg_set_rest (secptr, subseg);
+  mri_common_symbol = NULL;
+}
+
+#ifndef obj_sec_sym_ok_for_reloc
+#define obj_sec_sym_ok_for_reloc(SEC)  0
+#endif
+
+/* Get the gas information we are storing for a section.  */
+
+segment_info_type *
+seg_info (sec)
+     segT sec;
+{
+  if (sec == bfd_abs_section_ptr)
+    return abs_seg_info;
+  else if (sec == bfd_und_section_ptr)
+    return und_seg_info;
+  else
+    return (segment_info_type *) bfd_get_section_userdata (stdoutput, sec);
 }
 
 symbolS *
@@ -463,18 +505,36 @@ section_symbol (sec)
      segT sec;
 {
   segment_info_type *seginfo = seg_info (sec);
+  symbolS *s;
 
   if (seginfo == 0)
     abort ();
   if (seginfo->sym)
     return seginfo->sym;
-  seginfo->sym = symbol_find (sec->name);
-  if (!seginfo->sym)
+  s = symbol_find (sec->name);
+  if (!s)
     {
-      seginfo->sym = symbol_make (sec->name);
-      seginfo->sym->bsym = sec->symbol;
+#ifndef EMIT_SECTION_SYMBOLS
+#define EMIT_SECTION_SYMBOLS 1
+#endif
+
+      if (! EMIT_SECTION_SYMBOLS
+#ifdef BFD_ASSEMBLER
+         && symbol_table_frozen
+#endif
+         )
+       /* Here we know it won't be going into the symbol table.  */
+       s = symbol_create (sec->name, sec, 0, &zero_address_frag);
+      else
+       s = symbol_new (sec->name, sec, 0, &zero_address_frag);
+      S_CLEAR_EXTERNAL (s);
+
+      /* Use the BFD section symbol, if possible.  */
+      if (obj_sec_sym_ok_for_reloc (sec))
+       s->bsym = sec->symbol;
     }
-  return seginfo->sym;
+  seginfo->sym = s;
+  return s;
 }
 
 #endif /* BFD_ASSEMBLER */
This page took 0.027941 seconds and 4 git commands to generate.