Mercurial > hg > CbC > CbC_gcc
diff gcc/varasm.c @ 63:b7f97abdc517 gcc-4.6-20100522
update gcc from gcc-4.5.0 to gcc-4.6
author | ryoma <e075725@ie.u-ryukyu.ac.jp> |
---|---|
date | Mon, 24 May 2010 12:47:05 +0900 |
parents | 77e2b8dfacca |
children | f6334be47118 |
line wrap: on
line diff
--- a/gcc/varasm.c Fri Feb 12 23:41:23 2010 +0900 +++ b/gcc/varasm.c Mon May 24 12:47:05 2010 +0900 @@ -1,7 +1,7 @@ /* Output variables, constants and external declarations, for GNU compiler. Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, - 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 - Free Software Foundation, Inc. + 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, + 2010 Free Software Foundation, Inc. This file is part of GCC. @@ -38,7 +38,6 @@ #include "expr.h" #include "hard-reg-set.h" #include "regs.h" -#include "real.h" #include "output.h" #include "toplev.h" #include "hashtab.h" @@ -170,11 +169,9 @@ static GTY(()) section *unnamed_sections; /* Return a nonzero value if DECL has a section attribute. */ -#ifndef IN_NAMED_SECTION #define IN_NAMED_SECTION(DECL) \ ((TREE_CODE (DECL) == FUNCTION_DECL || TREE_CODE (DECL) == VAR_DECL) \ && DECL_SECTION_NAME (DECL) != NULL_TREE) -#endif /* Hash table of named sections. */ static GTY((param_is (section))) htab_t section_htab; @@ -367,7 +364,7 @@ /* Note that we use the hash of the decl's name, rather than a hash of the decl's pointer. In emutls_finish we iterate through the hash table, and we want this traversal to be predictable. */ - in.hash = htab_hash_string (IDENTIFIER_POINTER (name)); + in.hash = IDENTIFIER_HASH_VALUE (name); in.base.from = decl; loc = htab_find_slot_with_hash (emutls_htab, &in, in.hash, INSERT); h = (struct tree_map *) *loc; @@ -405,6 +402,8 @@ int foo() { return i; } __thread int i = 1; in which I goes from external to locally defined and initialized. */ + DECL_DLLIMPORT_P (to) = DECL_DLLIMPORT_P (decl); + DECL_ATTRIBUTES (to) = targetm.merge_decl_attributes (decl, to); TREE_STATIC (to) = TREE_STATIC (decl); TREE_USED (to) = TREE_USED (decl); @@ -1174,12 +1173,13 @@ if (TREE_TYPE (decl) != error_mark_node) as = TYPE_ADDR_SPACE (TREE_TYPE (decl)); - /* If the decl has been given an explicit section name, or it resides - in a non-generic address space, then it isn't common, and shouldn't - be handled as such. */ - if (DECL_COMMON (decl) && DECL_SECTION_NAME (decl) == NULL - && ADDR_SPACE_GENERIC_P (as)) - { + if (DECL_COMMON (decl)) + { + /* If the decl has been given an explicit section name, or it resides + in a non-generic address space, then it isn't common, and shouldn't + be handled as such. */ + gcc_assert (DECL_SECTION_NAME (decl) == NULL + && ADDR_SPACE_GENERIC_P (as)); if (DECL_THREAD_LOCAL_P (decl)) return tls_comm_section; /* This cannot be common bss for an emulated TLS object without @@ -1355,6 +1355,14 @@ return; } + /* If this variable belongs to the global constant pool, retrieve the + pre-computed RTL or recompute it in LTO mode. */ + if (TREE_CODE (decl) == VAR_DECL && DECL_IN_CONSTANT_POOL (decl)) + { + SET_DECL_RTL (decl, output_constant_def (DECL_INITIAL (decl), 1)); + return; + } + name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); if (name[0] != '*' && TREE_CODE (decl) != FUNCTION_DECL @@ -1434,6 +1442,10 @@ /* Specifying a section attribute on a variable forces it into a non-.bss section, and thus it cannot be common. */ + /* FIXME: In general this code should not be necessary because + visibility pass is doing the same work. But notice_global_symbol + is called early and it needs to make DECL_RTL to get the name. + we take care of recomputing the DECL_RTL after visibility is changed. */ if (TREE_CODE (decl) == VAR_DECL && DECL_SECTION_NAME (decl) != NULL_TREE && DECL_INITIAL (decl) == NULL_TREE @@ -1474,6 +1486,42 @@ if (flag_mudflap && TREE_CODE (decl) == VAR_DECL) mudflap_enqueue_decl (decl); } + +/* Like make_decl_rtl, but inhibit creation of new alias sets when + calling make_decl_rtl. Also, reset DECL_RTL before returning the + rtl. */ + +rtx +make_decl_rtl_for_debug (tree decl) +{ + unsigned int save_aliasing_flag, save_mudflap_flag; + rtx rtl; + + if (DECL_RTL_SET_P (decl)) + return DECL_RTL (decl); + + /* Kludge alert! Somewhere down the call chain, make_decl_rtl will + call new_alias_set. If running with -fcompare-debug, sometimes + we do not want to create alias sets that will throw the alias + numbers off in the comparison dumps. So... clearing + flag_strict_aliasing will keep new_alias_set() from creating a + new set. It is undesirable to register decl with mudflap + in this case as well. */ + save_aliasing_flag = flag_strict_aliasing; + flag_strict_aliasing = 0; + save_mudflap_flag = flag_mudflap; + flag_mudflap = 0; + + rtl = DECL_RTL (decl); + /* Reset DECL_RTL back, as various parts of the compiler expects + DECL_RTL set meaning it is actually going to be output. */ + SET_DECL_RTL (decl, NULL); + + flag_strict_aliasing = save_aliasing_flag; + flag_mudflap = save_mudflap_flag; + + return rtl; +} /* Output a string of literal assembler code for an `asm' keyword used between functions. */ @@ -2159,8 +2207,6 @@ if (flag_syntax_only) return; - app_disable (); - if (! dont_output_data && ! host_integerp (DECL_SIZE_UNIT (decl), 1)) { @@ -2171,6 +2217,19 @@ gcc_assert (MEM_P (decl_rtl)); gcc_assert (GET_CODE (XEXP (decl_rtl, 0)) == SYMBOL_REF); symbol = XEXP (decl_rtl, 0); + + /* If this symbol belongs to the tree constant pool, output the constant + if it hasn't already been written. */ + if (TREE_CONSTANT_POOL_ADDRESS_P (symbol)) + { + tree decl = SYMBOL_REF_DECL (symbol); + if (!TREE_ASM_WRITTEN (DECL_INITIAL (decl))) + output_constant_def_contents (symbol); + return; + } + + app_disable (); + name = XSTR (symbol, 0); if (TREE_PUBLIC (decl) && DECL_NAME (decl)) notice_global_symbol (decl); @@ -2337,13 +2396,15 @@ /* We want to output annotation for weak and external symbols at very last to check if they are references or not. */ - if (SUPPORTS_WEAK && DECL_WEAK (decl) + if (SUPPORTS_WEAK + && DECL_WEAK (decl) /* TREE_STATIC is a weird and abused creature which is not generally the right test for whether an entity has been locally emitted, inlined or otherwise not-really-extern, but for declarations that can be weak, it happens to be match. */ && !TREE_STATIC (decl) + && lookup_attribute ("weak", DECL_ATTRIBUTES (decl)) && value_member (decl, weak_decls) == NULL_TREE) weak_decls = tree_cons (NULL, decl, weak_decls); @@ -2749,7 +2810,6 @@ { if (TREE_CODE (target) == COMPONENT_REF && host_integerp (byte_position (TREE_OPERAND (target, 1)), 0)) - { offset += int_byte_position (TREE_OPERAND (target, 1)); target = TREE_OPERAND (target, 0); @@ -2761,6 +2821,11 @@ * tree_low_cst (TREE_OPERAND (target, 1), 0)); target = TREE_OPERAND (target, 0); } + else if (TREE_CODE (target) == INDIRECT_REF + && TREE_CODE (TREE_OPERAND (target, 0)) == NOP_EXPR + && TREE_CODE (TREE_OPERAND (TREE_OPERAND (target, 0), 0)) + == ADDR_EXPR) + target = TREE_OPERAND (TREE_OPERAND (TREE_OPERAND (target, 0), 0), 0); else break; } @@ -2801,7 +2866,6 @@ static GTY((param_is (struct constant_descriptor_tree))) htab_t const_desc_htab; -static struct constant_descriptor_tree * build_constant_desc (tree); static void maybe_output_constant_def_contents (struct constant_descriptor_tree *, int); /* Constant pool accessor function. */ @@ -2853,6 +2917,18 @@ return (const_hash_1 (TREE_REALPART (exp)) * 5 + const_hash_1 (TREE_IMAGPART (exp))); + case VECTOR_CST: + { + tree link; + + hi = 7 + TYPE_VECTOR_SUBPARTS (TREE_TYPE (exp)); + + for (link = TREE_VECTOR_CST_ELTS (exp); link; link = TREE_CHAIN (link)) + hi = hi * 563 + const_hash_1 (TREE_VALUE (link)); + + return hi; + } + case CONSTRUCTOR: { unsigned HOST_WIDE_INT idx; @@ -2981,6 +3057,27 @@ return (compare_constant (TREE_REALPART (t1), TREE_REALPART (t2)) && compare_constant (TREE_IMAGPART (t1), TREE_IMAGPART (t2))); + case VECTOR_CST: + { + tree link1, link2; + + if (TYPE_VECTOR_SUBPARTS (TREE_TYPE (t1)) + != TYPE_VECTOR_SUBPARTS (TREE_TYPE (t2))) + return 0; + + link2 = TREE_VECTOR_CST_ELTS (t2); + for (link1 = TREE_VECTOR_CST_ELTS (t1); + link1; + link1 = TREE_CHAIN (link1)) + { + if (!compare_constant (TREE_VALUE (link1), TREE_VALUE (link2))) + return 0; + link2 = TREE_CHAIN (link2); + } + + return 1; + } + case CONSTRUCTOR: { VEC(constructor_elt, gc) *v1, *v2; @@ -3041,11 +3138,34 @@ case FDESC_EXPR: { struct addr_const value1, value2; + enum rtx_code code; + int ret; decode_addr_const (t1, &value1); decode_addr_const (t2, &value2); - return (value1.offset == value2.offset - && strcmp (XSTR (value1.base, 0), XSTR (value2.base, 0)) == 0); + + if (value1.offset != value2.offset) + return 0; + + code = GET_CODE (value1.base); + if (code != GET_CODE (value2.base)) + return 0; + + switch (code) + { + case SYMBOL_REF: + ret = (strcmp (XSTR (value1.base, 0), XSTR (value2.base, 0)) == 0); + break; + + case LABEL_REF: + ret = (CODE_LABEL_NUMBER (XEXP (value1.base, 0)) + == CODE_LABEL_NUMBER (XEXP (value2.base, 0))); + break; + + default: + gcc_unreachable (); + } + return ret; } case PLUS_EXPR: @@ -3106,6 +3226,10 @@ return build1 (TREE_CODE (exp), TREE_TYPE (exp), copy_constant (TREE_OPERAND (exp, 0))); + case VECTOR_CST: + return build_vector (TREE_TYPE (exp), + copy_list (TREE_VECTOR_CST_ELTS (exp))); + case CONSTRUCTOR: { tree copy = copy_node (exp); @@ -3130,31 +3254,14 @@ } } -/* Return the alignment of constant EXP in bits. */ - -static unsigned int -get_constant_alignment (tree exp) -{ - unsigned int align; - - align = TYPE_ALIGN (TREE_TYPE (exp)); -#ifdef CONSTANT_ALIGNMENT - align = CONSTANT_ALIGNMENT (exp, align); -#endif - return align; -} - /* Return the section into which constant EXP should be placed. */ static section * -get_constant_section (tree exp) -{ - if (IN_NAMED_SECTION (exp)) - return get_named_section (exp, NULL, compute_reloc_for_constant (exp)); - else - return targetm.asm_out.select_section (exp, - compute_reloc_for_constant (exp), - get_constant_alignment (exp)); +get_constant_section (tree exp, unsigned int align) +{ + return targetm.asm_out.select_section (exp, + compute_reloc_for_constant (exp), + align); } /* Return the size of constant EXP in bytes. */ @@ -3180,11 +3287,11 @@ static struct constant_descriptor_tree * build_constant_desc (tree exp) { - rtx symbol; - rtx rtl; + struct constant_descriptor_tree *desc; + rtx symbol, rtl; char label[256]; int labelno; - struct constant_descriptor_tree *desc; + tree decl; desc = GGC_NEW (struct constant_descriptor_tree); desc->value = copy_constant (exp); @@ -3197,17 +3304,41 @@ labelno = const_labelno++; ASM_GENERATE_INTERNAL_LABEL (label, "LC", labelno); - /* We have a symbol name; construct the SYMBOL_REF and the MEM. */ + /* Construct the VAR_DECL associated with the constant. */ + decl = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (label), + TREE_TYPE (exp)); + DECL_ARTIFICIAL (decl) = 1; + DECL_IGNORED_P (decl) = 1; + TREE_READONLY (decl) = 1; + TREE_STATIC (decl) = 1; + TREE_ADDRESSABLE (decl) = 1; + /* We don't set the RTL yet as this would cause varpool to assume that the + variable is referenced. Moreover, it would just be dropped in LTO mode. + Instead we set the flag that will be recognized in make_decl_rtl. */ + DECL_IN_CONSTANT_POOL (decl) = 1; + DECL_INITIAL (decl) = desc->value; + /* ??? CONSTANT_ALIGNMENT hasn't been updated for vector types on most + architectures so use DATA_ALIGNMENT as well, except for strings. */ + if (TREE_CODE (exp) == STRING_CST) + { +#ifdef CONSTANT_ALIGNMENT + DECL_ALIGN (decl) = CONSTANT_ALIGNMENT (exp, DECL_ALIGN (decl)); +#endif + } + else + align_variable (decl, 0); + + /* Now construct the SYMBOL_REF and the MEM. */ if (use_object_blocks_p ()) { - section *sect = get_constant_section (exp); + section *sect = get_constant_section (exp, DECL_ALIGN (decl)); symbol = create_block_symbol (ggc_strdup (label), get_block_for_section (sect), -1); } else symbol = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (label)); SYMBOL_REF_FLAGS (symbol) |= SYMBOL_FLAG_LOCAL; - SET_SYMBOL_REF_DECL (symbol, desc->value); + SET_SYMBOL_REF_DECL (symbol, decl); TREE_CONSTANT_POOL_ADDRESS_P (symbol) = 1; rtl = gen_rtx_MEM (TYPE_MODE (TREE_TYPE (exp)), symbol); @@ -3224,7 +3355,6 @@ ASM_OUTPUT_LABELREF will have to know how to strip this information. This call might invalidate our local variable SYMBOL; we can't use it afterward. */ - targetm.encode_section_info (exp, rtl, true); desc->rtl = rtl; @@ -3331,7 +3461,8 @@ static void output_constant_def_contents (rtx symbol) { - tree exp = SYMBOL_REF_DECL (symbol); + tree decl = SYMBOL_REF_DECL (symbol); + tree exp = DECL_INITIAL (decl); unsigned int align; /* Make sure any other constants whose addresses appear in EXP @@ -3348,8 +3479,8 @@ place_block_symbol (symbol); else { - switch_to_section (get_constant_section (exp)); - align = get_constant_alignment (exp); + align = DECL_ALIGN (decl); + switch_to_section (get_constant_section (exp, align)); if (align > BITS_PER_UNIT) ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (align / BITS_PER_UNIT)); assemble_constant_contents (exp, XSTR (symbol, 0), align); @@ -3374,6 +3505,37 @@ return (desc ? desc->rtl : NULL_RTX); } + +/* Return a tree representing a reference to constant data in memory + for the constant expression EXP. + + This is the counterpart of output_constant_def at the Tree level. */ + +tree +tree_output_constant_def (tree exp) +{ + struct constant_descriptor_tree *desc, key; + void **loc; + tree decl; + + /* Look up EXP in the table of constant descriptors. If we didn't find + it, create a new one. */ + key.value = exp; + key.hash = const_hash_1 (exp); + loc = htab_find_slot_with_hash (const_desc_htab, &key, key.hash, INSERT); + + desc = (struct constant_descriptor_tree *) *loc; + if (desc == 0) + { + desc = build_constant_desc (exp); + desc->hash = key.hash; + *loc = desc; + } + + decl = SYMBOL_REF_DECL (XEXP (desc->rtl, 0)); + varpool_finalize_decl (decl); + return decl; +} /* Used in the hash tables to avoid outputting the same constant twice. Unlike 'struct constant_descriptor_tree', RTX constants @@ -3843,8 +4005,8 @@ } else if (TREE_CONSTANT_POOL_ADDRESS_P (x)) { - tree exp = SYMBOL_REF_DECL (x); - if (!TREE_ASM_WRITTEN (exp)) + tree decl = SYMBOL_REF_DECL (x); + if (!TREE_ASM_WRITTEN (DECL_INITIAL (decl))) { n_deferred_constants--; output_constant_def_contents (x); @@ -4091,6 +4253,9 @@ && !VEC_empty (constructor_elt, CONSTRUCTOR_ELTS (ctor))); } +static tree initializer_constant_valid_p_1 (tree value, tree endtype, + tree *cache); + /* A subroutine of initializer_constant_valid_p. VALUE is a MINUS_EXPR, PLUS_EXPR or POINTER_PLUS_EXPR. This looks for cases of VALUE which are valid when ENDTYPE is an integer of any size; in @@ -4100,7 +4265,7 @@ returns NULL. */ static tree -narrowing_initializer_constant_valid_p (tree value, tree endtype) +narrowing_initializer_constant_valid_p (tree value, tree endtype, tree *cache) { tree op0, op1; @@ -4139,11 +4304,14 @@ op1 = inner; } - op0 = initializer_constant_valid_p (op0, endtype); - op1 = initializer_constant_valid_p (op1, endtype); - + op0 = initializer_constant_valid_p_1 (op0, endtype, cache); + if (!op0) + return NULL_TREE; + + op1 = initializer_constant_valid_p_1 (op1, endtype, + cache ? cache + 2 : NULL); /* Both initializers must be known. */ - if (op0 && op1) + if (op1) { if (op0 == op1 && (op0 == null_pointer_node @@ -4164,7 +4332,8 @@ return NULL_TREE; } -/* Return nonzero if VALUE is a valid constant-valued expression +/* Helper function of initializer_constant_valid_p. + 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. @@ -4172,10 +4341,12 @@ if it is relocatable, return the variable that determines the relocation. We assume that VALUE has been folded as much as possible; therefore, we do not need to check for such things as - arithmetic-combinations of integers. */ - -tree -initializer_constant_valid_p (tree value, tree endtype) + arithmetic-combinations of integers. + + Use CACHE (pointer to 2 tree values) for caching if non-NULL. */ + +static tree +initializer_constant_valid_p_1 (tree value, tree endtype, tree *cache) { tree ret; @@ -4188,18 +4359,33 @@ tree elt; bool absolute = true; + if (cache && cache[0] == value) + return cache[1]; FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (value), idx, elt) { tree reloc; - reloc = initializer_constant_valid_p (elt, TREE_TYPE (elt)); + reloc = initializer_constant_valid_p_1 (elt, TREE_TYPE (elt), + NULL); if (!reloc) - return NULL_TREE; + { + if (cache) + { + cache[0] = value; + cache[1] = NULL_TREE; + } + return NULL_TREE; + } if (reloc != null_pointer_node) absolute = false; } /* For a non-absolute relocation, there is no single variable that can be "the variable that determines the relocation." */ + if (cache) + { + cache[0] = value; + cache[1] = absolute ? null_pointer_node : error_mark_node; + } return absolute ? null_pointer_node : error_mark_node; } @@ -4239,7 +4425,8 @@ } case NON_LVALUE_EXPR: - return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype); + return initializer_constant_valid_p_1 (TREE_OPERAND (value, 0), + endtype, cache); case VIEW_CONVERT_EXPR: { @@ -4254,13 +4441,13 @@ if (AGGREGATE_TYPE_P (src_type) && !AGGREGATE_TYPE_P (dest_type)) { if (TYPE_MODE (endtype) == TYPE_MODE (dest_type)) - return initializer_constant_valid_p (src, endtype); + return initializer_constant_valid_p_1 (src, endtype, cache); else return NULL_TREE; } /* Allow all other kinds of view-conversion. */ - return initializer_constant_valid_p (src, endtype); + return initializer_constant_valid_p_1 (src, endtype, cache); } CASE_CONVERT: @@ -4275,18 +4462,18 @@ || (FLOAT_TYPE_P (dest_type) && FLOAT_TYPE_P (src_type)) || (TREE_CODE (dest_type) == OFFSET_TYPE && TREE_CODE (src_type) == OFFSET_TYPE)) - return initializer_constant_valid_p (src, endtype); + return initializer_constant_valid_p_1 (src, endtype, cache); /* Allow length-preserving conversions between integer types. */ if (INTEGRAL_TYPE_P (dest_type) && INTEGRAL_TYPE_P (src_type) && (TYPE_PRECISION (dest_type) == TYPE_PRECISION (src_type))) - return initializer_constant_valid_p (src, endtype); + return initializer_constant_valid_p_1 (src, endtype, cache); /* Allow conversions between other integer types only if explicit value. */ if (INTEGRAL_TYPE_P (dest_type) && INTEGRAL_TYPE_P (src_type)) { - tree inner = initializer_constant_valid_p (src, endtype); + tree inner = initializer_constant_valid_p_1 (src, endtype, cache); if (inner == null_pointer_node) return null_pointer_node; break; @@ -4295,7 +4482,7 @@ /* Allow (int) &foo provided int is as wide as a pointer. */ if (INTEGRAL_TYPE_P (dest_type) && POINTER_TYPE_P (src_type) && (TYPE_PRECISION (dest_type) >= TYPE_PRECISION (src_type))) - return initializer_constant_valid_p (src, endtype); + return initializer_constant_valid_p_1 (src, endtype, cache); /* Likewise conversions from int to pointers, but also allow conversions from 0. */ @@ -4309,14 +4496,14 @@ if (integer_zerop (src)) return null_pointer_node; else if (TYPE_PRECISION (dest_type) <= TYPE_PRECISION (src_type)) - return initializer_constant_valid_p (src, endtype); + return initializer_constant_valid_p_1 (src, endtype, cache); } /* Allow conversions to struct or union types if the value inside is okay. */ if (TREE_CODE (dest_type) == RECORD_TYPE || TREE_CODE (dest_type) == UNION_TYPE) - return initializer_constant_valid_p (src, endtype); + return initializer_constant_valid_p_1 (src, endtype, cache); } break; @@ -4326,66 +4513,102 @@ with -frounding-math we hit this with addition of two constants. */ if (TREE_CODE (endtype) == REAL_TYPE) return NULL_TREE; + if (cache && cache[0] == value) + return cache[1]; if (! INTEGRAL_TYPE_P (endtype) || TYPE_PRECISION (endtype) >= TYPE_PRECISION (TREE_TYPE (value))) { - tree valid0 = initializer_constant_valid_p (TREE_OPERAND (value, 0), - endtype); - tree valid1 = initializer_constant_valid_p (TREE_OPERAND (value, 1), - endtype); + tree ncache[4] = { NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE }; + tree valid0 + = initializer_constant_valid_p_1 (TREE_OPERAND (value, 0), + endtype, ncache); + tree valid1 + = initializer_constant_valid_p_1 (TREE_OPERAND (value, 1), + endtype, ncache + 2); /* 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; + ret = valid1; + else if (valid1 == null_pointer_node) + ret = valid0; + /* Support narrowing pointer differences. */ + else + ret = narrowing_initializer_constant_valid_p (value, endtype, + ncache); } - + else /* Support narrowing pointer differences. */ - ret = narrowing_initializer_constant_valid_p (value, endtype); - if (ret != NULL_TREE) - return ret; - - break; + ret = narrowing_initializer_constant_valid_p (value, endtype, NULL); + if (cache) + { + cache[0] = value; + cache[1] = ret; + } + return ret; case MINUS_EXPR: if (TREE_CODE (endtype) == REAL_TYPE) return NULL_TREE; + if (cache && cache[0] == value) + return cache[1]; if (! INTEGRAL_TYPE_P (endtype) || TYPE_PRECISION (endtype) >= TYPE_PRECISION (TREE_TYPE (value))) { - tree valid0 = initializer_constant_valid_p (TREE_OPERAND (value, 0), - endtype); - tree valid1 = initializer_constant_valid_p (TREE_OPERAND (value, 1), - endtype); + tree ncache[4] = { NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE }; + tree valid0 + = initializer_constant_valid_p_1 (TREE_OPERAND (value, 0), + endtype, ncache); + tree valid1 + = initializer_constant_valid_p_1 (TREE_OPERAND (value, 1), + endtype, ncache + 2); /* Win if second argument is absolute. */ if (valid1 == null_pointer_node) - return valid0; + ret = valid0; /* Win if both arguments have the same relocation. Then the value is absolute. */ - if (valid0 == valid1 && valid0 != 0) - return null_pointer_node; - + else if (valid0 == valid1 && valid0 != 0) + ret = null_pointer_node; /* Since GCC guarantees that string constants are unique in the generated code, a subtraction between two copies of the same constant string is absolute. */ - if (valid0 && TREE_CODE (valid0) == STRING_CST - && valid1 && TREE_CODE (valid1) == STRING_CST - && operand_equal_p (valid0, valid1, 1)) - return null_pointer_node; + else if (valid0 && TREE_CODE (valid0) == STRING_CST + && valid1 && TREE_CODE (valid1) == STRING_CST + && operand_equal_p (valid0, valid1, 1)) + ret = null_pointer_node; + /* Support narrowing differences. */ + else + ret = narrowing_initializer_constant_valid_p (value, endtype, + ncache); } - - /* Support narrowing differences. */ - ret = narrowing_initializer_constant_valid_p (value, endtype); - if (ret != NULL_TREE) - return ret; - - break; + else + /* Support narrowing differences. */ + ret = narrowing_initializer_constant_valid_p (value, endtype, NULL); + if (cache) + { + cache[0] = value; + cache[1] = ret; + } + return ret; default: break; } - return 0; + 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. + + Return null_pointer_node if the value is absolute; + if it is relocatable, return the variable that determines the relocation. + We assume that VALUE has been folded as much as possible; + therefore, we do not need to check for such things as + arithmetic-combinations of integers. */ +tree +initializer_constant_valid_p (tree value, tree endtype) +{ + return initializer_constant_valid_p_1 (value, endtype, NULL); } /* Return true if VALUE is a valid constant-valued expression @@ -5227,6 +5450,9 @@ warning (0, "weak declaration of %q+D not supported", decl); mark_weak (decl); + if (!lookup_attribute ("weak", DECL_ATTRIBUTES (decl))) + DECL_ATTRIBUTES (decl) + = tree_cons (get_identifier ("weak"), NULL, DECL_ATTRIBUTES (decl)); } static void @@ -5425,6 +5651,7 @@ else if (vnode) { varpool_mark_needed_node (vnode); + vnode->force_output = 1; return vnode->decl; } else @@ -5441,6 +5668,10 @@ if (TREE_ASM_WRITTEN (decl)) return; + /* We must force creation of DECL_RTL for debug info generation, even though + we don't use it here. */ + make_decl_rtl (decl); + TREE_ASM_WRITTEN (decl) = 1; TREE_ASM_WRITTEN (DECL_ASSEMBLER_NAME (decl)) = 1; @@ -5658,10 +5889,6 @@ # endif #endif } - - /* We must force creation of DECL_RTL for debug info generation, even though - we don't use it here. */ - make_decl_rtl (decl); TREE_USED (decl) = 1; /* A quirk of the initial implementation of aliases required that the user @@ -5696,8 +5923,10 @@ the visibility type VIS, which must not be VISIBILITY_DEFAULT. */ void -default_assemble_visibility (tree decl, int vis) -{ +default_assemble_visibility (tree decl ATTRIBUTE_UNUSED, + int vis ATTRIBUTE_UNUSED) +{ +#ifdef HAVE_GAS_HIDDEN static const char * const visibility_types[] = { NULL, "protected", "hidden", "internal" }; @@ -5707,7 +5936,6 @@ name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); type = visibility_types[vis]; -#ifdef HAVE_GAS_HIDDEN fprintf (asm_out_file, "\t.%s\t", type); assemble_name (asm_out_file, name); fprintf (asm_out_file, "\n"); @@ -5963,6 +6191,10 @@ gcc_unreachable (); } +#ifndef TLS_SECTION_ASM_FLAG +#define TLS_SECTION_ASM_FLAG 'T' +#endif + void default_elf_asm_named_section (const char *name, unsigned int flags, tree decl ATTRIBUTE_UNUSED) @@ -5993,7 +6225,7 @@ if (flags & SECTION_STRINGS) *f++ = 'S'; if (flags & SECTION_TLS) - *f++ = 'T'; + *f++ = TLS_SECTION_ASM_FLAG; if (HAVE_COMDAT_GROUP && (flags & SECTION_LINKONCE)) *f++ = 'G'; *f = '\0'; @@ -6737,8 +6969,8 @@ else if (TREE_CONSTANT_POOL_ADDRESS_P (symbol)) { decl = SYMBOL_REF_DECL (symbol); - alignment = get_constant_alignment (decl); - size = get_constant_size (decl); + alignment = DECL_ALIGN (decl); + size = get_constant_size (DECL_INITIAL (decl)); } else { @@ -6884,9 +7116,9 @@ else if (TREE_CONSTANT_POOL_ADDRESS_P (symbol)) { decl = SYMBOL_REF_DECL (symbol); - assemble_constant_contents (decl, XSTR (symbol, 0), - get_constant_alignment (decl)); - offset += get_constant_size (decl); + assemble_constant_contents (DECL_INITIAL (decl), XSTR (symbol, 0), + DECL_ALIGN (decl)); + offset += get_constant_size (DECL_INITIAL (decl)); } else { @@ -7031,4 +7263,31 @@ maybe_assemble_visibility (decl); } +/* Create a DEBUG_EXPR_DECL / DEBUG_EXPR pair from RTL expression + EXP. */ +rtx +make_debug_expr_from_rtl (const_rtx exp) +{ + tree ddecl = make_node (DEBUG_EXPR_DECL), type; + enum machine_mode mode = GET_MODE (exp); + rtx dval; + + DECL_ARTIFICIAL (ddecl) = 1; + if (REG_P (exp) && REG_EXPR (exp)) + type = TREE_TYPE (REG_EXPR (exp)); + else if (MEM_P (exp) && MEM_EXPR (exp)) + type = TREE_TYPE (MEM_EXPR (exp)); + else + type = NULL_TREE; + if (type && TYPE_MODE (type) == mode) + TREE_TYPE (ddecl) = type; + else + TREE_TYPE (ddecl) = lang_hooks.types.type_for_mode (mode, 1); + DECL_MODE (ddecl) = mode; + dval = gen_rtx_DEBUG_EXPR (mode); + DEBUG_EXPR_TREE_DECL (dval) = ddecl; + SET_DECL_RTL (ddecl, dval); + return dval; +} + #include "gt-varasm.h"