/* 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
+ 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
Free Software Foundation, Inc.
This file is part of GCC.
void
emutls_finish (void)
{
- if (!targetm.emutls.register_common)
+ if (targetm.emutls.register_common)
{
tree body = NULL_TREE;
if (DECL_ONE_ONLY (decl) && HAVE_COMDAT_GROUP)
{
- size_t len = strlen (name) + 3;
- char* rname = (char *) alloca (len);
+ const char *dot;
+ size_t len;
+ char* rname;
+
+ dot = strchr (name + 1, '.');
+ if (!dot)
+ dot = name;
+ len = strlen (dot) + 8;
+ rname = (char *) alloca (len);
strcpy (rname, ".rodata");
- strcat (rname, name + 5);
+ strcat (rname, dot);
return get_section (rname, SECTION_LINKONCE, decl);
}
/* For .gnu.linkonce.t.foo we want to use .gnu.linkonce.r.foo. */
/* When the function starts with a cold section, we need to explicitly
align the hot section and write out the hot section label.
But if the current function is a thunk, we do not have a CFG. */
- if (!crtl->is_thunk
+ if (!cfun->is_thunk
&& BB_PARTITION (ENTRY_BLOCK_PTR->next_bb) == BB_COLD_PARTITION)
{
switch_to_section (text_section);
because ASM_OUTPUT_MAX_SKIP_ALIGN might not do any alignment at all. */
if (! DECL_USER_ALIGN (decl)
&& align_functions_log > align
- && cfun->function_frequency != FUNCTION_FREQUENCY_UNLIKELY_EXECUTED)
+ && optimize_function_for_speed_p (cfun))
{
#ifdef ASM_OUTPUT_MAX_SKIP_ALIGN
ASM_OUTPUT_MAX_SKIP_ALIGN (asm_out_file,
/* First make the assembler name(s) global if appropriate. */
sect = get_variable_section (decl, false);
if (TREE_PUBLIC (decl)
- && DECL_NAME (decl)
&& (sect->common.flags & SECTION_COMMON) == 0)
globalize_decl (decl);
return true;
name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
- if (strncmp (name, "__builtin_", strlen ("__builtin_")) == 0)
+ if (is_builtin_name (name))
return true;
}
return false;
to be emitted. */
static GTY(()) tree weak_decls;
-/* Output something to declare an external symbol to the assembler.
- (Most assemblers don't need this, so we normally output nothing.)
- Do nothing if DECL is not external. */
+/* Output something to declare an external symbol to the assembler,
+ and qualifiers such as weakness. (Most assemblers don't need
+ extern declaration, so we normally output nothing.) Do nothing if
+ DECL is not external. */
void
assemble_external (tree decl ATTRIBUTE_UNUSED)
open. If it's not, we should not be calling this function. */
gcc_assert (asm_out_file);
-#ifdef ASM_OUTPUT_EXTERNAL
if (!DECL_P (decl) || !DECL_EXTERNAL (decl) || !TREE_PUBLIC (decl))
return;
- if (SUPPORTS_WEAK && DECL_WEAK (decl))
- weak_decls = tree_cons (NULL, decl, weak_decls);
+ /* We want to output annotation for weak and external symbols at
+ very last to check if they are references or not. */
- /* We want to output external symbols at very last to check if they
- are references or not. */
- pending_assemble_externals = tree_cons (0, decl,
- pending_assemble_externals);
+ 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)
+ && tree_find_value (weak_decls, decl) == NULL_TREE)
+ weak_decls = tree_cons (NULL, decl, weak_decls);
+
+#ifdef ASM_OUTPUT_EXTERNAL
+ if (tree_find_value (pending_assemble_externals, decl) == NULL_TREE)
+ pending_assemble_externals = tree_cons (NULL, decl,
+ pending_assemble_externals);
#endif
}
enum machine_mode omode, imode;
unsigned int subalign;
unsigned int subsize, i;
- unsigned char mclass;
+ enum mode_class mclass;
subsize = size > UNITS_PER_WORD? UNITS_PER_WORD : 1;
subalign = MIN (align, subsize * BITS_PER_UNIT);
&& !VEC_empty (constructor_elt, CONSTRUCTOR_ELTS (ctor)));
}
+/* 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
+ particular, this does not accept a pointer minus a constant. This
+ returns null_pointer_node if the VALUE is an absolute constant
+ which can be used to initialize a static variable. Otherwise it
+ returns NULL. */
+
+static tree
+narrowing_initializer_constant_valid_p (tree value, tree endtype)
+{
+ tree op0, op1;
+
+ if (!INTEGRAL_TYPE_P (endtype))
+ return NULL_TREE;
+
+ op0 = TREE_OPERAND (value, 0);
+ op1 = TREE_OPERAND (value, 1);
+
+ /* Like STRIP_NOPS except allow the operand mode to widen. This
+ works around a feature of fold that simplifies (int)(p1 - p2) to
+ ((int)p1 - (int)p2) under the theory that the narrower operation
+ is cheaper. */
+
+ while (CONVERT_EXPR_P (op0)
+ || TREE_CODE (op0) == NON_LVALUE_EXPR)
+ {
+ tree inner = TREE_OPERAND (op0, 0);
+ if (inner == error_mark_node
+ || ! INTEGRAL_MODE_P (TYPE_MODE (TREE_TYPE (inner)))
+ || (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (op0)))
+ > GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (inner)))))
+ break;
+ op0 = inner;
+ }
+
+ while (CONVERT_EXPR_P (op1)
+ || TREE_CODE (op1) == NON_LVALUE_EXPR)
+ {
+ tree inner = TREE_OPERAND (op1, 0);
+ if (inner == error_mark_node
+ || ! INTEGRAL_MODE_P (TYPE_MODE (TREE_TYPE (inner)))
+ || (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (op1)))
+ > GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (inner)))))
+ break;
+ op1 = inner;
+ }
+
+ op0 = initializer_constant_valid_p (op0, endtype);
+ op1 = initializer_constant_valid_p (op1, endtype);
+
+ /* Both initializers must be known. */
+ if (op0 && op1)
+ {
+ if (op0 == op1
+ && (op0 == null_pointer_node
+ || TREE_CODE (value) == MINUS_EXPR))
+ return null_pointer_node;
+
+ /* Support differences between labels. */
+ if (TREE_CODE (op0) == LABEL_DECL
+ && TREE_CODE (op1) == LABEL_DECL)
+ return null_pointer_node;
+
+ if (TREE_CODE (op0) == STRING_CST
+ && TREE_CODE (op1) == STRING_CST
+ && operand_equal_p (op0, op1, 1))
+ return null_pointer_node;
+ }
+
+ 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.
tree
initializer_constant_valid_p (tree value, tree endtype)
{
+ tree ret;
+
switch (TREE_CODE (value))
{
case CONSTRUCTOR:
return op0;
}
- case VIEW_CONVERT_EXPR:
case NON_LVALUE_EXPR:
return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype);
- CASE_CONVERT:
+ case VIEW_CONVERT_EXPR:
{
- tree src;
- tree src_type;
- tree dest_type;
+ tree src = TREE_OPERAND (value, 0);
+ tree src_type = TREE_TYPE (src);
+ tree dest_type = TREE_TYPE (value);
+
+ /* Allow view-conversions from aggregate to non-aggregate type only
+ if the bit pattern is fully preserved afterwards; otherwise, the
+ RTL expander won't be able to apply a subsequent transformation
+ to the underlying constructor. */
+ 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);
+ else
+ return NULL_TREE;
+ }
- src = TREE_OPERAND (value, 0);
- src_type = TREE_TYPE (src);
- dest_type = TREE_TYPE (value);
+ /* Allow all other kinds of view-conversion. */
+ return initializer_constant_valid_p (src, endtype);
+ }
+
+ CASE_CONVERT:
+ {
+ tree src = TREE_OPERAND (value, 0);
+ tree src_type = TREE_TYPE (src);
+ tree dest_type = TREE_TYPE (value);
/* Allow conversions between pointer types, floating-point
types, and offset types. */
if (valid1 == null_pointer_node)
return valid0;
}
+
+ /* Support narrowing pointer differences. */
+ ret = narrowing_initializer_constant_valid_p (value, endtype);
+ if (ret != NULL_TREE)
+ return ret;
+
break;
case MINUS_EXPR:
}
/* Support narrowing differences. */
- if (INTEGRAL_TYPE_P (endtype))
- {
- tree op0, op1;
+ ret = narrowing_initializer_constant_valid_p (value, endtype);
+ if (ret != NULL_TREE)
+ return ret;
- op0 = TREE_OPERAND (value, 0);
- op1 = TREE_OPERAND (value, 1);
-
- /* Like STRIP_NOPS except allow the operand mode to widen.
- This works around a feature of fold that simplifies
- (int)(p1 - p2) to ((int)p1 - (int)p2) under the theory
- that the narrower operation is cheaper. */
-
- while (CONVERT_EXPR_P (op0)
- || TREE_CODE (op0) == NON_LVALUE_EXPR)
- {
- tree inner = TREE_OPERAND (op0, 0);
- if (inner == error_mark_node
- || ! INTEGRAL_MODE_P (TYPE_MODE (TREE_TYPE (inner)))
- || (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (op0)))
- > GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (inner)))))
- break;
- op0 = inner;
- }
-
- while (CONVERT_EXPR_P (op1)
- || TREE_CODE (op1) == NON_LVALUE_EXPR)
- {
- tree inner = TREE_OPERAND (op1, 0);
- if (inner == error_mark_node
- || ! INTEGRAL_MODE_P (TYPE_MODE (TREE_TYPE (inner)))
- || (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (op1)))
- > GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (inner)))))
- break;
- op1 = inner;
- }
-
- op0 = initializer_constant_valid_p (op0, endtype);
- op1 = initializer_constant_valid_p (op1, endtype);
-
- /* Both initializers must be known. */
- if (op0 && op1)
- {
- if (op0 == op1)
- return null_pointer_node;
-
- /* Support differences between labels. */
- if (TREE_CODE (op0) == LABEL_DECL
- && TREE_CODE (op1) == LABEL_DECL)
- return null_pointer_node;
-
- if (TREE_CODE (op0) == STRING_CST
- && TREE_CODE (op1) == STRING_CST
- && operand_equal_p (op0, op1, 1))
- return null_pointer_node;
- }
- }
break;
default:
void
default_file_start (void)
{
- if (targetm.file_start_app_off && !flag_verbose_asm)
+ if (targetm.file_start_app_off
+ && !(flag_verbose_asm || flag_debug_asm || flag_dump_rtl_in_asm))
fputs (ASM_APP_OFF, asm_out_file);
if (targetm.file_start_file_directive)