X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=blobdiff_plain;f=gcc%2Fvarasm.c;h=0a667fe2e3f88ef7cbd2fa43b815a2b66417f8de;hp=6019b5a7e063b7b6bf3b58857d3af91bfed9a1c8;hb=d48cb9c85a325ca11c989c3a7874cb69f8665256;hpb=5dea86897277316778ac91cd98b2ed698937109b diff --git a/gcc/varasm.c b/gcc/varasm.c index 6019b5a7e06..0a667fe2e3f 100644 --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -1,6 +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 Free Software Foundation, Inc. + 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 + Free Software Foundation, Inc. This file is part of GCC. @@ -454,13 +455,8 @@ named_section (tree decl, const char *name, int reloc) if (strcmp (name, UNLIKELY_EXECUTED_TEXT_SECTION_NAME) == 0 && !unlikely_text_section_name) - { - unlikely_text_section_name = xmalloc - (strlen (UNLIKELY_EXECUTED_TEXT_SECTION_NAME) + 1 - * sizeof (char)); - strcpy (unlikely_text_section_name, - UNLIKELY_EXECUTED_TEXT_SECTION_NAME); - } + unlikely_text_section_name = + xstrdup (UNLIKELY_EXECUTED_TEXT_SECTION_NAME); flags = targetm.section_type_flags (decl, name, reloc); @@ -791,7 +787,7 @@ set_user_assembler_name (tree decl, const char *name) int decode_reg_name (const char *asmspec) { - if (asmspec != 0 && strlen (asmspec) != 0) + if (asmspec != 0) { int i; @@ -901,10 +897,10 @@ make_decl_rtl (tree decl) name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); - reg_number = decode_reg_name (name); if (TREE_CODE (decl) != FUNCTION_DECL && DECL_REGISTER (decl)) { + reg_number = decode_reg_name (name); /* First detect errors in declaring global registers. */ if (reg_number == -1) error ("%Jregister name not specified for %qD", decl, decl); @@ -955,12 +951,19 @@ make_decl_rtl (tree decl) return; } } - /* Now handle ordinary static variables and functions (in memory). Also handle vars declared register invalidly. */ - - if (name[0] == '*' && (reg_number >= 0 || reg_number == -3)) - error ("%Jregister name given for non-register variable %qD", decl, decl); + else if (name[0] == '*') + { +#ifdef REGISTER_PREFIX + if (strlen (REGISTER_PREFIX) != 0) + { + reg_number = decode_reg_name (name); + if (reg_number >= 0 || reg_number == -3) + error ("%Jregister name given for non-register variable %qD", decl, decl); + } +#endif + } /* Specifying a section attribute on a variable forces it into a non-.bss section, and thus it cannot be common. */ @@ -1435,9 +1438,16 @@ asm_emit_uninitialised (tree decl, const char *name, 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; + } + if (destination == asm_dest_bss) globalize_decl (decl); - resolve_unique_section (decl, 0, flag_data_sections); if (flag_shared_data) { @@ -1618,16 +1628,6 @@ assemble_variable (tree decl, int top_level ATTRIBUTE_UNUSED, if (DECL_PRESERVE_P (decl)) targetm.asm_out.mark_decl_preserved (name); - /* Output any data that we will need to use the address of. */ - 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)); - output_addressed_constants (DECL_INITIAL (decl)); - } - resolve_unique_section (decl, reloc, flag_data_sections); - /* Handle uninitialized definitions. */ /* If the decl has been given an explicit section name, then it @@ -1681,7 +1681,17 @@ assemble_variable (tree decl, int top_level ATTRIBUTE_UNUSED, if (TREE_PUBLIC (decl) && DECL_NAME (decl)) globalize_decl (decl); + /* Output any data that we will need to use the address of. */ + 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)); + output_addressed_constants (DECL_INITIAL (decl)); + } + /* Switch to the appropriate section. */ + resolve_unique_section (decl, reloc, flag_data_sections); variable_section (decl, reloc); /* dbxout.c needs to know this. */ @@ -1752,6 +1762,12 @@ contains_pointers_p (tree type) } } +/* In unit-at-a-time mode, 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. */ +static GTY(()) tree pending_assemble_externals; + #ifdef ASM_OUTPUT_EXTERNAL /* True if DECL is a function decl for which no out-of-line copy exists. It is assumed that DECL's assembler name has been set. */ @@ -1773,7 +1789,36 @@ incorporeal_function_p (tree decl) } return false; } + +/* Actually do the tests to determine if this is necessary, and invoke + ASM_OUTPUT_EXTERNAL. */ +static void +assemble_external_real (tree decl) +{ + rtx rtl = DECL_RTL (decl); + + if (MEM_P (rtl) && GET_CODE (XEXP (rtl, 0)) == SYMBOL_REF + && !SYMBOL_REF_USED (XEXP (rtl, 0)) + && !incorporeal_function_p (decl)) + { + /* Some systems do require some output. */ + SYMBOL_REF_USED (XEXP (rtl, 0)) = 1; + ASM_OUTPUT_EXTERNAL (asm_out_file, decl, XSTR (XEXP (rtl, 0), 0)); + } +} +#endif + +void +process_pending_assemble_externals (void) +{ +#ifdef ASM_OUTPUT_EXTERNAL + tree list; + for (list = pending_assemble_externals; list; list = TREE_CHAIN (list)) + assemble_external_real (TREE_VALUE (list)); + + pending_assemble_externals = 0; #endif +} /* Output something to declare an external symbol to the assembler. (Most assemblers don't need this, so we normally output nothing.) @@ -1786,23 +1831,17 @@ assemble_external (tree decl ATTRIBUTE_UNUSED) main body of this code is only rarely exercised. To provide some testing, on all platforms, we make sure that the ASM_OUT_FILE is open. If it's not, we should not be calling this function. */ - if (!asm_out_file) - abort (); + gcc_assert (asm_out_file); #ifdef ASM_OUTPUT_EXTERNAL - if (DECL_P (decl) && DECL_EXTERNAL (decl) && TREE_PUBLIC (decl)) - { - rtx rtl = DECL_RTL (decl); + if (!DECL_P (decl) || !DECL_EXTERNAL (decl) || !TREE_PUBLIC (decl)) + return; - if (MEM_P (rtl) && GET_CODE (XEXP (rtl, 0)) == SYMBOL_REF - && !SYMBOL_REF_USED (XEXP (rtl, 0)) - && !incorporeal_function_p (decl)) - { - /* Some systems do require some output. */ - SYMBOL_REF_USED (XEXP (rtl, 0)) = 1; - ASM_OUTPUT_EXTERNAL (asm_out_file, decl, XSTR (XEXP (rtl, 0), 0)); - } - } + if (flag_unit_at_a_time) + pending_assemble_externals = tree_cons (0, decl, + pending_assemble_externals); + else + assemble_external_real (decl); #endif } @@ -1846,11 +1885,24 @@ mark_decl_referenced (tree decl) which do not need to be marked. */ } -/* Output to FILE a reference to the assembler name of a C-level name NAME. - If NAME starts with a *, the rest of NAME is output verbatim. - Otherwise NAME is transformed in an implementation-defined way - (usually by the addition of an underscore). - Many macros in the tm file are defined to call this function. */ +/* Output to FILE (an assembly file) a reference to NAME. If NAME + starts with a *, the rest of NAME is output verbatim. Otherwise + NAME is transformed in a target-specific way (usually by the + addition of an underscore). */ + +void +assemble_name_raw (FILE *file, const char *name) +{ + if (name[0] == '*') + fputs (&name[1], file); + else + ASM_OUTPUT_LABELREF (file, name); +} + +/* Like assemble_name_raw, but should be used when NAME might refer to + an entity that is also represented as a tree (like a function or + variable). If NAME does refer to such an entity, that entity will + be marked as referenced. */ void assemble_name (FILE *file, const char *name) @@ -1864,10 +1916,7 @@ assemble_name (FILE *file, const char *name) if (id) mark_referenced (id); - if (name[0] == '*') - fputs (&name[1], file); - else - ASM_OUTPUT_LABELREF (file, name); + assemble_name_raw (file, name); } /* Allocate SIZE bytes writable static space with a gensym name @@ -2026,8 +2075,9 @@ default_assemble_integer (rtx x ATTRIBUTE_UNUSED, int aligned_p ATTRIBUTE_UNUSED) { const char *op = integer_asm_op (size, aligned_p); - /* Avoid GAS bugs for values > word size. */ - if (size > UNITS_PER_WORD) + /* Avoid GAS bugs for large values. Specifically negative values whose + absolute value fits in a bfd_vma, but not in a bfd_signed_vma. */ + if (size > UNITS_PER_WORD && size > POINTER_SIZE / BITS_PER_UNIT) return false; return op && (assemble_integer_with_op (op, x), true); } @@ -2250,28 +2300,17 @@ const_hash_1 (const tree exp) + const_hash_1 (TREE_IMAGPART (exp))); case CONSTRUCTOR: - if (TREE_CODE (TREE_TYPE (exp)) == SET_TYPE) - { - char *tmp; - - len = int_size_in_bytes (TREE_TYPE (exp)); - tmp = alloca (len); - get_set_constructor_bytes (exp, (unsigned char *) tmp, len); - p = tmp; - break; - } - else - { - tree link; - - hi = 5 + int_size_in_bytes (TREE_TYPE (exp)); - - for (link = CONSTRUCTOR_ELTS (exp); link; link = TREE_CHAIN (link)) - if (TREE_VALUE (link)) - hi = hi * 603 + const_hash_1 (TREE_VALUE (link)); - - return hi; - } + { + tree link; + + hi = 5 + int_size_in_bytes (TREE_TYPE (exp)); + + for (link = CONSTRUCTOR_ELTS (exp); link; link = TREE_CHAIN (link)) + if (TREE_VALUE (link)) + hi = hi * 603 + const_hash_1 (TREE_VALUE (link)); + + return hi; + } case ADDR_EXPR: case FDESC_EXPR: @@ -2370,72 +2409,53 @@ compare_constant (const tree t1, const tree t2) && compare_constant (TREE_IMAGPART (t1), TREE_IMAGPART (t2))); case CONSTRUCTOR: - typecode = TREE_CODE (TREE_TYPE (t1)); - if (typecode != TREE_CODE (TREE_TYPE (t2))) - return 0; - - if (typecode == SET_TYPE) - { - int len = int_size_in_bytes (TREE_TYPE (t2)); - unsigned char *tmp1, *tmp2; - - if (int_size_in_bytes (TREE_TYPE (t1)) != len) - return 0; - - tmp1 = alloca (len); - tmp2 = alloca (len); - - if (get_set_constructor_bytes (t1, tmp1, len) != NULL_TREE) - return 0; - if (get_set_constructor_bytes (t2, tmp2, len) != NULL_TREE) - return 0; - - return memcmp (tmp1, tmp2, len) == 0; - } - else - { - tree l1, l2; - - if (typecode == ARRAY_TYPE) - { - HOST_WIDE_INT size_1 = int_size_in_bytes (TREE_TYPE (t1)); - /* For arrays, check that the sizes all match. */ - if (TYPE_MODE (TREE_TYPE (t1)) != TYPE_MODE (TREE_TYPE (t2)) - || size_1 == -1 - || size_1 != int_size_in_bytes (TREE_TYPE (t2))) - return 0; - } - else - { - /* For record and union constructors, require exact type - equality. */ - if (TREE_TYPE (t1) != TREE_TYPE (t2)) - return 0; - } + { + tree l1, l2; + + typecode = TREE_CODE (TREE_TYPE (t1)); + if (typecode != TREE_CODE (TREE_TYPE (t2))) + return 0; - for (l1 = CONSTRUCTOR_ELTS (t1), l2 = CONSTRUCTOR_ELTS (t2); - l1 && l2; - l1 = TREE_CHAIN (l1), l2 = TREE_CHAIN (l2)) - { - /* Check that each value is the same... */ - if (! compare_constant (TREE_VALUE (l1), TREE_VALUE (l2))) - return 0; - /* ... and that they apply to the same fields! */ - if (typecode == ARRAY_TYPE) - { - if (! compare_constant (TREE_PURPOSE (l1), - TREE_PURPOSE (l2))) - return 0; - } - else - { - if (TREE_PURPOSE (l1) != TREE_PURPOSE (l2)) - return 0; - } - } + if (typecode == ARRAY_TYPE) + { + HOST_WIDE_INT size_1 = int_size_in_bytes (TREE_TYPE (t1)); + /* For arrays, check that the sizes all match. */ + if (TYPE_MODE (TREE_TYPE (t1)) != TYPE_MODE (TREE_TYPE (t2)) + || size_1 == -1 + || size_1 != int_size_in_bytes (TREE_TYPE (t2))) + return 0; + } + else + { + /* For record and union constructors, require exact type + equality. */ + if (TREE_TYPE (t1) != TREE_TYPE (t2)) + return 0; + } - return l1 == NULL_TREE && l2 == NULL_TREE; - } + for (l1 = CONSTRUCTOR_ELTS (t1), l2 = CONSTRUCTOR_ELTS (t2); + l1 && l2; + l1 = TREE_CHAIN (l1), l2 = TREE_CHAIN (l2)) + { + /* Check that each value is the same... */ + if (! compare_constant (TREE_VALUE (l1), TREE_VALUE (l2))) + return 0; + /* ... and that they apply to the same fields! */ + if (typecode == ARRAY_TYPE) + { + if (! compare_constant (TREE_PURPOSE (l1), + TREE_PURPOSE (l2))) + return 0; + } + else + { + if (TREE_PURPOSE (l1) != TREE_PURPOSE (l2)) + return 0; + } + } + + return l1 == NULL_TREE && l2 == NULL_TREE; + } case ADDR_EXPR: case FDESC_EXPR: @@ -2525,9 +2545,6 @@ copy_constant (tree exp) CONSTRUCTOR_ELTS (copy) = list; for (tail = list; tail; tail = TREE_CHAIN (tail)) TREE_VALUE (tail) = copy_constant (TREE_VALUE (tail)); - if (TREE_CODE (TREE_TYPE (exp)) == SET_TYPE) - for (tail = list; tail; tail = TREE_CHAIN (tail)) - TREE_PURPOSE (tail) = copy_constant (TREE_PURPOSE (tail)); return copy; } @@ -2852,6 +2869,14 @@ const_rtx_hash_1 (rtx *xp, void *data) h ^= real_hash (CONST_DOUBLE_REAL_VALUE (x)); break; + case CONST_VECTOR: + { + int i; + for (i = XVECLEN (x, 0); i-- > 0; ) + h = h * 251 + const_rtx_hash_1 (&XVECEXP (x, 0, i), data); + } + break; + case SYMBOL_REF: h ^= htab_hash_string (XSTR (x, 0)); break; @@ -3000,6 +3025,7 @@ force_const_mem (enum machine_mode mode, rtx x) /* Construct the MEM. */ desc->mem = def = gen_const_mem (mode, symbol); set_mem_attributes (def, lang_hooks.types.type_for_mode (mode, 0), 1); + set_mem_align (def, align); /* If we're dropping a label to the constant pool, make sure we don't delete it. */ @@ -3478,6 +3504,12 @@ initializer_constant_valid_p (tree value, tree endtype) && 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 (value + && TREE_CODE (value) == FUNCTION_DECL + && ((decl_function_context (value) && !DECL_NO_STATIC_CHAIN (value)) + || DECL_NON_ADDR_CONST_P (value))) + return NULL_TREE; return value; case VIEW_CONVERT_EXPR: @@ -3486,63 +3518,61 @@ initializer_constant_valid_p (tree value, tree endtype) case CONVERT_EXPR: case NOP_EXPR: - /* Allow conversions between pointer types. */ - if (POINTER_TYPE_P (TREE_TYPE (value)) - && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (value, 0)))) - return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype); - - /* Allow conversions between real types. */ - if (FLOAT_TYPE_P (TREE_TYPE (value)) - && FLOAT_TYPE_P (TREE_TYPE (TREE_OPERAND (value, 0)))) - return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype); - - /* Allow length-preserving conversions between integer types. */ - if (INTEGRAL_TYPE_P (TREE_TYPE (value)) - && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (value, 0))) - && (TYPE_PRECISION (TREE_TYPE (value)) - == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (value, 0))))) - return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype); - - /* Allow conversions between other integer types only if - explicit value. */ - if (INTEGRAL_TYPE_P (TREE_TYPE (value)) - && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (value, 0)))) - { - tree inner = initializer_constant_valid_p (TREE_OPERAND (value, 0), - endtype); - if (inner == null_pointer_node) - return null_pointer_node; - break; - } + { + tree src; + tree src_type; + tree dest_type; + + src = TREE_OPERAND (value, 0); + src_type = TREE_TYPE (src); + dest_type = TREE_TYPE (value); + + /* Allow conversions between pointer types, floating-point + types, and offset types. */ + if ((POINTER_TYPE_P (dest_type) && POINTER_TYPE_P (src_type)) + || (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); + + /* 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); + + /* 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); + if (inner == null_pointer_node) + return null_pointer_node; + break; + } - /* Allow (int) &foo provided int is as wide as a pointer. */ - if (INTEGRAL_TYPE_P (TREE_TYPE (value)) - && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (value, 0))) - && (TYPE_PRECISION (TREE_TYPE (value)) - >= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (value, 0))))) - return initializer_constant_valid_p (TREE_OPERAND (value, 0), - endtype); - - /* Likewise conversions from int to pointers, but also allow - conversions from 0. */ - if ((POINTER_TYPE_P (TREE_TYPE (value)) - || TREE_CODE (TREE_TYPE (value)) == OFFSET_TYPE) - && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (value, 0)))) - { - if (integer_zerop (TREE_OPERAND (value, 0))) - return null_pointer_node; - else if (TYPE_PRECISION (TREE_TYPE (value)) - <= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (value, 0)))) - return initializer_constant_valid_p (TREE_OPERAND (value, 0), - endtype); - } + /* 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); + + /* Likewise conversions from int to pointers, but also allow + conversions from 0. */ + if ((POINTER_TYPE_P (dest_type) + || TREE_CODE (dest_type) == OFFSET_TYPE) + && INTEGRAL_TYPE_P (src_type)) + { + 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); + } - /* Allow conversions to struct or union types if the value - inside is okay. */ - if (TREE_CODE (TREE_TYPE (value)) == RECORD_TYPE - || TREE_CODE (TREE_TYPE (value)) == UNION_TYPE) - return initializer_constant_valid_p (TREE_OPERAND (value, 0), - endtype); + /* 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); + } break; case PLUS_EXPR: @@ -3790,22 +3820,6 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align) abort (); return; - case SET_TYPE: - if (TREE_CODE (exp) == INTEGER_CST) - assemble_integer (expand_expr (exp, NULL_RTX, - VOIDmode, EXPAND_INITIALIZER), - thissize, align, 1); - else if (TREE_CODE (exp) == CONSTRUCTOR) - { - unsigned char *buffer = alloca (thissize); - if (get_set_constructor_bytes (exp, buffer, thissize)) - abort (); - assemble_string ((char *) buffer, thissize); - } - else - error ("unknown set constructor type"); - return; - case ERROR_MARK: return; @@ -4334,20 +4348,67 @@ globalize_decl (tree decl) targetm.asm_out.globalize_label (asm_out_file, name); } +/* Some targets do not allow a forward or undefined reference in a + ASM_OUTPUT_DEF. Thus, a mechanism is needed to defer the output of + this assembler code. The following struct holds the declaration + and target for a deferred output define. */ +struct output_def_pair GTY(()) +{ + tree decl; + tree target; +}; +typedef struct output_def_pair *output_def_pair; + +/* Define gc'd vector type. */ +DEF_VEC_GC_P(output_def_pair); + +/* Vector of output_def_pair pointers. */ +static GTY(()) VEC(output_def_pair) *output_defs; + +#ifdef ASM_OUTPUT_DEF +/* Output the assembler code for a define (equate) using ASM_OUTPUT_DEF + or ASM_OUTPUT_DEF_FROM_DECLS. The function defines the symbol whose + tree node is DECL to have the value of the tree node TARGET. */ + +static void +assemble_output_def (tree decl ATTRIBUTE_UNUSED, tree target ATTRIBUTE_UNUSED) +{ +#ifdef ASM_OUTPUT_DEF_FROM_DECLS + ASM_OUTPUT_DEF_FROM_DECLS (asm_out_file, decl, target); +#else + ASM_OUTPUT_DEF (asm_out_file, + IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)), + IDENTIFIER_POINTER (target)); +#endif +} +#endif + +/* Process the vector of pending assembler defines. */ + +void +process_pending_assemble_output_defs (void) +{ +#ifdef ASM_OUTPUT_DEF + unsigned i; + output_def_pair p; + + for (i = 0; VEC_iterate (output_def_pair, output_defs, i, p); i++) + assemble_output_def (p->decl, p->target); + + output_defs = NULL; +#endif +} + /* Emit an assembler directive to make the symbol for DECL an alias to the symbol for TARGET. */ void -assemble_alias (tree decl, tree target ATTRIBUTE_UNUSED) +assemble_alias (tree decl, tree target) { - const char *name; - /* We must force creation of DECL_RTL for debug info generation, even though we don't use it here. */ make_decl_rtl (decl); - name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); - #ifdef ASM_OUTPUT_DEF /* Make name accessible from other files, if appropriate. */ @@ -4357,16 +4418,25 @@ assemble_alias (tree decl, tree target ATTRIBUTE_UNUSED) maybe_assemble_visibility (decl); } -#ifdef ASM_OUTPUT_DEF_FROM_DECLS - ASM_OUTPUT_DEF_FROM_DECLS (asm_out_file, decl, target); -#else - ASM_OUTPUT_DEF (asm_out_file, name, IDENTIFIER_POINTER (target)); -#endif + if (TARGET_DEFERRED_OUTPUT_DEFS (decl, target)) + { + output_def_pair p; + + p = ggc_alloc (sizeof (struct output_def_pair)); + p->decl = decl; + p->target = target; + VEC_safe_push (output_def_pair, output_defs, p); + } + else + assemble_output_def (decl, target); #else /* !ASM_OUTPUT_DEF */ #if defined (ASM_OUTPUT_WEAK_ALIAS) || defined (ASM_WEAKEN_DECL) if (DECL_WEAK (decl)) { + const char *name; tree *p, t; + + name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); #ifdef ASM_WEAKEN_DECL ASM_WEAKEN_DECL (asm_out_file, decl, name, IDENTIFIER_POINTER (target)); #else @@ -4389,6 +4459,44 @@ assemble_alias (tree decl, tree target ATTRIBUTE_UNUSED) #endif #endif + /* Tell cgraph that the aliased symbol is needed. We *could* be more + specific and tell cgraph about the relationship between the two + symbols, but given that aliases virtually always exist for a reason, + it doesn't seem worthwhile. */ + if (flag_unit_at_a_time) + { + struct cgraph_node *fnode = NULL; + struct cgraph_varpool_node *vnode = NULL; + + if (TREE_CODE (decl) == FUNCTION_DECL) + { + fnode = cgraph_node_for_asm (target); + if (fnode != NULL) + cgraph_mark_needed_node (fnode); + else + { + vnode = cgraph_varpool_node_for_asm (target); + if (vnode != NULL) + cgraph_varpool_mark_needed_node (vnode); + } + } + else + { + vnode = cgraph_varpool_node_for_asm (target); + if (vnode != NULL) + cgraph_varpool_mark_needed_node (vnode); + else + { + fnode = cgraph_node_for_asm (target); + if (fnode != NULL) + cgraph_mark_needed_node (fnode); + } + } + + if (fnode == NULL && vnode == NULL) + warning ("%qD aliased to undefined symbol %qE", decl, target); + } + TREE_USED (decl) = 1; TREE_ASM_WRITTEN (decl) = 1; TREE_ASM_WRITTEN (DECL_ASSEMBLER_NAME (decl)) = 1; @@ -4565,17 +4673,19 @@ default_section_type_flags_1 (tree decl, const char *name, int reloc, || strncmp (name, ".gnu.linkonce.b.", 16) == 0 || strcmp (name, ".sbss") == 0 || strncmp (name, ".sbss.", 6) == 0 - || strncmp (name, ".gnu.linkonce.sb.", 17) == 0 - || strcmp (name, ".tbss") == 0 - || strncmp (name, ".gnu.linkonce.tb.", 17) == 0) + || strncmp (name, ".gnu.linkonce.sb.", 17) == 0) flags |= SECTION_BSS; if (strcmp (name, ".tdata") == 0 - || strcmp (name, ".tbss") == 0 - || strncmp (name, ".gnu.linkonce.td.", 17) == 0 - || strncmp (name, ".gnu.linkonce.tb.", 17) == 0) + || strncmp (name, ".tdata.", 7) == 0 + || strncmp (name, ".gnu.linkonce.td.", 17) == 0) flags |= SECTION_TLS; + if (strcmp (name, ".tbss") == 0 + || strncmp (name, ".tbss.", 6) == 0 + || strncmp (name, ".gnu.linkonce.tb.", 17) == 0) + flags |= SECTION_TLS | SECTION_BSS; + /* These three sections have special ELF types. They are neither SHT_PROGBITS nor SHT_NOBITS, so when changing sections we don't want to print a section type (@progbits or @nobits). If someone @@ -4896,6 +5006,7 @@ void default_elf_select_section_1 (tree decl, int reloc, unsigned HOST_WIDE_INT align, int shlib) { + const char *sname; switch (categorize_decl_for_section (decl, reloc, shlib)) { case SECCAT_TEXT: @@ -4903,56 +5014,61 @@ default_elf_select_section_1 (tree decl, int reloc, abort (); case SECCAT_RODATA: readonly_data_section (); - break; + return; case SECCAT_RODATA_MERGE_STR: mergeable_string_section (decl, align, 0); - break; + return; case SECCAT_RODATA_MERGE_STR_INIT: mergeable_string_section (DECL_INITIAL (decl), align, 0); - break; + return; case SECCAT_RODATA_MERGE_CONST: mergeable_constant_section (DECL_MODE (decl), align, 0); - break; + return; case SECCAT_SRODATA: - named_section (NULL_TREE, ".sdata2", reloc); + sname = ".sdata2"; break; case SECCAT_DATA: data_section (); - break; + return; case SECCAT_DATA_REL: - named_section (NULL_TREE, ".data.rel", reloc); + sname = ".data.rel"; break; case SECCAT_DATA_REL_LOCAL: - named_section (NULL_TREE, ".data.rel.local", reloc); + sname = ".data.rel.local"; break; case SECCAT_DATA_REL_RO: - named_section (NULL_TREE, ".data.rel.ro", reloc); + sname = ".data.rel.ro"; break; case SECCAT_DATA_REL_RO_LOCAL: - named_section (NULL_TREE, ".data.rel.ro.local", reloc); + sname = ".data.rel.ro.local"; break; case SECCAT_SDATA: - named_section (NULL_TREE, ".sdata", reloc); + sname = ".sdata"; break; case SECCAT_TDATA: - named_section (NULL_TREE, ".tdata", reloc); + sname = ".tdata"; break; case SECCAT_BSS: #ifdef BSS_SECTION_ASM_OP bss_section (); + return; #else - named_section (NULL_TREE, ".bss", reloc); -#endif + sname = ".bss"; break; +#endif case SECCAT_SBSS: - named_section (NULL_TREE, ".sbss", reloc); + sname = ".sbss"; break; case SECCAT_TBSS: - named_section (NULL_TREE, ".tbss", reloc); + sname = ".tbss"; break; default: abort (); } + + if (!DECL_P (decl)) + decl = NULL_TREE; + named_section (decl, sname, reloc); } /* Construct a unique section name based on the decl name and the @@ -5090,10 +5206,10 @@ default_encode_section_info (tree decl, rtx rtl, int first ATTRIBUTE_UNUSED) flags |= SYMBOL_FLAG_FUNCTION; if (targetm.binds_local_p (decl)) flags |= SYMBOL_FLAG_LOCAL; - if (targetm.in_small_data_p (decl)) - flags |= SYMBOL_FLAG_SMALL; if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL (decl)) flags |= decl_tls_model (decl) << SYMBOL_FLAG_TLS_SHIFT; + else if (targetm.in_small_data_p (decl)) + flags |= SYMBOL_FLAG_SMALL; /* ??? Why is DECL_EXTERNAL ever set for non-PUBLIC names? Without being PUBLIC, the thing *must* be defined in this translation unit. Prevent this buglet from being propagated into rtl code as well. */ @@ -5203,7 +5319,7 @@ default_internal_label (FILE *stream, const char *prefix, { char *const buf = alloca (40 + strlen (prefix)); ASM_GENERATE_INTERNAL_LABEL (buf, prefix, labelno); - ASM_OUTPUT_LABEL (stream, buf); + ASM_OUTPUT_INTERNAL_LABEL (stream, buf); } /* This is the default behavior at the beginning of a file. It's