diff options
Diffstat (limited to 'gcc/varasm.c')
-rw-r--r-- | gcc/varasm.c | 126 |
1 files changed, 92 insertions, 34 deletions
diff --git a/gcc/varasm.c b/gcc/varasm.c index 8b321af8296..c9a9383fe24 100644 --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -1,6 +1,6 @@ /* 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 Free Software Foundation, Inc. + 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. This file is part of GCC. @@ -1586,6 +1586,8 @@ assemble_variable (decl, top_level, at_end, dont_output_data) else if (DECL_INITIAL (decl) == 0 || DECL_INITIAL (decl) == error_mark_node || (flag_zero_initialized_in_bss + /* Leave constant zeroes in .rodata so they can be shared. */ + && !TREE_READONLY (decl) && initializer_zerop (DECL_INITIAL (decl)))) { unsigned HOST_WIDE_INT size = tree_low_cst (DECL_SIZE_UNIT (decl), 1); @@ -2148,7 +2150,11 @@ struct rtx_const GTY(()) ENUM_BITFIELD(machine_mode) mode : 16; union rtx_const_un { REAL_VALUE_TYPE du; - struct addr_const GTY ((tag ("1"))) addr; + struct rtx_const_u_addr { + rtx base; + const char *symbol; + HOST_WIDE_INT offset; + } GTY ((tag ("1"))) addr; struct rtx_const_u_di { HOST_WIDE_INT high; HOST_WIDE_INT low; @@ -2405,7 +2411,7 @@ compare_constant (t1, t2) if (get_set_constructor_bytes (t2, tmp2, len) != NULL_TREE) return 0; - return memcmp (tmp1, tmp2, len) != 0; + return memcmp (tmp1, tmp2, len) == 0; } else { @@ -2656,6 +2662,7 @@ output_constant_def (exp, defer) int labelno = -1; rtx rtl; + /* We can't just use the saved RTL if this is a deferred string constant and we are not to defer anymore. */ if (TREE_CODE (exp) != INTEGER_CST && TREE_CST_RTL (exp) @@ -2819,6 +2826,7 @@ output_constant_def_contents (exp, reloc, labelno) int labelno; { int align; + HOST_WIDE_INT size; /* Align the location counter as required by EXP's data type. */ align = TYPE_ALIGN (TREE_TYPE (exp)); @@ -2836,17 +2844,24 @@ output_constant_def_contents (exp, reloc, labelno) ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (align / BITS_PER_UNIT)); } - /* Output the label itself. */ + size = int_size_in_bytes (TREE_TYPE (exp)); + if (TREE_CODE (exp) == STRING_CST) + size = MAX (TREE_STRING_LENGTH (exp), size); + + /* Do any machine/system dependent processing of the constant. */ +#ifdef ASM_DECLARE_CONSTANT_NAME + { + char label[256]; + ASM_GENERATE_INTERNAL_LABEL (label, "LC", labelno); + ASM_DECLARE_CONSTANT_NAME (asm_out_file, label, exp, size); + } +#else + /* Standard thing is just output label for the constant. */ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LC", labelno); +#endif /* ASM_DECLARE_CONSTANT_NAME */ /* Output the value of EXP. */ - output_constant (exp, - (TREE_CODE (exp) == STRING_CST - ? MAX (TREE_STRING_LENGTH (exp), - int_size_in_bytes (TREE_TYPE (exp))) - : int_size_in_bytes (TREE_TYPE (exp))), - align); - + output_constant (exp, size, align); } /* Used in the hash tables to avoid outputting the same constant @@ -2859,9 +2874,6 @@ struct constant_descriptor_rtx GTY(()) /* More constant_descriptors with the same hash code. */ struct constant_descriptor_rtx *next; - /* The label of the constant. */ - const char *label; - /* A MEM for the constant. */ rtx rtl; @@ -3081,13 +3093,12 @@ decode_rtx_const (mode, x, value) if (value->kind >= RTX_INT && value->un.addr.base != 0) switch (GET_CODE (value->un.addr.base)) { -#if 0 case SYMBOL_REF: /* Use the string's address, not the SYMBOL_REF's address, for the sake of addresses of library routines. */ - value->un.addr.base = (rtx) XSTR (value->un.addr.base, 0); + value->un.addr.symbol = XSTR (value->un.addr.base, 0); + value->un.addr.base = NULL_RTX; break; -#endif case LABEL_REF: /* For a LABEL_REF, compare labels. */ @@ -3112,7 +3123,8 @@ simplify_subtraction (x) if (val0.kind >= RTX_INT && val0.kind == val1.kind - && val0.un.addr.base == val1.un.addr.base) + && val0.un.addr.base == val1.un.addr.base + && val0.un.addr.symbol == val1.un.addr.symbol) return GEN_INT (val0.un.addr.offset - val1.un.addr.offset); return x; @@ -3764,11 +3776,27 @@ initializer_constant_valid_p (value, endtype) || TREE_CODE (TREE_TYPE (value)) == RECORD_TYPE) && TREE_CONSTANT (value) && CONSTRUCTOR_ELTS (value)) - return - initializer_constant_valid_p (TREE_VALUE (CONSTRUCTOR_ELTS (value)), - endtype); + { + tree elt; + bool absolute = true; + + for (elt = CONSTRUCTOR_ELTS (value); elt; elt = TREE_CHAIN (elt)) + { + tree reloc; + value = TREE_VALUE (elt); + reloc = initializer_constant_valid_p (value, TREE_TYPE (value)); + if (!reloc) + 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." */ + return absolute ? null_pointer_node : error_mark_node; + } - return TREE_STATIC (value) ? null_pointer_node : 0; + return TREE_STATIC (value) ? null_pointer_node : NULL_TREE; case INTEGER_CST: case VECTOR_CST: @@ -4047,6 +4075,23 @@ output_constant (exp, size, align) thissize = MIN (TREE_STRING_LENGTH (exp), size); assemble_string (TREE_STRING_POINTER (exp), thissize); } + else if (TREE_CODE (exp) == VECTOR_CST) + { + int elt_size; + tree link; + unsigned int nalign; + enum machine_mode inner; + + inner = GET_MODE_INNER (TYPE_MODE (TREE_TYPE (exp))); + nalign = MIN (align, GET_MODE_ALIGNMENT (inner)); + + elt_size = GET_MODE_UNIT_SIZE (TYPE_MODE (TREE_TYPE (exp))); + + link = TREE_VECTOR_CST_ELTS (exp); + output_constant (TREE_VALUE (link), elt_size, align); + while ((link = TREE_CHAIN (link)) != NULL) + output_constant (TREE_VALUE (link), elt_size, nalign); + } else abort (); break; @@ -4628,14 +4673,26 @@ assemble_alias (decl, target) #endif #else /* !ASM_OUTPUT_DEF */ #if defined (ASM_OUTPUT_WEAK_ALIAS) || defined (ASM_WEAKEN_DECL) - if (! DECL_WEAK (decl)) - warning ("only weak aliases are supported in this configuration"); - + if (DECL_WEAK (decl)) + { + tree *p, t; #ifdef ASM_WEAKEN_DECL - ASM_WEAKEN_DECL (asm_out_file, decl, name, IDENTIFIER_POINTER (target)); + ASM_WEAKEN_DECL (asm_out_file, decl, name, IDENTIFIER_POINTER (target)); #else - ASM_OUTPUT_WEAK_ALIAS (asm_out_file, name, IDENTIFIER_POINTER (target)); + ASM_OUTPUT_WEAK_ALIAS (asm_out_file, name, IDENTIFIER_POINTER (target)); #endif + /* Remove this function from the pending weak list so that + we do not emit multiple .weak directives for it. */ + for (p = &weak_decls; (t = *p) ; ) + if (DECL_ASSEMBLER_NAME (decl) + == DECL_ASSEMBLER_NAME (TREE_VALUE (t))) + *p = TREE_CHAIN (t); + else + p = &TREE_CHAIN (t); + } + else + warning ("only weak aliases are supported in this configuration"); + #else warning ("alias definitions not supported in this configuration; ignored"); #endif @@ -4660,12 +4717,13 @@ default_assemble_visibility (decl, vis) const char *name, *type; - name = (* targetm.strip_name_encoding) - (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))); + name = (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))); type = visibility_types[vis]; #ifdef HAVE_GAS_HIDDEN - fprintf (asm_out_file, "\t.%s\t%s\n", type, name); + fprintf (asm_out_file, "\t.%s\t", type); + assemble_name (asm_out_file, name); + fprintf (asm_out_file, "\n"); #else warning ("visibility attribute not supported in this configuration; ignored"); #endif @@ -4708,16 +4766,16 @@ make_decl_one_only (decl) TREE_PUBLIC (decl) = 1; - if (TREE_CODE (decl) == VAR_DECL - && (DECL_INITIAL (decl) == 0 || DECL_INITIAL (decl) == error_mark_node)) - DECL_COMMON (decl) = 1; - else if (SUPPORTS_ONE_ONLY) + if (SUPPORTS_ONE_ONLY) { #ifdef MAKE_DECL_ONE_ONLY MAKE_DECL_ONE_ONLY (decl); #endif DECL_ONE_ONLY (decl) = 1; } + else if (TREE_CODE (decl) == VAR_DECL + && (DECL_INITIAL (decl) == 0 || DECL_INITIAL (decl) == error_mark_node)) + DECL_COMMON (decl) = 1; else if (SUPPORTS_WEAK) DECL_WEAK (decl) = 1; else |