diff options
Diffstat (limited to 'contrib/gcc/varasm.c')
-rw-r--r-- | contrib/gcc/varasm.c | 1814 |
1 files changed, 773 insertions, 1041 deletions
diff --git a/contrib/gcc/varasm.c b/contrib/gcc/varasm.c index 9a76099..e61b5b4 100644 --- a/contrib/gcc/varasm.c +++ b/contrib/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, 2003 Free Software Foundation, Inc. + 1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. This file is part of GCC. @@ -29,6 +29,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "config.h" #include "system.h" +#include "coretypes.h" +#include "tm.h" #include "rtl.h" #include "tree.h" #include "flags.h" @@ -41,12 +43,12 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "toplev.h" #include "hashtab.h" #include "c-pragma.h" -#include "c-tree.h" #include "ggc.h" #include "langhooks.h" #include "tm_p.h" #include "debug.h" #include "target.h" +#include "cgraph.h" #ifdef XCOFF_DEBUGGING_INFO #include "xcoffout.h" /* Needed for external data @@ -94,6 +96,10 @@ struct varasm_status GTY(()) /* Current offset in constant pool (does not include any machine-specific header). */ HOST_WIDE_INT x_pool_offset; + + /* Number of tree-constants deferred during the expansion of this + function. */ + unsigned int deferred_constants; }; #define const_rtx_hash_table (cfun->varasm->x_const_rtx_hash_table) @@ -101,16 +107,12 @@ struct varasm_status GTY(()) #define first_pool (cfun->varasm->x_first_pool) #define last_pool (cfun->varasm->x_last_pool) #define pool_offset (cfun->varasm->x_pool_offset) +#define n_deferred_constants (cfun->varasm->deferred_constants) /* Number for making the label on the next constant that is stored in memory. */ -int const_labelno; - -/* Number for making the label on the next - static variable internal to a function. */ - -int var_labelno; +static GTY(()) int const_labelno; /* Carry information from ASM_DECLARE_OBJECT_NAME to ASM_FINISH_DECLARE_OBJECT. */ @@ -133,51 +135,53 @@ tree last_assemble_variable_decl; static HOST_WIDE_INT const_alias_set; -static const char *strip_reg_name PARAMS ((const char *)); -static int contains_pointers_p PARAMS ((tree)); -static void decode_addr_const PARAMS ((tree, struct addr_const *)); -static unsigned int const_hash PARAMS ((tree)); -static unsigned int const_hash_1 PARAMS ((tree)); -static int compare_constant PARAMS ((tree, tree)); -static tree copy_constant PARAMS ((tree)); -static void output_constant_def_contents PARAMS ((tree, int, int)); -static void decode_rtx_const PARAMS ((enum machine_mode, rtx, - struct rtx_const *)); -static unsigned int const_hash_rtx PARAMS ((enum machine_mode, rtx)); -static int compare_constant_rtx - PARAMS ((enum machine_mode, rtx, struct constant_descriptor_rtx *)); +static const char *strip_reg_name (const char *); +static int contains_pointers_p (tree); +#ifdef ASM_OUTPUT_EXTERNAL +static bool incorporeal_function_p (tree); +#endif +static void decode_addr_const (tree, struct addr_const *); +static hashval_t const_desc_hash (const void *); +static int const_desc_eq (const void *, const void *); +static hashval_t const_hash_1 (const tree); +static int compare_constant (const tree, const tree); +static tree copy_constant (tree); +static void output_constant_def_contents (rtx); +static void decode_rtx_const (enum machine_mode, rtx, struct rtx_const *); +static unsigned int const_hash_rtx (enum machine_mode, rtx); +static int compare_constant_rtx (enum machine_mode, rtx, + struct constant_descriptor_rtx *); static struct constant_descriptor_rtx * record_constant_rtx - PARAMS ((enum machine_mode, rtx)); -static struct pool_constant *find_pool_constant PARAMS ((struct function *, rtx)); -static void mark_constant_pool PARAMS ((void)); -static void mark_constants PARAMS ((rtx)); -static int mark_constant PARAMS ((rtx *current_rtx, void *data)); -static int output_addressed_constants PARAMS ((tree)); -static void output_after_function_constants PARAMS ((void)); -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)); -static void globalize_decl PARAMS ((tree)); -static void maybe_assemble_visibility PARAMS ((tree)); -static int in_named_entry_eq PARAMS ((const PTR, const PTR)); -static hashval_t in_named_entry_hash PARAMS ((const PTR)); + (enum machine_mode, rtx); +static struct pool_constant *find_pool_constant (struct function *, rtx); +static void mark_constant_pool (void); +static void mark_constants (rtx); +static int mark_constant (rtx *current_rtx, void *data); +static void output_addressed_constants (tree); +static unsigned HOST_WIDE_INT array_size_for_constructor (tree); +static unsigned min_align (unsigned, unsigned); +static void output_constructor (tree, unsigned HOST_WIDE_INT, unsigned int); +static void globalize_decl (tree); +static void maybe_assemble_visibility (tree); +static int in_named_entry_eq (const void *, const void *); +static hashval_t in_named_entry_hash (const void *); #ifdef ASM_OUTPUT_BSS -static void asm_output_bss PARAMS ((FILE *, tree, const char *, int, int)); +static void asm_output_bss (FILE *, tree, const char *, + unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT); #endif #ifdef BSS_SECTION_ASM_OP #ifdef ASM_OUTPUT_ALIGNED_BSS -static void asm_output_aligned_bss PARAMS ((FILE *, tree, const char *, - int, int)); +static void asm_output_aligned_bss (FILE *, tree, const char *, + unsigned HOST_WIDE_INT, int) + ATTRIBUTE_UNUSED; #endif #endif /* BSS_SECTION_ASM_OP */ -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 bool asm_emit_uninitialised PARAMS ((tree, const char*, int, int)); -static void resolve_unique_section PARAMS ((tree, int, int)); -static void mark_weak PARAMS ((tree)); +static bool asm_emit_uninitialised (tree, const char*, + unsigned HOST_WIDE_INT, + unsigned HOST_WIDE_INT); +static void mark_weak (tree); -static enum in_section { no_section, in_text, in_data, in_named +enum in_section { no_section, in_text, in_data, in_named #ifdef BSS_SECTION_ASM_OP , in_bss #endif @@ -193,7 +197,8 @@ static enum in_section { no_section, in_text, in_data, in_named #ifdef EXTRA_SECTIONS , EXTRA_SECTIONS #endif -} in_section = no_section; +}; +static GTY(()) enum in_section in_section = no_section; /* Return a nonzero value if DECL has a section attribute. */ #ifndef IN_NAMED_SECTION @@ -203,18 +208,18 @@ static enum in_section { no_section, in_text, in_data, in_named #endif /* Text of section name when in_section == in_named. */ -static const char *in_named_name; +static GTY(()) const char *in_named_name; /* Hash table of flags that have been used for a particular named section. */ -struct in_named_entry +struct in_named_entry GTY(()) { const char *name; unsigned int flags; bool declared; }; -static htab_t in_named_htab; +static GTY((param_is (struct in_named_entry))) htab_t in_named_htab; /* Define functions like text_section for any extra sections. */ #ifdef EXTRA_SECTION_FUNCTIONS @@ -224,23 +229,19 @@ EXTRA_SECTION_FUNCTIONS /* Tell assembler to switch to text section. */ void -text_section () +text_section (void) { if (in_section != in_text) { in_section = in_text; -#ifdef TEXT_SECTION - TEXT_SECTION (); -#else fprintf (asm_out_file, "%s\n", TEXT_SECTION_ASM_OP); -#endif } } /* Tell assembler to switch to data section. */ void -data_section () +data_section (void) { if (in_section != in_data) { @@ -258,21 +259,11 @@ data_section () } } -/* Tell assembler to ALWAYS switch to data section, in case - it's not sure where it is. */ - -void -force_data_section () -{ - in_section = no_section; - data_section (); -} - /* Tell assembler to switch to read-only data section. This is normally the text section. */ void -readonly_data_section () +readonly_data_section (void) { #ifdef READONLY_DATA_SECTION READONLY_DATA_SECTION (); /* Note this can call data_section. */ @@ -293,7 +284,7 @@ readonly_data_section () /* Determine if we're in the text section. */ int -in_text_section () +in_text_section (void) { return in_section == in_text; } @@ -301,7 +292,7 @@ in_text_section () /* Determine if we're in the data section. */ int -in_data_section () +in_data_section (void) { return in_section == in_data; } @@ -309,9 +300,7 @@ in_data_section () /* Helper routines for maintaining in_named_htab. */ static int -in_named_entry_eq (p1, p2) - const PTR p1; - const PTR p2; +in_named_entry_eq (const void *p1, const void *p2) { const struct in_named_entry *old = p1; const char *new = p2; @@ -320,8 +309,7 @@ in_named_entry_eq (p1, p2) } static hashval_t -in_named_entry_hash (p) - const PTR p; +in_named_entry_hash (const void *p) { const struct in_named_entry *old = p; return htab_hash_string (old->name); @@ -333,8 +321,7 @@ in_named_entry_hash (p) has not been seen. */ unsigned int -get_named_section_flags (section) - const char *section; +get_named_section_flags (const char *section) { struct in_named_entry **slot; @@ -350,8 +337,7 @@ get_named_section_flags (section) section will return false. */ bool -named_section_first_declaration (name) - const char *name; +named_section_first_declaration (const char *name) { struct in_named_entry **slot; @@ -374,9 +360,7 @@ named_section_first_declaration (name) different set of flags, return false. */ bool -set_named_section_flags (section, flags) - const char *section; - unsigned int flags; +set_named_section_flags (const char *section, unsigned int flags) { struct in_named_entry **slot, *entry; @@ -387,7 +371,7 @@ set_named_section_flags (section, flags) if (!entry) { - entry = (struct in_named_entry *) xmalloc (sizeof (*entry)); + entry = ggc_alloc (sizeof (*entry)); *slot = entry; entry->name = ggc_strdup (section); entry->flags = flags; @@ -402,9 +386,7 @@ set_named_section_flags (section, flags) /* Tell assembler to change to section NAME with attributes FLAGS. */ void -named_section_flags (name, flags) - const char *name; - unsigned int flags; +named_section_flags (const char *name, unsigned int flags) { if (in_section != in_named || strcmp (name, in_named_name) != 0) { @@ -429,10 +411,7 @@ named_section_flags (name, flags) If RELOC is 1, the initializer for DECL contains relocs. */ void -named_section (decl, name, reloc) - tree decl; - const char *name; - int reloc; +named_section (tree decl, const char *name, int reloc) { unsigned int flags; @@ -452,7 +431,7 @@ named_section (decl, name, reloc) { flags = get_named_section_flags (name); if ((flags & SECTION_OVERRIDE) == 0) - error_with_decl (decl, "%s causes a section type conflict"); + error ("%J%D causes a section type conflict", decl, decl); } named_section_flags (name, flags); @@ -460,11 +439,9 @@ named_section (decl, name, reloc) /* If required, set DECL_SECTION_NAME to a unique name. */ -static void -resolve_unique_section (decl, reloc, flag_function_or_data_sections) - tree decl; - int reloc ATTRIBUTE_UNUSED; - int flag_function_or_data_sections; +void +resolve_unique_section (tree decl, int reloc ATTRIBUTE_UNUSED, + int flag_function_or_data_sections) { if (DECL_SECTION_NAME (decl) == NULL_TREE && targetm.have_named_sections @@ -478,17 +455,11 @@ resolve_unique_section (decl, reloc, flag_function_or_data_sections) /* Tell the assembler to switch to the bss section. */ void -bss_section () +bss_section (void) { if (in_section != in_bss) { -#ifdef SHARED_BSS_SECTION_ASM_OP - if (flag_shared_data) - fprintf (asm_out_file, "%s\n", SHARED_BSS_SECTION_ASM_OP); - else -#endif - fprintf (asm_out_file, "%s\n", BSS_SECTION_ASM_OP); - + fprintf (asm_out_file, "%s\n", BSS_SECTION_ASM_OP); in_section = in_bss; } } @@ -501,11 +472,10 @@ bss_section () support is localized here. */ static void -asm_output_bss (file, decl, name, size, rounded) - FILE *file; - tree decl ATTRIBUTE_UNUSED; - const char *name; - int size ATTRIBUTE_UNUSED, rounded; +asm_output_bss (FILE *file, tree decl ATTRIBUTE_UNUSED, + const char *name, + unsigned HOST_WIDE_INT size ATTRIBUTE_UNUSED, + unsigned HOST_WIDE_INT rounded) { (*targetm.asm_out.globalize_label) (file, name); bss_section (); @@ -529,11 +499,9 @@ asm_output_bss (file, decl, name, size, rounded) support is localized here. */ static void -asm_output_aligned_bss (file, decl, name, size, align) - FILE *file; - tree decl ATTRIBUTE_UNUSED; - const char *name; - int size, align; +asm_output_aligned_bss (FILE *file, tree decl ATTRIBUTE_UNUSED, + const char *name, unsigned HOST_WIDE_INT size, + int align) { bss_section (); ASM_OUTPUT_ALIGN (file, floor_log2 (align / BITS_PER_UNIT)); @@ -558,8 +526,7 @@ asm_output_aligned_bss (file, decl, name, size, align) safer to handle it. */ void -function_section (decl) - tree decl; +function_section (tree decl) { if (decl != NULL_TREE && DECL_SECTION_NAME (decl) != NULL_TREE) @@ -572,9 +539,7 @@ function_section (decl) argument to SELECT_SECTION. */ void -variable_section (decl, reloc) - tree decl; - int reloc; +variable_section (tree decl, int reloc) { if (IN_NAMED_SECTION (decl)) named_section (decl, NULL, reloc); @@ -585,13 +550,11 @@ variable_section (decl, reloc) /* Tell assembler to switch to the section for string merging. */ void -mergeable_string_section (decl, align, flags) - tree decl ATTRIBUTE_UNUSED; - unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED; - unsigned int flags ATTRIBUTE_UNUSED; +mergeable_string_section (tree decl ATTRIBUTE_UNUSED, + unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED, + unsigned int flags ATTRIBUTE_UNUSED) { -#ifdef HAVE_GAS_SHF_MERGE - if (flag_merge_constants + if (HAVE_GAS_SHF_MERGE && flag_merge_constants && TREE_CODE (decl) == STRING_CST && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE && align <= 256 @@ -653,22 +616,20 @@ mergeable_string_section (decl, align, flags) } } } -#endif + readonly_data_section (); } /* Tell assembler to switch to the section for constant merging. */ void -mergeable_constant_section (mode, align, flags) - enum machine_mode mode ATTRIBUTE_UNUSED; - unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED; - unsigned int flags ATTRIBUTE_UNUSED; +mergeable_constant_section (enum machine_mode mode ATTRIBUTE_UNUSED, + unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED, + unsigned int flags ATTRIBUTE_UNUSED) { -#ifdef HAVE_GAS_SHF_MERGE unsigned int modesize = GET_MODE_BITSIZE (mode); - if (flag_merge_constants + if (HAVE_GAS_SHF_MERGE && flag_merge_constants && mode != VOIDmode && mode != BLKmode && modesize <= align @@ -683,15 +644,14 @@ mergeable_constant_section (mode, align, flags) named_section_flags (name, flags); return; } -#endif + readonly_data_section (); } /* Given NAME, a putative register name, discard any customary prefixes. */ static const char * -strip_reg_name (name) - const char *name; +strip_reg_name (const char *name) { #ifdef REGISTER_PREFIX if (!strncmp (name, REGISTER_PREFIX, strlen (REGISTER_PREFIX))) @@ -711,8 +671,7 @@ strip_reg_name (name) Prefixes such as % are optional. */ int -decode_reg_name (asmspec) - const char *asmspec; +decode_reg_name (const char *asmspec) { if (asmspec != 0) { @@ -775,13 +734,9 @@ decode_reg_name (asmspec) This is never called for PARM_DECL nodes. */ void -make_decl_rtl (decl, asmspec) - tree decl; - const char *asmspec; +make_decl_rtl (tree decl, const char *asmspec) { - int top_level = (DECL_CONTEXT (decl) == NULL_TREE); const char *name = 0; - const char *new_name = 0; int reg_number; rtx x; @@ -817,12 +772,10 @@ make_decl_rtl (decl, asmspec) /* Let the target reassign the RTL if it wants. This is necessary, for example, when one machine specific decl attribute overrides another. */ - (* targetm.encode_section_info) (decl, false); + (* targetm.encode_section_info) (decl, DECL_RTL (decl), false); return; } - new_name = name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); - reg_number = decode_reg_name (asmspec); if (reg_number == -2) { @@ -831,22 +784,24 @@ make_decl_rtl (decl, asmspec) char *starred = alloca (strlen (asmspec) + 2); starred[0] = '*'; strcpy (starred + 1, asmspec); - new_name = starred; + change_decl_assembler_name (decl, get_identifier (starred)); } + name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); + if (TREE_CODE (decl) != FUNCTION_DECL && DECL_REGISTER (decl)) { /* First detect errors in declaring global registers. */ if (reg_number == -1) - error_with_decl (decl, "register name not specified for `%s'"); + error ("%Jregister name not specified for '%D'", decl, decl); else if (reg_number < 0) - error_with_decl (decl, "invalid register name for `%s'"); + error ("%Jinvalid register name for '%D'", decl, decl); else if (TYPE_MODE (TREE_TYPE (decl)) == BLKmode) - error_with_decl (decl, - "data type of `%s' isn't suitable for a register"); + error ("%Jdata type of '%D' isn't suitable for a register", + decl, decl); else if (! HARD_REGNO_MODE_OK (reg_number, TYPE_MODE (TREE_TYPE (decl)))) - error_with_decl (decl, - "register specified for `%s' isn't suitable for data type"); + error ("%Jregister specified for '%D' isn't suitable for data type", + decl, decl); /* Now handle properly declared static register variables. */ else { @@ -890,8 +845,7 @@ make_decl_rtl (decl, asmspec) Also handle vars declared register invalidly. */ if (reg_number >= 0 || reg_number == -3) - error_with_decl (decl, - "register name given for non-register variable `%s'"); + error ("%Jregister name given for non-register variable '%D'", decl, decl); /* Specifying a section attribute on a variable forces it into a non-.bss section, and thus it cannot be common. */ @@ -905,38 +859,11 @@ make_decl_rtl (decl, asmspec) if (TREE_CODE (decl) == VAR_DECL && DECL_WEAK (decl)) DECL_COMMON (decl) = 0; - /* Can't use just the variable's own name for a variable - whose scope is less than the whole file, unless it's a member - of a local class (which will already be unambiguous). - Concatenate a distinguishing number. */ - if (!top_level && !TREE_PUBLIC (decl) - && ! (DECL_CONTEXT (decl) && TYPE_P (DECL_CONTEXT (decl))) - && asmspec == 0 - && name == IDENTIFIER_POINTER (DECL_NAME (decl))) - { - char *label; - - ASM_FORMAT_PRIVATE_NAME (label, name, var_labelno); - var_labelno++; - new_name = label; - } - - if (name != new_name) - { - SET_DECL_ASSEMBLER_NAME (decl, get_identifier (new_name)); - name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); - } - - /* If this variable is to be treated as volatile, show its - tree node has side effects. */ - if ((flag_volatile_global && TREE_CODE (decl) == VAR_DECL - && TREE_PUBLIC (decl)) - || ((flag_volatile_static && TREE_CODE (decl) == VAR_DECL - && (TREE_PUBLIC (decl) || TREE_STATIC (decl))))) - TREE_SIDE_EFFECTS (decl) = 1; + x = gen_rtx_SYMBOL_REF (Pmode, name); + SYMBOL_REF_WEAK (x) = DECL_WEAK (decl); + SYMBOL_REF_DECL (x) = decl; - x = gen_rtx_MEM (DECL_MODE (decl), gen_rtx_SYMBOL_REF (Pmode, name)); - SYMBOL_REF_WEAK (XEXP (x, 0)) = DECL_WEAK (decl); + x = gen_rtx_MEM (DECL_MODE (decl), x); if (TREE_CODE (decl) != FUNCTION_DECL) set_mem_attributes (x, decl, 1); SET_DECL_RTL (decl, x); @@ -945,15 +872,14 @@ make_decl_rtl (decl, asmspec) such as that it is a function name. If the name is changed, the macro ASM_OUTPUT_LABELREF will have to know how to strip this information. */ - (* targetm.encode_section_info) (decl, true); + (* targetm.encode_section_info) (decl, DECL_RTL (decl), true); } /* Make the rtl for variable VAR be volatile. Use this only for static variables. */ void -make_var_volatile (var) - tree var; +make_var_volatile (tree var) { if (GET_CODE (DECL_RTL (var)) != MEM) abort (); @@ -961,32 +887,11 @@ make_var_volatile (var) MEM_VOLATILE_P (DECL_RTL (var)) = 1; } -/* Output alignment directive to align for constant expression EXP. */ - -void -assemble_constant_align (exp) - tree exp; -{ - int align; - - /* Align the location counter as required by EXP's data type. */ - align = TYPE_ALIGN (TREE_TYPE (exp)); -#ifdef CONSTANT_ALIGNMENT - align = CONSTANT_ALIGNMENT (exp, align); -#endif - - if (align > BITS_PER_UNIT) - { - ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (align / BITS_PER_UNIT)); - } -} - /* Output a string of literal assembler code for an `asm' keyword used between functions. */ void -assemble_asm (string) - tree string; +assemble_asm (tree string) { app_enable (); @@ -1001,9 +906,7 @@ assemble_asm (string) between 0 and MAX_INIT_PRIORITY. */ void -default_stabs_asm_out_destructor (symbol, priority) - rtx symbol; - int priority ATTRIBUTE_UNUSED; +default_stabs_asm_out_destructor (rtx symbol, int priority ATTRIBUTE_UNUSED) { /* Tell GNU LD that this is part of the static destructor set. This will work for any system that uses stabs, most usefully @@ -1014,9 +917,7 @@ default_stabs_asm_out_destructor (symbol, priority) } void -default_named_section_asm_out_destructor (symbol, priority) - rtx symbol; - int priority; +default_named_section_asm_out_destructor (rtx symbol, int priority) { const char *section = ".dtors"; char buf[16]; @@ -1039,7 +940,7 @@ default_named_section_asm_out_destructor (symbol, priority) #ifdef DTORS_SECTION_ASM_OP void -dtors_section () +dtors_section (void) { if (in_section != in_dtors) { @@ -1050,9 +951,8 @@ dtors_section () } void -default_dtor_section_asm_out_destructor (symbol, priority) - rtx symbol; - int priority ATTRIBUTE_UNUSED; +default_dtor_section_asm_out_destructor (rtx symbol, + int priority ATTRIBUTE_UNUSED) { dtors_section (); assemble_align (POINTER_SIZE); @@ -1063,9 +963,7 @@ default_dtor_section_asm_out_destructor (symbol, priority) /* Likewise for global constructors. */ void -default_stabs_asm_out_constructor (symbol, priority) - rtx symbol; - int priority ATTRIBUTE_UNUSED; +default_stabs_asm_out_constructor (rtx symbol, int priority ATTRIBUTE_UNUSED) { /* Tell GNU LD that this is part of the static destructor set. This will work for any system that uses stabs, most usefully @@ -1076,9 +974,7 @@ default_stabs_asm_out_constructor (symbol, priority) } void -default_named_section_asm_out_constructor (symbol, priority) - rtx symbol; - int priority; +default_named_section_asm_out_constructor (rtx symbol, int priority) { const char *section = ".ctors"; char buf[16]; @@ -1101,7 +997,7 @@ default_named_section_asm_out_constructor (symbol, priority) #ifdef CTORS_SECTION_ASM_OP void -ctors_section () +ctors_section (void) { if (in_section != in_ctors) { @@ -1112,9 +1008,8 @@ ctors_section () } void -default_ctor_section_asm_out_constructor (symbol, priority) - rtx symbol; - int priority ATTRIBUTE_UNUSED; +default_ctor_section_asm_out_constructor (rtx symbol, + int priority ATTRIBUTE_UNUSED) { ctors_section (); assemble_align (POINTER_SIZE); @@ -1132,15 +1027,51 @@ default_ctor_section_asm_out_constructor (symbol, priority) #define CONSTANT_POOL_BEFORE_FUNCTION 1 #endif +/* DECL is an object (either VAR_DECL or FUNCTION_DECL) which is going + to be output to assembler. + Set first_global_object_name and weak_global_object_name as appropriate. */ + +void +notice_global_symbol (tree decl) +{ + const char **type = &first_global_object_name; + + if (first_global_object_name + || !TREE_PUBLIC (decl) || DECL_EXTERNAL (decl) + || !DECL_NAME (decl) + || (TREE_CODE (decl) != FUNCTION_DECL + && (TREE_CODE (decl) != VAR_DECL + || (DECL_COMMON (decl) + && (DECL_INITIAL (decl) == 0 + || DECL_INITIAL (decl) == error_mark_node)))) + || GET_CODE (DECL_RTL (decl)) != MEM) + return; + + /* We win when global object is found, but it is usefull to know about weak + symbol as well so we can produce nicer unique names. */ + if (DECL_WEAK (decl) || DECL_ONE_ONLY (decl)) + type = &weak_global_object_name; + + if (!*type) + { + const char *p; + char *name; + rtx decl_rtl = DECL_RTL (decl); + + p = (* targetm.strip_name_encoding) (XSTR (XEXP (decl_rtl, 0), 0)); + name = xstrdup (p); + + *type = name; + } +} + /* Output assembler code for the constant pool of a function and associated with defining the name of the function. DECL describes the function. NAME is the function's name. For the constant pool, we use the current constant pool data. */ void -assemble_start_function (decl, fnname) - tree decl; - const char *fnname; +assemble_start_function (tree decl, const char *fnname) { int align; @@ -1187,26 +1118,14 @@ assemble_start_function (decl, fnname) if (TREE_PUBLIC (decl)) { - if (! first_global_object_name) - { - const char *p; - char *name; - - p = (* targetm.strip_name_encoding) (fnname); - name = xstrdup (p); - - if (! DECL_WEAK (decl) && ! DECL_ONE_ONLY (decl)) - first_global_object_name = name; - else - weak_global_object_name = name; - } + notice_global_symbol (decl); globalize_decl (decl); maybe_assemble_visibility (decl); } - /* Do any machine/system dependent processing of the function name */ + /* Do any machine/system dependent processing of the function name. */ #ifdef ASM_DECLARE_FUNCTION_NAME ASM_DECLARE_FUNCTION_NAME (asm_out_file, fnname, current_function_decl); #else @@ -1219,9 +1138,7 @@ assemble_start_function (decl, fnname) function. DECL describes the function. NAME is the function's name. */ void -assemble_end_function (decl, fnname) - tree decl; - const char *fnname; +assemble_end_function (tree decl, const char *fnname) { #ifdef ASM_DECLARE_FUNCTION_SIZE ASM_DECLARE_FUNCTION_SIZE (asm_out_file, fnname, decl); @@ -1231,16 +1148,12 @@ assemble_end_function (decl, fnname) output_constant_pool (fnname, decl); function_section (decl); /* need to switch back */ } - - /* Output any constants which should appear after the function. */ - output_after_function_constants (); } /* Assemble code to leave SIZE bytes of zeros. */ void -assemble_zeros (size) - int size; +assemble_zeros (unsigned HOST_WIDE_INT size) { /* Do no output if -fsyntax-only. */ if (flag_syntax_only) @@ -1251,7 +1164,7 @@ assemble_zeros (size) so we must output 0s explicitly in the text section. */ if (ASM_NO_SKIP_IN_TEXT && in_text_section ()) { - int i; + unsigned HOST_WIDE_INT i; for (i = 0; i < size; i++) assemble_integer (const0_rtx, 1, BITS_PER_UNIT, 1); } @@ -1264,8 +1177,7 @@ assemble_zeros (size) /* Assemble an alignment pseudo op for an ALIGN-bit boundary. */ void -assemble_align (align) - int align; +assemble_align (int align) { if (align > BITS_PER_UNIT) { @@ -1276,9 +1188,7 @@ assemble_align (align) /* Assemble a string constant with the specified C string as contents. */ void -assemble_string (p, size) - const char *p; - int size; +assemble_string (const char *p, int size) { int pos = 0; int maximum = 2000; @@ -1338,11 +1248,9 @@ assemble_string (p, size) #endif static bool -asm_emit_uninitialised (decl, name, size, rounded) - tree decl; - const char *name; - int size ATTRIBUTE_UNUSED; - int rounded ATTRIBUTE_UNUSED; +asm_emit_uninitialised (tree decl, const char *name, + unsigned HOST_WIDE_INT size ATTRIBUTE_UNUSED, + unsigned HOST_WIDE_INT rounded ATTRIBUTE_UNUSED) { enum { @@ -1425,17 +1333,17 @@ asm_emit_uninitialised (decl, name, size, rounded) initial value (that will be done by the caller). */ void -assemble_variable (decl, top_level, at_end, dont_output_data) - tree decl; - int top_level ATTRIBUTE_UNUSED; - int at_end ATTRIBUTE_UNUSED; - int dont_output_data; +assemble_variable (tree decl, int top_level ATTRIBUTE_UNUSED, + int at_end ATTRIBUTE_UNUSED, int dont_output_data) { const char *name; unsigned int align; int reloc = 0; rtx decl_rtl; + if (lang_hooks.decls.prepare_assemble_variable) + (*lang_hooks.decls.prepare_assemble_variable) (decl); + last_assemble_variable_decl = 0; /* Normally no need to say anything here for external references, @@ -1469,10 +1377,7 @@ assemble_variable (decl, top_level, at_end, dont_output_data) if (!dont_output_data && DECL_SIZE (decl) == 0) { - error_with_file_and_line (DECL_SOURCE_FILE (decl), - DECL_SOURCE_LINE (decl), - "storage size of `%s' isn't known", - IDENTIFIER_POINTER (DECL_NAME (decl))); + error ("%Jstorage size of `%D' isn't known", decl, decl); TREE_ASM_WRITTEN (decl) = 1; return; } @@ -1500,25 +1405,13 @@ assemble_variable (decl, top_level, at_end, dont_output_data) if (! dont_output_data && ! host_integerp (DECL_SIZE_UNIT (decl), 1)) { - error_with_decl (decl, "size of variable `%s' is too large"); + error ("%Jsize of variable '%D' is too large", decl, decl); return; } name = XSTR (XEXP (decl_rtl, 0), 0); - if (TREE_PUBLIC (decl) && DECL_NAME (decl) - && ! first_global_object_name - && ! (DECL_COMMON (decl) && (DECL_INITIAL (decl) == 0 - || DECL_INITIAL (decl) == error_mark_node)) - && ! DECL_WEAK (decl) - && ! DECL_ONE_ONLY (decl)) - { - const char *p; - char *xname; - - p = (* targetm.strip_name_encoding) (name); - xname = xstrdup (p); - first_global_object_name = xname; - } + if (TREE_PUBLIC (decl) && DECL_NAME (decl)) + notice_global_symbol (decl); /* Compute the alignment of this data. */ @@ -1538,9 +1431,9 @@ assemble_variable (decl, top_level, at_end, dont_output_data) #endif if (align > MAX_OFILE_ALIGNMENT) { - warning_with_decl (decl, - "alignment of `%s' is greater than maximum object file alignment. Using %d", - MAX_OFILE_ALIGNMENT/BITS_PER_UNIT); + warning ("%Jalignment of '%D' is greater than maximum object " + "file alignment. Using %d", decl, decl, + MAX_OFILE_ALIGNMENT/BITS_PER_UNIT); align = MAX_OFILE_ALIGNMENT; } @@ -1568,7 +1461,10 @@ assemble_variable (decl, top_level, at_end, dont_output_data) if (DECL_INITIAL (decl) == error_mark_node) reloc = contains_pointers_p (TREE_TYPE (decl)) ? 3 : 0; else if (DECL_INITIAL (decl)) - reloc = output_addressed_constants (DECL_INITIAL (decl)); + { + reloc = compute_reloc_for_constant (DECL_INITIAL (decl)); + output_addressed_constants (DECL_INITIAL (decl)); + } resolve_unique_section (decl, reloc, flag_data_sections); /* Handle uninitialized definitions. */ @@ -1606,8 +1502,8 @@ assemble_variable (decl, top_level, at_end, dont_output_data) #if !defined(ASM_OUTPUT_ALIGNED_COMMON) && !defined(ASM_OUTPUT_ALIGNED_DECL_COMMON) && !defined(ASM_OUTPUT_ALIGNED_BSS) if ((unsigned HOST_WIDE_INT) DECL_ALIGN (decl) / BITS_PER_UNIT > rounded) - warning_with_decl - (decl, "requested alignment for %s is greater than implemented alignment of %d",rounded); + warning ("%Jrequested alignment for '%D' is greater than " + "implemented alignment of %d", decl, decl, rounded); #endif /* If the target cannot output uninitialized but not common global data @@ -1663,8 +1559,7 @@ assemble_variable (decl, top_level, at_end, dont_output_data) /* Return 1 if type TYPE contains any pointers. */ static int -contains_pointers_p (type) - tree type; +contains_pointers_p (tree type) { switch (TREE_CODE (type)) { @@ -1697,13 +1592,35 @@ contains_pointers_p (type) } } +#ifdef ASM_OUTPUT_EXTERNAL +/* True if DECL is a function decl for which no out-of-line copy exists. + It is assumed that DECL's assembler name has been set. */ + +static bool +incorporeal_function_p (tree decl) +{ + if (TREE_CODE (decl) == FUNCTION_DECL && DECL_BUILT_IN (decl)) + { + const char *name; + + if (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL + && DECL_FUNCTION_CODE (decl) == BUILT_IN_ALLOCA) + return true; + + name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); + if (strncmp (name, "__builtin_", strlen ("__builtin_")) == 0) + return true; + } + return false; +} +#endif + /* 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. */ void -assemble_external (decl) - tree decl ATTRIBUTE_UNUSED; +assemble_external (tree decl ATTRIBUTE_UNUSED) { /* Because most platforms do not define ASM_OUTPUT_EXTERNAL, the main body of this code is only rarely exercised. To provide some @@ -1718,7 +1635,8 @@ assemble_external (decl) rtx rtl = DECL_RTL (decl); if (GET_CODE (rtl) == MEM && GET_CODE (XEXP (rtl, 0)) == SYMBOL_REF - && ! SYMBOL_REF_USED (XEXP (rtl, 0))) + && !SYMBOL_REF_USED (XEXP (rtl, 0)) + && !incorporeal_function_p (decl)) { /* Some systems do require some output. */ SYMBOL_REF_USED (XEXP (rtl, 0)) = 1; @@ -1731,28 +1649,47 @@ assemble_external (decl) /* Similar, for calling a library function FUN. */ void -assemble_external_libcall (fun) - rtx fun ATTRIBUTE_UNUSED; +assemble_external_libcall (rtx fun) { -#ifdef ASM_OUTPUT_EXTERNAL_LIBCALL /* Declare library function name external when first used, if nec. */ if (! SYMBOL_REF_USED (fun)) { SYMBOL_REF_USED (fun) = 1; - ASM_OUTPUT_EXTERNAL_LIBCALL (asm_out_file, fun); + (*targetm.asm_out.external_libcall) (fun); } -#endif } /* Assemble a label named NAME. */ void -assemble_label (name) - const char *name; +assemble_label (const char *name) { ASM_OUTPUT_LABEL (asm_out_file, name); } +/* Set the symbol_referenced flag for ID and notify callgraph code. */ +void +mark_referenced (tree id) +{ + if (!TREE_SYMBOL_REFERENCED (id)) + { + struct cgraph_node *node; + struct cgraph_varpool_node *vnode; + + if (!cgraph_global_info_ready) + { + node = cgraph_node_for_identifier (id); + if (node) + cgraph_mark_needed_node (node); + } + + vnode = cgraph_varpool_node_for_identifier (id); + if (vnode) + cgraph_varpool_mark_needed_node (vnode); + } + TREE_SYMBOL_REFERENCED (id) = 1; +} + /* Output to FILE a reference to the assembler name of a C-level name NAME. If NAME starts with a *, the rest of NAME is output verbatim. Otherwise NAME is transformed in an implementation-defined way @@ -1760,9 +1697,7 @@ assemble_label (name) Many macros in the tm file are defined to call this function. */ void -assemble_name (file, name) - FILE *file; - const char *name; +assemble_name (FILE *file, const char *name) { const char *real_name; tree id; @@ -1771,7 +1706,7 @@ assemble_name (file, name) id = maybe_get_identifier (real_name); if (id) - TREE_SYMBOL_REFERENCED (id) = 1; + mark_referenced (id); if (name[0] == '*') fputs (&name[1], file); @@ -1783,8 +1718,7 @@ assemble_name (file, name) and return an RTX to refer to its address. */ rtx -assemble_static_space (size) - int size; +assemble_static_space (unsigned HOST_WIDE_INT size) { char name[12]; const char *namestring; @@ -1800,6 +1734,7 @@ assemble_static_space (size) namestring = ggc_strdup (name); x = gen_rtx_SYMBOL_REF (Pmode, namestring); + SYMBOL_REF_FLAGS (x) = SYMBOL_FLAG_LOCAL; #ifdef ASM_OUTPUT_ALIGNED_DECL_LOCAL ASM_OUTPUT_ALIGNED_DECL_LOCAL (asm_out_file, NULL_TREE, name, size, @@ -1812,7 +1747,7 @@ assemble_static_space (size) /* Round size up to multiple of BIGGEST_ALIGNMENT bits so that each uninitialized object starts on such a boundary. */ /* Variable `rounded' might or might not be used in ASM_OUTPUT_LOCAL. */ - int rounded ATTRIBUTE_UNUSED + unsigned HOST_WIDE_INT rounded ATTRIBUTE_UNUSED = ((size + (BIGGEST_ALIGNMENT / BITS_PER_UNIT) - 1) / (BIGGEST_ALIGNMENT / BITS_PER_UNIT) * (BIGGEST_ALIGNMENT / BITS_PER_UNIT)); @@ -1829,11 +1764,12 @@ assemble_static_space (size) #ifdef TRAMPOLINE_TEMPLATE rtx -assemble_trampoline_template () +assemble_trampoline_template (void) { char label[256]; const char *name; int align; + rtx symbol; /* By default, put trampoline templates in read-only data section. */ @@ -1850,13 +1786,16 @@ assemble_trampoline_template () ASM_OUTPUT_ALIGN (asm_out_file, align); } - ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LTRAMP", 0); + (*targetm.asm_out.internal_label) (asm_out_file, "LTRAMP", 0); TRAMPOLINE_TEMPLATE (asm_out_file); /* Record the rtl to refer to it. */ ASM_GENERATE_INTERNAL_LABEL (label, "LTRAMP", 0); name = ggc_strdup (label); - return gen_rtx_SYMBOL_REF (Pmode, name); + symbol = gen_rtx_SYMBOL_REF (Pmode, name); + SYMBOL_REF_FLAGS (symbol) = SYMBOL_FLAG_LOCAL; + + return symbol; } #endif @@ -1864,8 +1803,7 @@ assemble_trampoline_template () that may be assumed after adding the two together. */ static inline unsigned -min_align (a, b) - unsigned int a, b; +min_align (unsigned int a, unsigned int b) { return (a | b) & -(a | b); } @@ -1879,9 +1817,7 @@ min_align (a, b) be followed immediately by the object's initial value. */ const char * -integer_asm_op (size, aligned_p) - int size; - int aligned_p; +integer_asm_op (int size, int aligned_p) { struct asm_int_op *ops; @@ -1911,9 +1847,7 @@ integer_asm_op (size, aligned_p) start of the line, followed immediately by the value of X. */ void -assemble_integer_with_op (op, x) - const char *op; - rtx x; +assemble_integer_with_op (const char *op, rtx x) { fputs (op, asm_out_file); output_addr_const (asm_out_file, x); @@ -1923,10 +1857,9 @@ assemble_integer_with_op (op, x) /* The default implementation of the asm_out.integer target hook. */ bool -default_assemble_integer (x, size, aligned_p) - rtx x ATTRIBUTE_UNUSED; - unsigned int size ATTRIBUTE_UNUSED; - int aligned_p ATTRIBUTE_UNUSED; +default_assemble_integer (rtx x ATTRIBUTE_UNUSED, + unsigned int size ATTRIBUTE_UNUSED, + int aligned_p ATTRIBUTE_UNUSED) { const char *op = integer_asm_op (size, aligned_p); return op && (assemble_integer_with_op (op, x), true); @@ -1938,11 +1871,7 @@ default_assemble_integer (x, size, aligned_p) the constant. */ bool -assemble_integer (x, size, align, force) - rtx x; - unsigned int size; - unsigned int align; - int force; +assemble_integer (rtx x, unsigned int size, unsigned int align, int force) { int aligned_p; @@ -1987,83 +1916,42 @@ assemble_integer (x, size, align, force) } void -assemble_real (d, mode, align) - REAL_VALUE_TYPE d; - enum machine_mode mode; - unsigned int align; +assemble_real (REAL_VALUE_TYPE d, enum machine_mode mode, unsigned int align) { long data[4]; - long l; - unsigned int nalign = min_align (align, 32); + int i; + int bitsize, nelts, nunits, units_per; - switch (BITS_PER_UNIT) - { - case 8: - switch (mode) - { - case SFmode: - REAL_VALUE_TO_TARGET_SINGLE (d, l); - assemble_integer (GEN_INT (l), 4, align, 1); - break; - case DFmode: - REAL_VALUE_TO_TARGET_DOUBLE (d, data); - assemble_integer (GEN_INT (data[0]), 4, align, 1); - assemble_integer (GEN_INT (data[1]), 4, nalign, 1); - break; - case XFmode: - REAL_VALUE_TO_TARGET_LONG_DOUBLE (d, data); - assemble_integer (GEN_INT (data[0]), 4, align, 1); - assemble_integer (GEN_INT (data[1]), 4, nalign, 1); - assemble_integer (GEN_INT (data[2]), 4, nalign, 1); - break; - case TFmode: - REAL_VALUE_TO_TARGET_LONG_DOUBLE (d, data); - assemble_integer (GEN_INT (data[0]), 4, align, 1); - assemble_integer (GEN_INT (data[1]), 4, nalign, 1); - assemble_integer (GEN_INT (data[2]), 4, nalign, 1); - assemble_integer (GEN_INT (data[3]), 4, nalign, 1); - break; - default: - abort (); - } - break; + /* This is hairy. We have a quantity of known size. real_to_target + will put it into an array of *host* longs, 32 bits per element + (even if long is more than 32 bits). We need to determine the + number of array elements that are occupied (nelts) and the number + of *target* min-addressable units that will be occupied in the + object file (nunits). We cannot assume that 32 divides the + mode's bitsize (size * BITS_PER_UNIT) evenly. - case 16: - switch (mode) - { - case HFmode: - REAL_VALUE_TO_TARGET_SINGLE (d, l); - assemble_integer (GEN_INT (l), 2, align, 1); - break; - case TQFmode: - REAL_VALUE_TO_TARGET_DOUBLE (d, data); - assemble_integer (GEN_INT (data[0]), 2, align, 1); - assemble_integer (GEN_INT (data[1]), 1, nalign, 1); - break; - default: - abort (); - } - break; + size * BITS_PER_UNIT is used here to make sure that padding bits + (which might appear at either end of the value; real_to_target + will include the padding bits in its output array) are included. */ - case 32: - switch (mode) - { - case QFmode: - REAL_VALUE_TO_TARGET_SINGLE (d, l); - assemble_integer (GEN_INT (l), 1, align, 1); - break; - case HFmode: - REAL_VALUE_TO_TARGET_DOUBLE (d, data); - assemble_integer (GEN_INT (data[0]), 1, align, 1); - assemble_integer (GEN_INT (data[1]), 1, nalign, 1); - break; - default: - abort (); - } - break; + nunits = GET_MODE_SIZE (mode); + bitsize = nunits * BITS_PER_UNIT; + nelts = CEIL (bitsize, 32); + units_per = 32 / BITS_PER_UNIT; - default: - abort (); + real_to_target (data, &d, mode); + + /* Put out the first word with the specified alignment. */ + assemble_integer (GEN_INT (data[0]), MIN (nunits, units_per), align, 1); + nunits -= units_per; + + /* Subsequent words need only 32-bit alignment. */ + align = min_align (align, 32); + + for (i = 1; i < nelts; i++) + { + assemble_integer (GEN_INT (data[i]), MIN (nunits, units_per), align, 1); + nunits -= units_per; } } @@ -2079,9 +1967,7 @@ struct addr_const GTY(()) }; static void -decode_addr_const (exp, value) - tree exp; - struct addr_const *value; +decode_addr_const (tree exp, struct addr_const *value) { tree target = TREE_OPERAND (exp, 0); int offset = 0; @@ -2116,8 +2002,7 @@ decode_addr_const (exp, value) case LABEL_DECL: x = gen_rtx_MEM (FUNCTION_MODE, - gen_rtx_LABEL_REF (VOIDmode, - label_rtx (TREE_OPERAND (exp, 0)))); + gen_rtx_LABEL_REF (VOIDmode, force_label_rtx (target))); break; case REAL_CST: @@ -2125,8 +2010,6 @@ decode_addr_const (exp, value) case COMPLEX_CST: case CONSTRUCTOR: case INTEGER_CST: - /* This constant should have been output already, but we can't simply - use TREE_CST_RTL since INTEGER_CST doesn't have one. */ x = output_constant_def (target, 1); break; @@ -2149,7 +2032,7 @@ struct rtx_const GTY(()) ENUM_BITFIELD(kind) kind : 16; ENUM_BITFIELD(machine_mode) mode : 16; union rtx_const_un { - REAL_VALUE_TYPE du; + REAL_VALUE_TYPE GTY ((tag ("4"))) du; struct rtx_const_u_addr { rtx base; const char *symbol; @@ -2174,16 +2057,10 @@ struct rtx_const GTY(()) /* Uniquize all constants that appear in memory. Each constant in memory thus far output is recorded - in `const_hash_table'. */ + in `const_desc_table'. */ struct constant_descriptor_tree GTY(()) { - /* More constant_descriptors with the same hash code. */ - struct constant_descriptor_tree *next; - - /* The label of the constant. */ - const char *label; - /* A MEM for the constant. */ rtx rtl; @@ -2191,63 +2068,25 @@ struct constant_descriptor_tree GTY(()) tree value; }; -#define MAX_HASH_TABLE 1009 -static GTY(()) struct constant_descriptor_tree * - const_hash_table[MAX_HASH_TABLE]; - -/* We maintain a hash table of STRING_CST values. Unless we are asked to force - out a string constant, we defer output of the constants until we know - they are actually used. This will be if something takes its address or if - there is a usage of the string in the RTL of a function. */ - -#define STRHASH(x) htab_hash_pointer (x) - -struct deferred_string GTY(()) -{ - const char *label; - tree exp; - int labelno; -}; - -static GTY ((param_is (struct deferred_string))) htab_t const_str_htab; - -/* Returns a hash code for X (which is a really a - struct deferred_string *). */ - -static hashval_t -const_str_htab_hash (x) - const void *x; -{ - return STRHASH (((const struct deferred_string *) x)->label); -} +static GTY((param_is (struct constant_descriptor_tree))) + htab_t const_desc_htab; -/* Returns nonzero if the value represented by X (which is really a - struct deferred_string *) is the same as that given by Y - (which is really a char *). */ - -static int -const_str_htab_eq (x, y) - const void *x; - const void *y; -{ - return (((const struct deferred_string *) x)->label == (const char *) y); -} +static struct constant_descriptor_tree * build_constant_desc (tree); +static void maybe_output_constant_def_contents (struct constant_descriptor_tree *, int); /* Compute a hash code for a constant expression. */ -static unsigned int -const_hash (exp) - tree exp; +static hashval_t +const_desc_hash (const void *ptr) { - return const_hash_1 (exp) % MAX_HASH_TABLE; + return const_hash_1 (((struct constant_descriptor_tree *)ptr)->value); } -static unsigned int -const_hash_1 (exp) - tree exp; +static hashval_t +const_hash_1 (const tree exp) { const char *p; - unsigned int hi; + hashval_t hi; int len, i; enum tree_code code = TREE_CODE (exp); @@ -2265,8 +2104,16 @@ const_hash_1 (exp) return real_hash (TREE_REAL_CST_PTR (exp)); case STRING_CST: - p = TREE_STRING_POINTER (exp); - len = TREE_STRING_LENGTH (exp); + if (flag_writable_strings) + { + p = (char *) &exp; + len = sizeof exp; + } + else + { + p = TREE_STRING_POINTER (exp); + len = TREE_STRING_LENGTH (exp); + } break; case COMPLEX_CST: @@ -2279,7 +2126,7 @@ const_hash_1 (exp) char *tmp; len = int_size_in_bytes (TREE_TYPE (exp)); - tmp = (char *) alloca (len); + tmp = alloca (len); get_set_constructor_bytes (exp, (unsigned char *) tmp, len); p = tmp; break; @@ -2334,7 +2181,7 @@ const_hash_1 (exp) return code; } - /* Compute hashing function */ + /* Compute hashing function. */ hi = len; for (i = 0; i < len; i++) hi = ((hi * 613) + (unsigned) (p[i])); @@ -2342,13 +2189,19 @@ const_hash_1 (exp) return hi; } +/* Wrapper of compare_constant, for the htab interface. */ +static int +const_desc_eq (const void *p1, const void *p2) +{ + return compare_constant (((struct constant_descriptor_tree *)p1)->value, + ((struct constant_descriptor_tree *)p2)->value); +} + /* Compare t1 and t2, and return 1 only if they are known to result in the same bit pattern on output. */ static int -compare_constant (t1, t2) - tree t1; - tree t2; +compare_constant (const tree t1, const tree t2) { enum tree_code typecode; @@ -2377,7 +2230,7 @@ compare_constant (t1, t2) case STRING_CST: if (flag_writable_strings) - return 0; + return t1 == t2; if (TYPE_MODE (TREE_TYPE (t1)) != TYPE_MODE (TREE_TYPE (t2))) return 0; @@ -2403,8 +2256,8 @@ compare_constant (t1, t2) if (int_size_in_bytes (TREE_TYPE (t1)) != len) return 0; - tmp1 = (unsigned char *) alloca (len); - tmp2 = (unsigned char *) alloca (len); + tmp1 = alloca (len); + tmp2 = alloca (len); if (get_set_constructor_bytes (t1, tmp1, len) != NULL_TREE) return 0; @@ -2496,81 +2349,11 @@ compare_constant (t1, t2) abort (); } -/* Record a list of constant expressions that were passed to - output_constant_def but that could not be output right away. */ - -struct deferred_constant -{ - struct deferred_constant *next; - tree exp; - int reloc; - int labelno; -}; - -static struct deferred_constant *deferred_constants; - -/* Another list of constants which should be output after the - function. */ -static struct deferred_constant *after_function_constants; - -/* Nonzero means defer output of addressed subconstants - (i.e., those for which output_constant_def is called.) */ -static int defer_addressed_constants_flag; - -/* Start deferring output of subconstants. */ - -void -defer_addressed_constants () -{ - defer_addressed_constants_flag++; -} - -/* Stop deferring output of subconstants, - and output now all those that have been deferred. */ - -void -output_deferred_addressed_constants () -{ - struct deferred_constant *p, *next; - - defer_addressed_constants_flag--; - - if (defer_addressed_constants_flag > 0) - return; - - for (p = deferred_constants; p; p = next) - { - output_constant_def_contents (p->exp, p->reloc, p->labelno); - next = p->next; - free (p); - } - - deferred_constants = 0; -} - -/* Output any constants which should appear after a function. */ - -static void -output_after_function_constants () -{ - struct deferred_constant *p, *next; - - for (p = after_function_constants; p; p = next) - { - output_constant_def_contents (p->exp, p->reloc, p->labelno); - next = p->next; - free (p); - } - - after_function_constants = 0; -} - /* Make a copy of the whole tree structure for a constant. This handles the same types of nodes that compare_constant handles. */ static tree -copy_constant (exp) - tree exp; +copy_constant (tree exp) { switch (TREE_CODE (exp)) { @@ -2602,6 +2385,7 @@ copy_constant (exp) case NOP_EXPR: case CONVERT_EXPR: case NON_LVALUE_EXPR: + case VIEW_CONVERT_EXPR: return build1 (TREE_CODE (exp), TREE_TYPE (exp), copy_constant (TREE_OPERAND (exp, 0))); @@ -2633,207 +2417,149 @@ copy_constant (exp) } } +/* Subroutine of output_constant_def: + No constant equal to EXP is known to have been output. + Make a constant descriptor to enter EXP in the hash table. + Assign the label number and construct RTL to refer to the + constant's location in memory. + Caller is responsible for updating the hash table. */ + +static struct constant_descriptor_tree * +build_constant_desc (tree exp) +{ + rtx symbol; + rtx rtl; + char label[256]; + int labelno; + struct constant_descriptor_tree *desc; + + desc = ggc_alloc (sizeof (*desc)); + if (flag_writable_strings && TREE_CODE (exp) == STRING_CST) + desc->value = exp; + else + desc->value = copy_constant (exp); + + /* Create a string containing the label name, in LABEL. */ + labelno = const_labelno++; + ASM_GENERATE_INTERNAL_LABEL (label, "LC", labelno); + + /* We have a symbol name; construct the SYMBOL_REF and the MEM. */ + symbol = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (label)); + SYMBOL_REF_FLAGS (symbol) = SYMBOL_FLAG_LOCAL; + SYMBOL_REF_DECL (symbol) = desc->value; + TREE_CONSTANT_POOL_ADDRESS_P (symbol) = 1; + + rtl = gen_rtx_MEM (TYPE_MODE (TREE_TYPE (exp)), symbol); + set_mem_attributes (rtl, exp, 1); + set_mem_alias_set (rtl, 0); + set_mem_alias_set (rtl, const_alias_set); + + /* Set flags or add text to the name to record information, such as + that it is a local symbol. If the name is changed, the macro + ASM_OUTPUT_LABELREF will have to know how to strip this + information. This call might invalidate our local variable + SYMBOL; we can't use it afterward. */ + + (*targetm.encode_section_info) (exp, rtl, true); + + desc->rtl = rtl; + + return desc; +} + /* Return an rtx representing a reference to constant data in memory for the constant expression EXP. If assembler code for such a constant has already been output, return an rtx to refer to it. - Otherwise, output such a constant in memory (or defer it for later) + Otherwise, output such a constant in memory and generate an rtx for it. - If DEFER is nonzero, the output of string constants can be deferred - and output only if referenced in the function after all optimizations. + If DEFER is nonzero, this constant can be deferred and output only + if referenced in the function after all optimizations. - The TREE_CST_RTL of EXP is set up to point to that rtx. - The const_hash_table records which constants already have label strings. */ + `const_desc_table' records which constants already have label strings. */ rtx -output_constant_def (exp, defer) - tree exp; - int defer; +output_constant_def (tree exp, int defer) { - int hash; struct constant_descriptor_tree *desc; - struct deferred_string **defstr; - char label[256]; - int reloc; - int found = 1; - int after_function = 0; - 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) - && (defer || !STRING_POOL_ADDRESS_P (XEXP (TREE_CST_RTL (exp), 0)))) - return TREE_CST_RTL (exp); - - /* Make sure any other constants whose addresses appear in EXP - are assigned label numbers. */ - - reloc = output_addressed_constants (exp); + struct constant_descriptor_tree key; + void **loc; - /* Compute hash code of EXP. Search the descriptors for that hash code - to see if any of them describes EXP. If yes, the descriptor records - the label number already assigned. */ - - hash = const_hash (exp); - - for (desc = const_hash_table[hash]; desc; desc = desc->next) - if (compare_constant (exp, desc->value)) - break; + /* Look up EXP in the table of constant descriptors. If we didn't find + it, create a new one. */ + key.value = exp; + loc = htab_find_slot (const_desc_htab, &key, INSERT); + desc = *loc; if (desc == 0) { - /* No constant equal to EXP is known to have been output. - Make a constant descriptor to enter EXP in the hash table. - Assign the label number and record it in the descriptor for - future calls to this function to find. */ - - /* Create a string containing the label name, in LABEL. */ - labelno = const_labelno++; - ASM_GENERATE_INTERNAL_LABEL (label, "LC", labelno); - - desc = ggc_alloc (sizeof (*desc)); - desc->next = const_hash_table[hash]; - desc->label = ggc_strdup (label); - desc->value = copy_constant (exp); - const_hash_table[hash] = desc; - - /* We have a symbol name; construct the SYMBOL_REF and the MEM. */ - rtl = desc->rtl - = gen_rtx_MEM (TYPE_MODE (TREE_TYPE (exp)), - gen_rtx_SYMBOL_REF (Pmode, desc->label)); - - set_mem_attributes (rtl, exp, 1); - set_mem_alias_set (rtl, 0); - set_mem_alias_set (rtl, const_alias_set); - - found = 0; + desc = build_constant_desc (exp); + *loc = desc; } - else - rtl = desc->rtl; - if (TREE_CODE (exp) != INTEGER_CST) - TREE_CST_RTL (exp) = rtl; - - /* Optionally set flags or add text to the name to record information - such as that it is a function name. If the name is changed, the macro - ASM_OUTPUT_LABELREF will have to know how to strip this information. */ - /* A previously-processed constant would already have section info - encoded in it. */ - if (! found) - { - /* Take care not to invoke targetm.encode_section_info for - constants which don't have a TREE_CST_RTL. */ - if (TREE_CODE (exp) != INTEGER_CST) - (*targetm.encode_section_info) (exp, true); + maybe_output_constant_def_contents (desc, defer); + return desc->rtl; +} - desc->rtl = rtl; - desc->label = XSTR (XEXP (desc->rtl, 0), 0); - } +/* Subroutine of output_constant_def: Decide whether or not we need to + output the constant DESC now, and if so, do it. */ +static void +maybe_output_constant_def_contents (struct constant_descriptor_tree *desc, + int defer) +{ + rtx symbol = XEXP (desc->rtl, 0); + tree exp = desc->value; -#ifdef CONSTANT_AFTER_FUNCTION_P - if (current_function_decl != 0 - && CONSTANT_AFTER_FUNCTION_P (exp)) - after_function = 1; -#endif + if (flag_syntax_only) + return; - if (found - && STRING_POOL_ADDRESS_P (XEXP (rtl, 0)) - && (!defer || defer_addressed_constants_flag || after_function)) - { - defstr = (struct deferred_string **) - htab_find_slot_with_hash (const_str_htab, desc->label, - STRHASH (desc->label), NO_INSERT); - if (defstr) - { - /* If the string is currently deferred but we need to output it now, - remove it from deferred string hash table. */ - found = 0; - labelno = (*defstr)->labelno; - STRING_POOL_ADDRESS_P (XEXP (rtl, 0)) = 0; - htab_clear_slot (const_str_htab, (void **) defstr); - } - } + if (TREE_ASM_WRITTEN (exp)) + /* Already output; don't do it again. */ + return; - /* If this is the first time we've seen this particular constant, - output it (or defer its output for later). */ - if (! found) + /* The only constants that cannot safely be deferred, assuming the + context allows it, are strings under flag_writable_strings. */ + if (defer && (TREE_CODE (exp) != STRING_CST || !flag_writable_strings)) { - if (defer_addressed_constants_flag || after_function) - { - struct deferred_constant *p - = (struct deferred_constant *) - xmalloc (sizeof (struct deferred_constant)); - - p->exp = desc->value; - p->reloc = reloc; - p->labelno = labelno; - if (after_function) - { - p->next = after_function_constants; - after_function_constants = p; - } - else - { - p->next = deferred_constants; - deferred_constants = p; - } - } - else - { - /* Do no output if -fsyntax-only. */ - if (! flag_syntax_only) - { - if (TREE_CODE (exp) != STRING_CST - || !defer - || flag_writable_strings - || (defstr = (struct deferred_string **) - htab_find_slot_with_hash (const_str_htab, - desc->label, - STRHASH (desc->label), - INSERT)) == NULL) - output_constant_def_contents (exp, reloc, labelno); - else - { - struct deferred_string *p; - - p = (struct deferred_string *) - ggc_alloc (sizeof (struct deferred_string)); - - p->exp = desc->value; - p->label = desc->label; - p->labelno = labelno; - *defstr = p; - STRING_POOL_ADDRESS_P (XEXP (rtl, 0)) = 1; - } - } - } + /* Increment n_deferred_constants if it exists. It needs to be at + least as large as the number of constants actually referred to + by the function. If it's too small we'll stop looking too early + and fail to emit constants; if it's too large we'll only look + through the entire function when we could have stopped earlier. */ + if (cfun) + n_deferred_constants++; + return; } - return rtl; + output_constant_def_contents (symbol); } -/* Now output assembler code to define the label for EXP, - and follow it with the data of EXP. */ +/* We must output the constant data referred to by SYMBOL; do so. */ static void -output_constant_def_contents (exp, reloc, labelno) - tree exp; - int reloc; - int labelno; +output_constant_def_contents (rtx symbol) { - int align; + tree exp = SYMBOL_REF_DECL (symbol); + const char *label = XSTR (symbol, 0); HOST_WIDE_INT size; + /* Make sure any other constants whose addresses appear in EXP + are assigned label numbers. */ + int reloc = compute_reloc_for_constant (exp); + /* Align the location counter as required by EXP's data type. */ - align = TYPE_ALIGN (TREE_TYPE (exp)); + int align = TYPE_ALIGN (TREE_TYPE (exp)); #ifdef CONSTANT_ALIGNMENT align = CONSTANT_ALIGNMENT (exp, align); #endif + output_addressed_constants (exp); + + /* We are no longer deferring this constant. */ + TREE_ASM_WRITTEN (exp) = 1; + if (IN_NAMED_SECTION (exp)) named_section (exp, NULL, reloc); else @@ -2850,19 +2576,39 @@ output_constant_def_contents (exp, reloc, labelno) /* 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); - } + 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); + ASM_OUTPUT_LABEL (asm_out_file, label); #endif /* ASM_DECLARE_CONSTANT_NAME */ /* Output the value of EXP. */ output_constant (exp, size, align); } + +/* A constant which was deferred in its original location has been + inserted by the RTL inliner into a different function. The + current function's deferred constant count must be incremented. */ +void +notice_rtl_inlining_of_deferred_constant (void) +{ + n_deferred_constants++; +} + +/* Look up EXP in the table of constant descriptors. Return the rtl + if it has been emitted, else null. */ + +rtx +lookup_constant_def (tree exp) +{ + struct constant_descriptor_tree *desc; + struct constant_descriptor_tree key; + + key.value = exp; + desc = htab_find (const_desc_htab, &key); + + return (desc ? desc->rtl : NULL_RTX); +} /* Used in the hash tables to avoid outputting the same constant twice. Unlike 'struct constant_descriptor_tree', RTX constants @@ -2907,23 +2653,21 @@ struct pool_constant GTY(()) /* Initialize constant pool hashing for a new function. */ void -init_varasm_status (f) - struct function *f; +init_varasm_status (struct function *f) { struct varasm_status *p; - p = (struct varasm_status *) ggc_alloc (sizeof (struct varasm_status)); + p = ggc_alloc (sizeof (struct varasm_status)); f->varasm = p; p->x_const_rtx_hash_table - = ((struct constant_descriptor_rtx **) - ggc_alloc_cleared (MAX_RTX_HASH_TABLE - * sizeof (struct constant_descriptor_rtx *))); + = ggc_alloc_cleared (MAX_RTX_HASH_TABLE + * sizeof (struct constant_descriptor_rtx *)); p->x_const_rtx_sym_hash_table - = ((struct pool_constant **) - ggc_alloc_cleared (MAX_RTX_HASH_TABLE - * sizeof (struct pool_constant *))); + = ggc_alloc_cleared (MAX_RTX_HASH_TABLE + * sizeof (struct pool_constant *)); p->x_first_pool = p->x_last_pool = 0; p->x_pool_offset = 0; + p->deferred_constants = 0; } @@ -2932,10 +2676,7 @@ init_varasm_status (f) They are stored into VALUE. */ static void -decode_rtx_const (mode, x, value) - enum machine_mode mode; - rtx x; - struct rtx_const *value; +decode_rtx_const (enum machine_mode mode, rtx x, struct rtx_const *value) { /* Clear the whole structure, including any gaps. */ memset (value, 0, sizeof (struct rtx_const)); @@ -2965,7 +2706,7 @@ decode_rtx_const (mode, x, value) break; case rvc_normal: value->un.du.exp = r->exp; - /* FALLTHRU */ + /* Fall through. */ case rvc_nan: memcpy (value->un.du.sig, r->sig, sizeof (r->sig)); break; @@ -3025,7 +2766,7 @@ decode_rtx_const (mode, x, value) break; case rvc_normal: d->exp = r->exp; - /* FALLTHRU */ + /* Fall through. */ case rvc_nan: memcpy (d->sig, r->sig, sizeof (r->sig)); break; @@ -3113,8 +2854,7 @@ decode_rtx_const (mode, x, value) include the same symbol. */ rtx -simplify_subtraction (x) - rtx x; +simplify_subtraction (rtx x) { struct rtx_const val0, val1; @@ -3133,9 +2873,7 @@ simplify_subtraction (x) /* Compute a hash code for a constant RTL expression. */ static unsigned int -const_hash_rtx (mode, x) - enum machine_mode mode; - rtx x; +const_hash_rtx (enum machine_mode mode, rtx x) { union { struct rtx_const value; @@ -3147,7 +2885,7 @@ const_hash_rtx (mode, x) decode_rtx_const (mode, x, &u.value); - /* Compute hashing function */ + /* Compute hashing function. */ hi = 0; for (i = 0; i < ARRAY_SIZE (u.data); i++) hi = hi * 613 + u.data[i]; @@ -3159,10 +2897,8 @@ const_hash_rtx (mode, x) Return 1 if DESC describes a constant with the same value as X. */ static int -compare_constant_rtx (mode, x, desc) - enum machine_mode mode; - rtx x; - struct constant_descriptor_rtx *desc; +compare_constant_rtx (enum machine_mode mode, rtx x, + struct constant_descriptor_rtx *desc) { struct rtx_const value; @@ -3176,48 +2912,26 @@ compare_constant_rtx (mode, x, desc) It is up to the caller to enter the descriptor in the hash table. */ static struct constant_descriptor_rtx * -record_constant_rtx (mode, x) - enum machine_mode mode; - rtx x; +record_constant_rtx (enum machine_mode mode, rtx x) { struct constant_descriptor_rtx *ptr; - ptr = (struct constant_descriptor_rtx *) ggc_alloc (sizeof (*ptr)); + ptr = ggc_alloc (sizeof (*ptr)); decode_rtx_const (mode, x, &ptr->value); return ptr; } -/* Given a constant rtx X, return a MEM for the location in memory at which - this constant has been placed. Return 0 if it not has been placed yet. */ - -rtx -mem_for_const_double (x) - rtx x; -{ - enum machine_mode mode = GET_MODE (x); - struct constant_descriptor_rtx *desc; - - for (desc = const_rtx_hash_table[const_hash_rtx (mode, x)]; desc; - desc = desc->next) - if (compare_constant_rtx (mode, x, desc)) - return desc->rtl; - - return 0; -} - /* Given a constant rtx X, make (or find) a memory constant for its value and return a MEM rtx to refer to it in memory. */ rtx -force_const_mem (mode, x) - enum machine_mode mode; - rtx x; +force_const_mem (enum machine_mode mode, rtx x) { int hash; struct constant_descriptor_rtx *desc; char label[256]; - rtx def; + rtx def, symbol; struct pool_constant *pool; unsigned int align; @@ -3230,7 +2944,7 @@ force_const_mem (mode, x) hash = const_hash_rtx (mode, x); for (desc = const_rtx_hash_table[hash]; desc; desc = desc->next) if (compare_constant_rtx (mode, x, desc)) - return desc->rtl; + return copy_rtx (desc->rtl); /* No constant equal to X is known to have been output. Make a constant descriptor to enter X in the hash table @@ -3242,8 +2956,11 @@ force_const_mem (mode, x) /* Align the location counter as required by EXP's data type. */ align = GET_MODE_ALIGNMENT (mode == VOIDmode ? word_mode : mode); #ifdef CONSTANT_ALIGNMENT - align = CONSTANT_ALIGNMENT (make_tree ((*lang_hooks.types.type_for_mode) - (mode, 0), x), align); + { + tree type = (*lang_hooks.types.type_for_mode) (mode, 0); + if (type != NULL_TREE) + align = CONSTANT_ALIGNMENT (make_tree (type, x), align); + } #endif pool_offset += (align / BITS_PER_UNIT) - 1; @@ -3253,7 +2970,7 @@ force_const_mem (mode, x) LABEL_PRESERVE_P (XEXP (x, 0)) = 1; /* Allocate a pool constant descriptor, fill it in, and chain it in. */ - pool = (struct pool_constant *) ggc_alloc (sizeof (struct pool_constant)); + pool = ggc_alloc (sizeof (struct pool_constant)); pool->desc = desc; pool->constant = x; pool->mode = mode; @@ -3278,31 +2995,31 @@ force_const_mem (mode, x) /* Construct the SYMBOL_REF and the MEM. */ - pool->desc->rtl = def - = gen_rtx_MEM (mode, gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (label))); - set_mem_alias_set (def, const_alias_set); + symbol = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (label)); + SYMBOL_REF_FLAGS (symbol) = SYMBOL_FLAG_LOCAL; + + pool->desc->rtl = def = gen_rtx_MEM (mode, symbol); set_mem_attributes (def, (*lang_hooks.types.type_for_mode) (mode, 0), 1); RTX_UNCHANGING_P (def) = 1; /* Add label to symbol hash table. */ - hash = SYMHASH (XSTR (XEXP (def, 0), 0)); + hash = SYMHASH (XSTR (symbol, 0)); pool->next_sym = const_rtx_sym_hash_table[hash]; const_rtx_sym_hash_table[hash] = pool; /* Mark the symbol_ref as belonging to this constants pool. */ - CONSTANT_POOL_ADDRESS_P (XEXP (def, 0)) = 1; + CONSTANT_POOL_ADDRESS_P (symbol) = 1; + SYMBOL_REF_FLAGS (symbol) = SYMBOL_FLAG_LOCAL; current_function_uses_const_pool = 1; - return def; + return copy_rtx (def); } /* Given a SYMBOL_REF with CONSTANT_POOL_ADDRESS_P true, return a pointer to the corresponding pool_constant structure. */ static struct pool_constant * -find_pool_constant (f, addr) - struct function *f; - rtx addr; +find_pool_constant (struct function *f, rtx addr) { struct pool_constant *pool; const char *label = XSTR (addr, 0); @@ -3318,8 +3035,7 @@ find_pool_constant (f, addr) /* Given a constant pool SYMBOL_REF, return the corresponding constant. */ rtx -get_pool_constant (addr) - rtx addr; +get_pool_constant (rtx addr) { return (find_pool_constant (cfun, addr))->constant; } @@ -3328,9 +3044,7 @@ get_pool_constant (addr) and whether it has been output or not. */ rtx -get_pool_constant_mark (addr, pmarked) - rtx addr; - bool *pmarked; +get_pool_constant_mark (rtx addr, bool *pmarked) { struct pool_constant *pool = find_pool_constant (cfun, addr); *pmarked = (pool->mark != 0); @@ -3340,9 +3054,7 @@ get_pool_constant_mark (addr, pmarked) /* Likewise, but for the constant pool of a specific function. */ rtx -get_pool_constant_for_function (f, addr) - struct function *f; - rtx addr; +get_pool_constant_for_function (struct function *f, rtx addr) { return (find_pool_constant (f, addr))->constant; } @@ -3350,16 +3062,13 @@ get_pool_constant_for_function (f, addr) /* Similar, return the mode. */ enum machine_mode -get_pool_mode (addr) - rtx addr; +get_pool_mode (rtx addr) { return (find_pool_constant (cfun, addr))->mode; } enum machine_mode -get_pool_mode_for_function (f, addr) - struct function *f; - rtx addr; +get_pool_mode_for_function (struct function *f, rtx addr) { return (find_pool_constant (f, addr))->mode; } @@ -3367,8 +3076,7 @@ get_pool_mode_for_function (f, addr) /* Similar, return the offset in the constant pool. */ int -get_pool_offset (addr) - rtx addr; +get_pool_offset (rtx addr) { return (find_pool_constant (cfun, addr))->offset; } @@ -3376,7 +3084,7 @@ get_pool_offset (addr) /* Return the size of the constant pool. */ int -get_pool_size () +get_pool_size (void) { return pool_offset; } @@ -3384,9 +3092,8 @@ get_pool_size () /* Write all the constants in the constant pool. */ void -output_constant_pool (fnname, fndecl) - const char *fnname ATTRIBUTE_UNUSED; - tree fndecl ATTRIBUTE_UNUSED; +output_constant_pool (const char *fnname ATTRIBUTE_UNUSED, + tree fndecl ATTRIBUTE_UNUSED) { struct pool_constant *pool; rtx x; @@ -3427,7 +3134,7 @@ output_constant_pool (fnname, fndecl) || GET_CODE (XEXP (XEXP (x, 0), 0)) != LABEL_REF) break; tmp = XEXP (XEXP (x, 0), 0); - /* FALLTHRU */ + /* Fall through. */ case LABEL_REF: tmp = XEXP (x, 0); @@ -3455,7 +3162,7 @@ output_constant_pool (fnname, fndecl) assemble_align (pool->align); /* Output the label. */ - ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LC", pool->labelno); + (*targetm.asm_out.internal_label) (asm_out_file, "LC", pool->labelno); /* Output the value of the constant itself. */ switch (GET_MODE_CLASS (pool->mode)) @@ -3536,17 +3243,17 @@ output_constant_pool (fnname, fndecl) } /* Look through the instructions for this function, and mark all the - entries in the constant pool which are actually being used. - Emit used deferred strings. */ + entries in the constant pool which are actually being used. Emit + deferred constants which have indeed been used. */ static void -mark_constant_pool () +mark_constant_pool (void) { rtx insn; rtx link; struct pool_constant *pool; - if (first_pool == 0 && htab_elements (const_str_htab) == 0) + if (first_pool == 0 && n_deferred_constants == 0) return; for (pool = first_pool; pool; pool = pool->next) @@ -3573,8 +3280,7 @@ mark_constant_pool () deferred strings that are used. */ static void -mark_constants (x) - rtx x; +mark_constants (rtx x) { int i; const char *format_ptr; @@ -3638,9 +3344,7 @@ mark_constants (x) be used with for_each_rtx to mark all SYMBOL_REFs in an rtx. */ static int -mark_constant (current_rtx, data) - rtx *current_rtx; - void *data ATTRIBUTE_UNUSED; +mark_constant (rtx *current_rtx, void *data ATTRIBUTE_UNUSED) { rtx x = *current_rtx; @@ -3660,33 +3364,23 @@ mark_constant (current_rtx, data) else return -1; } - else if (STRING_POOL_ADDRESS_P (x)) + else if (TREE_CONSTANT_POOL_ADDRESS_P (x)) { - struct deferred_string **defstr; - - defstr = (struct deferred_string **) - htab_find_slot_with_hash (const_str_htab, XSTR (x, 0), - STRHASH (XSTR (x, 0)), NO_INSERT); - if (defstr) + tree exp = SYMBOL_REF_DECL (x); + if (!TREE_ASM_WRITTEN (exp)) { - struct deferred_string *p = *defstr; - - STRING_POOL_ADDRESS_P (x) = 0; - output_constant_def_contents (p->exp, 0, p->labelno); - htab_clear_slot (const_str_htab, (void **) defstr); + n_deferred_constants--; + output_constant_def_contents (x); } } } return 0; } -/* Find all the constants whose addresses are referenced inside of EXP, - and make sure assembler code with a label has been output for each one. - Indicate whether an ADDR_EXPR has been encountered. */ +/* Determine what kind of relocations EXP may need. */ -static int -output_addressed_constants (exp) - tree exp; +int +compute_reloc_for_constant (tree exp) { int reloc = 0, reloc2; tree tem; @@ -3706,10 +3400,6 @@ output_addressed_constants (exp) tem = TREE_OPERAND (tem, 0)) ; - if (TREE_CODE_CLASS (TREE_CODE (tem)) == 'c' - || TREE_CODE (tem) == CONSTRUCTOR) - output_constant_def (tem, 0); - if (TREE_PUBLIC (tem)) reloc |= 2; else @@ -3717,13 +3407,13 @@ output_addressed_constants (exp) break; case PLUS_EXPR: - reloc = output_addressed_constants (TREE_OPERAND (exp, 0)); - reloc |= output_addressed_constants (TREE_OPERAND (exp, 1)); + reloc = compute_reloc_for_constant (TREE_OPERAND (exp, 0)); + reloc |= compute_reloc_for_constant (TREE_OPERAND (exp, 1)); break; case MINUS_EXPR: - reloc = output_addressed_constants (TREE_OPERAND (exp, 0)); - reloc2 = output_addressed_constants (TREE_OPERAND (exp, 1)); + reloc = compute_reloc_for_constant (TREE_OPERAND (exp, 0)); + reloc2 = compute_reloc_for_constant (TREE_OPERAND (exp, 1)); /* The difference of two local labels is computable at link time. */ if (reloc == 1 && reloc2 == 1) reloc = 0; @@ -3734,13 +3424,13 @@ output_addressed_constants (exp) case NOP_EXPR: case CONVERT_EXPR: case NON_LVALUE_EXPR: - reloc = output_addressed_constants (TREE_OPERAND (exp, 0)); + reloc = compute_reloc_for_constant (TREE_OPERAND (exp, 0)); break; case CONSTRUCTOR: for (tem = CONSTRUCTOR_ELTS (exp); tem; tem = TREE_CHAIN (tem)) if (TREE_VALUE (tem) != 0) - reloc |= output_addressed_constants (TREE_VALUE (tem)); + reloc |= compute_reloc_for_constant (TREE_VALUE (tem)); break; @@ -3749,6 +3439,58 @@ output_addressed_constants (exp) } return reloc; } + +/* Find all the constants whose addresses are referenced inside of EXP, + and make sure assembler code with a label has been output for each one. + Indicate whether an ADDR_EXPR has been encountered. */ + +static void +output_addressed_constants (tree exp) +{ + tree tem; + + /* Give the front-end a chance to convert VALUE to something that + looks more like a constant to the back-end. */ + exp = (*lang_hooks.expand_constant) (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. */ + for (tem = TREE_OPERAND (exp, 0); handled_component_p (tem); + tem = TREE_OPERAND (tem, 0)) + ; + + if (TREE_CODE_CLASS (TREE_CODE (tem)) == 'c' + || TREE_CODE (tem) == CONSTRUCTOR) + output_constant_def (tem, 0); + break; + + case PLUS_EXPR: + case MINUS_EXPR: + output_addressed_constants (TREE_OPERAND (exp, 1)); + /* Fall through. */ + + case NOP_EXPR: + case CONVERT_EXPR: + case NON_LVALUE_EXPR: + output_addressed_constants (TREE_OPERAND (exp, 0)); + break; + + case CONSTRUCTOR: + for (tem = CONSTRUCTOR_ELTS (exp); tem; tem = TREE_CHAIN (tem)) + if (TREE_VALUE (tem) != 0) + output_addressed_constants (TREE_VALUE (tem)); + + break; + + default: + break; + } +} /* Return nonzero if VALUE is a valid constant-valued expression for use in initializing a static variable; one that can be an @@ -3761,9 +3503,7 @@ output_addressed_constants (exp) arithmetic-combinations of integers. */ tree -initializer_constant_valid_p (value, endtype) - tree value; - tree endtype; +initializer_constant_valid_p (tree value, tree endtype) { /* Give the front-end a chance to convert VALUE to something that looks more like a constant to the back-end. */ @@ -3854,7 +3594,8 @@ initializer_constant_valid_p (value, endtype) /* Likewise conversions from int to pointers, but also allow conversions from 0. */ - if (POINTER_TYPE_P (TREE_TYPE (value)) + if ((POINTER_TYPE_P (TREE_TYPE (value)) + || TREE_CODE (TREE_TYPE (value)) == OFFSET_TYPE) && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (value, 0)))) { if (integer_zerop (TREE_OPERAND (value, 0))) @@ -3865,8 +3606,10 @@ initializer_constant_valid_p (value, endtype) endtype); } - /* Allow conversions to union types if the value inside is okay. */ - if (TREE_CODE (TREE_TYPE (value)) == UNION_TYPE) + /* Allow conversions to struct or union types if the value + inside is okay. */ + if (TREE_CODE (TREE_TYPE (value)) == RECORD_TYPE + || TREE_CODE (TREE_TYPE (value)) == UNION_TYPE) return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype); break; @@ -3920,7 +3663,7 @@ initializer_constant_valid_p (value, endtype) op1 = TREE_OPERAND (value, 1); /* Like STRIP_NOPS except allow the operand mode to widen. - This works around a feature of fold that simplfies + 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. */ @@ -3986,15 +3729,12 @@ initializer_constant_valid_p (value, endtype) ALIGN is the alignment of the data in bits. */ void -output_constant (exp, size, align) - tree exp; - HOST_WIDE_INT size; - unsigned int align; +output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align) { enum tree_code code; - HOST_WIDE_INT thissize; + unsigned HOST_WIDE_INT thissize; - /* Some front-ends use constants other than the standard language-indepdent + /* Some front-ends use constants other than the standard language-independent varieties, but which may still be output directly. Give the front-end a chance to convert EXP to a language-independent representation. */ exp = (*lang_hooks.expand_constant) (exp); @@ -4042,6 +3782,7 @@ output_constant (exp, size, align) case ENUMERAL_TYPE: case POINTER_TYPE: case REFERENCE_TYPE: + case OFFSET_TYPE: if (! assemble_integer (expand_expr (exp, NULL_RTX, VOIDmode, EXPAND_INITIALIZER), size, align, 0)) @@ -4052,9 +3793,7 @@ output_constant (exp, size, align) if (TREE_CODE (exp) != REAL_CST) error ("initializer for floating value is not a floating constant"); - assemble_real (TREE_REAL_CST (exp), - mode_for_size (size * BITS_PER_UNIT, MODE_FLOAT, 0), - align); + assemble_real (TREE_REAL_CST (exp), TYPE_MODE (TREE_TYPE (exp)), align); break; case COMPLEX_TYPE: @@ -4072,7 +3811,8 @@ output_constant (exp, size, align) } else if (TREE_CODE (exp) == STRING_CST) { - thissize = MIN (TREE_STRING_LENGTH (exp), size); + thissize = MIN ((unsigned HOST_WIDE_INT)TREE_STRING_LENGTH (exp), + size); assemble_string (TREE_STRING_POINTER (exp), thissize); } else if (TREE_CODE (exp) == VECTOR_CST) @@ -4111,7 +3851,7 @@ output_constant (exp, size, align) thissize, align, 1); else if (TREE_CODE (exp) == CONSTRUCTOR) { - unsigned char *buffer = (unsigned char *) alloca (thissize); + unsigned char *buffer = alloca (thissize); if (get_set_constructor_bytes (exp, buffer, thissize)) abort (); assemble_string ((char *) buffer, thissize); @@ -4127,9 +3867,8 @@ output_constant (exp, size, align) abort (); } - size -= thissize; - if (size > 0) - assemble_zeros (size); + if (size > thissize) + assemble_zeros (size - thissize); } @@ -4138,8 +3877,7 @@ output_constant (exp, size, align) type with an unspecified upper bound. */ static unsigned HOST_WIDE_INT -array_size_for_constructor (val) - tree val; +array_size_for_constructor (tree val) { tree max_index, i; @@ -4179,10 +3917,8 @@ array_size_for_constructor (val) Generate at least SIZE bytes, padding if necessary. */ static void -output_constructor (exp, size, align) - tree exp; - HOST_WIDE_INT size; - unsigned int align; +output_constructor (tree exp, unsigned HOST_WIDE_INT size, + unsigned int align) { tree type = TREE_TYPE (exp); tree link, field = 0; @@ -4190,7 +3926,7 @@ output_constructor (exp, size, align) /* Number of bytes output or skipped so far. In other words, current position within the constructor. */ HOST_WIDE_INT total_bytes = 0; - /* Non-zero means BYTE contains part of a byte, to be output. */ + /* Nonzero means BYTE contains part of a byte, to be output. */ int byte_buffer_in_use = 0; int byte = 0; @@ -4231,6 +3967,15 @@ output_constructor (exp, size, align) else if (TREE_CODE (type) == ARRAY_TYPE) index = TREE_PURPOSE (link); +#ifdef ASM_COMMENT_START + if (field && flag_verbose_asm) + fprintf (asm_out_file, "%s %s:\n", + ASM_COMMENT_START, + DECL_NAME (field) + ? IDENTIFIER_POINTER (DECL_NAME (field)) + : "<anonymous>"); +#endif + /* Eliminate the marker that makes a cast not be an lvalue. */ if (val != 0) STRIP_NOPS (val); @@ -4477,7 +4222,7 @@ output_constructor (exp, size, align) total_bytes++; } - if (total_bytes < size) + if ((unsigned HOST_WIDE_INT)total_bytes < size) assemble_zeros (size - total_bytes); } @@ -4488,8 +4233,7 @@ static GTY(()) tree weak_decls; /* Mark DECL as weak. */ static void -mark_weak (decl) - tree decl; +mark_weak (tree decl) { DECL_WEAK (decl) = 1; @@ -4503,9 +4247,7 @@ mark_weak (decl) /* Merge weak status between NEWDECL and OLDDECL. */ void -merge_weak (newdecl, olddecl) - tree newdecl; - tree olddecl; +merge_weak (tree newdecl, tree olddecl) { if (DECL_WEAK (newdecl) == DECL_WEAK (olddecl)) return; @@ -4521,15 +4263,16 @@ merge_weak (newdecl, olddecl) 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"); + error ("%Jweak declaration of '%D' must precede definition", + newdecl, newdecl); /* 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"); + warning ("%Jweak declaration of '%D' after first use results " + "in unspecified behavior", newdecl, newdecl); if (SUPPORTS_WEAK) { @@ -4559,20 +4302,19 @@ merge_weak (newdecl, olddecl) /* Declare DECL to be a weak symbol. */ void -declare_weak (decl) - tree decl; +declare_weak (tree decl) { if (! TREE_PUBLIC (decl)) - error_with_decl (decl, "weak declaration of `%s' must be public"); + error ("%Jweak declaration of '%D' must be public", decl, decl); else if (TREE_CODE (decl) == FUNCTION_DECL && TREE_ASM_WRITTEN (decl)) - error_with_decl (decl, "weak declaration of `%s' must precede definition"); + error ("%Jweak declaration of '%D' must precede definition", decl, decl); else if (SUPPORTS_WEAK) { if (! DECL_WEAK (decl)) weak_decls = tree_cons (NULL, decl, weak_decls); } else - warning_with_decl (decl, "weak declaration of `%s' not supported"); + warning ("%Jweak declaration of '%D' not supported", decl, decl); mark_weak (decl); } @@ -4580,14 +4322,16 @@ declare_weak (decl) /* Emit any pending weak declarations. */ void -weak_finish () +weak_finish (void) { tree t; for (t = weak_decls; t; t = TREE_CHAIN (t)) { tree decl = TREE_VALUE (t); - const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); +#if defined (ASM_WEAKEN_DECL) || defined (ASM_WEAKEN_LABEL) + const char *const name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); +#endif if (! TREE_USED (decl)) continue; @@ -4610,8 +4354,7 @@ weak_finish () /* Emit the assembly bits to indicate that DECL is globally visible. */ static void -globalize_decl (decl) - tree decl; +globalize_decl (tree decl) { const char *name = XSTR (XEXP (DECL_RTL (decl), 0), 0); @@ -4646,8 +4389,7 @@ globalize_decl (decl) the symbol for TARGET. */ void -assemble_alias (decl, target) - tree decl, target ATTRIBUTE_UNUSED; +assemble_alias (tree decl, tree target ATTRIBUTE_UNUSED) { const char *name; @@ -4673,14 +4415,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 @@ -4695,9 +4449,7 @@ assemble_alias (decl, target) the visibility type VIS, which must not be VISIBILITY_DEFAULT. */ void -default_assemble_visibility (decl, vis) - tree decl; - int vis; +default_assemble_visibility (tree decl, int vis) { static const char * const visibility_types[] = { NULL, "internal", "hidden", "protected" @@ -4720,10 +4472,9 @@ default_assemble_visibility (decl, vis) /* A helper function to call assemble_visibility when needed for a decl. */ static void -maybe_assemble_visibility (decl) - tree decl; +maybe_assemble_visibility (tree decl) { - enum symbol_visibility vis = decl_visibility (decl); + enum symbol_visibility vis = DECL_VISIBILITY (decl); if (vis != VISIBILITY_DEFAULT) (* targetm.asm_out.visibility) (decl, vis); @@ -4735,7 +4486,7 @@ maybe_assemble_visibility (decl) a target-specific mechanism for having duplicates discarded. */ int -supports_one_only () +supports_one_only (void) { if (SUPPORTS_ONE_ONLY) return 1; @@ -4746,24 +4497,23 @@ supports_one_only () translation units without generating a linker error. */ void -make_decl_one_only (decl) - tree decl; +make_decl_one_only (tree decl) { if (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != FUNCTION_DECL) abort (); 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 @@ -4771,19 +4521,18 @@ make_decl_one_only (decl) } void -init_varasm_once () +init_varasm_once (void) { - const_str_htab = htab_create_ggc (128, const_str_htab_hash, - const_str_htab_eq, NULL); - in_named_htab = htab_create (31, in_named_entry_hash, - in_named_entry_eq, NULL); + in_named_htab = htab_create_ggc (31, in_named_entry_hash, + in_named_entry_eq, NULL); + const_desc_htab = htab_create_ggc (1009, const_desc_hash, + const_desc_eq, NULL); const_alias_set = new_alias_set (); } enum tls_model -decl_tls_model (decl) - tree decl; +decl_tls_model (tree decl) { enum tls_model kind; tree attr = lookup_attribute ("tls_model", DECL_ATTRIBUTES (decl)); @@ -4827,31 +4576,6 @@ decl_tls_model (decl) return kind; } -enum symbol_visibility -decl_visibility (decl) - tree decl; -{ - tree attr = lookup_attribute ("visibility", DECL_ATTRIBUTES (decl)); - - if (attr) - { - const char *which = TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr))); - - if (strcmp (which, "default") == 0) - return VISIBILITY_DEFAULT; - if (strcmp (which, "internal") == 0) - return VISIBILITY_INTERNAL; - if (strcmp (which, "hidden") == 0) - return VISIBILITY_HIDDEN; - if (strcmp (which, "protected") == 0) - return VISIBILITY_PROTECTED; - - abort (); - } - - return VISIBILITY_DEFAULT; -} - /* Select a set of attributes for section NAME based on the properties of DECL and whether or not RELOC indicates that DECL's initializer might contain runtime relocations. @@ -4860,20 +4584,14 @@ decl_visibility (decl) read-only for a const data decl, and writable for a non-const data decl. */ unsigned int -default_section_type_flags (decl, name, reloc) - tree decl; - const char *name; - int reloc; +default_section_type_flags (tree decl, const char *name, int reloc) { return default_section_type_flags_1 (decl, name, reloc, flag_pic); } unsigned int -default_section_type_flags_1 (decl, name, reloc, shlib) - tree decl; - const char *name; - int reloc; - int shlib; +default_section_type_flags_1 (tree decl, const char *name, int reloc, + int shlib) { unsigned int flags; @@ -4924,9 +4642,8 @@ default_section_type_flags_1 (decl, name, reloc, shlib) Four variants for common object file formats. */ void -default_no_named_section (name, flags) - const char *name ATTRIBUTE_UNUSED; - unsigned int flags ATTRIBUTE_UNUSED; +default_no_named_section (const char *name ATTRIBUTE_UNUSED, + unsigned int flags ATTRIBUTE_UNUSED) { /* Some object formats don't support named sections at all. The front-end should already have flagged this as an error. */ @@ -4934,9 +4651,7 @@ default_no_named_section (name, flags) } void -default_elf_asm_named_section (name, flags) - const char *name; - unsigned int flags; +default_elf_asm_named_section (const char *name, unsigned int flags) { char flagchars[10], *f = flagchars; @@ -4983,9 +4698,7 @@ default_elf_asm_named_section (name, flags) } void -default_coff_asm_named_section (name, flags) - const char *name; - unsigned int flags; +default_coff_asm_named_section (const char *name, unsigned int flags) { char flagchars[8], *f = flagchars; @@ -4999,9 +4712,7 @@ default_coff_asm_named_section (name, flags) } void -default_pe_asm_named_section (name, flags) - const char *name; - unsigned int flags; +default_pe_asm_named_section (const char *name, unsigned int flags) { default_coff_asm_named_section (name, flags); @@ -5015,42 +4726,11 @@ default_pe_asm_named_section (name, flags) } } -/* Used for vtable gc in GNU binutils. Record that the pointer at OFFSET - from SYMBOL is used in all classes derived from SYMBOL. */ - -void -assemble_vtable_entry (symbol, offset) - rtx symbol; - HOST_WIDE_INT offset; -{ - fputs ("\t.vtable_entry ", asm_out_file); - output_addr_const (asm_out_file, symbol); - fputs (", ", asm_out_file); - fprintf (asm_out_file, HOST_WIDE_INT_PRINT_DEC, offset); - fputc ('\n', asm_out_file); -} - -/* Used for vtable gc in GNU binutils. Record the class hierarchy by noting - that the vtable symbol CHILD is derived from the vtable symbol PARENT. */ - -void -assemble_vtable_inherit (child, parent) - rtx child, parent; -{ - fputs ("\t.vtable_inherit ", asm_out_file); - output_addr_const (asm_out_file, child); - fputs (", ", asm_out_file); - output_addr_const (asm_out_file, parent); - fputc ('\n', asm_out_file); -} - /* The lame default section selector. */ void -default_select_section (decl, reloc, align) - tree decl; - int reloc; - unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED; +default_select_section (tree decl, int reloc, + unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED) { bool readonly = false; @@ -5116,13 +4796,10 @@ enum section_category }; static enum section_category -categorize_decl_for_section PARAMS ((tree, int, int)); +categorize_decl_for_section (tree, int, int); static enum section_category -categorize_decl_for_section (decl, reloc, shlib) - tree decl; - int reloc; - int shlib; +categorize_decl_for_section (tree decl, int reloc, int shlib) { enum section_category ret; @@ -5201,18 +4878,13 @@ categorize_decl_for_section (decl, reloc, shlib) } bool -decl_readonly_section (decl, reloc) - tree decl; - int reloc; +decl_readonly_section (tree decl, int reloc) { return decl_readonly_section_1 (decl, reloc, flag_pic); } bool -decl_readonly_section_1 (decl, reloc, shlib) - tree decl; - int reloc; - int shlib; +decl_readonly_section_1 (tree decl, int reloc, int shlib) { switch (categorize_decl_for_section (decl, reloc, shlib)) { @@ -5232,20 +4904,15 @@ decl_readonly_section_1 (decl, reloc, shlib) /* Select a section based on the above categorization. */ void -default_elf_select_section (decl, reloc, align) - tree decl; - int reloc; - unsigned HOST_WIDE_INT align; +default_elf_select_section (tree decl, int reloc, + unsigned HOST_WIDE_INT align) { default_elf_select_section_1 (decl, reloc, align, flag_pic); } void -default_elf_select_section_1 (decl, reloc, align, shlib) - tree decl; - int reloc; - unsigned HOST_WIDE_INT align; - int shlib; +default_elf_select_section_1 (tree decl, int reloc, + unsigned HOST_WIDE_INT align, int shlib) { switch (categorize_decl_for_section (decl, reloc, shlib)) { @@ -5310,18 +4977,13 @@ default_elf_select_section_1 (decl, reloc, align, shlib) categorization performed above. */ void -default_unique_section (decl, reloc) - tree decl; - int reloc; +default_unique_section (tree decl, int reloc) { default_unique_section_1 (decl, reloc, flag_pic); } void -default_unique_section_1 (decl, reloc, shlib) - tree decl; - int reloc; - int shlib; +default_unique_section_1 (tree decl, int reloc, int shlib) { bool one_only = DECL_ONE_ONLY (decl); const char *prefix, *name; @@ -5381,10 +5043,9 @@ default_unique_section_1 (decl, reloc, shlib) } void -default_select_rtx_section (mode, x, align) - enum machine_mode mode ATTRIBUTE_UNUSED; - rtx x; - unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED; +default_select_rtx_section (enum machine_mode mode ATTRIBUTE_UNUSED, + rtx x, + unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED) { if (flag_pic) switch (GET_CODE (x)) @@ -5403,10 +5064,8 @@ default_select_rtx_section (mode, x, align) } void -default_elf_select_rtx_section (mode, x, align) - enum machine_mode mode; - rtx x; - unsigned HOST_WIDE_INT align; +default_elf_select_rtx_section (enum machine_mode mode, rtx x, + unsigned HOST_WIDE_INT align) { /* ??? Handle small data here somehow. */ @@ -5429,12 +5088,44 @@ default_elf_select_rtx_section (mode, x, align) mergeable_constant_section (mode, align, 0); } +/* Set the generally applicable flags on the SYMBOL_REF for EXP. */ + +void +default_encode_section_info (tree decl, rtx rtl, int first ATTRIBUTE_UNUSED) +{ + rtx symbol; + int flags; + + /* Careful not to prod global register variables. */ + if (GET_CODE (rtl) != MEM) + return; + symbol = XEXP (rtl, 0); + if (GET_CODE (symbol) != SYMBOL_REF) + return; + + flags = 0; + if (TREE_CODE (decl) == FUNCTION_DECL) + flags |= SYMBOL_FLAG_FUNCTION; + if ((*targetm.binds_local_p) (decl)) + flags |= SYMBOL_FLAG_LOCAL; + if ((*targetm.in_small_data_p) (decl)) + flags |= SYMBOL_FLAG_SMALL; + if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL (decl)) + flags |= decl_tls_model (decl) << SYMBOL_FLAG_TLS_SHIFT; + /* ??? Why is DECL_EXTERNAL ever set for non-PUBLIC names? Without + being PUBLIC, the thing *must* be defined in this translation unit. + Prevent this buglet from being propagated into rtl code as well. */ + if (DECL_P (decl) && DECL_EXTERNAL (decl) && TREE_PUBLIC (decl)) + flags |= SYMBOL_FLAG_EXTERNAL; + + SYMBOL_REF_FLAGS (symbol) = flags; +} + /* By default, we do nothing for encode_section_info, so we need not do anything but discard the '*' marker. */ const char * -default_strip_name_encoding (str) - const char *str; +default_strip_name_encoding (const char *str) { return str + (*str == '*'); } @@ -5443,16 +5134,13 @@ default_strip_name_encoding (str) wrt cross-module name binding. */ bool -default_binds_local_p (exp) - tree exp; +default_binds_local_p (tree exp) { - return default_binds_local_p_1 (exp, flag_pic); + return default_binds_local_p_1 (exp, flag_shlib); } bool -default_binds_local_p_1 (exp, shlib) - tree exp; - int shlib; +default_binds_local_p_1 (tree exp, int shlib) { bool local_p; @@ -5463,7 +5151,7 @@ default_binds_local_p_1 (exp, shlib) else if (! TREE_PUBLIC (exp)) local_p = true; /* A variable is local if the user tells us so. */ - else if (decl_visibility (exp) != VISIBILITY_DEFAULT) + else if (DECL_VISIBILITY (exp) != VISIBILITY_DEFAULT) local_p = true; /* Otherwise, variables defined outside this object may not be local. */ else if (DECL_EXTERNAL (exp)) @@ -5489,19 +5177,63 @@ default_binds_local_p_1 (exp, shlib) return local_p; } +/* Determine whether or not a pointer mode is valid. Assume defaults + of ptr_mode or Pmode - can be overridden. */ +bool +default_valid_pointer_mode (enum machine_mode mode) +{ + return (mode == ptr_mode || mode == Pmode); +} + /* Default function to output code that will globalize a label. A target must define GLOBAL_ASM_OP or provide it's own function to globalize a label. */ #ifdef GLOBAL_ASM_OP void -default_globalize_label (stream, name) - FILE * stream; - const char *name; +default_globalize_label (FILE * stream, const char *name) { fputs (GLOBAL_ASM_OP, stream); assemble_name (stream, name); putc ('\n', stream); } #endif /* GLOBAL_ASM_OP */ - + +/* This is how to output an internal numbered label where PREFIX is + the class of label and LABELNO is the number within the class. */ + +void +default_internal_label (FILE *stream, const char *prefix, + unsigned long labelno) +{ + char *const buf = alloca (40 + strlen (prefix)); + ASM_GENERATE_INTERNAL_LABEL (buf, prefix, labelno); + ASM_OUTPUT_LABEL (stream, buf); +} + +/* This is the default behavior at the beginning of a file. It's + controlled by two other target-hook toggles. */ +void +default_file_start (void) +{ + if (targetm.file_start_app_off && !flag_verbose_asm) + fputs (ASM_APP_OFF, asm_out_file); + + if (targetm.file_start_file_directive) + output_file_directive (asm_out_file, main_input_filename); +} + +/* This is a generic routine suitable for use as TARGET_ASM_FILE_END + which emits a special section directive used to indicate whether or + not this object file needs an executable stack. This is primarily + a GNU extension to ELF but could be used on other targets. */ +void +file_end_indicate_exec_stack (void) +{ + unsigned int flags = SECTION_DEBUG; + if (trampolines_created) + flags |= SECTION_CODE; + + named_section_flags (".note.GNU-stack", flags); +} + #include "gt-varasm.h" |