aboutsummaryrefslogtreecommitdiff
path: root/gcc/varasm.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/varasm.c')
-rw-r--r--gcc/varasm.c269
1 files changed, 154 insertions, 115 deletions
diff --git a/gcc/varasm.c b/gcc/varasm.c
index 46810c6833f..dcfe381593c 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -166,9 +166,7 @@ static unsigned HOST_WIDE_INT array_size_for_constructor PARAMS ((tree));
static unsigned min_align PARAMS ((unsigned, unsigned));
static void output_constructor PARAMS ((tree, HOST_WIDE_INT,
unsigned int));
-#ifdef ASM_WEAKEN_LABEL
-static void remove_from_pending_weak_list PARAMS ((const char *));
-#endif
+static void globalize_decl PARAMS ((tree));
static int in_named_entry_eq PARAMS ((const PTR, const PTR));
static hashval_t in_named_entry_hash PARAMS ((const PTR));
#ifdef ASM_OUTPUT_BSS
@@ -188,7 +186,8 @@ static hashval_t const_str_htab_hash PARAMS ((const void *x));
static int const_str_htab_eq PARAMS ((const void *x, const void *y));
static void const_str_htab_del PARAMS ((void *));
static void asm_emit_uninitialised PARAMS ((tree, const char*, int, int));
-static void resolve_unique_section PARAMS ((tree, int));
+static void resolve_unique_section PARAMS ((tree, int, int));
+static void mark_weak PARAMS ((tree));
static enum in_section { no_section, in_text, in_data, in_named
#ifdef BSS_SECTION_ASM_OP
@@ -462,12 +461,13 @@ named_section (decl, name, reloc)
/* If required, set DECL_SECTION_NAME to a unique name. */
static void
-resolve_unique_section (decl, reloc)
+resolve_unique_section (decl, reloc, flag_function_or_data_sections)
tree decl;
int reloc ATTRIBUTE_UNUSED;
+ int flag_function_or_data_sections;
{
if (DECL_SECTION_NAME (decl) == NULL_TREE
- && (flag_function_sections
+ && (flag_function_or_data_sections
|| (targetm.have_named_sections
&& DECL_ONE_ONLY (decl))))
UNIQUE_SECTION (decl, reloc);
@@ -516,7 +516,7 @@ asm_output_bss (file, decl, name, size, rounded)
/* Standard thing is just output label for the object. */
ASM_OUTPUT_LABEL (file, name);
#endif /* ASM_DECLARE_OBJECT_NAME */
- ASM_OUTPUT_SKIP (file, rounded);
+ ASM_OUTPUT_SKIP (file, rounded ? rounded : 1);
}
#endif
@@ -535,7 +535,6 @@ asm_output_aligned_bss (file, decl, name, size, align)
const char *name;
int size, align;
{
- ASM_GLOBALIZE_LABEL (file, name);
bss_section ();
ASM_OUTPUT_ALIGN (file, floor_log2 (align / BITS_PER_UNIT));
#ifdef ASM_DECLARE_OBJECT_NAME
@@ -1189,11 +1188,13 @@ assemble_start_function (decl, fnname)
if (CONSTANT_POOL_BEFORE_FUNCTION)
output_constant_pool (fnname, decl);
- resolve_unique_section (decl, 0);
+ resolve_unique_section (decl, 0, flag_function_sections);
function_section (decl);
/* 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;
if (align > 0)
{
ASM_OUTPUT_ALIGN (asm_out_file, align);
@@ -1237,18 +1238,7 @@ assemble_start_function (decl, fnname)
weak_global_object_name = name;
}
-#ifdef ASM_WEAKEN_LABEL
- if (DECL_WEAK (decl))
- {
- ASM_WEAKEN_LABEL (asm_out_file, fnname);
- /* Remove this function from the pending weak list so that
- we do not emit multiple .weak directives for it. */
- remove_from_pending_weak_list
- (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
- }
- else
-#endif
- ASM_GLOBALIZE_LABEL (asm_out_file, fnname);
+ globalize_decl (decl);
}
/* Do any machine/system dependent processing of the function name */
@@ -1407,6 +1397,10 @@ asm_emit_uninitialised (decl, name, size, rounded)
destination = asm_dest_common;
}
+ if (destination == asm_dest_bss)
+ globalize_decl (decl);
+ resolve_unique_section (decl, 0, flag_data_sections);
+
if (flag_shared_data)
{
switch (destination)
@@ -1431,8 +1425,6 @@ asm_emit_uninitialised (decl, name, size, rounded)
}
}
- resolve_unique_section (decl, 0);
-
switch (destination)
{
#ifdef ASM_EMIT_BSS
@@ -1643,20 +1635,7 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
/* First make the assembler name(s) global if appropriate. */
if (TREE_PUBLIC (decl) && DECL_NAME (decl))
- {
-#ifdef ASM_WEAKEN_LABEL
- if (DECL_WEAK (decl))
- {
- ASM_WEAKEN_LABEL (asm_out_file, name);
- /* Remove this variable from the pending weak list so that
- we do not emit multiple .weak directives for it. */
- remove_from_pending_weak_list
- (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
- }
- else
-#endif
- ASM_GLOBALIZE_LABEL (asm_out_file, name);
- }
+ globalize_decl (decl);
/* Output any data that we will need to use the address of. */
if (DECL_INITIAL (decl) == error_mark_node)
@@ -1665,7 +1644,7 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
reloc = output_addressed_constants (DECL_INITIAL (decl));
/* Switch to the appropriate section. */
- resolve_unique_section (decl, reloc);
+ resolve_unique_section (decl, reloc, flag_data_sections);
variable_section (decl, reloc);
/* dbxout.c needs to know this. */
@@ -1690,7 +1669,7 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
if (!dont_output_data)
{
- if (DECL_INITIAL (decl))
+ if (DECL_INITIAL (decl) && DECL_INITIAL (decl) != error_mark_node)
/* Output the actual data. */
output_constant (DECL_INITIAL (decl),
tree_low_cst (DECL_SIZE_UNIT (decl), 1),
@@ -2583,6 +2562,7 @@ const_hash (exp)
}
case ADDR_EXPR:
+ case FDESC_EXPR:
{
struct addr_const value;
@@ -2824,6 +2804,7 @@ compare_constant_1 (exp, p)
}
case ADDR_EXPR:
+ case FDESC_EXPR:
{
struct addr_const value;
@@ -3305,7 +3286,11 @@ output_constant_def (exp, defer)
encoded in it. */
if (! found)
{
- ENCODE_SECTION_INFO (exp);
+ /* Take care not to invoque ENCODE_SECTION_INFO for constants
+ which don't have a TREE_CST_RTL. */
+ if (TREE_CODE (exp) != INTEGER_CST)
+ ENCODE_SECTION_INFO (exp);
+
desc->rtl = rtl;
desc->label = XSTR (XEXP (desc->rtl, 0), 0);
}
@@ -4266,6 +4251,7 @@ output_addressed_constants (exp)
switch (TREE_CODE (exp))
{
case ADDR_EXPR:
+ case FDESC_EXPR:
/* Go inside any operations that get_inner_reference can handle and see
if what's inside is a constant: no need to do anything here for
addresses of variables or functions. */
@@ -5006,39 +4992,79 @@ output_constructor (exp, size, align)
assemble_zeros (size - total_bytes);
}
-
-/* This structure contains any weak symbol declarations waiting
+/* This TREE_LIST contains any weak symbol declarations waiting
to be emitted. */
-struct weak_syms
-{
- struct weak_syms * next;
- const char * name;
- const char * value;
-};
+static tree weak_decls;
-static struct weak_syms * weak_decls;
+/* Mark DECL as weak. */
-/* Add function NAME to the weak symbols list. VALUE is a weak alias
- associated with NAME. */
-
-int
-add_weak (name, value)
- const char *name;
- const char *value;
+static void
+mark_weak (decl)
+ tree decl;
{
- struct weak_syms *weak;
+ DECL_WEAK (decl) = 1;
- weak = (struct weak_syms *) xmalloc (sizeof (struct weak_syms));
+ if (DECL_RTL_SET_P (decl)
+ && GET_CODE (DECL_RTL (decl)) == MEM
+ && XEXP (DECL_RTL (decl), 0)
+ && GET_CODE (XEXP (DECL_RTL (decl), 0)) == SYMBOL_REF)
+ SYMBOL_REF_WEAK (XEXP (DECL_RTL (decl), 0)) = 1;
+}
+
+/* Merge weak status between NEWDECL and OLDDECL. */
- if (weak == NULL)
- return 0;
+void
+merge_weak (newdecl, olddecl)
+ tree newdecl;
+ tree olddecl;
+{
+ if (DECL_WEAK (newdecl) == DECL_WEAK (olddecl))
+ return;
- weak->next = weak_decls;
- weak->name = name;
- weak->value = value;
- weak_decls = weak;
+ if (DECL_WEAK (newdecl))
+ {
+ tree wd;
+
+ /* 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
+ declare_weak because the NEWDECL and OLDDECL was not yet
+ been merged; therefore, TREE_ASM_WRITTEN was not set. */
+ if (TREE_ASM_WRITTEN (olddecl))
+ error_with_decl (newdecl,
+ "weak declaration of `%s' must precede definition");
+
+ /* If we've already generated rtl referencing OLDDECL, we may
+ have done so in a way that will not function properly with
+ a weak symbol. */
+ else if (TREE_USED (olddecl)
+ && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (olddecl)))
+ warning_with_decl (newdecl, "weak declaration of `%s' after first use results in unspecified behavior");
+
+ if (SUPPORTS_WEAK)
+ {
+ /* We put the NEWDECL on the weak_decls list at some point.
+ Replace it with the OLDDECL. */
+ for (wd = weak_decls; wd; wd = TREE_CHAIN (wd))
+ if (TREE_VALUE (wd) == newdecl)
+ {
+ TREE_VALUE (wd) = olddecl;
+ break;
+ }
+ /* We may not find the entry on the list. If NEWDECL is a
+ weak alias, then we will have already called
+ globalize_decl to remove the entry; in that case, we do
+ not need to do anything. */
+ }
- return 1;
+ /* Make the OLDDECL weak; it's OLDDECL that we'll be keeping. */
+ mark_weak (olddecl);
+ }
+ else
+ /* OLDDECL was weak, but NEWDECL was not explicitly marked as
+ weak. Just update NEWDECL to indicate that it's weak too. */
+ mark_weak (newdecl);
}
/* Declare DECL to be a weak symbol. */
@@ -5049,14 +5075,17 @@ declare_weak (decl)
{
if (! TREE_PUBLIC (decl))
error_with_decl (decl, "weak declaration of `%s' must be public");
- else if (TREE_ASM_WRITTEN (decl))
+ else if (TREE_CODE (decl) == FUNCTION_DECL && TREE_ASM_WRITTEN (decl))
error_with_decl (decl, "weak declaration of `%s' must precede definition");
else if (SUPPORTS_WEAK)
- add_weak (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)), NULL);
+ {
+ if (! DECL_WEAK (decl))
+ weak_decls = tree_cons (NULL, decl, weak_decls);
+ }
else
warning_with_decl (decl, "weak declaration of `%s' not supported");
- DECL_WEAK (decl) = 1;
+ mark_weak (decl);
}
/* Emit any pending weak declarations. */
@@ -5064,48 +5093,65 @@ declare_weak (decl)
void
weak_finish ()
{
- if (SUPPORTS_WEAK)
+ tree t;
+
+ for (t = weak_decls; t ; t = TREE_CHAIN (t))
{
- struct weak_syms *t;
- for (t = weak_decls; t; t = t->next)
- {
-#ifdef ASM_OUTPUT_WEAK_ALIAS
- ASM_OUTPUT_WEAK_ALIAS (asm_out_file, t->name, t->value);
+ tree decl = TREE_VALUE (t);
+ const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
+
+ if (! TREE_USED (decl))
+ continue;
+
+#ifdef ASM_WEAKEN_DECL
+ ASM_WEAKEN_DECL (asm_out_file, decl, name, NULL);
#else
#ifdef ASM_WEAKEN_LABEL
- if (t->value)
- abort ();
- ASM_WEAKEN_LABEL (asm_out_file, t->name);
+ ASM_WEAKEN_LABEL (asm_out_file, name);
+#else
+#ifdef ASM_OUTPUT_WEAK_ALIAS
+ warning ("only weak aliases are supported in this configuration");
+ return;
+#endif
#endif
#endif
- }
}
}
-/* Remove NAME from the pending list of weak symbols. This prevents
- the compiler from emitting multiple .weak directives which confuses
- some assemblers. */
-#ifdef ASM_WEAKEN_LABEL
+/* Emit the assembly bits to indicate that DECL is globally visible. */
+
static void
-remove_from_pending_weak_list (name)
- const char *name;
+globalize_decl (decl)
+ tree decl;
{
- struct weak_syms *t;
- struct weak_syms **p;
+ const char *name = XSTR (XEXP (DECL_RTL (decl), 0), 0);
- for (p = &weak_decls; *p; )
+#if defined (ASM_WEAKEN_LABEL) || defined (ASM_WEAKEN_DECL)
+ if (DECL_WEAK (decl))
{
- t = *p;
- if (strcmp (name, t->name) == 0)
- {
- *p = t->next;
- free (t);
- }
- else
- p = &(t->next);
+ tree *p, t;
+
+#ifdef ASM_WEAKEN_DECL
+ ASM_WEAKEN_DECL (asm_out_file, decl, name, 0);
+#else
+ ASM_WEAKEN_LABEL (asm_out_file, name);
+#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);
+ }
+ return;
}
+#endif
+
+ ASM_GLOBALIZE_LABEL (asm_out_file, name);
}
-#endif /* ASM_WEAKEN_LABEL */
/* Emit an assembler directive to make the symbol for DECL an alias to
the symbol for TARGET. */
@@ -5124,40 +5170,32 @@ assemble_alias (decl, target)
#ifdef ASM_OUTPUT_DEF
/* Make name accessible from other files, if appropriate. */
-
if (TREE_PUBLIC (decl))
- {
-#ifdef ASM_WEAKEN_LABEL
- if (DECL_WEAK (decl))
- {
- ASM_WEAKEN_LABEL (asm_out_file, name);
- /* Remove this function from the pending weak list so that
- we do not emit multiple .weak directives for it. */
- remove_from_pending_weak_list
- (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
- }
- else
-#endif
- ASM_GLOBALIZE_LABEL (asm_out_file, name);
- }
+ globalize_decl (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
- TREE_ASM_WRITTEN (decl) = 1;
-#else
-#ifdef ASM_OUTPUT_WEAK_ALIAS
+#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");
+#ifdef ASM_WEAKEN_DECL
+ ASM_WEAKEN_DECL (asm_out_file, decl, name, IDENTIFIER_POINTER (target));
+#else
ASM_OUTPUT_WEAK_ALIAS (asm_out_file, name, IDENTIFIER_POINTER (target));
- TREE_ASM_WRITTEN (decl) = 1;
+#endif
#else
warning ("alias definitions not supported in this configuration; ignored");
#endif
#endif
+
+ TREE_USED (decl) = 1;
+ TREE_ASM_WRITTEN (decl) = 1;
+ TREE_ASM_WRITTEN (DECL_ASSEMBLER_NAME (decl)) = 1;
}
/* Returns 1 if the target configuration supports defining public symbols
@@ -5213,6 +5251,7 @@ init_varasm_once ()
mark_const_hash_entry);
ggc_add_root (&const_str_htab, 1, sizeof const_str_htab,
mark_const_str_htab);
+ ggc_add_tree_root (&weak_decls, 1);
const_alias_set = new_alias_set ();
}