#endif
/* The (assembler) name of the first globally-visible object output. */
+extern GTY(()) const char *first_global_object_name;
+extern GTY(()) const char *weak_global_object_name;
+
const char *first_global_object_name;
const char *weak_global_object_name;
= ADDITIONAL_REGISTER_NAMES;
for (i = 0; i < (int) ARRAY_SIZE (table); i++)
- if (! strcmp (asmspec, table[i].name))
+ if (table[i].name[0]
+ && ! strcmp (asmspec, table[i].name))
return table[i].number;
}
#endif /* ADDITIONAL_REGISTER_NAMES */
}
name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
-
- if (TREE_CODE (decl) != FUNCTION_DECL && DECL_REGISTER (decl))
+
+ if (name[0] != '*' && TREE_CODE (decl) != FUNCTION_DECL
+ && DECL_REGISTER (decl))
+ {
+ error ("register name not specified for %q+D", decl);
+ }
+ else if (TREE_CODE (decl) != FUNCTION_DECL && DECL_REGISTER (decl))
{
- reg_number = decode_reg_name (name);
+ const char *asmspec = name+1;
+ reg_number = decode_reg_name (asmspec);
/* First detect errors in declaring global registers. */
if (reg_number == -1)
error ("register name not specified for %q+D", decl);
if (!*type)
{
const char *p;
- char *name;
+ const char *name;
rtx decl_rtl = DECL_RTL (decl);
p = targetm.strip_name_encoding (XSTR (XEXP (decl_rtl, 0), 0));
- name = xstrdup (p);
+ name = ggc_strdup (p);
*type = name;
}
unlikely_text_section ();
assemble_align (FUNCTION_BOUNDARY);
ASM_OUTPUT_LABEL (asm_out_file, cfun->cold_section_label);
- if (BB_PARTITION (ENTRY_BLOCK_PTR->next_bb) == BB_COLD_PARTITION)
+
+ /* 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 (!current_function_is_thunk
+ && BB_PARTITION (ENTRY_BLOCK_PTR->next_bb) == BB_COLD_PARTITION)
{
- /* Since the function starts with a cold section, we need to
- explicitly align the hot section and write out the hot
- section label. */
text_section ();
assemble_align (FUNCTION_BOUNDARY);
ASM_OUTPUT_LABEL (asm_out_file, cfun->hot_section_label);
/* Standard thing is just output label for the function. */
ASM_OUTPUT_LABEL (asm_out_file, fnname);
#endif /* ASM_DECLARE_FUNCTION_NAME */
-
- insert_section_boundary_note ();
}
/* Output assembler code associated with defining the size of the
assemble_end_function (tree decl, const char *fnname)
{
#ifdef ASM_DECLARE_FUNCTION_SIZE
+ /* We could have switched section in the middle of the function. */
+ if (flag_reorder_blocks_and_partition)
+ function_section (decl);
ASM_DECLARE_FUNCTION_SIZE (asm_out_file, fnname, decl);
#endif
if (! CONSTANT_POOL_BEFORE_FUNCTION)
if (value
&& TREE_CODE (value) == FUNCTION_DECL
&& ((decl_function_context (value) && !DECL_NO_STATIC_CHAIN (value))
- || DECL_NON_ADDR_CONST_P (value)))
+ || DECL_DLLIMPORT_P (value)))
return NULL_TREE;
return value;
if (size == 0 || flag_syntax_only)
return;
+ /* See if we're trying to initialize a pointer in a non-default mode
+ to the address of some declaration somewhere. If the target says
+ the mode is valid for pointers, assume the target has a way of
+ resolving it. */
+ if (TREE_CODE (exp) == NOP_EXPR
+ && POINTER_TYPE_P (TREE_TYPE (exp))
+ && targetm.valid_pointer_mode (TYPE_MODE (TREE_TYPE (exp))))
+ {
+ tree saved_type = TREE_TYPE (exp);
+
+ /* Peel off any intermediate conversions-to-pointer for valid
+ pointer modes. */
+ while (TREE_CODE (exp) == NOP_EXPR
+ && POINTER_TYPE_P (TREE_TYPE (exp))
+ && targetm.valid_pointer_mode (TYPE_MODE (TREE_TYPE (exp))))
+ exp = TREE_OPERAND (exp, 0);
+
+ /* If what we're left with is the address of something, we can
+ convert the address to the final type and output it that
+ way. */
+ if (TREE_CODE (exp) == ADDR_EXPR)
+ exp = build1 (ADDR_EXPR, saved_type, TREE_OPERAND (exp, 0));
+ }
+
/* Eliminate any conversions since we'll be outputting the underlying
constant. */
while (TREE_CODE (exp) == NOP_EXPR || TREE_CODE (exp) == CONVERT_EXPR
|| TREE_CODE (exp) == NON_LVALUE_EXPR
|| TREE_CODE (exp) == VIEW_CONVERT_EXPR)
- exp = TREE_OPERAND (exp, 0);
+ {
+ HOST_WIDE_INT type_size = int_size_in_bytes (TREE_TYPE (exp));
+ HOST_WIDE_INT op_size = int_size_in_bytes (TREE_TYPE (TREE_OPERAND (exp, 0)));
+
+ /* Make sure eliminating the conversion is really a no-op, except with
+ VIEW_CONVERT_EXPRs to allow for wild Ada unchecked conversions and
+ union types to allow for Ada unchecked unions. */
+ if (type_size > op_size
+ && TREE_CODE (exp) != VIEW_CONVERT_EXPR
+ && TREE_CODE (TREE_TYPE (exp)) != UNION_TYPE)
+ internal_error ("no-op convert from %wd to %wd bytes in initializer",
+ op_size, type_size);
+
+ exp = TREE_OPERAND (exp, 0);
+ }
code = TREE_CODE (TREE_TYPE (exp));
thissize = int_size_in_bytes (TREE_TYPE (exp));
struct cgraph_node *fnode = NULL;
struct cgraph_varpool_node *vnode = NULL;
- /* C++ thunk emitting code produces aliases late in the game.
- Avoid confusing cgraph code in that case. */
- if (!cgraph_global_info_ready)
+ if (TREE_CODE (decl) == FUNCTION_DECL)
{
- if (TREE_CODE (decl) == FUNCTION_DECL)
- {
- fnode = cgraph_node_for_asm (target);
- if (fnode == NULL)
- vnode = cgraph_varpool_node_for_asm (target);
- }
- else
- {
- vnode = cgraph_varpool_node_for_asm (target);
- if (vnode == NULL)
- fnode = cgraph_node_for_asm (target);
- }
+ fnode = cgraph_node_for_asm (target);
+ if (fnode == NULL)
+ vnode = cgraph_varpool_node_for_asm (target);
+ }
+ else
+ {
+ vnode = cgraph_varpool_node_for_asm (target);
+ if (vnode == NULL)
+ fnode = cgraph_node_for_asm (target);
}
if (fnode)
{
- cgraph_mark_needed_node (fnode);
+ /* We can't mark function nodes as used after cgraph global info
+ is finished. This wouldn't generally be necessary, but C++
+ virtual table thunks are introduced late in the game and
+ might seem like they need marking, although in fact they
+ don't. */
+ if (! cgraph_global_info_ready)
+ cgraph_mark_needed_node (fnode);
return fnode->decl;
}
else if (vnode)
data_section ();
}
-/* A helper function for default_elf_select_section and
- default_elf_unique_section. Categorizes the DECL. */
-
enum section_category
-{
- SECCAT_TEXT,
-
- SECCAT_RODATA,
- SECCAT_RODATA_MERGE_STR,
- SECCAT_RODATA_MERGE_STR_INIT,
- SECCAT_RODATA_MERGE_CONST,
- SECCAT_SRODATA,
-
- SECCAT_DATA,
-
- /* To optimize loading of shared programs, define following subsections
- of data section:
- _REL Contains data that has relocations, so they get grouped
- together and dynamic linker will visit fewer pages in memory.
- _RO Contains data that is otherwise read-only. This is useful
- with prelinking as most relocations won't be dynamically
- linked and thus stay read only.
- _LOCAL Marks data containing relocations only to local objects.
- These relocations will get fully resolved by prelinking. */
- SECCAT_DATA_REL,
- SECCAT_DATA_REL_LOCAL,
- SECCAT_DATA_REL_RO,
- SECCAT_DATA_REL_RO_LOCAL,
-
- SECCAT_SDATA,
- SECCAT_TDATA,
-
- SECCAT_BSS,
- SECCAT_SBSS,
- SECCAT_TBSS
-};
-
-static enum section_category
-categorize_decl_for_section (tree, int, int);
-
-static enum section_category
categorize_decl_for_section (tree decl, int reloc, int shlib)
{
enum section_category ret;