X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fvarasm.c;h=5728d195e095e018067440670c13a664a4c8cb75;hb=f1bc4b8ef9d942882057523ac52bb85edde7b915;hp=511bf89e6ec080379566cb705581eff18daff76a;hpb=0de36bdb2d7fa28a41b67b7ab3f8ccb92e1d2e03;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/varasm.c b/gcc/varasm.c index 511bf89e6ec..5728d195e09 100644 --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -7,7 +7,7 @@ This file is part of GCC. GCC 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) any later +Software Foundation; either version 3, or (at your option) any later version. GCC is distributed in the hope that it will be useful, but WITHOUT ANY @@ -16,9 +16,8 @@ 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 GCC; see the file COPYING. If not, write to the Free -Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301, USA. */ +along with GCC; see the file COPYING3. If not see +. */ /* This file handles generation of all the assembler code @@ -49,6 +48,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "tm_p.h" #include "debug.h" #include "target.h" +#include "targhooks.h" #include "tree-mudflap.h" #include "cgraph.h" #include "cfglayout.h" @@ -71,17 +71,7 @@ struct addr_const; struct constant_descriptor_rtx; struct rtx_constant_pool; -struct varasm_status GTY(()) -{ - /* If we're using a per-function constant pool, this is it. */ - struct rtx_constant_pool *pool; - - /* Number of tree-constants deferred during the expansion of this - function. */ - unsigned int deferred_constants; -}; - -#define n_deferred_constants (cfun->varasm->deferred_constants) +#define n_deferred_constants (crtl->varasm.deferred_constants) /* Number for making the label on the next constant that is stored in memory. */ @@ -108,7 +98,7 @@ bool first_function_block_is_cold; /* We give all constants their own alias set. Perhaps redundant with MEM_READONLY_P, but pre-dates it. */ -static HOST_WIDE_INT const_alias_set; +static alias_set_type const_alias_set; static const char *strip_reg_name (const char *); static int contains_pointers_p (tree); @@ -205,68 +195,95 @@ static GTY(()) struct rtx_constant_pool *shared_constant_pool; static GTY ((if_marked ("tree_map_marked_p"), param_is (struct tree_map))) htab_t emutls_htab; static GTY (()) tree emutls_object_type; - -#ifndef NO_DOT_IN_LABEL -# define EMUTLS_VAR_PREFIX "__emutls_v." -# define EMUTLS_TMPL_PREFIX "__emutls_t." -#elif !defined NO_DOLLAR_IN_LABEL -# define EMUTLS_VAR_PREFIX "__emutls_v$" -# define EMUTLS_TMPL_PREFIX "__emutls_t$" +/* Emulated TLS objects have the TLS model TLS_MODEL_EMULATED. This + macro can be used on them to distinguish the control variable from + the initialization template. */ +#define DECL_EMUTLS_VAR_P(D) (TREE_TYPE (D) == emutls_object_type) + +#if !defined (NO_DOT_IN_LABEL) +# define EMUTLS_SEPARATOR "." +#elif !defined (NO_DOLLAR_IN_LABEL) +# define EMUTLS_SEPARATOR "$" #else -# define EMUTLS_VAR_PREFIX "__emutls_v_" -# define EMUTLS_TMPL_PREFIX "__emutls_t_" +# define EMUTLS_SEPARATOR "_" #endif -/* Create an identifier for the struct __emutls_object, given an identifier - of the DECL_ASSEMBLY_NAME of the original object. */ +/* Create an IDENTIFIER_NODE by prefixing PREFIX to the + IDENTIFIER_NODE NAME's name. */ static tree -get_emutls_object_name (tree name) +prefix_name (const char *prefix, tree name) { - char *toname = alloca (strlen (IDENTIFIER_POINTER (name)) - + sizeof (EMUTLS_VAR_PREFIX)); - strcpy (toname, EMUTLS_VAR_PREFIX); - strcpy (toname + sizeof (EMUTLS_VAR_PREFIX) - 1, IDENTIFIER_POINTER (name)); + unsigned plen = strlen (prefix); + unsigned nlen = strlen (IDENTIFIER_POINTER (name)); + char *toname = (char *) alloca (plen + nlen + 1); + + memcpy (toname, prefix, plen); + memcpy (toname + plen, IDENTIFIER_POINTER (name), nlen + 1); return get_identifier (toname); } -/* Create the structure for struct __emutls_object. This should match the - structure at the top of emutls.c, modulo the union there. */ +/* Create an identifier for the struct __emutls_object, given an identifier + of the DECL_ASSEMBLY_NAME of the original object. */ static tree -get_emutls_object_type (void) +get_emutls_object_name (tree name) { - tree type, type_name, field, next_field, word_type_node; - - type = emutls_object_type; - if (type) - return type; - - emutls_object_type = type = lang_hooks.types.make_type (RECORD_TYPE); - type_name = get_identifier ("__emutls_object"); - type_name = build_decl (TYPE_DECL, type_name, type); - TYPE_NAME (type) = type_name; + const char *prefix = (targetm.emutls.var_prefix + ? targetm.emutls.var_prefix + : "__emutls_v" EMUTLS_SEPARATOR); + return prefix_name (prefix, name); +} +tree +default_emutls_var_fields (tree type, tree *name ATTRIBUTE_UNUSED) +{ + tree word_type_node, field, next_field; + field = build_decl (FIELD_DECL, get_identifier ("__templ"), ptr_type_node); DECL_CONTEXT (field) = type; next_field = field; - - field = build_decl (FIELD_DECL, get_identifier ("__offset"), ptr_type_node); + + field = build_decl (FIELD_DECL, get_identifier ("__offset"), + ptr_type_node); DECL_CONTEXT (field) = type; TREE_CHAIN (field) = next_field; next_field = field; - + word_type_node = lang_hooks.types.type_for_mode (word_mode, 1); - field = build_decl (FIELD_DECL, get_identifier ("__align"), word_type_node); + field = build_decl (FIELD_DECL, get_identifier ("__align"), + word_type_node); DECL_CONTEXT (field) = type; TREE_CHAIN (field) = next_field; next_field = field; - + field = build_decl (FIELD_DECL, get_identifier ("__size"), word_type_node); DECL_CONTEXT (field) = type; TREE_CHAIN (field) = next_field; + return field; +} + +/* Create the structure for struct __emutls_object. This should match the + structure at the top of emutls.c, modulo the union there. */ + +static tree +get_emutls_object_type (void) +{ + tree type, type_name, field; + + type = emutls_object_type; + if (type) + return type; + + emutls_object_type = type = lang_hooks.types.make_type (RECORD_TYPE); + type_name = NULL; + field = targetm.emutls.var_fields (type, &type_name); + if (!type_name) + type_name = get_identifier ("__emutls_object"); + type_name = build_decl (TYPE_DECL, type_name, type); + TYPE_NAME (type) = type_name; TYPE_FIELDS (type) = field; layout_type (type); @@ -280,26 +297,30 @@ static tree get_emutls_init_templ_addr (tree decl) { tree name, to; - char *toname; - - if (!DECL_INITIAL (decl)) + + if (targetm.emutls.register_common && !DECL_INITIAL (decl) + && !DECL_SECTION_NAME (decl)) return null_pointer_node; name = DECL_ASSEMBLER_NAME (decl); - toname = alloca (strlen (IDENTIFIER_POINTER (name)) - + sizeof (EMUTLS_TMPL_PREFIX)); - strcpy (toname, EMUTLS_TMPL_PREFIX); - strcpy (toname + sizeof (EMUTLS_TMPL_PREFIX) - 1, IDENTIFIER_POINTER (name)); - name = get_identifier (toname); + if (!targetm.emutls.tmpl_prefix || targetm.emutls.tmpl_prefix[0]) + { + const char *prefix = (targetm.emutls.tmpl_prefix + ? targetm.emutls.tmpl_prefix + : "__emutls_t" EMUTLS_SEPARATOR); + name = prefix_name (prefix, name); + } to = build_decl (VAR_DECL, name, TREE_TYPE (decl)); SET_DECL_ASSEMBLER_NAME (to, DECL_NAME (to)); - + DECL_TLS_MODEL (to) = TLS_MODEL_EMULATED; DECL_ARTIFICIAL (to) = 1; TREE_USED (to) = TREE_USED (decl); TREE_READONLY (to) = 1; DECL_IGNORED_P (to) = 1; DECL_CONTEXT (to) = DECL_CONTEXT (decl); + DECL_SECTION_NAME (to) = DECL_SECTION_NAME (decl); + DECL_WEAK (to) = DECL_WEAK (decl); if (DECL_ONE_ONLY (decl)) { @@ -345,7 +366,7 @@ emutls_decl (tree decl) in.hash = htab_hash_string (IDENTIFIER_POINTER (name)); in.base.from = decl; loc = htab_find_slot_with_hash (emutls_htab, &in, in.hash, INSERT); - h = *loc; + h = (struct tree_map *) *loc; if (h != NULL) to = h->to; else @@ -353,20 +374,24 @@ emutls_decl (tree decl) to = build_decl (VAR_DECL, get_emutls_object_name (name), get_emutls_object_type ()); - h = ggc_alloc (sizeof (struct tree_map)); + h = GGC_NEW (struct tree_map); h->hash = in.hash; h->base.from = decl; h->to = to; *(struct tree_map **) loc = h; + DECL_TLS_MODEL (to) = TLS_MODEL_EMULATED; DECL_ARTIFICIAL (to) = 1; DECL_IGNORED_P (to) = 1; TREE_READONLY (to) = 0; - SET_DECL_ASSEMBLER_NAME (to, DECL_NAME (to)); if (DECL_ONE_ONLY (decl)) make_decl_one_only (to); DECL_CONTEXT (to) = DECL_CONTEXT (decl); + if (targetm.emutls.var_align_fixed) + /* If we're not allowed to change the proxy object's + alignment, pretend it's been set by the user. */ + DECL_USER_ALIGN (to) = 1; } /* Note that these fields may need to be updated from time to time from @@ -424,16 +449,19 @@ emutls_common_1 (void **loc, void *xstmts) void emutls_finish (void) { - tree body = NULL_TREE; - - if (emutls_htab == NULL) - return; + if (!targetm.emutls.register_common) + { + tree body = NULL_TREE; - htab_traverse_noresize (emutls_htab, emutls_common_1, &body); - if (body == NULL_TREE) - return; + if (emutls_htab == NULL) + return; - cgraph_build_static_cdtor ('I', body, DEFAULT_INIT_PRIORITY); + htab_traverse_noresize (emutls_htab, emutls_common_1, &body); + if (body == NULL_TREE) + return; + + cgraph_build_static_cdtor ('I', body, DEFAULT_INIT_PRIORITY); + } } /* Helper routines for maintaining section_htab. */ @@ -441,16 +469,16 @@ emutls_finish (void) static int section_entry_eq (const void *p1, const void *p2) { - const section *old = p1; - const char *new = p2; + const section *old = (const section *) p1; + const char *new_name = (const char *) p2; - return strcmp (old->named.name, new) == 0; + return strcmp (old->named.name, new_name) == 0; } static hashval_t section_entry_hash (const void *p) { - const section *old = p; + const section *old = (const section *) p; return htab_hash_string (old->named.name); } @@ -469,16 +497,16 @@ hash_section (section *sect) static int object_block_entry_eq (const void *p1, const void *p2) { - const struct object_block *old = p1; - const section *new = p2; + const struct object_block *old = (const struct object_block *) p1; + const section *new_section = (const section *) p2; - return old->sect == new; + return old->sect == new_section; } static hashval_t object_block_entry_hash (const void *p) { - const struct object_block *old = p; + const struct object_block *old = (const struct object_block *) p; return hash_section (old->sect); } @@ -490,7 +518,7 @@ get_unnamed_section (unsigned int flags, void (*callback) (const void *), { section *sect; - sect = ggc_alloc (sizeof (struct unnamed_section)); + sect = GGC_NEW (section); sect->unnamed.common.flags = flags | SECTION_UNNAMED; sect->unnamed.callback = callback; sect->unnamed.data = data; @@ -507,7 +535,7 @@ get_noswitch_section (unsigned int flags, noswitch_section_callback callback) { section *sect; - sect = ggc_alloc (sizeof (struct unnamed_section)); + sect = GGC_NEW (section); sect->noswitch.common.flags = flags | SECTION_NOSWITCH; sect->noswitch.callback = callback; @@ -528,7 +556,7 @@ get_section (const char *name, unsigned int flags, tree decl) flags |= SECTION_NAMED; if (*slot == NULL) { - sect = ggc_alloc (sizeof (struct named_section)); + sect = GGC_NEW (section); sect->named.common.flags = flags; sect->named.name = ggc_strdup (name); sect->named.decl = decl; @@ -598,7 +626,7 @@ create_block_symbol (const char *label, struct object_block *block, /* Create the extended SYMBOL_REF. */ size = RTX_HDR_SIZE + sizeof (struct block_symbol); - symbol = ggc_alloc_zone (size, &rtl_zone); + symbol = (rtx) ggc_alloc_zone (size, &rtl_zone); /* Initialize the normal SYMBOL_REF fields. */ memset (symbol, 0, size); @@ -622,22 +650,22 @@ initialize_cold_section_name (void) tree dsn; gcc_assert (cfun && current_function_decl); - if (cfun->unlikely_text_section_name) + if (crtl->subsections.unlikely_text_section_name) return; dsn = DECL_SECTION_NAME (current_function_decl); if (flag_function_sections && dsn) { - name = alloca (TREE_STRING_LENGTH (dsn) + 1); + name = (char *) alloca (TREE_STRING_LENGTH (dsn) + 1); memcpy (name, TREE_STRING_POINTER (dsn), TREE_STRING_LENGTH (dsn) + 1); stripped_name = targetm.strip_name_encoding (name); buffer = ACONCAT ((stripped_name, "_unlikely", NULL)); - cfun->unlikely_text_section_name = ggc_strdup (buffer); + crtl->subsections.unlikely_text_section_name = ggc_strdup (buffer); } else - cfun->unlikely_text_section_name = UNLIKELY_EXECUTED_TEXT_SECTION_NAME; + crtl->subsections.unlikely_text_section_name = UNLIKELY_EXECUTED_TEXT_SECTION_NAME; } /* Tell assembler to switch to unlikely-to-be-executed text section. */ @@ -647,10 +675,10 @@ unlikely_text_section (void) { if (cfun) { - if (!cfun->unlikely_text_section_name) + if (!crtl->subsections.unlikely_text_section_name) initialize_cold_section_name (); - return get_named_section (NULL, cfun->unlikely_text_section_name, 0); + return get_named_section (NULL, crtl->subsections.unlikely_text_section_name, 0); } else return get_named_section (NULL, UNLIKELY_EXECUTED_TEXT_SECTION_NAME, 0); @@ -667,7 +695,7 @@ unlikely_text_section_p (section *sect) const char *name; if (cfun) - name = cfun->unlikely_text_section_name; + name = crtl->subsections.unlikely_text_section_name; else name = UNLIKELY_EXECUTED_TEXT_SECTION_NAME; @@ -842,7 +870,7 @@ default_function_rodata_section (tree decl) if (DECL_ONE_ONLY (decl) && HAVE_COMDAT_GROUP) { size_t len = strlen (name) + 3; - char* rname = alloca (len); + char* rname = (char *) alloca (len); strcpy (rname, ".rodata"); strcat (rname, name + 5); @@ -853,7 +881,7 @@ default_function_rodata_section (tree decl) && strncmp (name, ".gnu.linkonce.t.", 16) == 0) { size_t len = strlen (name) + 1; - char *rname = alloca (len); + char *rname = (char *) alloca (len); memcpy (rname, name, len); rname[14] = 'r'; @@ -864,7 +892,7 @@ default_function_rodata_section (tree decl) && strncmp (name, ".text.", 6) == 0) { size_t len = strlen (name) + 1; - char *rname = alloca (len + 2); + char *rname = (char *) alloca (len + 2); memcpy (rname, ".rodata", 7); memcpy (rname + 7, name + 5, len - 5); @@ -987,7 +1015,7 @@ strip_reg_name (const char *name) void set_user_assembler_name (tree decl, const char *name) { - char *starred = alloca (strlen (name) + 2); + char *starred = (char *) alloca (strlen (name) + 2); starred[0] = '*'; strcpy (starred + 1, name); change_decl_assembler_name (decl, get_identifier (starred)); @@ -1057,7 +1085,7 @@ decode_reg_name (const char *asmspec) /* Return true if DECL's initializer is suitable for a BSS section. */ static bool -bss_initializer_p (tree decl) +bss_initializer_p (const_tree decl) { return (DECL_INITIAL (decl) == NULL || DECL_INITIAL (decl) == error_mark_node @@ -1136,7 +1164,12 @@ get_variable_section (tree decl, bool prefer_noswitch_p) { if (DECL_THREAD_LOCAL_P (decl)) return tls_comm_section; - if (TREE_PUBLIC (decl) && bss_initializer_p (decl)) + /* This cannot be common bss for an emulated TLS object without + a register_common hook. */ + else if (DECL_TLS_MODEL (decl) == TLS_MODEL_EMULATED + && !targetm.emutls.register_common) + ; + else if (TREE_PUBLIC (decl) && bss_initializer_p (decl)) return comm_section; } @@ -1598,27 +1631,27 @@ assemble_start_function (tree decl, const char *fnname) char tmp_label[100]; bool hot_label_written = false; - cfun->unlikely_text_section_name = NULL; + crtl->subsections.unlikely_text_section_name = NULL; first_function_block_is_cold = false; if (flag_reorder_blocks_and_partition) { ASM_GENERATE_INTERNAL_LABEL (tmp_label, "LHOTB", const_labelno); - cfun->hot_section_label = ggc_strdup (tmp_label); + crtl->subsections.hot_section_label = ggc_strdup (tmp_label); ASM_GENERATE_INTERNAL_LABEL (tmp_label, "LCOLDB", const_labelno); - cfun->cold_section_label = ggc_strdup (tmp_label); + crtl->subsections.cold_section_label = ggc_strdup (tmp_label); ASM_GENERATE_INTERNAL_LABEL (tmp_label, "LHOTE", const_labelno); - cfun->hot_section_end_label = ggc_strdup (tmp_label); + crtl->subsections.hot_section_end_label = ggc_strdup (tmp_label); ASM_GENERATE_INTERNAL_LABEL (tmp_label, "LCOLDE", const_labelno); - cfun->cold_section_end_label = ggc_strdup (tmp_label); + crtl->subsections.cold_section_end_label = ggc_strdup (tmp_label); const_labelno++; } else { - cfun->hot_section_label = NULL; - cfun->cold_section_label = NULL; - cfun->hot_section_end_label = NULL; - cfun->cold_section_end_label = NULL; + crtl->subsections.hot_section_label = NULL; + crtl->subsections.cold_section_label = NULL; + crtl->subsections.hot_section_end_label = NULL; + crtl->subsections.cold_section_end_label = NULL; } /* The following code does not need preprocessing in the assembler. */ @@ -1638,18 +1671,18 @@ assemble_start_function (tree decl, const char *fnname) if (flag_reorder_blocks_and_partition) { switch_to_section (unlikely_text_section ()); - assemble_align (FUNCTION_BOUNDARY); - ASM_OUTPUT_LABEL (asm_out_file, cfun->cold_section_label); + assemble_align (DECL_ALIGN (decl)); + ASM_OUTPUT_LABEL (asm_out_file, crtl->subsections.cold_section_label); /* When the function starts with a cold section, we need to explicitly align the hot section and write out the hot section label. But if the current function is a thunk, we do not have a CFG. */ - if (!current_function_is_thunk + if (!crtl->is_thunk && BB_PARTITION (ENTRY_BLOCK_PTR->next_bb) == BB_COLD_PARTITION) { switch_to_section (text_section); - assemble_align (FUNCTION_BOUNDARY); - ASM_OUTPUT_LABEL (asm_out_file, cfun->hot_section_label); + assemble_align (DECL_ALIGN (decl)); + ASM_OUTPUT_LABEL (asm_out_file, crtl->subsections.hot_section_label); hot_label_written = true; first_function_block_is_cold = true; } @@ -1663,9 +1696,9 @@ assemble_start_function (tree decl, const char *fnname) initialize_cold_section_name (); - if (cfun->unlikely_text_section_name + if (crtl->subsections.unlikely_text_section_name && strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)), - cfun->unlikely_text_section_name) == 0) + crtl->subsections.unlikely_text_section_name) == 0) first_function_block_is_cold = true; } @@ -1676,22 +1709,21 @@ assemble_start_function (tree decl, const char *fnname) switch_to_section (function_section (decl)); if (flag_reorder_blocks_and_partition && !hot_label_written) - ASM_OUTPUT_LABEL (asm_out_file, cfun->hot_section_label); + ASM_OUTPUT_LABEL (asm_out_file, crtl->subsections.hot_section_label); /* Tell assembler to move to target machine's alignment for functions. */ - align = floor_log2 (FUNCTION_BOUNDARY / BITS_PER_UNIT); - if (align < force_align_functions_log) - align = force_align_functions_log; + align = floor_log2 (DECL_ALIGN (decl) / BITS_PER_UNIT); if (align > 0) { ASM_OUTPUT_ALIGN (asm_out_file, align); } /* Handle a user-specified function alignment. - Note that we still need to align to FUNCTION_BOUNDARY, as above, + Note that we still need to align to DECL_ALIGN, as above, because ASM_OUTPUT_MAX_SKIP_ALIGN might not do any alignment at all. */ - if (align_functions_log > align - && cfun->function_frequency != FUNCTION_FREQUENCY_UNLIKELY_EXECUTED) + if (! DECL_USER_ALIGN (decl) + && align_functions_log > align + && optimize_function_for_speed_p (cfun)) { #ifdef ASM_OUTPUT_MAX_SKIP_ALIGN ASM_OUTPUT_MAX_SKIP_ALIGN (asm_out_file, @@ -1755,12 +1787,12 @@ assemble_end_function (tree decl, const char *fnname ATTRIBUTE_UNUSED) save_text_section = in_section; switch_to_section (unlikely_text_section ()); - ASM_OUTPUT_LABEL (asm_out_file, cfun->cold_section_end_label); + ASM_OUTPUT_LABEL (asm_out_file, crtl->subsections.cold_section_end_label); if (first_function_block_is_cold) switch_to_section (text_section); else switch_to_section (function_section (decl)); - ASM_OUTPUT_LABEL (asm_out_file, cfun->hot_section_end_label); + ASM_OUTPUT_LABEL (asm_out_file, crtl->subsections.hot_section_end_label); switch_to_section (save_text_section); } } @@ -1962,6 +1994,40 @@ assemble_variable_contents (tree decl, const char *name, } } +/* Initialize emulated tls object TO, which refers to TLS variable + DECL and is initialized by PROXY. */ + +tree +default_emutls_var_init (tree to, tree decl, tree proxy) +{ + VEC(constructor_elt,gc) *v = VEC_alloc (constructor_elt, gc, 4); + constructor_elt *elt; + tree type = TREE_TYPE (to); + tree field = TYPE_FIELDS (type); + + elt = VEC_quick_push (constructor_elt, v, NULL); + elt->index = field; + elt->value = fold_convert (TREE_TYPE (field), DECL_SIZE_UNIT (decl)); + + elt = VEC_quick_push (constructor_elt, v, NULL); + field = TREE_CHAIN (field); + elt->index = field; + elt->value = build_int_cst (TREE_TYPE (field), + DECL_ALIGN_UNIT (decl)); + + elt = VEC_quick_push (constructor_elt, v, NULL); + field = TREE_CHAIN (field); + elt->index = field; + elt->value = null_pointer_node; + + elt = VEC_quick_push (constructor_elt, v, NULL); + field = TREE_CHAIN (field); + elt->index = field; + elt->value = proxy; + + return build_constructor (type, v); +} + /* Assemble everything that is needed for a variable or function declaration. Not used for automatic variables, and not used for function definitions. Should not be called for variables of incomplete structure type. @@ -1996,32 +2062,8 @@ assemble_variable (tree decl, int top_level ATTRIBUTE_UNUSED, || (DECL_INITIAL (decl) && DECL_INITIAL (decl) != error_mark_node))) { - VEC(constructor_elt,gc) *v = VEC_alloc (constructor_elt, gc, 4); - constructor_elt *elt; - tree type = TREE_TYPE (to); - tree field = TYPE_FIELDS (type); - - elt = VEC_quick_push (constructor_elt, v, NULL); - elt->index = field; - elt->value = fold_convert (TREE_TYPE (field), DECL_SIZE_UNIT (decl)); - - elt = VEC_quick_push (constructor_elt, v, NULL); - field = TREE_CHAIN (field); - elt->index = field; - elt->value = build_int_cst (TREE_TYPE (field), - DECL_ALIGN_UNIT (decl)); - - elt = VEC_quick_push (constructor_elt, v, NULL); - field = TREE_CHAIN (field); - elt->index = field; - elt->value = null_pointer_node; - - elt = VEC_quick_push (constructor_elt, v, NULL); - field = TREE_CHAIN (field); - elt->index = field; - elt->value = get_emutls_init_templ_addr (decl); - - DECL_INITIAL (to) = build_constructor (type, v); + DECL_INITIAL (to) = targetm.emutls.var_init + (to, decl, get_emutls_init_templ_addr (decl)); /* Make sure the template is marked as needed early enough. Without this, if the variable is placed in a @@ -2186,7 +2228,7 @@ contains_pointers_p (tree type) } } -/* In unit-at-a-time mode, we delay assemble_external processing until +/* We delay assemble_external processing until the compilation unit is finalized. This is the best we can do for right now (i.e. stage 3 of GCC 4.0) - the right thing is to delay it all the way to final. See PR 17982 for further discussion. */ @@ -2244,6 +2286,10 @@ process_pending_assemble_externals (void) #endif } +/* This TREE_LIST contains any weak symbol declarations waiting + to be emitted. */ +static GTY(()) tree weak_decls; + /* Output something to declare an external symbol to the assembler. (Most assemblers don't need this, so we normally output nothing.) Do nothing if DECL is not external. */ @@ -2261,6 +2307,9 @@ assemble_external (tree decl ATTRIBUTE_UNUSED) if (!DECL_P (decl) || !DECL_EXTERNAL (decl) || !TREE_PUBLIC (decl)) return; + if (SUPPORTS_WEAK && DECL_WEAK (decl)) + weak_decls = tree_cons (NULL, decl, weak_decls); + /* We want to output external symbols at very last to check if they are references or not. */ pending_assemble_externals = tree_cons (0, decl, @@ -2572,11 +2621,17 @@ assemble_integer (rtx x, unsigned int size, unsigned int align, int force) enum machine_mode omode, imode; unsigned int subalign; unsigned int subsize, i; + unsigned char mclass; subsize = size > UNITS_PER_WORD? UNITS_PER_WORD : 1; subalign = MIN (align, subsize * BITS_PER_UNIT); - omode = mode_for_size (subsize * BITS_PER_UNIT, MODE_INT, 0); - imode = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 0); + if (GET_CODE (x) == CONST_FIXED) + mclass = GET_MODE_CLASS (GET_MODE (x)); + else + mclass = MODE_INT; + + omode = mode_for_size (subsize * BITS_PER_UNIT, mclass, 0); + imode = mode_for_size (size * BITS_PER_UNIT, mclass, 0); for (i = 0; i < size; i += subsize) { @@ -2688,6 +2743,7 @@ decode_addr_const (tree exp, struct addr_const *value) break; case REAL_CST: + case FIXED_CST: case STRING_CST: case COMPLEX_CST: case CONSTRUCTOR: @@ -2735,7 +2791,7 @@ static void maybe_output_constant_def_contents (struct constant_descriptor_tree static hashval_t const_desc_hash (const void *ptr) { - return ((struct constant_descriptor_tree *)ptr)->hash; + return ((const struct constant_descriptor_tree *)ptr)->hash; } static hashval_t @@ -2759,6 +2815,9 @@ const_hash_1 (const tree exp) case REAL_CST: return real_hash (TREE_REAL_CST_PTR (exp)); + case FIXED_CST: + return fixed_hash (TREE_FIXED_CST_PTR (exp)); + case STRING_CST: p = TREE_STRING_POINTER (exp); len = TREE_STRING_LENGTH (exp); @@ -2815,9 +2874,7 @@ const_hash_1 (const tree exp) return (const_hash_1 (TREE_OPERAND (exp, 0)) * 9 + const_hash_1 (TREE_OPERAND (exp, 1))); - case NOP_EXPR: - case CONVERT_EXPR: - case NON_LVALUE_EXPR: + CASE_CONVERT: return const_hash_1 (TREE_OPERAND (exp, 0)) * 7 + 2; default: @@ -2837,8 +2894,10 @@ const_hash_1 (const tree exp) static int const_desc_eq (const void *p1, const void *p2) { - const struct constant_descriptor_tree *c1 = p1; - const struct constant_descriptor_tree *c2 = p2; + const struct constant_descriptor_tree *const c1 + = (const struct constant_descriptor_tree *) p1; + const struct constant_descriptor_tree *const c2 + = (const struct constant_descriptor_tree *) p2; if (c1->hash != c2->hash) return 0; return compare_constant (c1->value, c2->value); @@ -2877,6 +2936,13 @@ compare_constant (const tree t1, const tree t2) return REAL_VALUES_IDENTICAL (TREE_REAL_CST (t1), TREE_REAL_CST (t2)); + case FIXED_CST: + /* Fixed constants are the same only if the same width of type. */ + if (TYPE_PRECISION (TREE_TYPE (t1)) != TYPE_PRECISION (TREE_TYPE (t2))) + return 0; + + return FIXED_VALUES_IDENTICAL (TREE_FIXED_CST (t1), TREE_FIXED_CST (t2)); + case STRING_CST: if (TYPE_MODE (TREE_TYPE (t1)) != TYPE_MODE (TREE_TYPE (t2))) return 0; @@ -2963,22 +3029,12 @@ compare_constant (const tree t1, const tree t2) return (compare_constant (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0)) && compare_constant(TREE_OPERAND (t1, 1), TREE_OPERAND (t2, 1))); - case NOP_EXPR: - case CONVERT_EXPR: - case NON_LVALUE_EXPR: + CASE_CONVERT: case VIEW_CONVERT_EXPR: return compare_constant (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0)); default: - { - tree nt1, nt2; - nt1 = lang_hooks.expand_constant (t1); - nt2 = lang_hooks.expand_constant (t2); - if (nt1 != t1 || nt2 != t2) - return compare_constant (nt1, nt2); - else - return 0; - } + return 0; } gcc_unreachable (); @@ -3003,6 +3059,7 @@ copy_constant (tree exp) case INTEGER_CST: case REAL_CST: + case FIXED_CST: case STRING_CST: return copy_node (exp); @@ -3018,9 +3075,7 @@ copy_constant (tree exp) copy_constant (TREE_OPERAND (exp, 0)), copy_constant (TREE_OPERAND (exp, 1))); - case NOP_EXPR: - case CONVERT_EXPR: - case NON_LVALUE_EXPR: + CASE_CONVERT: case VIEW_CONVERT_EXPR: return build1 (TREE_CODE (exp), TREE_TYPE (exp), copy_constant (TREE_OPERAND (exp, 0))); @@ -3045,12 +3100,7 @@ copy_constant (tree exp) } default: - { - tree t = lang_hooks.expand_constant (exp); - - gcc_assert (t != exp); - return copy_constant (t); - } + gcc_unreachable (); } } @@ -3110,7 +3160,7 @@ build_constant_desc (tree exp) int labelno; struct constant_descriptor_tree *desc; - desc = ggc_alloc (sizeof (*desc)); + desc = GGC_NEW (struct constant_descriptor_tree); desc->value = copy_constant (exp); /* Propagate marked-ness to copied constant. */ @@ -3178,7 +3228,7 @@ output_constant_def (tree exp, int defer) key.hash = const_hash_1 (exp); loc = htab_find_slot_with_hash (const_desc_htab, &key, key.hash, INSERT); - desc = *loc; + desc = (struct constant_descriptor_tree *) *loc; if (desc == 0) { desc = build_constant_desc (exp); @@ -3289,7 +3339,8 @@ lookup_constant_def (tree exp) key.value = exp; key.hash = const_hash_1 (exp); - desc = htab_find_with_hash (const_desc_htab, &key, key.hash); + desc = (struct constant_descriptor_tree *) + htab_find_with_hash (const_desc_htab, &key, key.hash); return (desc ? desc->rtl : NULL_RTX); } @@ -3337,15 +3388,18 @@ struct constant_descriptor_rtx GTY((chain_next ("%h.next"))) static hashval_t const_desc_rtx_hash (const void *ptr) { - const struct constant_descriptor_rtx *desc = ptr; + const struct constant_descriptor_rtx *const desc + = (const struct constant_descriptor_rtx *) ptr; return desc->hash; } static int const_desc_rtx_eq (const void *a, const void *b) { - const struct constant_descriptor_rtx *x = a; - const struct constant_descriptor_rtx *y = b; + const struct constant_descriptor_rtx *const x + = (const struct constant_descriptor_rtx *) a; + const struct constant_descriptor_rtx *const y + = (const struct constant_descriptor_rtx *) b; if (x->mode != y->mode) return 0; @@ -3397,6 +3451,10 @@ const_rtx_hash_1 (rtx *xp, void *data) h ^= real_hash (CONST_DOUBLE_REAL_VALUE (x)); break; + case CONST_FIXED: + h ^= fixed_hash (CONST_FIXED_VALUE (x)); + break; + case CONST_VECTOR: { int i; @@ -3422,7 +3480,7 @@ const_rtx_hash_1 (rtx *xp, void *data) break; } - hp = data; + hp = (hashval_t *) data; *hp = *hp * 509 + h; return 0; } @@ -3445,7 +3503,7 @@ create_constant_pool (void) { struct rtx_constant_pool *pool; - pool = ggc_alloc (sizeof (struct rtx_constant_pool)); + pool = GGC_NEW (struct rtx_constant_pool); pool->const_rtx_htab = htab_create_ggc (31, const_desc_rtx_hash, const_desc_rtx_eq, NULL); pool->first = NULL; @@ -3457,15 +3515,10 @@ create_constant_pool (void) /* Initialize constant pool hashing for a new function. */ void -init_varasm_status (struct function *f) +init_varasm_status (void) { - struct varasm_status *p; - - p = ggc_alloc (sizeof (struct varasm_status)); - f->varasm = p; - - p->pool = create_constant_pool (); - p->deferred_constants = 0; + crtl->varasm.pool = create_constant_pool (); + crtl->varasm.deferred_constants = 0; } /* Given a MINUS expression, simplify it if both sides @@ -3497,26 +3550,26 @@ force_const_mem (enum machine_mode mode, rtx x) return NULL_RTX; /* Record that this function has used a constant pool entry. */ - current_function_uses_const_pool = 1; + crtl->uses_const_pool = 1; /* Decide which pool to use. */ pool = (targetm.use_blocks_for_constant_p (mode, x) ? shared_constant_pool - : cfun->varasm->pool); + : crtl->varasm.pool); /* Lookup the value in the hashtable. */ tmp.constant = x; tmp.mode = mode; hash = const_rtx_hash (x); slot = htab_find_slot_with_hash (pool->const_rtx_htab, &tmp, hash, INSERT); - desc = *slot; + desc = (struct constant_descriptor_rtx *) *slot; /* If the constant was already present, return its memory. */ if (desc) return copy_rtx (desc->mem); /* Otherwise, create a new descriptor. */ - desc = ggc_alloc (sizeof (*desc)); + desc = GGC_NEW (struct constant_descriptor_rtx); *slot = desc; /* Align the location counter as required by EXP's data type. */ @@ -3604,7 +3657,7 @@ get_pool_constant_mark (rtx addr, bool *pmarked) /* Similar, return the mode. */ enum machine_mode -get_pool_mode (rtx addr) +get_pool_mode (const_rtx addr) { return SYMBOL_REF_CONSTANT (addr)->mode; } @@ -3614,7 +3667,7 @@ get_pool_mode (rtx addr) int get_pool_size (void) { - return cfun->varasm->pool->offset; + return crtl->varasm.pool->offset; } /* Worker function for output_constant_pool_1. Emit assembly for X @@ -3638,11 +3691,19 @@ output_constant_pool_2 (enum machine_mode mode, rtx x, unsigned int align) case MODE_INT: case MODE_PARTIAL_INT: + case MODE_FRACT: + case MODE_UFRACT: + case MODE_ACCUM: + case MODE_UACCUM: assemble_integer (x, GET_MODE_SIZE (mode), align, 1); break; case MODE_VECTOR_FLOAT: case MODE_VECTOR_INT: + case MODE_VECTOR_FRACT: + case MODE_VECTOR_UFRACT: + case MODE_VECTOR_ACCUM: + case MODE_VECTOR_UACCUM: { int i, units; enum machine_mode submode = GET_MODE_INNER (mode); @@ -3685,17 +3746,17 @@ output_constant_pool_1 (struct constant_descriptor_rtx *desc, functioning even with INSN_DELETED_P and friends. */ tmp = x; - switch (GET_CODE (x)) + switch (GET_CODE (tmp)) { case CONST: - if (GET_CODE (XEXP (x, 0)) != PLUS - || GET_CODE (XEXP (XEXP (x, 0), 0)) != LABEL_REF) + if (GET_CODE (XEXP (tmp, 0)) != PLUS + || GET_CODE (XEXP (XEXP (tmp, 0), 0)) != LABEL_REF) break; - tmp = XEXP (XEXP (x, 0), 0); + tmp = XEXP (XEXP (tmp, 0), 0); /* FALLTHRU */ case LABEL_REF: - tmp = XEXP (x, 0); + tmp = XEXP (tmp, 0); gcc_assert (!INSN_DELETED_P (tmp)); gcc_assert (!NOTE_P (tmp) || NOTE_KIND (tmp) != NOTE_INSN_DELETED); @@ -3803,13 +3864,13 @@ mark_constant_pool (void) { rtx insn, link; - if (!current_function_uses_const_pool && n_deferred_constants == 0) + if (!crtl->uses_const_pool && n_deferred_constants == 0) return; for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) mark_constants (insn); - for (link = current_function_epilogue_delay_list; + for (link = crtl->epilogue_delay_list; link; link = XEXP (link, 1)) mark_constants (XEXP (link, 0)); @@ -3848,7 +3909,7 @@ static void output_constant_pool (const char *fnname ATTRIBUTE_UNUSED, tree fndecl ATTRIBUTE_UNUSED) { - struct rtx_constant_pool *pool = cfun->varasm->pool; + struct rtx_constant_pool *pool = crtl->varasm.pool; /* It is possible for gcc to call force_const_mem and then to later discard the instructions which refer to the constant. In such a @@ -3882,10 +3943,6 @@ compute_reloc_for_constant (tree exp) int reloc = 0, reloc2; tree tem; - /* Give the front-end a chance to convert VALUE to something that - looks more like a constant to the back-end. */ - exp = lang_hooks.expand_constant (exp); - switch (TREE_CODE (exp)) { case ADDR_EXPR: @@ -3919,9 +3976,7 @@ compute_reloc_for_constant (tree exp) reloc |= reloc2; break; - case NOP_EXPR: - case CONVERT_EXPR: - case NON_LVALUE_EXPR: + CASE_CONVERT: case VIEW_CONVERT_EXPR: reloc = compute_reloc_for_constant (TREE_OPERAND (exp, 0)); break; @@ -3950,10 +4005,6 @@ output_addressed_constants (tree exp) { tree tem; - /* Give the front-end a chance to convert VALUE to something that - looks more like a constant to the back-end. */ - exp = lang_hooks.expand_constant (exp); - switch (TREE_CODE (exp)) { case ADDR_EXPR: @@ -3979,9 +4030,7 @@ output_addressed_constants (tree exp) output_addressed_constants (TREE_OPERAND (exp, 1)); /* Fall through. */ - case NOP_EXPR: - case CONVERT_EXPR: - case NON_LVALUE_EXPR: + CASE_CONVERT: case VIEW_CONVERT_EXPR: output_addressed_constants (TREE_OPERAND (exp, 0)); break; @@ -4006,7 +4055,7 @@ output_addressed_constants (tree exp) evaluate the property while walking a constructor for other purposes. */ bool -constructor_static_from_elts_p (tree ctor) +constructor_static_from_elts_p (const_tree ctor) { return (TREE_CONSTANT (ctor) && (TREE_CODE (TREE_TYPE (ctor)) == UNION_TYPE @@ -4014,6 +4063,73 @@ constructor_static_from_elts_p (tree ctor) && !VEC_empty (constructor_elt, CONSTRUCTOR_ELTS (ctor))); } +/* A subroutine of initializer_constant_valid_p. VALUE is either a + MINUS_EXPR or a POINTER_PLUS_EXPR, and ENDTYPE is a narrowing + conversion to something smaller than a pointer. This returns + null_pointer_node if the resulting value is an absolute constant + which can be used to initialize a static variable. Otherwise it + returns NULL. */ + +static tree +narrowing_initializer_constant_valid_p (tree value, tree endtype) +{ + tree op0, op1; + + op0 = TREE_OPERAND (value, 0); + op1 = TREE_OPERAND (value, 1); + + /* Like STRIP_NOPS except allow the operand mode to widen. This + works around a feature of fold that simplifies (int)(p1 - p2) to + ((int)p1 - (int)p2) under the theory that the narrower operation + is cheaper. */ + + while (CONVERT_EXPR_P (op0) + || TREE_CODE (op0) == NON_LVALUE_EXPR) + { + tree inner = TREE_OPERAND (op0, 0); + if (inner == error_mark_node + || ! INTEGRAL_MODE_P (TYPE_MODE (TREE_TYPE (inner))) + || (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (op0))) + > GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (inner))))) + break; + op0 = inner; + } + + while (CONVERT_EXPR_P (op1) + || TREE_CODE (op1) == NON_LVALUE_EXPR) + { + tree inner = TREE_OPERAND (op1, 0); + if (inner == error_mark_node + || ! INTEGRAL_MODE_P (TYPE_MODE (TREE_TYPE (inner))) + || (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (op1))) + > GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (inner))))) + break; + op1 = inner; + } + + op0 = initializer_constant_valid_p (op0, endtype); + op1 = initializer_constant_valid_p (op1, endtype); + + /* Both initializers must be known. */ + if (op0 && op1) + { + if (op0 == op1) + return null_pointer_node; + + /* Support differences between labels. */ + if (TREE_CODE (op0) == LABEL_DECL + && TREE_CODE (op1) == LABEL_DECL) + return null_pointer_node; + + if (TREE_CODE (op0) == STRING_CST + && TREE_CODE (op1) == STRING_CST + && operand_equal_p (op0, op1, 1)) + return null_pointer_node; + } + + return NULL_TREE; +} + /* Return nonzero if VALUE is a valid constant-valued expression for use in initializing a static variable; one that can be an element of a "constant" initializer. @@ -4027,9 +4143,7 @@ constructor_static_from_elts_p (tree ctor) tree initializer_constant_valid_p (tree value, tree endtype) { - /* Give the front-end a chance to convert VALUE to something that - looks more like a constant to the back-end. */ - value = lang_hooks.expand_constant (value); + tree ret; switch (TREE_CODE (value)) { @@ -4060,38 +4174,42 @@ initializer_constant_valid_p (tree value, tree endtype) case INTEGER_CST: case VECTOR_CST: case REAL_CST: + case FIXED_CST: case STRING_CST: case COMPLEX_CST: return null_pointer_node; case ADDR_EXPR: case FDESC_EXPR: - value = staticp (TREE_OPERAND (value, 0)); - if (value) - { - /* "&(*a).f" is like unto pointer arithmetic. If "a" turns out to - be a constant, this is old-skool offsetof-like nonsense. */ - if (TREE_CODE (value) == INDIRECT_REF - && TREE_CONSTANT (TREE_OPERAND (value, 0))) - return null_pointer_node; - /* Taking the address of a nested function involves a trampoline. */ - if (TREE_CODE (value) == FUNCTION_DECL - && decl_function_context (value) - && !DECL_NO_STATIC_CHAIN (value)) - return NULL_TREE; - /* "&{...}" requires a temporary to hold the constructed - object. */ - if (TREE_CODE (value) == CONSTRUCTOR) - return NULL_TREE; - } - return value; + { + tree op0 = staticp (TREE_OPERAND (value, 0)); + if (op0) + { + /* "&(*a).f" is like unto pointer arithmetic. If "a" turns out + to be a constant, this is old-skool offsetof-like nonsense. */ + if (TREE_CODE (op0) == INDIRECT_REF + && TREE_CONSTANT (TREE_OPERAND (op0, 0))) + return null_pointer_node; + /* Taking the address of a nested function involves a trampoline, + unless we don't need or want one. */ + if (TREE_CODE (op0) == FUNCTION_DECL + && decl_function_context (op0) + && !DECL_NO_STATIC_CHAIN (op0) + && !TREE_NO_TRAMPOLINE (value)) + return NULL_TREE; + /* "&{...}" requires a temporary to hold the constructed + object. */ + if (TREE_CODE (op0) == CONSTRUCTOR) + return NULL_TREE; + } + return op0; + } case VIEW_CONVERT_EXPR: case NON_LVALUE_EXPR: return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype); - case CONVERT_EXPR: - case NOP_EXPR: + CASE_CONVERT: { tree src; tree src_type; @@ -4161,12 +4279,20 @@ initializer_constant_valid_p (tree value, tree endtype) endtype); tree valid1 = initializer_constant_valid_p (TREE_OPERAND (value, 1), endtype); - /* If either term is absolute, use the other terms relocation. */ + /* If either term is absolute, use the other term's relocation. */ if (valid0 == null_pointer_node) return valid1; if (valid1 == null_pointer_node) return valid0; } + + /* Support narrowing pointer differences. */ + if (TREE_CODE (value) == POINTER_PLUS_EXPR) + { + ret = narrowing_initializer_constant_valid_p (value, endtype); + if (ret != NULL_TREE) + return ret; + } break; case MINUS_EXPR: @@ -4195,64 +4321,10 @@ initializer_constant_valid_p (tree value, tree endtype) } /* Support narrowing differences. */ - if (INTEGRAL_TYPE_P (endtype)) - { - tree op0, op1; - - op0 = TREE_OPERAND (value, 0); - op1 = TREE_OPERAND (value, 1); - - /* Like STRIP_NOPS except allow the operand mode to widen. - This works around a feature of fold that simplifies - (int)(p1 - p2) to ((int)p1 - (int)p2) under the theory - that the narrower operation is cheaper. */ - - while (TREE_CODE (op0) == NOP_EXPR - || TREE_CODE (op0) == CONVERT_EXPR - || TREE_CODE (op0) == NON_LVALUE_EXPR) - { - tree inner = TREE_OPERAND (op0, 0); - if (inner == error_mark_node - || ! INTEGRAL_MODE_P (TYPE_MODE (TREE_TYPE (inner))) - || (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (op0))) - > GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (inner))))) - break; - op0 = inner; - } + ret = narrowing_initializer_constant_valid_p (value, endtype); + if (ret != NULL_TREE) + return ret; - while (TREE_CODE (op1) == NOP_EXPR - || TREE_CODE (op1) == CONVERT_EXPR - || TREE_CODE (op1) == NON_LVALUE_EXPR) - { - tree inner = TREE_OPERAND (op1, 0); - if (inner == error_mark_node - || ! INTEGRAL_MODE_P (TYPE_MODE (TREE_TYPE (inner))) - || (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (op1))) - > GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (inner))))) - break; - op1 = inner; - } - - op0 = initializer_constant_valid_p (op0, endtype); - op1 = initializer_constant_valid_p (op1, endtype); - - /* Both initializers must be known. */ - if (op0 && op1) - { - if (op0 == op1) - return null_pointer_node; - - /* Support differences between labels. */ - if (TREE_CODE (op0) == LABEL_DECL - && TREE_CODE (op1) == LABEL_DECL) - return null_pointer_node; - - if (TREE_CODE (op0) == STRING_CST - && TREE_CODE (op1) == STRING_CST - && operand_equal_p (op0, op1, 1)) - return null_pointer_node; - } - } break; default: @@ -4288,11 +4360,6 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align) enum tree_code code; unsigned HOST_WIDE_INT thissize; - /* Some front-ends use constants other than the standard language-independent - varieties, but which may still be output directly. Give the front-end a - chance to convert EXP to a language-independent representation. */ - exp = lang_hooks.expand_constant (exp); - if (size == 0 || flag_syntax_only) return; @@ -4327,7 +4394,7 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align) /* Eliminate any conversions since we'll be outputting the underlying constant. */ - while (TREE_CODE (exp) == NOP_EXPR || TREE_CODE (exp) == CONVERT_EXPR + while (CONVERT_EXPR_P (exp) || TREE_CODE (exp) == NON_LVALUE_EXPR || TREE_CODE (exp) == VIEW_CONVERT_EXPR) { @@ -4349,9 +4416,6 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align) code = TREE_CODE (TREE_TYPE (exp)); thissize = int_size_in_bytes (TREE_TYPE (exp)); - /* Give the front end another chance to expand constants. */ - exp = lang_hooks.expand_constant (exp); - /* Allow a constructor with no elements for any data type. This means to fill the space with zeros. */ if (TREE_CODE (exp) == CONSTRUCTOR @@ -4383,10 +4447,11 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align) case POINTER_TYPE: case REFERENCE_TYPE: case OFFSET_TYPE: + case FIXED_POINT_TYPE: if (! assemble_integer (expand_expr (exp, NULL_RTX, VOIDmode, EXPAND_INITIALIZER), MIN (size, thissize), align, 0)) - error ("initializer for integer value is too complicated"); + error ("initializer for integer/fixed-point value is too complicated"); break; case REAL_TYPE: @@ -4813,10 +4878,6 @@ output_constructor (tree exp, unsigned HOST_WIDE_INT size, assemble_zeros (size - total_bytes); } -/* This TREE_LIST contains any weak symbol declarations waiting - to be emitted. */ -static GTY(()) tree weak_decls; - /* Mark DECL as weak. */ static void @@ -4860,7 +4921,7 @@ merge_weak (tree newdecl, tree olddecl) /* NEWDECL is weak, but OLDDECL is not. */ /* If we already output the OLDDECL, we're in trouble; we can't - go back and make it weak. This error cannot caught in + go back and make it weak. This error cannot be caught in declare_weak because the NEWDECL and OLDDECL was not yet been merged; therefore, TREE_ASM_WRITTEN was not set. */ if (TREE_ASM_WRITTEN (olddecl)) @@ -4909,12 +4970,7 @@ declare_weak (tree decl) error ("weak declaration of %q+D must be public", decl); else if (TREE_CODE (decl) == FUNCTION_DECL && TREE_ASM_WRITTEN (decl)) error ("weak declaration of %q+D must precede definition", decl); - else if (SUPPORTS_WEAK) - { - if (! DECL_WEAK (decl)) - weak_decls = tree_cons (NULL, decl, weak_decls); - } - else + else if (!SUPPORTS_WEAK) warning (0, "weak declaration of %q+D not supported", decl); mark_weak (decl); @@ -4978,7 +5034,7 @@ weak_finish (void) else if (! TREE_SYMBOL_REFERENCED (target)) { /* Use ASM_WEAKEN_LABEL only if ASM_WEAKEN_DECL is not - defined, otherwise we and weak_finish_1 would use a + defined, otherwise we and weak_finish_1 would use different macros. */ # if defined ASM_WEAKEN_LABEL && ! defined ASM_WEAKEN_DECL ASM_WEAKEN_LABEL (asm_out_file, IDENTIFIER_POINTER (target)); @@ -5346,8 +5402,11 @@ assemble_alias (tree decl, tree target) varpool_node (decl)->alias = true; /* If the target has already been emitted, we don't have to queue the - alias. This saves a tad o memory. */ - target_decl = find_decl_and_mark_needed (decl, target); + alias. This saves a tad of memory. */ + if (cgraph_global_info_ready) + target_decl = find_decl_and_mark_needed (decl, target); + else + target_decl= NULL; if (target_decl && TREE_ASM_WRITTEN (target_decl)) do_assemble_alias (decl, target); else @@ -5514,7 +5573,7 @@ init_varasm_once (void) } enum tls_model -decl_default_tls_model (tree decl) +decl_default_tls_model (const_tree decl) { enum tls_model kind; bool is_local; @@ -5558,8 +5617,8 @@ default_section_type_flags (tree decl, const char *name, int reloc) flags = 0; else if (current_function_decl && cfun - && cfun->unlikely_text_section_name - && strcmp (name, cfun->unlikely_text_section_name) == 0) + && crtl->subsections.unlikely_text_section_name + && strcmp (name, crtl->subsections.unlikely_text_section_name) == 0) flags = SECTION_CODE; else if (!decl && (!current_function_decl || !cfun) @@ -5754,7 +5813,7 @@ default_select_section (tree decl, int reloc, } enum section_category -categorize_decl_for_section (tree decl, int reloc) +categorize_decl_for_section (const_tree decl, int reloc) { enum section_category ret; @@ -5809,13 +5868,26 @@ categorize_decl_for_section (tree decl, int reloc) ret = SECCAT_RODATA; /* There are no read-only thread-local sections. */ - if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL_P (decl)) + if (TREE_CODE (decl) == VAR_DECL && DECL_TLS_MODEL (decl)) { + if (DECL_TLS_MODEL (decl) == TLS_MODEL_EMULATED) + { + if (DECL_EMUTLS_VAR_P (decl)) + { + if (targetm.emutls.var_section) + ret = SECCAT_EMUTLS_VAR; + } + else + { + if (targetm.emutls.tmpl_prefix) + ret = SECCAT_EMUTLS_TMPL; + } + } /* Note that this would be *just* SECCAT_BSS, except that there's no concept of a read-only thread-local-data section. */ - if (ret == SECCAT_BSS - || (flag_zero_initialized_in_bss - && initializer_zerop (DECL_INITIAL (decl)))) + else if (ret == SECCAT_BSS + || (flag_zero_initialized_in_bss + && initializer_zerop (DECL_INITIAL (decl)))) ret = SECCAT_TBSS; else ret = SECCAT_TDATA; @@ -5836,7 +5908,7 @@ categorize_decl_for_section (tree decl, int reloc) } bool -decl_readonly_section (tree decl, int reloc) +decl_readonly_section (const_tree decl, int reloc) { switch (categorize_decl_for_section (decl, reloc)) { @@ -5907,6 +5979,12 @@ default_elf_select_section (tree decl, int reloc, case SECCAT_TBSS: sname = ".tbss"; break; + case SECCAT_EMUTLS_VAR: + sname = targetm.emutls.var_section; + break; + case SECCAT_EMUTLS_TMPL: + sname = targetm.emutls.tmpl_section; + break; default: gcc_unreachable (); } @@ -5924,69 +6002,73 @@ default_unique_section (tree decl, int reloc) { /* We only need to use .gnu.linkonce if we don't have COMDAT groups. */ bool one_only = DECL_ONE_ONLY (decl) && !HAVE_COMDAT_GROUP; - const char *prefix, *name; - size_t nlen, plen; + const char *prefix, *name, *linkonce; char *string; switch (categorize_decl_for_section (decl, reloc)) { case SECCAT_TEXT: - prefix = one_only ? ".gnu.linkonce.t." : ".text."; + prefix = one_only ? ".t" : ".text"; break; case SECCAT_RODATA: case SECCAT_RODATA_MERGE_STR: case SECCAT_RODATA_MERGE_STR_INIT: case SECCAT_RODATA_MERGE_CONST: - prefix = one_only ? ".gnu.linkonce.r." : ".rodata."; + prefix = one_only ? ".r" : ".rodata"; break; case SECCAT_SRODATA: - prefix = one_only ? ".gnu.linkonce.s2." : ".sdata2."; + prefix = one_only ? ".s2" : ".sdata2"; break; case SECCAT_DATA: - prefix = one_only ? ".gnu.linkonce.d." : ".data."; + prefix = one_only ? ".d" : ".data"; break; case SECCAT_DATA_REL: - prefix = one_only ? ".gnu.linkonce.d.rel." : ".data.rel."; + prefix = one_only ? ".d.rel" : ".data.rel"; break; case SECCAT_DATA_REL_LOCAL: - prefix = one_only ? ".gnu.linkonce.d.rel.local." : ".data.rel.local."; + prefix = one_only ? ".d.rel.local" : ".data.rel.local"; break; case SECCAT_DATA_REL_RO: - prefix = one_only ? ".gnu.linkonce.d.rel.ro." : ".data.rel.ro."; + prefix = one_only ? ".d.rel.ro" : ".data.rel.ro"; break; case SECCAT_DATA_REL_RO_LOCAL: - prefix = one_only ? ".gnu.linkonce.d.rel.ro.local." - : ".data.rel.ro.local."; + prefix = one_only ? ".d.rel.ro.local" : ".data.rel.ro.local"; break; case SECCAT_SDATA: - prefix = one_only ? ".gnu.linkonce.s." : ".sdata."; + prefix = one_only ? ".s" : ".sdata"; break; case SECCAT_BSS: - prefix = one_only ? ".gnu.linkonce.b." : ".bss."; + prefix = one_only ? ".b" : ".bss"; break; case SECCAT_SBSS: - prefix = one_only ? ".gnu.linkonce.sb." : ".sbss."; + prefix = one_only ? ".sb" : ".sbss"; break; case SECCAT_TDATA: - prefix = one_only ? ".gnu.linkonce.td." : ".tdata."; + prefix = one_only ? ".td" : ".tdata"; break; case SECCAT_TBSS: - prefix = one_only ? ".gnu.linkonce.tb." : ".tbss."; + prefix = one_only ? ".tb" : ".tbss"; + break; + case SECCAT_EMUTLS_VAR: + prefix = targetm.emutls.var_section; + break; + case SECCAT_EMUTLS_TMPL: + prefix = targetm.emutls.tmpl_section; break; default: gcc_unreachable (); } - plen = strlen (prefix); name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); name = targetm.strip_name_encoding (name); - nlen = strlen (name); - string = alloca (nlen + plen + 1); - memcpy (string, prefix, plen); - memcpy (string + plen, name, nlen + 1); + /* If we're using one_only, then there needs to be a .gnu.linkonce + prefix to the section name. */ + linkonce = one_only ? ".gnu.linkonce" : ""; + + string = ACONCAT ((linkonce, prefix, ".", name, NULL)); - DECL_SECTION_NAME (decl) = build_string (nlen + plen, string); + DECL_SECTION_NAME (decl) = build_string (strlen (string), string); } /* Like compute_reloc_for_constant, except for an RTX. The return value @@ -5996,7 +6078,7 @@ default_unique_section (tree decl, int reloc) static int compute_reloc_for_rtx_1 (rtx *xp, void *data) { - int *preloc = data; + int *preloc = (int *) data; rtx x = *xp; switch (GET_CODE (x)) @@ -6124,7 +6206,7 @@ default_asm_output_anchor (rtx symbol) /* The default implementation of TARGET_USE_ANCHORS_FOR_SYMBOL_P. */ bool -default_use_anchors_for_symbol_p (rtx symbol) +default_use_anchors_for_symbol_p (const_rtx symbol) { section *sect; tree decl; @@ -6163,13 +6245,13 @@ default_use_anchors_for_symbol_p (rtx symbol) wrt cross-module name binding. */ bool -default_binds_local_p (tree exp) +default_binds_local_p (const_tree exp) { return default_binds_local_p_1 (exp, flag_shlib); } bool -default_binds_local_p_1 (tree exp, int shlib) +default_binds_local_p_1 (const_tree exp, int shlib) { bool local_p; @@ -6200,9 +6282,10 @@ default_binds_local_p_1 (tree exp, int shlib) else if (DECL_WEAK (exp)) local_p = false; /* If PIC, then assume that any global name can be overridden by - symbols resolved from other modules. */ + symbols resolved from other modules, unless we are compiling with + -fwhole-program, which assumes that names are local. */ else if (shlib) - local_p = false; + local_p = flag_whole_program; /* Uninitialized COMMON variable may be unified with symbols resolved from other modules. */ else if (DECL_COMMON (exp) @@ -6272,7 +6355,7 @@ void default_internal_label (FILE *stream, const char *prefix, unsigned long labelno) { - char *const buf = alloca (40 + strlen (prefix)); + char *const buf = (char *) alloca (40 + strlen (prefix)); ASM_GENERATE_INTERNAL_LABEL (buf, prefix, labelno); ASM_OUTPUT_INTERNAL_LABEL (stream, buf); } @@ -6333,10 +6416,10 @@ switch_to_section (section *new_section) { case SECTION_NAMED: if (cfun - && !cfun->unlikely_text_section_name + && !crtl->subsections.unlikely_text_section_name && strcmp (new_section->named.name, UNLIKELY_EXECUTED_TEXT_SECTION_NAME) == 0) - cfun->unlikely_text_section_name = UNLIKELY_EXECUTED_TEXT_SECTION_NAME; + crtl->subsections.unlikely_text_section_name = UNLIKELY_EXECUTED_TEXT_SECTION_NAME; targetm.asm_out.named_section (new_section->named.name, new_section->named.common.flags,