diff options
-rw-r--r-- | gcc/ChangeLog | 62 | ||||
-rw-r--r-- | gcc/ada/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/ada/utils.c | 8 | ||||
-rw-r--r-- | gcc/config/elfos.h | 2 | ||||
-rw-r--r-- | gcc/config/iq2000/iq2000.c | 5 | ||||
-rw-r--r-- | gcc/config/stormy16/stormy16.c | 4 | ||||
-rw-r--r-- | gcc/config/v850/v850.c | 5 | ||||
-rw-r--r-- | gcc/cp/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/cp/decl.c | 11 | ||||
-rw-r--r-- | gcc/doc/rtl.texi | 2 | ||||
-rw-r--r-- | gcc/doc/tm.texi | 25 | ||||
-rw-r--r-- | gcc/explow.c | 1 | ||||
-rw-r--r-- | gcc/output.h | 56 | ||||
-rw-r--r-- | gcc/rtl.h | 4 | ||||
-rw-r--r-- | gcc/target-def.h | 5 | ||||
-rw-r--r-- | gcc/target.h | 4 | ||||
-rw-r--r-- | gcc/varasm.c | 460 |
17 files changed, 432 insertions, 232 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7967d68..55bb0ad 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,65 @@ +2006-03-02 Richard Sandiford <richard@codesourcery.com> + + * doc/tm.texi (TARGET_HAVE_SWITCHABLE_BSS_SECTIONS): Document. + (ASM_OUTPUT_BSS): Describe the two ways of handling global BSS, + and say that only one is needed. + * doc/rtl.texi (SYMBOL_REF_BLOCK): Say that the block can be null. + * target.h (have_switchable_bss_sections): New hook. + * explow.c (use_anchored_address): Check that the symbol is in a block. + * varasm.c (tls_comm_section, comm_section, lcomm_section) + (bss_noswitch_section): New variables. + (get_unnamed_section): Add SECTION_UNNAMED to the flags. + (get_noswitch_section): New function. + (get_block_for_section): Allow SECT to be null. + (unlikely_text_section_p): Use SECTION_STYLE. + (bss_initializer_p): New function. + (get_variable_section): Move earlier in file. Take a new argument, + prefer_noswitch_p. Move bss checks from assemble_variable to here. + Return one of the new *_sections in such cases. + (get_block_for_decl): New function, extracting some logic from + use_blocks_for_decl_p. + (change_symbol_section): Remove in favor of... + (change_symbol_block): ...this new function. + (use_blocks_for_decl_p): Remove checks now performed by + get_block_for_decl. + (make_decl_rtl): Use change_symbol_block and get_block_for_decl. + (ASM_EMIT_LOCAL, ASM_EMIT_BSS, ASM_EMIT_COMMON): Delete in favor of... + (emit_local, emit_bss, emit_common): ...these new functions. + Return true if the alignment was honored. + (emit_tls_common): New function. + (asm_emit_uninitialised): Delete. + (assemble_variable_noswitch): New function, split out from... + (assemble_variable): ...here. Don't make decisions about common + variables here. Globalize all public decls that go into non-common + sections. Check whether SYMBOL_REF_BLOCK is null. + (output_constant_def_contents): Check whether SYMBOL_REF_BLOCK is null. + (output_constant_pool): Likewise. + (init_varasm_once): Initialize the new section variables. + (have_global_bss_p): New function. + (categorize_decl_for_section): Use bss_initializer_p. + (switch_to_section): Use SECTION_STYLE. Abort for SECTION_NOSWITCH. + (place_block_symbol): Assert that the symbol must be in a block. + * target-def.h (TARGET_HAVE_SWITCHABLE_BSS_SECTIONS): New macro. + (TARGET_INITIALIZER): Include it. + * rtl.h (SYMBOL_REF_BLOCK): Document the null alternative. + * output.h (SECTION_STYLE_MASK, SECTION_COMMON): New macros. + (SECTION_MACH_DEP): Bump by two. + (SECTION_UNNAMED, SECTION_NOSWITCH): New macros. + (unnamed_section): Mention SECTION_UNNAMED in comment. + (named_section): Likewise SECTION_NAMED. + (noswitch_section_callback): New type. + (noswitch_section): New structure. + (section): Add a noswitch_section alternative. + (SECTION_STYLE): New macro. + (tls_comm_section, comm_section, lcomm_section): Declare. + (bss_noswitch_section, have_global_bss_p): Declare. + * config/elfos.h (TARGET_HAVE_SWITCHABLE_BSS_SECTIONS): Override. + * config/iq2000/iq2000.c (TARGET_HAVE_SWITCHABLE_BSS_SECTIONS): + Override. + * config/v850/v850.c (TARGET_HAVE_SWITCHABLE_BSS_SECTIONS): Override. + * config/stormy16/stormy16.c (TARGET_HAVE_SWITCHABLE_BSS_SECTIONS): + Override. + 2006-03-02 Daniel Berlin <dberlin@dberlin.org> * gcc/tree-vrp.c (execute_vrp): Return value. diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog index c5ecc91..d87a8d6 100644 --- a/gcc/ada/ChangeLog +++ b/gcc/ada/ChangeLog @@ -1,3 +1,8 @@ +2006-03-02 Richard Sandiford <richard@codesourcery.com> + + * utils.c (create_var_decl): Use have_global_bss_p when deciding + whether to make the decl common. + 2006-02-20 Rafael Ávila de Espíndola <rafael.espindola@gmail.com> * Make-lang.in (Ada): Remove (.PHONY): Remove Ada diff --git a/gcc/ada/utils.c b/gcc/ada/utils.c index 78c1237..a3fdb0d 100644 --- a/gcc/ada/utils.c +++ b/gcc/ada/utils.c @@ -1293,10 +1293,10 @@ create_var_decl (tree var_name, tree asm_name, tree type, tree var_init, try to fiddle with DECL_COMMON. However, on platforms that don't support global BSS sections, uninitialized global variables would go in DATA instead, thus increasing the size of the executable. */ -#if !defined(ASM_OUTPUT_BSS) && !defined(ASM_OUTPUT_ALIGNED_BSS) - if (TREE_CODE (var_decl) == VAR_DECL) - DECL_COMMON (var_decl) = !flag_no_common; -#endif + if (!flag_no_common + && TREE_CODE (var_decl) == VAR_DECL + && !have_global_bss_p ()) + DECL_COMMON (var_decl) = 1; DECL_INITIAL (var_decl) = var_init; TREE_READONLY (var_decl) = const_flag; DECL_EXTERNAL (var_decl) = extern_flag; diff --git a/gcc/config/elfos.h b/gcc/config/elfos.h index 181072c..31e309d 100644 --- a/gcc/config/elfos.h +++ b/gcc/config/elfos.h @@ -221,6 +221,8 @@ Boston, MA 02110-1301, USA. */ #define TARGET_ASM_SELECT_RTX_SECTION default_elf_select_rtx_section #undef TARGET_ASM_SELECT_SECTION #define TARGET_ASM_SELECT_SECTION default_elf_select_section +#undef TARGET_HAVE_SWITCHABLE_BSS_SECTIONS +#define TARGET_HAVE_SWITCHABLE_BSS_SECTIONS true /* Define the strings used for the special svr4 .type and .size directives. These strings generally do not vary from one system running svr4 to diff --git a/gcc/config/iq2000/iq2000.c b/gcc/config/iq2000/iq2000.c index dd42fe9..4b1cb3e 100644 --- a/gcc/config/iq2000/iq2000.c +++ b/gcc/config/iq2000/iq2000.c @@ -186,6 +186,11 @@ static int iq2000_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode, #undef TARGET_ASM_SELECT_SECTION #define TARGET_ASM_SELECT_SECTION iq2000_select_section +/* The assembler supports switchable .bss sections, but + iq2000_select_section doesn't yet make use of them. */ +#undef TARGET_HAVE_SWITCHABLE_BSS_SECTIONS +#define TARGET_HAVE_SWITCHABLE_BSS_SECTIONS false + #undef TARGET_PROMOTE_FUNCTION_ARGS #define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_true #undef TARGET_PROMOTE_FUNCTION_RETURN diff --git a/gcc/config/stormy16/stormy16.c b/gcc/config/stormy16/stormy16.c index 76becfc..32513d2 100644 --- a/gcc/config/stormy16/stormy16.c +++ b/gcc/config/stormy16/stormy16.c @@ -2653,6 +2653,10 @@ xstormy16_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED) #undef TARGET_ENCODE_SECTION_INFO #define TARGET_ENCODE_SECTION_INFO xstormy16_encode_section_info +/* select_section doesn't handle .bss_below100. */ +#undef TARGET_HAVE_SWITCHABLE_BSS_SECTIONS +#define TARGET_HAVE_SWITCHABLE_BSS_SECTIONS false + #undef TARGET_ASM_OUTPUT_MI_THUNK #define TARGET_ASM_OUTPUT_MI_THUNK xstormy16_asm_output_mi_thunk #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK diff --git a/gcc/config/v850/v850.c b/gcc/config/v850/v850.c index 7629a7a..eb2771c 100644 --- a/gcc/config/v850/v850.c +++ b/gcc/config/v850/v850.c @@ -117,6 +117,11 @@ static GTY(()) section *zbss_section; #undef TARGET_ASM_SELECT_SECTION #define TARGET_ASM_SELECT_SECTION v850_select_section +/* The assembler supports switchable .bss sections, but + v850_select_section doesn't yet make use of them. */ +#undef TARGET_HAVE_SWITCHABLE_BSS_SECTIONS +#define TARGET_HAVE_SWITCHABLE_BSS_SECTIONS false + #undef TARGET_ENCODE_SECTION_INFO #define TARGET_ENCODE_SECTION_INFO v850_encode_section_info diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index c092c39..71541e1 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,8 @@ +2006-03-02 Richard Sandiford <richard@codesourcery.com> + + * decl.c (start_decl): Use have_global_bss_p when deciding + whether to make the decl common. + 2006-03-01 Mike Stump <mrs@apple.com> PR darwin/25908 diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 21ef001..a9aec67 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -3824,16 +3824,17 @@ start_decl (const cp_declarator *declarator, if (tem == error_mark_node) return error_mark_node; -#if ! defined (ASM_OUTPUT_BSS) && ! defined (ASM_OUTPUT_ALIGNED_BSS) /* Tell the back-end to use or not use .common as appropriate. If we say -fconserve-space, we want this to save .data space, at the expense of wrong semantics. If we say -fno-conserve-space, we want this to produce errors about redefs; to do this we force variables into the data segment. */ - DECL_COMMON (tem) = ((TREE_CODE (tem) != VAR_DECL - || !DECL_THREAD_LOCAL_P (tem)) - && (flag_conserve_space || ! TREE_PUBLIC (tem))); -#endif + if (flag_conserve_space + && TREE_CODE (tem) == VAR_DECL + && TREE_PUBLIC (tem) + && !DECL_THREAD_LOCAL_P (tem) + && !have_global_bss_p ()) + DECL_COMMON (tem) = 1; if (! processing_template_decl) start_decl_1 (tem); diff --git a/gcc/doc/rtl.texi b/gcc/doc/rtl.texi index de4a8e73..76b3a3c 100644 --- a/gcc/doc/rtl.texi +++ b/gcc/doc/rtl.texi @@ -528,7 +528,7 @@ the target's use. @findex SYMBOL_REF_BLOCK @item SYMBOL_REF_BLOCK (@var{x}) If @samp{SYMBOL_REF_IN_BLOCK_P (@var{x})}, this is the @samp{object_block} -structure to which the symbol belongs. The value is always nonnull. +structure to which the symbol belongs, or @code{NULL} if none. @findex SYMBOL_REF_BLOCK_OFFSET @item SYMBOL_REF_BLOCK_OFFSET (@var{x}) diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 778ecc9..e99989f 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -6477,6 +6477,13 @@ specify an alignment within the section directive need pay attention to This flag is true if the target supports @code{TARGET_ASM_NAMED_SECTION}. @end deftypefn +@anchor{TARGET_HAVE_SWITCHABLE_BSS_SECTIONS} +@deftypefn {Target Hook} bool TARGET_HAVE_SWITCHABLE_BSS_SECTIONS +This flag is true if we can create zeroed data by switching to a BSS +section and then using @code{ASM_OUTPUT_SKIP} to allocate the space. +This is true on most ELF targets. +@end deftypefn + @deftypefn {Target Hook} {unsigned int} TARGET_SECTION_TYPE_FLAGS (tree @var{decl}, const char *@var{name}, int @var{reloc}) Choose a set of section attributes for use by @code{TARGET_ASM_NAMED_SECTION} based on a variable or function decl, a section name, and whether or not the @@ -6705,13 +6712,17 @@ defining this macro. If unable, use the expression before and after that, output the additional assembler syntax for defining the name, and a newline. -This macro controls how the assembler definitions of uninitialized global -variables are output. This macro exists to properly support languages like -C++ which do not have @code{common} data. However, this macro currently -is not defined for all targets. If this macro and -@code{ASM_OUTPUT_ALIGNED_BSS} are not defined then @code{ASM_OUTPUT_COMMON} -or @code{ASM_OUTPUT_ALIGNED_COMMON} or -@code{ASM_OUTPUT_ALIGNED_DECL_COMMON} is used. +There are two ways of handling global BSS. One is to define either +this macro or its aligned counterpart, @code{ASM_OUTPUT_ALIGNED_BSS}. +The other is to have @code{TARGET_ASM_SELECT_SECTION} return a +switchable BSS section (@pxref{TARGET_HAVE_SWITCHABLE_BSS_SECTIONS}). +You do not need to do both. + +Some languages do not have @code{common} data, and require a +non-common form of global BSS in order to handle uninitialized globals +efficiently. C++ is one example of this. However, if the target does +not support global BSS, the front end may choose to make globals +common in order to save space in the object file. @end defmac @defmac ASM_OUTPUT_ALIGNED_BSS (@var{stream}, @var{decl}, @var{name}, @var{size}, @var{alignment}) diff --git a/gcc/explow.c b/gcc/explow.c index b56373c..361c717 100644 --- a/gcc/explow.c +++ b/gcc/explow.c @@ -568,6 +568,7 @@ use_anchored_address (rtx x) if (GET_CODE (base) != SYMBOL_REF || !SYMBOL_REF_IN_BLOCK_P (base) || SYMBOL_REF_ANCHOR_P (base) + || SYMBOL_REF_BLOCK (base) == NULL || !targetm.use_anchors_for_symbol_p (base)) return x; diff --git a/gcc/output.h b/gcc/output.h index 5fda5ea..8974351 100644 --- a/gcc/output.h +++ b/gcc/output.h @@ -402,8 +402,22 @@ extern void no_asm_to_stream (FILE *); #define SECTION_TLS 0x40000 /* contains thread-local storage */ #define SECTION_NOTYPE 0x80000 /* don't output @progbits */ #define SECTION_DECLARED 0x100000 /* section has been used */ -#define SECTION_NAMED 0x200000 /* section has a name */ -#define SECTION_MACH_DEP 0x400000 /* subsequent bits reserved for target */ +#define SECTION_STYLE_MASK 0x600000 /* bits used for SECTION_STYLE */ +#define SECTION_COMMON 0x800000 /* contains common data */ +#define SECTION_MACH_DEP 0x1000000 /* subsequent bits reserved for target */ + +/* This SECTION_STYLE is used for unnamed sections that we can switch + to using a special assembler directive. */ +#define SECTION_UNNAMED 0x000000 + +/* This SECTION_STYLE is used for named sections that we can switch + to using a general section directive. */ +#define SECTION_NAMED 0x200000 + +/* This SECTION_STYLE is used for sections that we cannot switch to at + all. The choice of section is implied by the directive that we use + to declare the object. */ +#define SECTION_NOSWITCH 0x400000 /* A helper function for default_elf_select_section and default_elf_unique_section. Categorizes the DECL. */ @@ -448,7 +462,7 @@ struct section_common GTY(()) { unsigned int flags; }; -/* Information that is provided by named sections. */ +/* Information about a SECTION_NAMED section. */ struct named_section GTY(()) { struct section_common common; @@ -464,7 +478,7 @@ struct named_section GTY(()) { section. The argument provides callback-specific data. */ typedef void (*unnamed_section_callback) (const void *); -/* Information that is provided by unnamed sections. */ +/* Information about a SECTION_UNNAMED section. */ struct unnamed_section GTY(()) { struct section_common common; @@ -477,14 +491,39 @@ struct unnamed_section GTY(()) { section *next; }; +/* A callback that writes the assembly code for a decl in a + SECTION_NOSWITCH section. DECL is the decl that should be assembled + and NAME is the name of its SYMBOL_REF. SIZE is the size of the decl + in bytes and ROUNDED is that size rounded up to the next + BIGGEST_ALIGNMENT / BITS_PER_UNIT boundary. + + Return true if the callback used DECL_ALIGN to set the object's + alignment. A false return value implies that we are relying + on the rounded size to align the decl. */ +typedef bool (*noswitch_section_callback) (tree decl, const char *name, + unsigned HOST_WIDE_INT size, + unsigned HOST_WIDE_INT rounded); + +/* Information about a SECTION_NOSWITCH section. */ +struct noswitch_section GTY(()) { + struct section_common common; + + /* The callback used to assemble decls in this section. */ + noswitch_section_callback GTY ((skip)) callback; +}; + /* Information about a section, which may be named or unnamed. */ -union section GTY ((desc ("(%h).common.flags & SECTION_NAMED"))) +union section GTY ((desc ("SECTION_STYLE (&(%h))"))) { struct section_common GTY ((skip)) common; struct named_section GTY ((tag ("SECTION_NAMED"))) named; - struct unnamed_section GTY ((tag ("0"))) unnamed; + struct unnamed_section GTY ((tag ("SECTION_UNNAMED"))) unnamed; + struct noswitch_section GTY ((tag ("SECTION_NOSWITCH"))) noswitch; }; +/* Return the style of section SECT. */ +#define SECTION_STYLE(SECT) ((SECT)->common.flags & SECTION_STYLE_MASK) + struct object_block; /* Special well-known sections. */ @@ -498,6 +537,10 @@ extern GTY(()) section *bss_section; extern GTY(()) section *sbss_section; extern GTY(()) section *exception_section; extern GTY(()) section *eh_frame_section; +extern GTY(()) section *tls_comm_section; +extern GTY(()) section *comm_section; +extern GTY(()) section *lcomm_section; +extern GTY(()) section *bss_noswitch_section; extern GTY(()) section *in_section; extern GTY(()) bool in_cold_section_p; @@ -523,6 +566,7 @@ extern void output_section_asm_op (const void *); extern unsigned int default_section_type_flags (tree, const char *, int); extern unsigned int default_section_type_flags_1 (tree, const char *, int, int); +extern bool have_global_bss_p (void); extern void default_no_named_section (const char *, unsigned int, tree); extern void default_elf_asm_named_section (const char *, unsigned int, tree); extern enum section_category categorize_decl_for_section (tree, int, int); @@ -1331,8 +1331,8 @@ do { \ #define SYMBOL_FLAG_MACH_DEP_SHIFT 9 #define SYMBOL_FLAG_MACH_DEP (1 << SYMBOL_FLAG_MACH_DEP_SHIFT) -/* The block to which the given SYMBOL_REF belongs. Only valid if - SYMBOL_REF_IN_BLOCK_P (RTX). */ +/* The block to which the given SYMBOL_REF belongs, or NULL if none. + Only valid if SYMBOL_REF_IN_BLOCK_P (RTX). */ #define SYMBOL_REF_BLOCK(RTX) (BLOCK_SYMBOL_CHECK (RTX)->block) /* The byte offset of the given SYMBOL_REF from the start of its block, diff --git a/gcc/target-def.h b/gcc/target-def.h index c292567..fa38166 100644 --- a/gcc/target-def.h +++ b/gcc/target-def.h @@ -140,6 +140,10 @@ Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # endif #endif +#ifndef TARGET_HAVE_SWITCHABLE_BSS_SECTIONS +#define TARGET_HAVE_SWITCHABLE_BSS_SECTIONS false +#endif + #ifndef TARGET_ASM_INIT_SECTIONS #define TARGET_ASM_INIT_SECTIONS hook_void_void #endif @@ -651,6 +655,7 @@ Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. TARGET_EXTRA_LIVE_ON_ENTRY, \ TARGET_UNWIND_TABLES_DEFAULT, \ TARGET_HAVE_NAMED_SECTIONS, \ + TARGET_HAVE_SWITCHABLE_BSS_SECTIONS, \ TARGET_HAVE_CTORS_DTORS, \ TARGET_HAVE_TLS, \ TARGET_HAVE_SRODATA_SECTION, \ diff --git a/gcc/target.h b/gcc/target.h index 63f5d4e..e6e6ba8 100644 --- a/gcc/target.h +++ b/gcc/target.h @@ -734,6 +734,10 @@ struct gcc_target /* True if arbitrary sections are supported. */ bool have_named_sections; + /* True if we can create zeroed data by switching to a BSS section + and then using ASM_OUTPUT_SKIP to allocate the space. */ + bool have_switchable_bss_sections; + /* True if "native" constructors and destructors are supported, false if we're using collect2 for the job. */ bool have_ctors_dtors; diff --git a/gcc/varasm.c b/gcc/varasm.c index f07ed39..801d11e 100644 --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -138,9 +138,6 @@ static void asm_output_aligned_bss (FILE *, tree, const char *, ATTRIBUTE_UNUSED; #endif #endif /* BSS_SECTION_ASM_OP */ -static bool asm_emit_uninitialised (tree, const char*, - unsigned HOST_WIDE_INT, - unsigned HOST_WIDE_INT); static void mark_weak (tree); /* Well-known sections, each one associated with some sort of *_ASM_OP. */ @@ -153,6 +150,15 @@ section *dtors_section; section *bss_section; section *sbss_section; +/* Various forms of common section. All are guaranteed to be nonnull. */ +section *tls_comm_section; +section *comm_section; +section *lcomm_section; + +/* A SECTION_NOSWITCH section used for declaring global BSS variables. + May be null. */ +section *bss_noswitch_section; + /* The section that holds the main exception table, when known. The section is set either by the target's init_sections hook or by the first call to switch_to_exception_section. */ @@ -245,7 +251,7 @@ get_unnamed_section (unsigned int flags, void (*callback) (const void *), section *sect; sect = ggc_alloc (sizeof (struct unnamed_section)); - sect->unnamed.common.flags = flags; + sect->unnamed.common.flags = flags | SECTION_UNNAMED; sect->unnamed.callback = callback; sect->unnamed.data = data; sect->unnamed.next = unnamed_sections; @@ -254,6 +260,20 @@ get_unnamed_section (unsigned int flags, void (*callback) (const void *), return sect; } +/* Return a SECTION_NOSWITCH section with the given fields. */ + +static section * +get_noswitch_section (unsigned int flags, noswitch_section_callback callback) +{ + section *sect; + + sect = ggc_alloc (sizeof (struct unnamed_section)); + sect->noswitch.common.flags = flags | SECTION_NOSWITCH; + sect->noswitch.callback = callback; + + return sect; +} + /* Return the named section structure associated with NAME. Create a new section with the given fields if no such structure exists. */ @@ -300,7 +320,8 @@ use_object_blocks_p (void) } /* Return the object_block structure for section SECT. Create a new - structure if we haven't created one already. */ + structure if we haven't created one already. Return null if SECT + itself is null. */ static struct object_block * get_block_for_section (section *sect) @@ -308,6 +329,9 @@ get_block_for_section (section *sect) struct object_block *block; void **slot; + if (sect == NULL) + return NULL; + slot = htab_find_slot_with_hash (object_block_htab, sect, hash_section (sect), INSERT); block = (struct object_block *) *slot; @@ -409,7 +433,7 @@ unlikely_text_section_p (section *sect) return (name && sect - && (sect->common.flags & SECTION_NAMED) != 0 + && SECTION_STYLE (sect) == SECTION_NAMED && strcmp (name, sect->named.name) == 0); } @@ -786,81 +810,127 @@ decode_reg_name (const char *asmspec) return -1; } -/* Return true if it is possible to put DECL in an object_block. */ +/* Return true if DECL's initializer is suitable for a BSS section. */ static bool -use_blocks_for_decl_p (tree decl) +bss_initializer_p (tree decl) { - /* Only data DECLs can be placed into object blocks. */ - if (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != CONST_DECL) - return false; + return (DECL_INITIAL (decl) == NULL + || DECL_INITIAL (decl) == error_mark_node + || (flag_zero_initialized_in_bss + /* Leave constant zeroes in .rodata so they + can be shared. */ + && !TREE_READONLY (decl) + && initializer_zerop (DECL_INITIAL (decl)))); +} + +/* Return the section into which the given VAR_DECL or CONST_DECL + should be placed. PREFER_NOSWITCH_P is true if a noswitch + section should be used wherever possible. */ + +static section * +get_variable_section (tree decl, bool prefer_noswitch_p) +{ + int reloc; + + /* If the decl has been given an explicit section name, then it + isn't common, and shouldn't be handled as such. */ + if (DECL_COMMON (decl) && DECL_SECTION_NAME (decl) == NULL) + { + if (DECL_THREAD_LOCAL_P (decl)) + return tls_comm_section; + if (TREE_PUBLIC (decl) && bss_initializer_p (decl)) + return comm_section; + } + + if (DECL_INITIAL (decl) == error_mark_node) + reloc = contains_pointers_p (TREE_TYPE (decl)) ? 3 : 0; + else if (DECL_INITIAL (decl)) + reloc = compute_reloc_for_constant (DECL_INITIAL (decl)); + else + reloc = 0; + + resolve_unique_section (decl, reloc, flag_data_sections); + if (IN_NAMED_SECTION (decl)) + return get_named_section (decl, NULL, reloc); + + if (!DECL_THREAD_LOCAL_P (decl) + && !(prefer_noswitch_p && targetm.have_switchable_bss_sections) + && bss_initializer_p (decl)) + { + if (!TREE_PUBLIC (decl)) + return lcomm_section; + if (bss_noswitch_section) + return bss_noswitch_section; + } + + return targetm.asm_out.select_section (decl, reloc, DECL_ALIGN (decl)); +} + +/* Return the block into which object_block DECL should be placed. */ + +static struct object_block * +get_block_for_decl (tree decl) +{ + section *sect; if (TREE_CODE (decl) == VAR_DECL) { /* The object must be defined in this translation unit. */ if (DECL_EXTERNAL (decl)) - return false; + return NULL; /* There's no point using object blocks for something that is isolated by definition. */ if (DECL_ONE_ONLY (decl)) - return false; - - /* Symbols that use .common cannot be put into blocks. */ - if (DECL_COMMON (decl) && DECL_INITIAL (decl) == NULL) - return false; + return NULL; } /* We can only calculate block offsets if the decl has a known constant size. */ if (DECL_SIZE_UNIT (decl) == NULL) - return false; + return NULL; if (!host_integerp (DECL_SIZE_UNIT (decl), 1)) - return false; + return NULL; - /* Detect decls created by dw2_force_const_mem. Such decls are - special because DECL_INITIAL doesn't specify the decl's true value. - dw2_output_indirect_constants will instead call assemble_variable - with dont_output_data set to 1 and then print the contents itself. */ - if (DECL_INITIAL (decl) == decl) - return false; + /* Find out which section should contain DECL. We cannot put it into + an object block if it requires a standalone definition. */ + sect = get_variable_section (decl, true); + if (SECTION_STYLE (sect) == SECTION_NOSWITCH) + return NULL; - return true; + return get_block_for_section (sect); } -/* Make sure block symbol SYMBOL is in section SECT, moving it to a - different block if necessary. */ +/* Make sure block symbol SYMBOL is in block BLOCK. */ static void -change_symbol_section (rtx symbol, section *sect) +change_symbol_block (rtx symbol, struct object_block *block) { - if (sect != SYMBOL_REF_BLOCK (symbol)->sect) + if (block != SYMBOL_REF_BLOCK (symbol)) { gcc_assert (SYMBOL_REF_BLOCK_OFFSET (symbol) < 0); - SYMBOL_REF_BLOCK (symbol) = get_block_for_section (sect); + SYMBOL_REF_BLOCK (symbol) = block; } } -/* Return the section into which the given VAR_DECL or CONST_DECL - should be placed. */ +/* Return true if it is possible to put DECL in an object_block. */ -static section * -get_variable_section (tree decl) +static bool +use_blocks_for_decl_p (tree decl) { - int reloc; + /* Only data DECLs can be placed into object blocks. */ + if (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != CONST_DECL) + return false; - if (DECL_INITIAL (decl) == error_mark_node) - reloc = contains_pointers_p (TREE_TYPE (decl)) ? 3 : 0; - else if (DECL_INITIAL (decl)) - reloc = compute_reloc_for_constant (DECL_INITIAL (decl)); - else - reloc = 0; + /* Detect decls created by dw2_force_const_mem. Such decls are + special because DECL_INITIAL doesn't specify the decl's true value. + dw2_output_indirect_constants will instead call assemble_variable + with dont_output_data set to 1 and then print the contents itself. */ + if (DECL_INITIAL (decl) == decl) + return false; - resolve_unique_section (decl, reloc, flag_data_sections); - if (IN_NAMED_SECTION (decl)) - return get_named_section (decl, NULL, reloc); - else - return targetm.asm_out.select_section (decl, reloc, DECL_ALIGN (decl)); + return true; } /* Create the DECL_RTL for a VAR_DECL or FUNCTION_DECL. DECL should @@ -921,7 +991,7 @@ make_decl_rtl (tree decl) if (MEM_P (x) && GET_CODE (XEXP (x, 0)) == SYMBOL_REF && SYMBOL_REF_IN_BLOCK_P (XEXP (x, 0))) - change_symbol_section (XEXP (x, 0), get_variable_section (decl)); + change_symbol_block (XEXP (x, 0), get_block_for_decl (decl)); /* Make this function static known to the mudflap runtime. */ if (flag_mudflap && TREE_CODE (decl) == VAR_DECL) @@ -1020,10 +1090,7 @@ make_decl_rtl (tree decl) DECL_COMMON (decl) = 0; if (use_object_blocks_p () && use_blocks_for_decl_p (decl)) - { - section *sect = get_variable_section (decl); - x = create_block_symbol (name, get_block_for_section (sect), -1); - } + x = create_block_symbol (name, get_block_for_decl (decl), -1); else x = gen_rtx_SYMBOL_REF (Pmode, name); SYMBOL_REF_WEAK (x) = DECL_WEAK (decl); @@ -1458,100 +1525,110 @@ assemble_string (const char *p, int size) } -#if defined ASM_OUTPUT_ALIGNED_DECL_LOCAL -#define ASM_EMIT_LOCAL(decl, name, size, rounded) \ - ASM_OUTPUT_ALIGNED_DECL_LOCAL (asm_out_file, decl, name, size, DECL_ALIGN (decl)) -#else -#if defined ASM_OUTPUT_ALIGNED_LOCAL -#define ASM_EMIT_LOCAL(decl, name, size, rounded) \ - ASM_OUTPUT_ALIGNED_LOCAL (asm_out_file, name, size, DECL_ALIGN (decl)) +/* A noswitch_section_callback for lcomm_section. */ + +static bool +emit_local (tree decl ATTRIBUTE_UNUSED, + const char *name ATTRIBUTE_UNUSED, + unsigned HOST_WIDE_INT size ATTRIBUTE_UNUSED, + unsigned HOST_WIDE_INT rounded ATTRIBUTE_UNUSED) +{ +#if defined ASM_OUTPUT_ALIGNED_DECL_LOCAL + ASM_OUTPUT_ALIGNED_DECL_LOCAL (asm_out_file, decl, name, + size, DECL_ALIGN (decl)); + return true; +#elif defined ASM_OUTPUT_ALIGNED_LOCAL + ASM_OUTPUT_ALIGNED_LOCAL (asm_out_file, name, size, DECL_ALIGN (decl)); + return true; #else -#define ASM_EMIT_LOCAL(decl, name, size, rounded) \ - ASM_OUTPUT_LOCAL (asm_out_file, name, size, rounded) -#endif + ASM_OUTPUT_LOCAL (asm_out_file, name, size, rounded); + return false; #endif +} +/* A noswitch_section_callback for bss_noswitch_section. */ + +#if defined ASM_OUTPUT_ALIGNED_BSS || defined ASM_OUTPUT_BSS +static bool +emit_bss (tree decl ATTRIBUTE_UNUSED, + const char *name ATTRIBUTE_UNUSED, + unsigned HOST_WIDE_INT size ATTRIBUTE_UNUSED, + unsigned HOST_WIDE_INT rounded ATTRIBUTE_UNUSED) +{ #if defined ASM_OUTPUT_ALIGNED_BSS -#define ASM_EMIT_BSS(decl, name, size, rounded) \ - ASM_OUTPUT_ALIGNED_BSS (asm_out_file, decl, name, size, DECL_ALIGN (decl)) -#else -#if defined ASM_OUTPUT_BSS -#define ASM_EMIT_BSS(decl, name, size, rounded) \ - ASM_OUTPUT_BSS (asm_out_file, decl, name, size, rounded) + ASM_OUTPUT_ALIGNED_BSS (asm_out_file, decl, name, size, DECL_ALIGN (decl)); + return true; #else -#undef ASM_EMIT_BSS + ASM_OUTPUT_BSS (asm_out_file, decl, name, size, rounded); + return false; #endif +} #endif +/* A noswitch_section_callback for comm_section. */ + +static bool +emit_common (tree decl ATTRIBUTE_UNUSED, + const char *name ATTRIBUTE_UNUSED, + unsigned HOST_WIDE_INT size ATTRIBUTE_UNUSED, + unsigned HOST_WIDE_INT rounded ATTRIBUTE_UNUSED) +{ #if defined ASM_OUTPUT_ALIGNED_DECL_COMMON -#define ASM_EMIT_COMMON(decl, name, size, rounded) \ - ASM_OUTPUT_ALIGNED_DECL_COMMON (asm_out_file, decl, name, size, DECL_ALIGN (decl)) -#else -#if defined ASM_OUTPUT_ALIGNED_COMMON -#define ASM_EMIT_COMMON(decl, name, size, rounded) \ - ASM_OUTPUT_ALIGNED_COMMON (asm_out_file, name, size, DECL_ALIGN (decl)) + ASM_OUTPUT_ALIGNED_DECL_COMMON (asm_out_file, decl, name, + size, DECL_ALIGN (decl)); + return true; +#elif defined ASM_OUTPUT_ALIGNED_COMMON + ASM_OUTPUT_ALIGNED_COMMON (asm_out_file, name, size, DECL_ALIGN (decl)); + return true; #else -#define ASM_EMIT_COMMON(decl, name, size, rounded) \ - ASM_OUTPUT_COMMON (asm_out_file, name, size, rounded) -#endif + ASM_OUTPUT_COMMON (asm_out_file, name, size, rounded); + return false; #endif +} + +/* A noswitch_section_callback for tls_comm_section. */ static bool -asm_emit_uninitialised (tree decl, const char *name, - unsigned HOST_WIDE_INT size ATTRIBUTE_UNUSED, - unsigned HOST_WIDE_INT rounded ATTRIBUTE_UNUSED) +emit_tls_common (tree decl ATTRIBUTE_UNUSED, + const char *name ATTRIBUTE_UNUSED, + unsigned HOST_WIDE_INT size ATTRIBUTE_UNUSED, + unsigned HOST_WIDE_INT rounded ATTRIBUTE_UNUSED) { - enum - { - asm_dest_common, - asm_dest_bss, - asm_dest_local - } - destination = asm_dest_local; - - /* ??? We should handle .bss via select_section mechanisms rather than - via special target hooks. That would eliminate this special case. */ - if (TREE_PUBLIC (decl)) - { - if (!DECL_COMMON (decl)) -#ifdef ASM_EMIT_BSS - destination = asm_dest_bss; +#ifdef ASM_OUTPUT_TLS_COMMON + ASM_OUTPUT_TLS_COMMON (asm_out_file, decl, name, size); + return true; #else - return false; + sorry ("thread-local COMMON data not implemented"); + return true; #endif - else - destination = asm_dest_common; - } +} - if (destination != asm_dest_common) - { - resolve_unique_section (decl, 0, flag_data_sections); - /* Custom sections don't belong here. */ - if (DECL_SECTION_NAME (decl)) - return false; - } +/* Assemble DECL given that it belongs in SECTION_NOSWITCH section SECT. + NAME is the name of DECL's SYMBOL_REF. */ - if (destination == asm_dest_bss) - globalize_decl (decl); +static void +assemble_noswitch_variable (tree decl, const char *name, section *sect) +{ + unsigned HOST_WIDE_INT size, rounded; - switch (destination) - { -#ifdef ASM_EMIT_BSS - case asm_dest_bss: - ASM_EMIT_BSS (decl, name, size, rounded); - break; -#endif - case asm_dest_common: - ASM_EMIT_COMMON (decl, name, size, rounded); - break; - case asm_dest_local: - ASM_EMIT_LOCAL (decl, name, size, rounded); - break; - default: - gcc_unreachable (); - } + size = tree_low_cst (DECL_SIZE_UNIT (decl), 1); + rounded = size; - return true; + /* Don't allocate zero bytes of common, + since that means "undefined external" in the linker. */ + if (size == 0) + rounded = 1; + + /* Round size up to multiple of BIGGEST_ALIGNMENT bits + so that each uninitialized object starts on such a boundary. */ + rounded += (BIGGEST_ALIGNMENT / BITS_PER_UNIT) - 1; + rounded = (rounded / (BIGGEST_ALIGNMENT / BITS_PER_UNIT) + * (BIGGEST_ALIGNMENT / BITS_PER_UNIT)); + + if (!sect->noswitch.callback (decl, name, size, rounded) + && (unsigned HOST_WIDE_INT) DECL_ALIGN_UNIT (decl) > rounded) + warning (0, "requested alignment for %q+D is greater than " + "implemented alignment of %wu", decl, rounded); } /* A subroutine of assemble_variable. Output the label and contents of @@ -1602,8 +1679,8 @@ assemble_variable (tree decl, int top_level ATTRIBUTE_UNUSED, { const char *name; unsigned int align; - rtx decl_rtl; - bool in_block_p; + rtx decl_rtl, symbol; + section *sect; if (lang_hooks.decls.prepare_assemble_variable) lang_hooks.decls.prepare_assemble_variable (decl); @@ -1675,8 +1752,8 @@ assemble_variable (tree decl, int top_level ATTRIBUTE_UNUSED, gcc_assert (MEM_P (decl_rtl)); gcc_assert (GET_CODE (XEXP (decl_rtl, 0)) == SYMBOL_REF); - in_block_p = SYMBOL_REF_IN_BLOCK_P (XEXP (decl_rtl, 0)); - name = XSTR (XEXP (decl_rtl, 0), 0); + symbol = XEXP (decl_rtl, 0); + name = XSTR (symbol, 0); if (TREE_PUBLIC (decl) && DECL_NAME (decl)) notice_global_symbol (decl); @@ -1724,70 +1801,11 @@ assemble_variable (tree decl, int top_level ATTRIBUTE_UNUSED, if (DECL_PRESERVE_P (decl)) targetm.asm_out.mark_decl_preserved (name); - /* Handle uninitialized definitions. */ - - /* If the decl has been given an explicit section name, then it - isn't common, and shouldn't be handled as such. */ - if (DECL_SECTION_NAME (decl) || dont_output_data) - ; - else if (DECL_THREAD_LOCAL_P (decl)) - { - if (DECL_COMMON (decl)) - { -#ifdef ASM_OUTPUT_TLS_COMMON - unsigned HOST_WIDE_INT size; - - size = tree_low_cst (DECL_SIZE_UNIT (decl), 1); - ASM_OUTPUT_TLS_COMMON (asm_out_file, decl, name, size); - return; -#else - sorry ("thread-local COMMON data not implemented"); -#endif - } - } - /* Do not handle decls as common if they will be assigned a - specific section position. */ - else if (in_block_p) - ; - else if (DECL_INITIAL (decl) == 0 - || DECL_INITIAL (decl) == error_mark_node - || (flag_zero_initialized_in_bss - /* Leave constant zeroes in .rodata so they can be shared. */ - && !TREE_READONLY (decl) - && initializer_zerop (DECL_INITIAL (decl)))) - { - unsigned HOST_WIDE_INT size = tree_low_cst (DECL_SIZE_UNIT (decl), 1); - unsigned HOST_WIDE_INT rounded = size; - - /* Don't allocate zero bytes of common, - since that means "undefined external" in the linker. */ - if (size == 0) - rounded = 1; - - /* Round size up to multiple of BIGGEST_ALIGNMENT bits - so that each uninitialized object starts on such a boundary. */ - rounded += (BIGGEST_ALIGNMENT / BITS_PER_UNIT) - 1; - rounded = (rounded / (BIGGEST_ALIGNMENT / BITS_PER_UNIT) - * (BIGGEST_ALIGNMENT / BITS_PER_UNIT)); - -#if !defined(ASM_OUTPUT_ALIGNED_COMMON) && !defined(ASM_OUTPUT_ALIGNED_DECL_COMMON) && !defined(ASM_OUTPUT_ALIGNED_BSS) - if ((unsigned HOST_WIDE_INT) DECL_ALIGN_UNIT (decl) > rounded) - warning (0, "requested alignment for %q+D is greater than " - "implemented alignment of %wu", decl, rounded); -#endif - - /* If the target cannot output uninitialized but not common global data - in .bss, then we have to use .data, so fall through. */ - if (asm_emit_uninitialised (decl, name, size, rounded)) - return; - } - - /* Handle initialized definitions. - Also handle uninitialized global definitions if -fno-common and the - target doesn't support ASM_OUTPUT_BSS. */ - /* First make the assembler name(s) global if appropriate. */ - if (TREE_PUBLIC (decl) && DECL_NAME (decl)) + sect = get_variable_section (decl, false); + if (TREE_PUBLIC (decl) + && DECL_NAME (decl) + && (sect->common.flags & SECTION_COMMON) == 0) globalize_decl (decl); /* Output any data that we will need to use the address of. */ @@ -1801,14 +1819,16 @@ assemble_variable (tree decl, int top_level ATTRIBUTE_UNUSED, /* If the decl is part of an object_block, make sure that the decl has been positioned within its block, but do not write out its definition yet. output_object_blocks will do that later. */ - if (in_block_p) + if (SYMBOL_REF_IN_BLOCK_P (symbol) && SYMBOL_REF_BLOCK (symbol)) { gcc_assert (!dont_output_data); - place_block_symbol (XEXP (decl_rtl, 0)); + place_block_symbol (symbol); } + else if (SECTION_STYLE (sect) == SECTION_NOSWITCH) + assemble_noswitch_variable (decl, name, sect); else { - switch_to_section (get_variable_section (decl)); + switch_to_section (sect); if (align > BITS_PER_UNIT) ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (DECL_ALIGN_UNIT (decl))); assemble_variable_contents (decl, name, dont_output_data); @@ -2927,7 +2947,7 @@ output_constant_def_contents (rtx symbol) /* If the constant is part of an object block, make sure that the decl has been positioned within its block, but do not write out its definition yet. output_object_blocks will do that later. */ - if (SYMBOL_REF_IN_BLOCK_P (symbol)) + if (SYMBOL_REF_IN_BLOCK_P (symbol) && SYMBOL_REF_BLOCK (symbol)) place_block_symbol (symbol); else { @@ -3488,7 +3508,7 @@ output_constant_pool (const char *fnname ATTRIBUTE_UNUSED, the constant has been positioned within its block, but do not write out its definition yet. output_object_blocks will do that later. */ - if (SYMBOL_REF_IN_BLOCK_P (desc->sym)) + if (SYMBOL_REF_IN_BLOCK_P (desc->sym) && SYMBOL_REF_BLOCK (desc->sym)) place_block_symbol (desc->sym); else { @@ -5085,6 +5105,18 @@ init_varasm_once (void) SBSS_SECTION_ASM_OP); #endif + tls_comm_section = get_noswitch_section (SECTION_WRITE | SECTION_BSS + | SECTION_COMMON, emit_tls_common); + lcomm_section = get_noswitch_section (SECTION_WRITE | SECTION_BSS + | SECTION_COMMON, emit_local); + comm_section = get_noswitch_section (SECTION_WRITE | SECTION_BSS + | SECTION_COMMON, emit_common); + +#if defined ASM_OUTPUT_ALIGNED_BSS || defined ASM_OUTPUT_BSS + bss_noswitch_section = get_noswitch_section (SECTION_WRITE | SECTION_BSS, + emit_bss); +#endif + targetm.asm_out.init_sections (); if (readonly_data_section == NULL) @@ -5191,6 +5223,16 @@ default_section_type_flags_1 (tree decl, const char *name, int reloc, return flags; } +/* Return true if the target supports some form of global BSS, + either through bss_noswitch_section, or by selecting a BSS + section in TARGET_ASM_SELECT_SECTION. */ + +bool +have_global_bss_p (void) +{ + return bss_noswitch_section || targetm.have_switchable_bss_sections; +} + /* Output assembly to switch to section NAME with attribute FLAGS. Four variants for common object file formats. */ @@ -5344,12 +5386,7 @@ categorize_decl_for_section (tree decl, int reloc, int shlib) } else if (TREE_CODE (decl) == VAR_DECL) { - if (DECL_INITIAL (decl) == NULL - || DECL_INITIAL (decl) == error_mark_node - || (flag_zero_initialized_in_bss - /* Leave constant zeroes in .rodata so they can be shared. */ - && !TREE_READONLY (decl) - && initializer_zerop (DECL_INITIAL (decl)))) + if (bss_initializer_p (decl)) ret = SECCAT_BSS; else if (! TREE_READONLY (decl) || TREE_SIDE_EFFECTS (decl) @@ -5888,8 +5925,9 @@ switch_to_section (section *new_section) else in_section = new_section; - if (new_section->common.flags & SECTION_NAMED) + switch (SECTION_STYLE (new_section)) { + case SECTION_NAMED: if (cfun && !cfun->unlikely_text_section_name && strcmp (new_section->named.name, @@ -5899,9 +5937,16 @@ switch_to_section (section *new_section) targetm.asm_out.named_section (new_section->named.name, new_section->named.common.flags, new_section->named.decl); + break; + + case SECTION_UNNAMED: + new_section->unnamed.callback (new_section->unnamed.data); + break; + + case SECTION_NOSWITCH: + gcc_unreachable (); + break; } - else - new_section->unnamed.callback (new_section->unnamed.data); new_section->common.flags |= SECTION_DECLARED; } @@ -5918,6 +5963,7 @@ place_block_symbol (rtx symbol) struct object_block *block; tree decl; + gcc_assert (SYMBOL_REF_BLOCK (symbol)); if (SYMBOL_REF_BLOCK_OFFSET (symbol) >= 0) return; |