aboutsummaryrefslogtreecommitdiff
path: root/gcc/varasm.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/varasm.c')
-rw-r--r--gcc/varasm.c126
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