X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gas%2Ffrags.c;h=f930268d264e8947d5a7fe8b2039b24c657de58c;hb=cc9ad334a71b0c032f711e86885fb73821f3be16;hp=83625d7fbf608d357eac8c9093a9bfaa09376200;hpb=0530d30a58dd8ba07c9f0b9ab30d11835d3fb7c3;p=deliverable%2Fbinutils-gdb.git diff --git a/gas/frags.c b/gas/frags.c index 83625d7fbf..f930268d26 100644 --- a/gas/frags.c +++ b/gas/frags.c @@ -1,13 +1,11 @@ /* frags.c - manage frags - - Copyright 1987, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2003 - Free Software Foundation, Inc. + Copyright (C) 1987-2015 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 2, or (at your option) + 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, @@ -17,15 +15,29 @@ 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, 59 Temple Place - Suite 330, Boston, MA - 02111-1307, USA. */ + 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 bss_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. */ @@ -33,7 +45,7 @@ void frag_init (void) { zero_address_frag.fr_type = rs_fill; - bss_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 @@ -72,6 +84,7 @@ frag_alloc (struct obstack *ob) ptr = (fragS *) obstack_alloc (ob, SIZEOF_STRUCT_FRAG); obstack_alignment_mask (ob) = oalign; memset (ptr, 0, SIZEOF_STRUCT_FRAG); + totalfrags++; return ptr; } @@ -81,28 +94,44 @@ frag_alloc (struct obstack *ob) do not return. Do not set up any fields of *now_frag. */ void -frag_grow (unsigned int nchars) +frag_grow (size_t nchars) { if (obstack_room (&frchain_now->frch_obstack) < nchars) { - unsigned int n; - long oldc; - - frag_wane (frag_now); - frag_new (0); - oldc = frchain_now->frch_obstack.chunk_size; - frchain_now->frch_obstack.chunk_size = 2 * nchars + SIZEOF_STRUCT_FRAG; - if (frchain_now->frch_obstack.chunk_size > 0) - while ((n = obstack_room (&frchain_now->frch_obstack)) < nchars - && (unsigned long) frchain_now->frch_obstack.chunk_size > nchars) - { - frag_wane (frag_now); - frag_new (0); - } - frchain_now->frch_obstack.chunk_size = oldc; + 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; } - if (obstack_room (&frchain_now->frch_obstack) < nchars) - as_fatal (_("can't extend frag %u chars"), nchars); } /* Call this to close off a completed frag, and start up a new (empty) @@ -123,19 +152,19 @@ frag_grow (unsigned int nchars) of frchain_now. */ void -frag_new (int old_frags_var_max_size +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; - assert (frchain_now->frch_last == frag_now); + 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. */ - assert (frag_now->fr_type != 0); + 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. */ @@ -143,8 +172,8 @@ frag_new (int old_frags_var_max_size frchP = frchain_now; know (frchP); former_last_fragP = frchP->frch_last; - assert (former_last_fragP != 0); - assert (former_last_fragP == frag_now); + 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); @@ -163,7 +192,7 @@ frag_new (int old_frags_var_max_size } #endif - assert (frchain_now->frch_last == frag_now); + gas_assert (frchain_now->frch_last == frag_now); frag_now->fr_next = NULL; } @@ -175,33 +204,25 @@ frag_new (int old_frags_var_max_size frag_now_growth past the new chars. */ char * -frag_more (int nchars) +frag_more (size_t nchars) { - register char *retval; + 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); + return retval; } -/* 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. */ +/* Close the current frag, setting its fields for a relaxable frag. Start a + new frag. */ -char * -frag_var (relax_stateT type, int max_chars, int var, relax_substateT subtype, - symbolS *symbol, offsetT offset, char *opcode) +static void +frag_var_init (relax_stateT type, size_t max_chars, size_t var, + relax_substateT subtype, symbolS *symbol, offsetT offset, + char *opcode) { - register char *retval; - - frag_grow (max_chars); - retval = obstack_next_free (&frchain_now->frch_obstack); - obstack_blank_fast (&frchain_now->frch_obstack, max_chars); frag_now->fr_var = var; frag_now->fr_type = type; frag_now->fr_subtype = subtype; @@ -217,8 +238,29 @@ frag_var (relax_stateT type, int max_chars, int var, relax_substateT subtype, TC_FRAG_INIT (frag_now); #endif as_where (&frag_now->fr_file, &frag_now->fr_line); + frag_new (max_chars); - return (retval); +} + +/* 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 @@ -226,36 +268,22 @@ frag_var (relax_stateT type, int max_chars, int var, relax_substateT subtype, No call to frag_grow is done. */ char * -frag_variant (relax_stateT type, int max_chars, int var, +frag_variant (relax_stateT type, size_t max_chars, size_t var, relax_substateT subtype, symbolS *symbol, offsetT offset, char *opcode) { - register char *retval; + char *retval; retval = obstack_next_free (&frchain_now->frch_obstack); - 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); - return (retval); + 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 (register fragS *fragP) +frag_wane (fragS *fragP) { fragP->fr_type = rs_fill; fragP->fr_offset = 0; @@ -264,7 +292,7 @@ frag_wane (register fragS *fragP) /* Return the number of bytes by which the current frag can be grown. */ -int +size_t frag_room (void) { return obstack_room (&frchain_now->frch_obstack); @@ -309,7 +337,7 @@ frag_align (int alignment, int fill_character, int max) void frag_align_pattern (int alignment, const char *fill_pattern, - int n_fill, int max) + size_t n_fill, int max) { char *p; @@ -376,3 +404,56 @@ frag_append_1_char (int datum) } 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; +}