| /* frags.c - manage frags - | 
 |    Copyright (C) 1987-2016 Free Software Foundation, Inc. | 
 |  | 
 |    This file is part of GAS, the GNU Assembler. | 
 |  | 
 |    GAS is free software; you can redistribute it and/or modify | 
 |    it under the terms of the GNU General Public License as published by | 
 |    the Free Software Foundation; either version 3, or (at your option) | 
 |    any later version. | 
 |  | 
 |    GAS is distributed in the hope that it will be useful, | 
 |    but WITHOUT ANY WARRANTY; without even the implied warranty of | 
 |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
 |    GNU General Public License for more details. | 
 |  | 
 |    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, 51 Franklin Street - Fifth Floor, Boston, MA | 
 |    02110-1301, USA.  */ | 
 |  | 
 | #include "as.h" | 
 | #include "subsegs.h" | 
 | #include "obstack.h" | 
 |  | 
 | extern fragS zero_address_frag; | 
 | extern fragS predefined_address_frag; | 
 |  | 
 | static int totalfrags; | 
 |  | 
 | int | 
 | get_frag_count (void) | 
 | { | 
 |   return totalfrags; | 
 | } | 
 |  | 
 | void | 
 | clear_frag_count (void) | 
 | { | 
 |   totalfrags = 0; | 
 | } | 
 |  | 
 | /* Initialization for frag routines.  */ | 
 |  | 
 | void | 
 | frag_init (void) | 
 | { | 
 |   zero_address_frag.fr_type = rs_fill; | 
 |   predefined_address_frag.fr_type = rs_fill; | 
 | } | 
 |  | 
 | /* Check that we're not trying to assemble into a section that can't | 
 |    allocate frags (currently, this is only possible in the absolute | 
 |    section), or into an mri common.  */ | 
 |  | 
 | static void | 
 | frag_alloc_check (const struct obstack *ob) | 
 | { | 
 |   if (ob->chunk_size == 0) | 
 |     { | 
 |       as_bad (_("attempt to allocate data in absolute section")); | 
 |       subseg_set (text_section, 0); | 
 |     } | 
 |  | 
 |   if (mri_common_symbol != NULL) | 
 |     { | 
 |       as_bad (_("attempt to allocate data in common section")); | 
 |       mri_common_symbol = NULL; | 
 |     } | 
 | } | 
 |  | 
 | /* Allocate a frag on the specified obstack. | 
 |    Call this routine from everywhere else, so that all the weird alignment | 
 |    hackery can be done in just one place.  */ | 
 |  | 
 | fragS * | 
 | frag_alloc (struct obstack *ob) | 
 | { | 
 |   fragS *ptr; | 
 |   int oalign; | 
 |  | 
 |   (void) obstack_alloc (ob, 0); | 
 |   oalign = obstack_alignment_mask (ob); | 
 |   obstack_alignment_mask (ob) = 0; | 
 |   ptr = (fragS *) obstack_alloc (ob, SIZEOF_STRUCT_FRAG); | 
 |   obstack_alignment_mask (ob) = oalign; | 
 |   memset (ptr, 0, SIZEOF_STRUCT_FRAG); | 
 |   totalfrags++; | 
 |   return ptr; | 
 | } | 
 |  | 
 | /* Try to augment current frag by nchars chars. | 
 |    If there is no room, close of the current frag with a ".fill 0" | 
 |    and begin a new frag. Unless the new frag has nchars chars available | 
 |    do not return. Do not set up any fields of *now_frag.  */ | 
 |  | 
 | void | 
 | frag_grow (size_t nchars) | 
 | { | 
 |   if (obstack_room (&frchain_now->frch_obstack) < nchars) | 
 |     { | 
 |       size_t oldc; | 
 |       size_t newc; | 
 |  | 
 |       /* Try to allocate a bit more than needed right now.  But don't do | 
 |          this if we would waste too much memory.  Especially necessary | 
 |          for extremely big (like 2GB initialized) frags.  */ | 
 |       if (nchars < 0x10000) | 
 |         newc = 2 * nchars; | 
 |       else | 
 |         newc = nchars + 0x10000; | 
 |       newc += SIZEOF_STRUCT_FRAG; | 
 |  | 
 |       /* Check for possible overflow.  */ | 
 |       if (newc < nchars) | 
 |         as_fatal (_("can't extend frag %lu chars"), (unsigned long) nchars); | 
 |  | 
 |       /* Force to allocate at least NEWC bytes, but not less than the | 
 |          default.  */ | 
 |       oldc = obstack_chunk_size (&frchain_now->frch_obstack); | 
 |       if (newc > oldc) | 
 | 	obstack_chunk_size (&frchain_now->frch_obstack) = newc; | 
 |  | 
 |       while (obstack_room (&frchain_now->frch_obstack) < nchars) | 
 |         { | 
 |           /* Not enough room in this frag.  Close it and start a new one. | 
 |              This must be done in a loop because the created frag may not | 
 |              be big enough if the current obstack chunk is used.  */ | 
 |           frag_wane (frag_now); | 
 |           frag_new (0); | 
 |         } | 
 |  | 
 |       /* Restore the old chunk size.  */ | 
 |       obstack_chunk_size (&frchain_now->frch_obstack) = oldc; | 
 |     } | 
 | } | 
 |  | 
 | /* Call this to close off a completed frag, and start up a new (empty) | 
 |    frag, in the same subsegment as the old frag. | 
 |    [frchain_now remains the same but frag_now is updated.] | 
 |    Because this calculates the correct value of fr_fix by | 
 |    looking at the obstack 'frags', it needs to know how many | 
 |    characters at the end of the old frag belong to the maximal | 
 |    variable part;  The rest must belong to fr_fix. | 
 |    It doesn't actually set up the old frag's fr_var.  You may have | 
 |    set fr_var == 1, but allocated 10 chars to the end of the frag; | 
 |    In this case you pass old_frags_var_max_size == 10. | 
 |    In fact, you may use fr_var for something totally unrelated to the | 
 |    size of the variable part of the frag;  None of the generic frag | 
 |    handling code makes use of fr_var. | 
 |  | 
 |    Make a new frag, initialising some components. Link new frag at end | 
 |    of frchain_now.  */ | 
 |  | 
 | void | 
 | frag_new (size_t old_frags_var_max_size | 
 | 	  /* Number of chars (already allocated on obstack frags) in | 
 | 	     variable_length part of frag.  */) | 
 | { | 
 |   fragS *former_last_fragP; | 
 |   frchainS *frchP; | 
 |  | 
 |   gas_assert (frchain_now->frch_last == frag_now); | 
 |  | 
 |   /* Fix up old frag's fr_fix.  */ | 
 |   frag_now->fr_fix = frag_now_fix_octets () - old_frags_var_max_size; | 
 |   /* Make sure its type is valid.  */ | 
 |   gas_assert (frag_now->fr_type != 0); | 
 |  | 
 |   /* This will align the obstack so the next struct we allocate on it | 
 |      will begin at a correct boundary.  */ | 
 |   obstack_finish (&frchain_now->frch_obstack); | 
 |   frchP = frchain_now; | 
 |   know (frchP); | 
 |   former_last_fragP = frchP->frch_last; | 
 |   gas_assert (former_last_fragP != 0); | 
 |   gas_assert (former_last_fragP == frag_now); | 
 |   frag_now = frag_alloc (&frchP->frch_obstack); | 
 |  | 
 |   as_where (&frag_now->fr_file, &frag_now->fr_line); | 
 |  | 
 |   /* Generally, frag_now->points to an address rounded up to next | 
 |      alignment.  However, characters will add to obstack frags | 
 |      IMMEDIATELY after the struct frag, even if they are not starting | 
 |      at an alignment address.  */ | 
 |   former_last_fragP->fr_next = frag_now; | 
 |   frchP->frch_last = frag_now; | 
 |  | 
 | #ifndef NO_LISTING | 
 |   { | 
 |     extern struct list_info_struct *listing_tail; | 
 |     frag_now->line = listing_tail; | 
 |   } | 
 | #endif | 
 |  | 
 |   gas_assert (frchain_now->frch_last == frag_now); | 
 |  | 
 |   frag_now->fr_next = NULL; | 
 | } | 
 |  | 
 | /* Start a new frag unless we have n more chars of room in the current frag. | 
 |    Close off the old frag with a .fill 0. | 
 |  | 
 |    Return the address of the 1st char to write into. Advance | 
 |    frag_now_growth past the new chars.  */ | 
 |  | 
 | char * | 
 | frag_more (size_t nchars) | 
 | { | 
 |   char *retval; | 
 |  | 
 |   frag_alloc_check (&frchain_now->frch_obstack); | 
 |   frag_grow (nchars); | 
 |   retval = obstack_next_free (&frchain_now->frch_obstack); | 
 |   obstack_blank_fast (&frchain_now->frch_obstack, nchars); | 
 |   return retval; | 
 | } | 
 |  | 
 | /* Close the current frag, setting its fields for a relaxable frag.  Start a | 
 |    new frag.  */ | 
 |  | 
 | static void | 
 | frag_var_init (relax_stateT type, size_t max_chars, size_t var, | 
 | 	       relax_substateT subtype, symbolS *symbol, offsetT offset, | 
 |                char *opcode) | 
 | { | 
 |   frag_now->fr_var = var; | 
 |   frag_now->fr_type = type; | 
 |   frag_now->fr_subtype = subtype; | 
 |   frag_now->fr_symbol = symbol; | 
 |   frag_now->fr_offset = offset; | 
 |   frag_now->fr_opcode = opcode; | 
 | #ifdef USING_CGEN | 
 |   frag_now->fr_cgen.insn = 0; | 
 |   frag_now->fr_cgen.opindex = 0; | 
 |   frag_now->fr_cgen.opinfo = 0; | 
 | #endif | 
 | #ifdef TC_FRAG_INIT | 
 |   TC_FRAG_INIT (frag_now); | 
 | #endif | 
 |   as_where (&frag_now->fr_file, &frag_now->fr_line); | 
 |  | 
 |   frag_new (max_chars); | 
 | } | 
 |  | 
 | /* Start a new frag unless we have max_chars more chars of room in the | 
 |    current frag.  Close off the old frag with a .fill 0. | 
 |  | 
 |    Set up a machine_dependent relaxable frag, then start a new frag. | 
 |    Return the address of the 1st char of the var part of the old frag | 
 |    to write into.  */ | 
 |  | 
 | char * | 
 | frag_var (relax_stateT type, size_t max_chars, size_t var, | 
 | 	  relax_substateT subtype, symbolS *symbol, offsetT offset, | 
 | 	  char *opcode) | 
 | { | 
 |   char *retval; | 
 |  | 
 |   frag_grow (max_chars); | 
 |   retval = obstack_next_free (&frchain_now->frch_obstack); | 
 |   obstack_blank_fast (&frchain_now->frch_obstack, max_chars); | 
 |   frag_var_init (type, max_chars, var, subtype, symbol, offset, opcode); | 
 |   return retval; | 
 | } | 
 |  | 
 | /* OVE: This variant of frag_var assumes that space for the tail has been | 
 | 	allocated by caller. | 
 | 	No call to frag_grow is done.  */ | 
 |  | 
 | char * | 
 | frag_variant (relax_stateT type, size_t max_chars, size_t var, | 
 | 	      relax_substateT subtype, symbolS *symbol, offsetT offset, | 
 | 	      char *opcode) | 
 | { | 
 |   char *retval; | 
 |  | 
 |   retval = obstack_next_free (&frchain_now->frch_obstack); | 
 |   frag_var_init (type, max_chars, var, subtype, symbol, offset, opcode); | 
 |  | 
 |   return retval; | 
 | } | 
 |  | 
 | /* Reduce the variable end of a frag to a harmless state.  */ | 
 |  | 
 | void | 
 | frag_wane (fragS *fragP) | 
 | { | 
 |   fragP->fr_type = rs_fill; | 
 |   fragP->fr_offset = 0; | 
 |   fragP->fr_var = 0; | 
 | } | 
 |  | 
 | /* Return the number of bytes by which the current frag can be grown.  */ | 
 |  | 
 | size_t | 
 | frag_room (void) | 
 | { | 
 |   return obstack_room (&frchain_now->frch_obstack); | 
 | } | 
 |  | 
 | /* Make an alignment frag.  The size of this frag will be adjusted to | 
 |    force the next frag to have the appropriate alignment.  ALIGNMENT | 
 |    is the power of two to which to align.  FILL_CHARACTER is the | 
 |    character to use to fill in any bytes which are skipped.  MAX is | 
 |    the maximum number of characters to skip when doing the alignment, | 
 |    or 0 if there is no maximum.  */ | 
 |  | 
 | void | 
 | frag_align (int alignment, int fill_character, int max) | 
 | { | 
 |   if (now_seg == absolute_section) | 
 |     { | 
 |       addressT new_off; | 
 |       addressT mask; | 
 |  | 
 |       mask = (~(addressT) 0) << alignment; | 
 |       new_off = (abs_section_offset + ~mask) & mask; | 
 |       if (max == 0 || new_off - abs_section_offset <= (addressT) max) | 
 | 	abs_section_offset = new_off; | 
 |     } | 
 |   else | 
 |     { | 
 |       char *p; | 
 |  | 
 |       p = frag_var (rs_align, 1, 1, (relax_substateT) max, | 
 | 		    (symbolS *) 0, (offsetT) alignment, (char *) 0); | 
 |       *p = fill_character; | 
 |     } | 
 | } | 
 |  | 
 | /* Make an alignment frag like frag_align, but fill with a repeating | 
 |    pattern rather than a single byte.  ALIGNMENT is the power of two | 
 |    to which to align.  FILL_PATTERN is the fill pattern to repeat in | 
 |    the bytes which are skipped.  N_FILL is the number of bytes in | 
 |    FILL_PATTERN.  MAX is the maximum number of characters to skip when | 
 |    doing the alignment, or 0 if there is no maximum.  */ | 
 |  | 
 | void | 
 | frag_align_pattern (int alignment, const char *fill_pattern, | 
 | 		    size_t n_fill, int max) | 
 | { | 
 |   char *p; | 
 |  | 
 |   p = frag_var (rs_align, n_fill, n_fill, (relax_substateT) max, | 
 | 		(symbolS *) 0, (offsetT) alignment, (char *) 0); | 
 |   memcpy (p, fill_pattern, n_fill); | 
 | } | 
 |  | 
 | /* The NOP_OPCODE is for the alignment fill value.  Fill it with a nop | 
 |    instruction so that the disassembler does not choke on it.  */ | 
 | #ifndef NOP_OPCODE | 
 | #define NOP_OPCODE 0x00 | 
 | #endif | 
 |  | 
 | /* Use this to restrict the amount of memory allocated for representing | 
 |    the alignment code.  Needs to be large enough to hold any fixed sized | 
 |    prologue plus the replicating portion.  */ | 
 | #ifndef MAX_MEM_FOR_RS_ALIGN_CODE | 
 |   /* Assume that if HANDLE_ALIGN is not defined then no special action | 
 |      is required to code fill, which means that we get just repeat the | 
 |      one NOP_OPCODE byte.  */ | 
 | # ifndef HANDLE_ALIGN | 
 | #  define MAX_MEM_FOR_RS_ALIGN_CODE  1 | 
 | # else | 
 | #  define MAX_MEM_FOR_RS_ALIGN_CODE  ((1 << alignment) - 1) | 
 | # endif | 
 | #endif | 
 |  | 
 | void | 
 | frag_align_code (int alignment, int max) | 
 | { | 
 |   char *p; | 
 |  | 
 |   p = frag_var (rs_align_code, MAX_MEM_FOR_RS_ALIGN_CODE, 1, | 
 | 		(relax_substateT) max, (symbolS *) 0, | 
 | 		(offsetT) alignment, (char *) 0); | 
 |   *p = NOP_OPCODE; | 
 | } | 
 |  | 
 | addressT | 
 | frag_now_fix_octets (void) | 
 | { | 
 |   if (now_seg == absolute_section) | 
 |     return abs_section_offset; | 
 |  | 
 |   return ((char *) obstack_next_free (&frchain_now->frch_obstack) | 
 | 	  - frag_now->fr_literal); | 
 | } | 
 |  | 
 | addressT | 
 | frag_now_fix (void) | 
 | { | 
 |   return frag_now_fix_octets () / OCTETS_PER_BYTE; | 
 | } | 
 |  | 
 | void | 
 | frag_append_1_char (int datum) | 
 | { | 
 |   frag_alloc_check (&frchain_now->frch_obstack); | 
 |   if (obstack_room (&frchain_now->frch_obstack) <= 1) | 
 |     { | 
 |       frag_wane (frag_now); | 
 |       frag_new (0); | 
 |     } | 
 |   obstack_1grow (&frchain_now->frch_obstack, datum); | 
 | } | 
 |  | 
 | /* Return TRUE if FRAG1 and FRAG2 have a fixed relationship between | 
 |    their start addresses.  Set OFFSET to the difference in address | 
 |    not already accounted for in the frag FR_ADDRESS.  */ | 
 |  | 
 | bfd_boolean | 
 | frag_offset_fixed_p (const fragS *frag1, const fragS *frag2, offsetT *offset) | 
 | { | 
 |   const fragS *frag; | 
 |   offsetT off; | 
 |  | 
 |   /* Start with offset initialised to difference between the two frags. | 
 |      Prior to assigning frag addresses this will be zero.  */ | 
 |   off = frag1->fr_address - frag2->fr_address; | 
 |   if (frag1 == frag2) | 
 |     { | 
 |       *offset = off; | 
 |       return TRUE; | 
 |     } | 
 |  | 
 |   /* Maybe frag2 is after frag1.  */ | 
 |   frag = frag1; | 
 |   while (frag->fr_type == rs_fill) | 
 |     { | 
 |       off += frag->fr_fix + frag->fr_offset * frag->fr_var; | 
 |       frag = frag->fr_next; | 
 |       if (frag == NULL) | 
 | 	break; | 
 |       if (frag == frag2) | 
 | 	{ | 
 | 	  *offset = off; | 
 | 	  return TRUE; | 
 | 	} | 
 |     } | 
 |  | 
 |   /* Maybe frag1 is after frag2.  */ | 
 |   off = frag1->fr_address - frag2->fr_address; | 
 |   frag = frag2; | 
 |   while (frag->fr_type == rs_fill) | 
 |     { | 
 |       off -= frag->fr_fix + frag->fr_offset * frag->fr_var; | 
 |       frag = frag->fr_next; | 
 |       if (frag == NULL) | 
 | 	break; | 
 |       if (frag == frag1) | 
 | 	{ | 
 | 	  *offset = off; | 
 | 	  return TRUE; | 
 | 	} | 
 |     } | 
 |  | 
 |   return FALSE; | 
 | } |