varasm.c revision 117395
118334Speter/* Output variables, constants and external declarations, for GNU compiler. 290075Sobrien Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 3117395Skan 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. 418334Speter 590075SobrienThis file is part of GCC. 618334Speter 790075SobrienGCC is free software; you can redistribute it and/or modify it under 890075Sobrienthe terms of the GNU General Public License as published by the Free 990075SobrienSoftware Foundation; either version 2, or (at your option) any later 1090075Sobrienversion. 1118334Speter 1290075SobrienGCC is distributed in the hope that it will be useful, but WITHOUT ANY 1390075SobrienWARRANTY; without even the implied warranty of MERCHANTABILITY or 1490075SobrienFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1590075Sobrienfor more details. 1618334Speter 1718334SpeterYou should have received a copy of the GNU General Public License 1890075Sobrienalong with GCC; see the file COPYING. If not, write to the Free 1990075SobrienSoftware Foundation, 59 Temple Place - Suite 330, Boston, MA 2090075Sobrien02111-1307, USA. */ 2118334Speter 2218334Speter 2318334Speter/* This file handles generation of all the assembler code 2418334Speter *except* the instructions of a function. 2518334Speter This includes declarations of variables and their initial values. 2618334Speter 2718334Speter We also output the assembler code for constants stored in memory 2818334Speter and are responsible for combining constants with the same value. */ 2918334Speter 3050397Sobrien#include "config.h" 3150397Sobrien#include "system.h" 3218334Speter#include "rtl.h" 3318334Speter#include "tree.h" 3418334Speter#include "flags.h" 3518334Speter#include "function.h" 3618334Speter#include "expr.h" 3718334Speter#include "hard-reg-set.h" 3818334Speter#include "regs.h" 39117395Skan#include "real.h" 4090075Sobrien#include "output.h" 4150397Sobrien#include "toplev.h" 4290075Sobrien#include "hashtab.h" 4318334Speter#include "c-pragma.h" 44117395Skan#include "c-tree.h" 4590075Sobrien#include "ggc.h" 4690075Sobrien#include "langhooks.h" 4790075Sobrien#include "tm_p.h" 4890075Sobrien#include "debug.h" 4990075Sobrien#include "target.h" 5018334Speter 5118334Speter#ifdef XCOFF_DEBUGGING_INFO 5290075Sobrien#include "xcoffout.h" /* Needed for external data 5390075Sobrien declarations for e.g. AIX 4.x. */ 5418334Speter#endif 5518334Speter 5650397Sobrien#ifndef TRAMPOLINE_ALIGNMENT 5750397Sobrien#define TRAMPOLINE_ALIGNMENT FUNCTION_BOUNDARY 5850397Sobrien#endif 5918334Speter 6018334Speter#ifndef ASM_STABS_OP 6190075Sobrien#define ASM_STABS_OP "\t.stabs\t" 6218334Speter#endif 6318334Speter 6418334Speter/* The (assembler) name of the first globally-visible object output. */ 6590075Sobrienconst char *first_global_object_name; 6690075Sobrienconst char *weak_global_object_name; 6718334Speter 6890075Sobrienstruct addr_const; 69117395Skanstruct constant_descriptor_rtx; 7090075Sobrienstruct rtx_const; 7190075Sobrienstruct pool_constant; 7290075Sobrien 7390075Sobrien#define MAX_RTX_HASH_TABLE 61 7490075Sobrien 75117395Skanstruct varasm_status GTY(()) 7690075Sobrien{ 7790075Sobrien /* Hash facility for making memory-constants 7890075Sobrien from constant rtl-expressions. It is used on RISC machines 7990075Sobrien where immediate integer arguments and constant addresses are restricted 8090075Sobrien so that such constants must be stored in memory. 8190075Sobrien 8290075Sobrien This pool of constants is reinitialized for each function 8390075Sobrien so each function gets its own constants-pool that comes right before 8490075Sobrien it. */ 85117395Skan struct constant_descriptor_rtx ** GTY ((length ("MAX_RTX_HASH_TABLE"))) 86117395Skan x_const_rtx_hash_table; 87117395Skan struct pool_constant ** GTY ((length ("MAX_RTX_HASH_TABLE"))) 88117395Skan x_const_rtx_sym_hash_table; 8990075Sobrien 9090075Sobrien /* Pointers to first and last constant in pool. */ 91117395Skan struct pool_constant *x_first_pool; 92117395Skan struct pool_constant *x_last_pool; 9390075Sobrien 9490075Sobrien /* Current offset in constant pool (does not include any machine-specific 9590075Sobrien header). */ 9690075Sobrien HOST_WIDE_INT x_pool_offset; 9790075Sobrien}; 9890075Sobrien 9990075Sobrien#define const_rtx_hash_table (cfun->varasm->x_const_rtx_hash_table) 10090075Sobrien#define const_rtx_sym_hash_table (cfun->varasm->x_const_rtx_sym_hash_table) 10190075Sobrien#define first_pool (cfun->varasm->x_first_pool) 10290075Sobrien#define last_pool (cfun->varasm->x_last_pool) 10390075Sobrien#define pool_offset (cfun->varasm->x_pool_offset) 10490075Sobrien 10518334Speter/* Number for making the label on the next 10618334Speter constant that is stored in memory. */ 10718334Speter 10818334Speterint const_labelno; 10918334Speter 11018334Speter/* Number for making the label on the next 11118334Speter static variable internal to a function. */ 11218334Speter 11318334Speterint var_labelno; 11418334Speter 11518334Speter/* Carry information from ASM_DECLARE_OBJECT_NAME 11618334Speter to ASM_FINISH_DECLARE_OBJECT. */ 11718334Speter 11818334Speterint size_directive_output; 11918334Speter 12018334Speter/* The last decl for which assemble_variable was called, 12118334Speter if it did ASM_DECLARE_OBJECT_NAME. 12218334Speter If the last call to assemble_variable didn't do that, 12318334Speter this holds 0. */ 12418334Speter 12518334Spetertree last_assemble_variable_decl; 12618334Speter 12790075Sobrien/* RTX_UNCHANGING_P in a MEM can mean it is stored into, for initialization. 12890075Sobrien So giving constant the alias set for the type will allow such 12990075Sobrien initializations to appear to conflict with the load of the constant. We 13090075Sobrien avoid this by giving all constants an alias set for just constants. 13190075Sobrien Since there will be no stores to that alias set, nothing will ever 13290075Sobrien conflict with them. */ 13318334Speter 13490075Sobrienstatic HOST_WIDE_INT const_alias_set; 13518334Speter 13690075Sobrienstatic const char *strip_reg_name PARAMS ((const char *)); 13790075Sobrienstatic int contains_pointers_p PARAMS ((tree)); 13890075Sobrienstatic void decode_addr_const PARAMS ((tree, struct addr_const *)); 139117395Skanstatic unsigned int const_hash PARAMS ((tree)); 140117395Skanstatic unsigned int const_hash_1 PARAMS ((tree)); 141117395Skanstatic int compare_constant PARAMS ((tree, tree)); 14290075Sobrienstatic tree copy_constant PARAMS ((tree)); 14390075Sobrienstatic void output_constant_def_contents PARAMS ((tree, int, int)); 14490075Sobrienstatic void decode_rtx_const PARAMS ((enum machine_mode, rtx, 14518334Speter struct rtx_const *)); 146117395Skanstatic unsigned int const_hash_rtx PARAMS ((enum machine_mode, rtx)); 147117395Skanstatic int compare_constant_rtx 148117395Skan PARAMS ((enum machine_mode, rtx, struct constant_descriptor_rtx *)); 149117395Skanstatic struct constant_descriptor_rtx * record_constant_rtx 150117395Skan PARAMS ((enum machine_mode, rtx)); 15190075Sobrienstatic struct pool_constant *find_pool_constant PARAMS ((struct function *, rtx)); 15290075Sobrienstatic void mark_constant_pool PARAMS ((void)); 15390075Sobrienstatic void mark_constants PARAMS ((rtx)); 15490075Sobrienstatic int mark_constant PARAMS ((rtx *current_rtx, void *data)); 15590075Sobrienstatic int output_addressed_constants PARAMS ((tree)); 15690075Sobrienstatic void output_after_function_constants PARAMS ((void)); 15790075Sobrienstatic unsigned HOST_WIDE_INT array_size_for_constructor PARAMS ((tree)); 15890075Sobrienstatic unsigned min_align PARAMS ((unsigned, unsigned)); 15990075Sobrienstatic void output_constructor PARAMS ((tree, HOST_WIDE_INT, 16090075Sobrien unsigned int)); 16196263Sobrienstatic void globalize_decl PARAMS ((tree)); 162117395Skanstatic void maybe_assemble_visibility PARAMS ((tree)); 16390075Sobrienstatic int in_named_entry_eq PARAMS ((const PTR, const PTR)); 16490075Sobrienstatic hashval_t in_named_entry_hash PARAMS ((const PTR)); 16550397Sobrien#ifdef ASM_OUTPUT_BSS 16690075Sobrienstatic void asm_output_bss PARAMS ((FILE *, tree, const char *, int, int)); 16750397Sobrien#endif 16850397Sobrien#ifdef BSS_SECTION_ASM_OP 16950397Sobrien#ifdef ASM_OUTPUT_ALIGNED_BSS 17090075Sobrienstatic void asm_output_aligned_bss PARAMS ((FILE *, tree, const char *, 17190075Sobrien int, int)); 17250397Sobrien#endif 17350397Sobrien#endif /* BSS_SECTION_ASM_OP */ 17490075Sobrienstatic hashval_t const_str_htab_hash PARAMS ((const void *x)); 17590075Sobrienstatic int const_str_htab_eq PARAMS ((const void *x, const void *y)); 176117395Skanstatic bool asm_emit_uninitialised PARAMS ((tree, const char*, int, int)); 177102780Skanstatic void resolve_unique_section PARAMS ((tree, int, int)); 17896263Sobrienstatic void mark_weak PARAMS ((tree)); 17918334Speter 18050397Sobrienstatic enum in_section { no_section, in_text, in_data, in_named 18150397Sobrien#ifdef BSS_SECTION_ASM_OP 18250397Sobrien , in_bss 18350397Sobrien#endif 18490075Sobrien#ifdef CTORS_SECTION_ASM_OP 18590075Sobrien , in_ctors 18650397Sobrien#endif 18790075Sobrien#ifdef DTORS_SECTION_ASM_OP 18890075Sobrien , in_dtors 18990075Sobrien#endif 190117395Skan#ifdef READONLY_DATA_SECTION_ASM_OP 191117395Skan , in_readonly_data 192117395Skan#endif 19318334Speter#ifdef EXTRA_SECTIONS 19450397Sobrien , EXTRA_SECTIONS 19518334Speter#endif 19650397Sobrien} in_section = no_section; 19718334Speter 198117395Skan/* Return a nonzero value if DECL has a section attribute. */ 19990075Sobrien#ifndef IN_NAMED_SECTION 20018334Speter#define IN_NAMED_SECTION(DECL) \ 20118334Speter ((TREE_CODE (DECL) == FUNCTION_DECL || TREE_CODE (DECL) == VAR_DECL) \ 20218334Speter && DECL_SECTION_NAME (DECL) != NULL_TREE) 20390075Sobrien#endif 20418334Speter 20518334Speter/* Text of section name when in_section == in_named. */ 20690075Sobrienstatic const char *in_named_name; 20718334Speter 20890075Sobrien/* Hash table of flags that have been used for a particular named section. */ 20990075Sobrien 21090075Sobrienstruct in_named_entry 21190075Sobrien{ 21290075Sobrien const char *name; 21390075Sobrien unsigned int flags; 21490075Sobrien bool declared; 21590075Sobrien}; 21690075Sobrien 21790075Sobrienstatic htab_t in_named_htab; 21890075Sobrien 21918334Speter/* Define functions like text_section for any extra sections. */ 22018334Speter#ifdef EXTRA_SECTION_FUNCTIONS 22118334SpeterEXTRA_SECTION_FUNCTIONS 22218334Speter#endif 22318334Speter 22418334Speter/* Tell assembler to switch to text section. */ 22518334Speter 22618334Spetervoid 22718334Spetertext_section () 22818334Speter{ 22918334Speter if (in_section != in_text) 23018334Speter { 231117395Skan in_section = in_text; 23290075Sobrien#ifdef TEXT_SECTION 23390075Sobrien TEXT_SECTION (); 23490075Sobrien#else 23550397Sobrien fprintf (asm_out_file, "%s\n", TEXT_SECTION_ASM_OP); 23690075Sobrien#endif 23718334Speter } 23818334Speter} 23918334Speter 24018334Speter/* Tell assembler to switch to data section. */ 24118334Speter 24218334Spetervoid 24318334Speterdata_section () 24418334Speter{ 24518334Speter if (in_section != in_data) 24618334Speter { 247117395Skan in_section = in_data; 24850397Sobrien if (flag_shared_data) 24918334Speter { 25018334Speter#ifdef SHARED_SECTION_ASM_OP 25150397Sobrien fprintf (asm_out_file, "%s\n", SHARED_SECTION_ASM_OP); 25218334Speter#else 25350397Sobrien fprintf (asm_out_file, "%s\n", DATA_SECTION_ASM_OP); 25418334Speter#endif 25518334Speter } 25650397Sobrien else 25750397Sobrien fprintf (asm_out_file, "%s\n", DATA_SECTION_ASM_OP); 25818334Speter } 25918334Speter} 260117395Skan 26152284Sobrien/* Tell assembler to ALWAYS switch to data section, in case 26290075Sobrien it's not sure where it is. */ 26318334Speter 26452284Sobrienvoid 26552284Sobrienforce_data_section () 26652284Sobrien{ 26752284Sobrien in_section = no_section; 26852284Sobrien data_section (); 26952284Sobrien} 27052284Sobrien 27118334Speter/* Tell assembler to switch to read-only data section. This is normally 27218334Speter the text section. */ 27318334Speter 27418334Spetervoid 27518334Speterreadonly_data_section () 27618334Speter{ 27718334Speter#ifdef READONLY_DATA_SECTION 27818334Speter READONLY_DATA_SECTION (); /* Note this can call data_section. */ 27918334Speter#else 280117395Skan#ifdef READONLY_DATA_SECTION_ASM_OP 281117395Skan if (in_section != in_readonly_data) 282117395Skan { 283117395Skan in_section = in_readonly_data; 284117395Skan fputs (READONLY_DATA_SECTION_ASM_OP, asm_out_file); 285117395Skan fputc ('\n', asm_out_file); 286117395Skan } 287117395Skan#else 28818334Speter text_section (); 28918334Speter#endif 290117395Skan#endif 29118334Speter} 29218334Speter 29350397Sobrien/* Determine if we're in the text section. */ 29418334Speter 29518334Speterint 29618334Speterin_text_section () 29718334Speter{ 29818334Speter return in_section == in_text; 29918334Speter} 30018334Speter 30150397Sobrien/* Determine if we're in the data section. */ 30250397Sobrien 30350397Sobrienint 30450397Sobrienin_data_section () 30550397Sobrien{ 30650397Sobrien return in_section == in_data; 30750397Sobrien} 30850397Sobrien 30990075Sobrien/* Helper routines for maintaining in_named_htab. */ 31090075Sobrien 31190075Sobrienstatic int 31290075Sobrienin_named_entry_eq (p1, p2) 31390075Sobrien const PTR p1; 31490075Sobrien const PTR p2; 31590075Sobrien{ 31690075Sobrien const struct in_named_entry *old = p1; 31790075Sobrien const char *new = p2; 31890075Sobrien 31990075Sobrien return strcmp (old->name, new) == 0; 32090075Sobrien} 32190075Sobrien 32290075Sobrienstatic hashval_t 32390075Sobrienin_named_entry_hash (p) 32490075Sobrien const PTR p; 32590075Sobrien{ 32690075Sobrien const struct in_named_entry *old = p; 32790075Sobrien return htab_hash_string (old->name); 32890075Sobrien} 32990075Sobrien 33090075Sobrien/* If SECTION has been seen before as a named section, return the flags 33190075Sobrien that were used. Otherwise, return 0. Note, that 0 is a perfectly valid 33290075Sobrien set of flags for a section to have, so 0 does not mean that the section 33390075Sobrien has not been seen. */ 33490075Sobrien 33590075Sobrienunsigned int 33690075Sobrienget_named_section_flags (section) 33790075Sobrien const char *section; 33890075Sobrien{ 33990075Sobrien struct in_named_entry **slot; 34090075Sobrien 341117395Skan slot = (struct in_named_entry **) 34290075Sobrien htab_find_slot_with_hash (in_named_htab, section, 34390075Sobrien htab_hash_string (section), NO_INSERT); 34490075Sobrien 34590075Sobrien return slot ? (*slot)->flags : 0; 34690075Sobrien} 34790075Sobrien 34890075Sobrien/* Returns true if the section has been declared before. Sets internal 349117395Skan flag on this section in in_named_hash so subsequent calls on this 35090075Sobrien section will return false. */ 35190075Sobrien 35290075Sobrienbool 35390075Sobriennamed_section_first_declaration (name) 35490075Sobrien const char *name; 35590075Sobrien{ 35690075Sobrien struct in_named_entry **slot; 35790075Sobrien 358117395Skan slot = (struct in_named_entry **) 359117395Skan htab_find_slot_with_hash (in_named_htab, name, 36090075Sobrien htab_hash_string (name), NO_INSERT); 36190075Sobrien if (! (*slot)->declared) 36290075Sobrien { 36390075Sobrien (*slot)->declared = true; 36490075Sobrien return true; 36590075Sobrien } 366117395Skan else 36790075Sobrien { 36890075Sobrien return false; 36990075Sobrien } 37090075Sobrien} 37190075Sobrien 37290075Sobrien 37390075Sobrien/* Record FLAGS for SECTION. If SECTION was previously recorded with a 37490075Sobrien different set of flags, return false. */ 37590075Sobrien 37690075Sobrienbool 37790075Sobrienset_named_section_flags (section, flags) 37890075Sobrien const char *section; 37990075Sobrien unsigned int flags; 38090075Sobrien{ 38190075Sobrien struct in_named_entry **slot, *entry; 38290075Sobrien 383117395Skan slot = (struct in_named_entry **) 38490075Sobrien htab_find_slot_with_hash (in_named_htab, section, 38590075Sobrien htab_hash_string (section), INSERT); 38690075Sobrien entry = *slot; 38790075Sobrien 38890075Sobrien if (!entry) 38990075Sobrien { 39090075Sobrien entry = (struct in_named_entry *) xmalloc (sizeof (*entry)); 39190075Sobrien *slot = entry; 39290075Sobrien entry->name = ggc_strdup (section); 39390075Sobrien entry->flags = flags; 39490075Sobrien entry->declared = false; 39590075Sobrien } 39690075Sobrien else if (entry->flags != flags) 39790075Sobrien return false; 39890075Sobrien 39990075Sobrien return true; 40090075Sobrien} 40190075Sobrien 40290075Sobrien/* Tell assembler to change to section NAME with attributes FLAGS. */ 40390075Sobrien 40490075Sobrienvoid 40590075Sobriennamed_section_flags (name, flags) 40690075Sobrien const char *name; 40790075Sobrien unsigned int flags; 40890075Sobrien{ 40990075Sobrien if (in_section != in_named || strcmp (name, in_named_name) != 0) 41090075Sobrien { 41190075Sobrien if (! set_named_section_flags (name, flags)) 41290075Sobrien abort (); 41390075Sobrien 414117395Skan (*targetm.asm_out.named_section) (name, flags); 41590075Sobrien 41690075Sobrien if (flags & SECTION_FORGET) 41790075Sobrien in_section = no_section; 41890075Sobrien else 41990075Sobrien { 42090075Sobrien in_named_name = ggc_strdup (name); 42190075Sobrien in_section = in_named; 42290075Sobrien } 42390075Sobrien } 42490075Sobrien} 42590075Sobrien 42618334Speter/* Tell assembler to change to section NAME for DECL. 42718334Speter If DECL is NULL, just switch to section NAME. 42850397Sobrien If NAME is NULL, get the name from DECL. 42950397Sobrien If RELOC is 1, the initializer for DECL contains relocs. */ 43018334Speter 43118334Spetervoid 43250397Sobriennamed_section (decl, name, reloc) 43318334Speter tree decl; 43452284Sobrien const char *name; 43590075Sobrien int reloc; 43618334Speter{ 43790075Sobrien unsigned int flags; 43890075Sobrien 43990075Sobrien if (decl != NULL_TREE && !DECL_P (decl)) 44018334Speter abort (); 44118334Speter if (name == NULL) 44218334Speter name = TREE_STRING_POINTER (DECL_SECTION_NAME (decl)); 44318334Speter 44490075Sobrien flags = (* targetm.section_type_flags) (decl, name, reloc); 44590075Sobrien 44690075Sobrien /* Sanity check user variables for flag changes. Non-user 44796263Sobrien section flag changes will abort in named_section_flags. 44896263Sobrien However, don't complain if SECTION_OVERRIDE is set. 44996263Sobrien We trust that the setter knows that it is safe to ignore 45096263Sobrien the default flags for this decl. */ 45190075Sobrien if (decl && ! set_named_section_flags (name, flags)) 45218334Speter { 45390075Sobrien flags = get_named_section_flags (name); 45496263Sobrien if ((flags & SECTION_OVERRIDE) == 0) 45596263Sobrien error_with_decl (decl, "%s causes a section type conflict"); 45690075Sobrien } 45750397Sobrien 45890075Sobrien named_section_flags (name, flags); 45918334Speter} 46018334Speter 46190075Sobrien/* If required, set DECL_SECTION_NAME to a unique name. */ 46250397Sobrien 46390075Sobrienstatic void 464102780Skanresolve_unique_section (decl, reloc, flag_function_or_data_sections) 46590075Sobrien tree decl; 46690075Sobrien int reloc ATTRIBUTE_UNUSED; 467102780Skan int flag_function_or_data_sections; 46890075Sobrien{ 46990075Sobrien if (DECL_SECTION_NAME (decl) == NULL_TREE 470117395Skan && targetm.have_named_sections 471102780Skan && (flag_function_or_data_sections 472117395Skan || DECL_ONE_ONLY (decl))) 473117395Skan (*targetm.asm_out.unique_section) (decl, reloc); 47490075Sobrien} 47590075Sobrien 47650397Sobrien#ifdef BSS_SECTION_ASM_OP 47750397Sobrien 47850397Sobrien/* Tell the assembler to switch to the bss section. */ 47950397Sobrien 48050397Sobrienvoid 48150397Sobrienbss_section () 48250397Sobrien{ 48350397Sobrien if (in_section != in_bss) 48450397Sobrien { 48550397Sobrien#ifdef SHARED_BSS_SECTION_ASM_OP 48650397Sobrien if (flag_shared_data) 48750397Sobrien fprintf (asm_out_file, "%s\n", SHARED_BSS_SECTION_ASM_OP); 48850397Sobrien else 48950397Sobrien#endif 49050397Sobrien fprintf (asm_out_file, "%s\n", BSS_SECTION_ASM_OP); 49150397Sobrien 49250397Sobrien in_section = in_bss; 49350397Sobrien } 49450397Sobrien} 49550397Sobrien 49650397Sobrien#ifdef ASM_OUTPUT_BSS 49750397Sobrien 49850397Sobrien/* Utility function for ASM_OUTPUT_BSS for targets to use if 49950397Sobrien they don't support alignments in .bss. 50050397Sobrien ??? It is believed that this function will work in most cases so such 50150397Sobrien support is localized here. */ 50250397Sobrien 50350397Sobrienstatic void 50450397Sobrienasm_output_bss (file, decl, name, size, rounded) 50550397Sobrien FILE *file; 50690075Sobrien tree decl ATTRIBUTE_UNUSED; 50790075Sobrien const char *name; 50890075Sobrien int size ATTRIBUTE_UNUSED, rounded; 50950397Sobrien{ 510117395Skan (*targetm.asm_out.globalize_label) (file, name); 51150397Sobrien bss_section (); 51250397Sobrien#ifdef ASM_DECLARE_OBJECT_NAME 51350397Sobrien last_assemble_variable_decl = decl; 51450397Sobrien ASM_DECLARE_OBJECT_NAME (file, name, decl); 51550397Sobrien#else 51650397Sobrien /* Standard thing is just output label for the object. */ 51750397Sobrien ASM_OUTPUT_LABEL (file, name); 51850397Sobrien#endif /* ASM_DECLARE_OBJECT_NAME */ 519102780Skan ASM_OUTPUT_SKIP (file, rounded ? rounded : 1); 52050397Sobrien} 52150397Sobrien 52250397Sobrien#endif 52350397Sobrien 52450397Sobrien#ifdef ASM_OUTPUT_ALIGNED_BSS 52550397Sobrien 52650397Sobrien/* Utility function for targets to use in implementing 52750397Sobrien ASM_OUTPUT_ALIGNED_BSS. 52850397Sobrien ??? It is believed that this function will work in most cases so such 52950397Sobrien support is localized here. */ 53050397Sobrien 53150397Sobrienstatic void 53250397Sobrienasm_output_aligned_bss (file, decl, name, size, align) 53350397Sobrien FILE *file; 53490075Sobrien tree decl ATTRIBUTE_UNUSED; 53590075Sobrien const char *name; 53650397Sobrien int size, align; 53750397Sobrien{ 53850397Sobrien bss_section (); 53950397Sobrien ASM_OUTPUT_ALIGN (file, floor_log2 (align / BITS_PER_UNIT)); 54050397Sobrien#ifdef ASM_DECLARE_OBJECT_NAME 54150397Sobrien last_assemble_variable_decl = decl; 54250397Sobrien ASM_DECLARE_OBJECT_NAME (file, name, decl); 54350397Sobrien#else 54450397Sobrien /* Standard thing is just output label for the object. */ 54550397Sobrien ASM_OUTPUT_LABEL (file, name); 54650397Sobrien#endif /* ASM_DECLARE_OBJECT_NAME */ 54750397Sobrien ASM_OUTPUT_SKIP (file, size ? size : 1); 54850397Sobrien} 54950397Sobrien 55050397Sobrien#endif 55150397Sobrien 55250397Sobrien#endif /* BSS_SECTION_ASM_OP */ 55350397Sobrien 55418334Speter/* Switch to the section for function DECL. 55518334Speter 55618334Speter If DECL is NULL_TREE, switch to the text section. 55718334Speter ??? It's not clear that we will ever be passed NULL_TREE, but it's 55818334Speter safer to handle it. */ 55918334Speter 56018334Spetervoid 56118334Speterfunction_section (decl) 56218334Speter tree decl; 56318334Speter{ 56418334Speter if (decl != NULL_TREE 56518334Speter && DECL_SECTION_NAME (decl) != NULL_TREE) 56650397Sobrien named_section (decl, (char *) 0, 0); 56750397Sobrien else 56850397Sobrien text_section (); 56918334Speter} 57050397Sobrien 571117395Skan/* Switch to section for variable DECL. RELOC is the same as the 572117395Skan argument to SELECT_SECTION. */ 57350397Sobrien 57450397Sobrienvoid 57550397Sobrienvariable_section (decl, reloc) 57650397Sobrien tree decl; 57750397Sobrien int reloc; 57850397Sobrien{ 57950397Sobrien if (IN_NAMED_SECTION (decl)) 58050397Sobrien named_section (decl, NULL, reloc); 58150397Sobrien else 582117395Skan (*targetm.asm_out.select_section) (decl, reloc, DECL_ALIGN (decl)); 58350397Sobrien} 58450397Sobrien 58590075Sobrien/* Tell assembler to switch to the section for string merging. */ 58690075Sobrien 58718334Spetervoid 58890075Sobrienmergeable_string_section (decl, align, flags) 589117395Skan tree decl ATTRIBUTE_UNUSED; 590117395Skan unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED; 591117395Skan unsigned int flags ATTRIBUTE_UNUSED; 59218334Speter{ 59390075Sobrien#ifdef HAVE_GAS_SHF_MERGE 59490075Sobrien if (flag_merge_constants 59590075Sobrien && TREE_CODE (decl) == STRING_CST 59690075Sobrien && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE 59790075Sobrien && align <= 256 59890075Sobrien && TREE_STRING_LENGTH (decl) >= int_size_in_bytes (TREE_TYPE (decl))) 59918334Speter { 60090075Sobrien enum machine_mode mode; 60190075Sobrien unsigned int modesize; 60290075Sobrien const char *str; 60390075Sobrien int i, j, len, unit; 60490075Sobrien char name[30]; 60518334Speter 60690075Sobrien mode = TYPE_MODE (TREE_TYPE (TREE_TYPE (decl))); 60790075Sobrien modesize = GET_MODE_BITSIZE (mode); 60890075Sobrien if (modesize >= 8 && modesize <= 256 60990075Sobrien && (modesize & (modesize - 1)) == 0) 61090075Sobrien { 61190075Sobrien if (align < modesize) 61290075Sobrien align = modesize; 61318334Speter 61490075Sobrien str = TREE_STRING_POINTER (decl); 61590075Sobrien len = TREE_STRING_LENGTH (decl); 61690075Sobrien unit = GET_MODE_SIZE (mode); 61718334Speter 61890075Sobrien /* Check for embedded NUL characters. */ 61990075Sobrien for (i = 0; i < len; i += unit) 62090075Sobrien { 62190075Sobrien for (j = 0; j < unit; j++) 622117395Skan if (str[i + j] != '\0') 62390075Sobrien break; 62490075Sobrien if (j == unit) 62590075Sobrien break; 62690075Sobrien } 62790075Sobrien if (i == len - unit) 62890075Sobrien { 62990075Sobrien sprintf (name, ".rodata.str%d.%d", modesize / 8, 63090075Sobrien (int) (align / 8)); 63190075Sobrien flags |= (modesize / 8) | SECTION_MERGE | SECTION_STRINGS; 63290075Sobrien if (!i && modesize < align) 63390075Sobrien { 63490075Sobrien /* A "" string with requested alignment greater than 63590075Sobrien character size might cause a problem: 63690075Sobrien if some other string required even bigger 63790075Sobrien alignment than "", then linker might think the 63890075Sobrien "" is just part of padding after some other string 63990075Sobrien and not put it into the hash table initially. 64090075Sobrien But this means "" could have smaller alignment 64190075Sobrien than requested. */ 64290075Sobrien#ifdef ASM_OUTPUT_SECTION_START 64390075Sobrien named_section_flags (name, flags); 64490075Sobrien ASM_OUTPUT_SECTION_START (asm_out_file); 64590075Sobrien#else 64690075Sobrien readonly_data_section (); 64718334Speter#endif 64890075Sobrien return; 64990075Sobrien } 65090075Sobrien 65190075Sobrien named_section_flags (name, flags); 65290075Sobrien return; 65390075Sobrien } 65490075Sobrien } 65518334Speter } 65690075Sobrien#endif 65790075Sobrien readonly_data_section (); 658117395Skan} 65990075Sobrien 66090075Sobrien/* Tell assembler to switch to the section for constant merging. */ 66190075Sobrien 66290075Sobrienvoid 66390075Sobrienmergeable_constant_section (mode, align, flags) 664117395Skan enum machine_mode mode ATTRIBUTE_UNUSED; 665117395Skan unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED; 666117395Skan unsigned int flags ATTRIBUTE_UNUSED; 66790075Sobrien{ 66890075Sobrien#ifdef HAVE_GAS_SHF_MERGE 66990075Sobrien unsigned int modesize = GET_MODE_BITSIZE (mode); 67090075Sobrien 67190075Sobrien if (flag_merge_constants 67290075Sobrien && mode != VOIDmode 67390075Sobrien && mode != BLKmode 67490075Sobrien && modesize <= align 67590075Sobrien && align >= 8 67690075Sobrien && align <= 256 67790075Sobrien && (align & (align - 1)) == 0) 67850397Sobrien { 67990075Sobrien char name[24]; 68090075Sobrien 68190075Sobrien sprintf (name, ".rodata.cst%d", (int) (align / 8)); 68290075Sobrien flags |= (align / 8) | SECTION_MERGE; 68390075Sobrien named_section_flags (name, flags); 68490075Sobrien return; 685117395Skan } 68650397Sobrien#endif 68790075Sobrien readonly_data_section (); 68818334Speter} 68990075Sobrien 69018334Speter/* Given NAME, a putative register name, discard any customary prefixes. */ 69118334Speter 69252284Sobrienstatic const char * 69318334Speterstrip_reg_name (name) 694117395Skan const char *name; 69518334Speter{ 69618334Speter#ifdef REGISTER_PREFIX 69718334Speter if (!strncmp (name, REGISTER_PREFIX, strlen (REGISTER_PREFIX))) 69818334Speter name += strlen (REGISTER_PREFIX); 69918334Speter#endif 70018334Speter if (name[0] == '%' || name[0] == '#') 70118334Speter name++; 70218334Speter return name; 70318334Speter} 70418334Speter 70518334Speter/* Decode an `asm' spec for a declaration as a register name. 70618334Speter Return the register number, or -1 if nothing specified, 70718334Speter or -2 if the ASMSPEC is not `cc' or `memory' and is not recognized, 70818334Speter or -3 if ASMSPEC is `cc' and is not recognized, 70918334Speter or -4 if ASMSPEC is `memory' and is not recognized. 71018334Speter Accept an exact spelling or a decimal number. 71118334Speter Prefixes such as % are optional. */ 71218334Speter 71318334Speterint 71418334Speterdecode_reg_name (asmspec) 715117395Skan const char *asmspec; 71618334Speter{ 71718334Speter if (asmspec != 0) 71818334Speter { 71918334Speter int i; 72018334Speter 72118334Speter /* Get rid of confusing prefixes. */ 72218334Speter asmspec = strip_reg_name (asmspec); 72390075Sobrien 72418334Speter /* Allow a decimal number as a "register name". */ 72518334Speter for (i = strlen (asmspec) - 1; i >= 0; i--) 72690075Sobrien if (! ISDIGIT (asmspec[i])) 72718334Speter break; 72818334Speter if (asmspec[0] != 0 && i < 0) 72918334Speter { 73018334Speter i = atoi (asmspec); 73118334Speter if (i < FIRST_PSEUDO_REGISTER && i >= 0) 73218334Speter return i; 73318334Speter else 73418334Speter return -2; 73518334Speter } 73618334Speter 73718334Speter for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) 73818334Speter if (reg_names[i][0] 73918334Speter && ! strcmp (asmspec, strip_reg_name (reg_names[i]))) 74018334Speter return i; 74118334Speter 74218334Speter#ifdef ADDITIONAL_REGISTER_NAMES 74318334Speter { 74490075Sobrien static const struct { const char *const name; const int number; } table[] 74518334Speter = ADDITIONAL_REGISTER_NAMES; 74618334Speter 74790075Sobrien for (i = 0; i < (int) ARRAY_SIZE (table); i++) 74818334Speter if (! strcmp (asmspec, table[i].name)) 74918334Speter return table[i].number; 75018334Speter } 75118334Speter#endif /* ADDITIONAL_REGISTER_NAMES */ 75218334Speter 75318334Speter if (!strcmp (asmspec, "memory")) 75418334Speter return -4; 75518334Speter 75618334Speter if (!strcmp (asmspec, "cc")) 75718334Speter return -3; 75818334Speter 75918334Speter return -2; 76018334Speter } 76118334Speter 76218334Speter return -1; 76318334Speter} 76418334Speter 76590075Sobrien/* Create the DECL_RTL for a VAR_DECL or FUNCTION_DECL. DECL should 76690075Sobrien have static storage duration. In other words, it should not be an 76790075Sobrien automatic variable, including PARM_DECLs. 76818334Speter 76990075Sobrien There is, however, one exception: this function handles variables 77090075Sobrien explicitly placed in a particular register by the user. 77190075Sobrien 77290075Sobrien ASMSPEC, if not 0, is the string which the user specified as the 77390075Sobrien assembler symbol name. 77490075Sobrien 77518334Speter This is never called for PARM_DECL nodes. */ 77618334Speter 77718334Spetervoid 77890075Sobrienmake_decl_rtl (decl, asmspec) 77918334Speter tree decl; 78052284Sobrien const char *asmspec; 78118334Speter{ 78290075Sobrien int top_level = (DECL_CONTEXT (decl) == NULL_TREE); 78390075Sobrien const char *name = 0; 78490075Sobrien const char *new_name = 0; 78518334Speter int reg_number; 78690075Sobrien rtx x; 78718334Speter 78890075Sobrien /* Check that we are not being given an automatic variable. */ 78990075Sobrien /* A weak alias has TREE_PUBLIC set but not the other bits. */ 79090075Sobrien if (TREE_CODE (decl) == PARM_DECL 79190075Sobrien || TREE_CODE (decl) == RESULT_DECL 79290075Sobrien || (TREE_CODE (decl) == VAR_DECL 79390075Sobrien && !TREE_STATIC (decl) 79490075Sobrien && !TREE_PUBLIC (decl) 79590075Sobrien && !DECL_EXTERNAL (decl) 79690075Sobrien && !DECL_REGISTER (decl))) 79790075Sobrien abort (); 79890075Sobrien /* And that we were not given a type or a label. */ 79990075Sobrien else if (TREE_CODE (decl) == TYPE_DECL 80090075Sobrien || TREE_CODE (decl) == LABEL_DECL) 80190075Sobrien abort (); 80218334Speter 80390075Sobrien /* For a duplicate declaration, we can be called twice on the 80490075Sobrien same DECL node. Don't discard the RTL already made. */ 80590075Sobrien if (DECL_RTL_SET_P (decl)) 80690075Sobrien { 80790075Sobrien /* If the old RTL had the wrong mode, fix the mode. */ 80890075Sobrien if (GET_MODE (DECL_RTL (decl)) != DECL_MODE (decl)) 80990075Sobrien SET_DECL_RTL (decl, adjust_address_nv (DECL_RTL (decl), 81090075Sobrien DECL_MODE (decl), 0)); 81118334Speter 812117395Skan /* ??? Another way to do this would be to maintain a hashed 813117395Skan table of such critters. Instead of adding stuff to a DECL 814117395Skan to give certain attributes to it, we could use an external 815117395Skan hash map from DECL to set of attributes. */ 816117395Skan 81790075Sobrien /* Let the target reassign the RTL if it wants. 81890075Sobrien This is necessary, for example, when one machine specific 81990075Sobrien decl attribute overrides another. */ 820117395Skan (* targetm.encode_section_info) (decl, false); 82190075Sobrien return; 82290075Sobrien } 82390075Sobrien 82490075Sobrien new_name = name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); 82590075Sobrien 82690075Sobrien reg_number = decode_reg_name (asmspec); 82718334Speter if (reg_number == -2) 82818334Speter { 82990075Sobrien /* ASMSPEC is given, and not the name of a register. Mark the 83090075Sobrien name with a star so assemble_name won't munge it. */ 83190075Sobrien char *starred = alloca (strlen (asmspec) + 2); 83290075Sobrien starred[0] = '*'; 83390075Sobrien strcpy (starred + 1, asmspec); 83490075Sobrien new_name = starred; 83518334Speter } 83618334Speter 83790075Sobrien if (TREE_CODE (decl) != FUNCTION_DECL && DECL_REGISTER (decl)) 83818334Speter { 83918334Speter /* First detect errors in declaring global registers. */ 84090075Sobrien if (reg_number == -1) 84190075Sobrien error_with_decl (decl, "register name not specified for `%s'"); 84290075Sobrien else if (reg_number < 0) 84390075Sobrien error_with_decl (decl, "invalid register name for `%s'"); 84490075Sobrien else if (TYPE_MODE (TREE_TYPE (decl)) == BLKmode) 84518334Speter error_with_decl (decl, 84650397Sobrien "data type of `%s' isn't suitable for a register"); 84790075Sobrien else if (! HARD_REGNO_MODE_OK (reg_number, TYPE_MODE (TREE_TYPE (decl)))) 84850397Sobrien error_with_decl (decl, 84990075Sobrien "register specified for `%s' isn't suitable for data type"); 85018334Speter /* Now handle properly declared static register variables. */ 85190075Sobrien else 85218334Speter { 85318334Speter int nregs; 85450397Sobrien 85590075Sobrien if (DECL_INITIAL (decl) != 0 && TREE_STATIC (decl)) 85618334Speter { 85718334Speter DECL_INITIAL (decl) = 0; 85818334Speter error ("global register variable has initial value"); 85918334Speter } 86018334Speter if (TREE_THIS_VOLATILE (decl)) 86118334Speter warning ("volatile register variables don't work as you might wish"); 86218334Speter 86318334Speter /* If the user specified one of the eliminables registers here, 86418334Speter e.g., FRAME_POINTER_REGNUM, we don't want to get this variable 86590075Sobrien confused with that register and be eliminated. This usage is 86690075Sobrien somewhat suspect... */ 86718334Speter 86890075Sobrien SET_DECL_RTL (decl, gen_rtx_raw_REG (DECL_MODE (decl), reg_number)); 86990075Sobrien ORIGINAL_REGNO (DECL_RTL (decl)) = reg_number; 87018334Speter REG_USERVAR_P (DECL_RTL (decl)) = 1; 87118334Speter 87290075Sobrien if (TREE_STATIC (decl)) 87318334Speter { 87418334Speter /* Make this register global, so not usable for anything 87518334Speter else. */ 87690075Sobrien#ifdef ASM_DECLARE_REGISTER_GLOBAL 87790075Sobrien ASM_DECLARE_REGISTER_GLOBAL (asm_out_file, decl, reg_number, name); 87890075Sobrien#endif 87918334Speter nregs = HARD_REGNO_NREGS (reg_number, DECL_MODE (decl)); 88018334Speter while (nregs > 0) 88118334Speter globalize_reg (reg_number + --nregs); 88218334Speter } 88390075Sobrien 88490075Sobrien /* As a register variable, it has no section. */ 88590075Sobrien return; 88618334Speter } 88790075Sobrien } 88818334Speter 88990075Sobrien /* Now handle ordinary static variables and functions (in memory). 89090075Sobrien Also handle vars declared register invalidly. */ 89118334Speter 89290075Sobrien if (reg_number >= 0 || reg_number == -3) 89390075Sobrien error_with_decl (decl, 89490075Sobrien "register name given for non-register variable `%s'"); 89518334Speter 89690075Sobrien /* Specifying a section attribute on a variable forces it into a 89790075Sobrien non-.bss section, and thus it cannot be common. */ 89890075Sobrien if (TREE_CODE (decl) == VAR_DECL 89990075Sobrien && DECL_SECTION_NAME (decl) != NULL_TREE 90090075Sobrien && DECL_INITIAL (decl) == NULL_TREE 90190075Sobrien && DECL_COMMON (decl)) 90290075Sobrien DECL_COMMON (decl) = 0; 90318334Speter 904117395Skan /* Variables can't be both common and weak. */ 905117395Skan if (TREE_CODE (decl) == VAR_DECL && DECL_WEAK (decl)) 906117395Skan DECL_COMMON (decl) = 0; 907117395Skan 90890075Sobrien /* Can't use just the variable's own name for a variable 90990075Sobrien whose scope is less than the whole file, unless it's a member 91090075Sobrien of a local class (which will already be unambiguous). 91190075Sobrien Concatenate a distinguishing number. */ 91290075Sobrien if (!top_level && !TREE_PUBLIC (decl) 91390075Sobrien && ! (DECL_CONTEXT (decl) && TYPE_P (DECL_CONTEXT (decl))) 91490075Sobrien && asmspec == 0 91590075Sobrien && name == IDENTIFIER_POINTER (DECL_NAME (decl))) 91690075Sobrien { 91790075Sobrien char *label; 91818334Speter 91990075Sobrien ASM_FORMAT_PRIVATE_NAME (label, name, var_labelno); 92090075Sobrien var_labelno++; 92190075Sobrien new_name = label; 92290075Sobrien } 92352284Sobrien 92490075Sobrien if (name != new_name) 92590075Sobrien { 92690075Sobrien SET_DECL_ASSEMBLER_NAME (decl, get_identifier (new_name)); 92790075Sobrien name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); 92890075Sobrien } 92918334Speter 93090075Sobrien /* If this variable is to be treated as volatile, show its 93190075Sobrien tree node has side effects. */ 93290075Sobrien if ((flag_volatile_global && TREE_CODE (decl) == VAR_DECL 93390075Sobrien && TREE_PUBLIC (decl)) 93490075Sobrien || ((flag_volatile_static && TREE_CODE (decl) == VAR_DECL 93590075Sobrien && (TREE_PUBLIC (decl) || TREE_STATIC (decl))))) 93690075Sobrien TREE_SIDE_EFFECTS (decl) = 1; 93718334Speter 93890075Sobrien x = gen_rtx_MEM (DECL_MODE (decl), gen_rtx_SYMBOL_REF (Pmode, name)); 93990075Sobrien SYMBOL_REF_WEAK (XEXP (x, 0)) = DECL_WEAK (decl); 94090075Sobrien if (TREE_CODE (decl) != FUNCTION_DECL) 94190075Sobrien set_mem_attributes (x, decl, 1); 94290075Sobrien SET_DECL_RTL (decl, x); 94390075Sobrien 94490075Sobrien /* Optionally set flags or add text to the name to record information 94590075Sobrien such as that it is a function name. 94690075Sobrien If the name is changed, the macro ASM_OUTPUT_LABELREF 94790075Sobrien will have to know how to strip this information. */ 948117395Skan (* targetm.encode_section_info) (decl, true); 94918334Speter} 95018334Speter 95118334Speter/* Make the rtl for variable VAR be volatile. 95218334Speter Use this only for static variables. */ 95318334Speter 95418334Spetervoid 95518334Spetermake_var_volatile (var) 95618334Speter tree var; 95718334Speter{ 95818334Speter if (GET_CODE (DECL_RTL (var)) != MEM) 95918334Speter abort (); 96018334Speter 96118334Speter MEM_VOLATILE_P (DECL_RTL (var)) = 1; 96218334Speter} 96318334Speter 96418334Speter/* Output alignment directive to align for constant expression EXP. */ 96518334Speter 96618334Spetervoid 96718334Speterassemble_constant_align (exp) 96818334Speter tree exp; 96918334Speter{ 97018334Speter int align; 97118334Speter 97218334Speter /* Align the location counter as required by EXP's data type. */ 97318334Speter align = TYPE_ALIGN (TREE_TYPE (exp)); 97418334Speter#ifdef CONSTANT_ALIGNMENT 97518334Speter align = CONSTANT_ALIGNMENT (exp, align); 97618334Speter#endif 97718334Speter 97818334Speter if (align > BITS_PER_UNIT) 97990075Sobrien { 98090075Sobrien ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (align / BITS_PER_UNIT)); 98190075Sobrien } 98218334Speter} 98318334Speter 98418334Speter/* Output a string of literal assembler code 98518334Speter for an `asm' keyword used between functions. */ 98618334Speter 98718334Spetervoid 98818334Speterassemble_asm (string) 98918334Speter tree string; 99018334Speter{ 99118334Speter app_enable (); 99218334Speter 99318334Speter if (TREE_CODE (string) == ADDR_EXPR) 99418334Speter string = TREE_OPERAND (string, 0); 99518334Speter 99618334Speter fprintf (asm_out_file, "\t%s\n", TREE_STRING_POINTER (string)); 99718334Speter} 99818334Speter 99990075Sobrien/* Record an element in the table of global destructors. SYMBOL is 100090075Sobrien a SYMBOL_REF of the function to be called; PRIORITY is a number 100190075Sobrien between 0 and MAX_INIT_PRIORITY. */ 100218334Speter 100390075Sobrienvoid 100490075Sobriendefault_stabs_asm_out_destructor (symbol, priority) 100590075Sobrien rtx symbol; 100690075Sobrien int priority ATTRIBUTE_UNUSED; 100790075Sobrien{ 100890075Sobrien /* Tell GNU LD that this is part of the static destructor set. 100990075Sobrien This will work for any system that uses stabs, most usefully 101090075Sobrien aout systems. */ 101190075Sobrien fprintf (asm_out_file, "%s\"___DTOR_LIST__\",22,0,0,", ASM_STABS_OP); 101290075Sobrien assemble_name (asm_out_file, XSTR (symbol, 0)); 101390075Sobrien fputc ('\n', asm_out_file); 101490075Sobrien} 101518334Speter 101690075Sobrienvoid 101790075Sobriendefault_named_section_asm_out_destructor (symbol, priority) 101890075Sobrien rtx symbol; 101990075Sobrien int priority; 102090075Sobrien{ 102190075Sobrien const char *section = ".dtors"; 102290075Sobrien char buf[16]; 102318334Speter 102490075Sobrien /* ??? This only works reliably with the GNU linker. */ 102590075Sobrien if (priority != DEFAULT_INIT_PRIORITY) 102690075Sobrien { 102790075Sobrien sprintf (buf, ".dtors.%.5u", 102890075Sobrien /* Invert the numbering so the linker puts us in the proper 102990075Sobrien order; constructors are run from right to left, and the 103090075Sobrien linker sorts in increasing order. */ 103190075Sobrien MAX_INIT_PRIORITY - priority); 103290075Sobrien section = buf; 103390075Sobrien } 103490075Sobrien 103590075Sobrien named_section_flags (section, SECTION_WRITE); 103690075Sobrien assemble_align (POINTER_SIZE); 103790075Sobrien assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1); 103890075Sobrien} 103990075Sobrien 104090075Sobrien#ifdef DTORS_SECTION_ASM_OP 104118334Spetervoid 104290075Sobriendtors_section () 104318334Speter{ 104490075Sobrien if (in_section != in_dtors) 104518334Speter { 104690075Sobrien in_section = in_dtors; 104790075Sobrien fputs (DTORS_SECTION_ASM_OP, asm_out_file); 104818334Speter fputc ('\n', asm_out_file); 104918334Speter } 105018334Speter} 105118334Speter 105290075Sobrienvoid 105390075Sobriendefault_dtor_section_asm_out_destructor (symbol, priority) 105490075Sobrien rtx symbol; 105590075Sobrien int priority ATTRIBUTE_UNUSED; 105690075Sobrien{ 105790075Sobrien dtors_section (); 105890075Sobrien assemble_align (POINTER_SIZE); 105990075Sobrien assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1); 106090075Sobrien} 106190075Sobrien#endif 106290075Sobrien 106318334Speter/* Likewise for global constructors. */ 106418334Speter 106518334Spetervoid 106690075Sobriendefault_stabs_asm_out_constructor (symbol, priority) 106790075Sobrien rtx symbol; 106890075Sobrien int priority ATTRIBUTE_UNUSED; 106918334Speter{ 107090075Sobrien /* Tell GNU LD that this is part of the static destructor set. 107190075Sobrien This will work for any system that uses stabs, most usefully 107290075Sobrien aout systems. */ 107390075Sobrien fprintf (asm_out_file, "%s\"___CTOR_LIST__\",22,0,0,", ASM_STABS_OP); 107490075Sobrien assemble_name (asm_out_file, XSTR (symbol, 0)); 107590075Sobrien fputc ('\n', asm_out_file); 107690075Sobrien} 107790075Sobrien 107890075Sobrienvoid 107990075Sobriendefault_named_section_asm_out_constructor (symbol, priority) 108090075Sobrien rtx symbol; 108190075Sobrien int priority; 108290075Sobrien{ 108390075Sobrien const char *section = ".ctors"; 108490075Sobrien char buf[16]; 108590075Sobrien 108690075Sobrien /* ??? This only works reliably with the GNU linker. */ 108790075Sobrien if (priority != DEFAULT_INIT_PRIORITY) 108818334Speter { 108990075Sobrien sprintf (buf, ".ctors.%.5u", 109090075Sobrien /* Invert the numbering so the linker puts us in the proper 109190075Sobrien order; constructors are run from right to left, and the 109290075Sobrien linker sorts in increasing order. */ 109390075Sobrien MAX_INIT_PRIORITY - priority); 109490075Sobrien section = buf; 109518334Speter } 109690075Sobrien 109790075Sobrien named_section_flags (section, SECTION_WRITE); 109890075Sobrien assemble_align (POINTER_SIZE); 109990075Sobrien assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1); 110018334Speter} 110118334Speter 110290075Sobrien#ifdef CTORS_SECTION_ASM_OP 110318334Spetervoid 110490075Sobrienctors_section () 110518334Speter{ 110690075Sobrien if (in_section != in_ctors) 110718334Speter { 110890075Sobrien in_section = in_ctors; 110990075Sobrien fputs (CTORS_SECTION_ASM_OP, asm_out_file); 111018334Speter fputc ('\n', asm_out_file); 111118334Speter } 111290075Sobrien} 111390075Sobrien 111490075Sobrienvoid 111590075Sobriendefault_ctor_section_asm_out_constructor (symbol, priority) 111690075Sobrien rtx symbol; 111790075Sobrien int priority ATTRIBUTE_UNUSED; 111890075Sobrien{ 111990075Sobrien ctors_section (); 112090075Sobrien assemble_align (POINTER_SIZE); 112190075Sobrien assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1); 112290075Sobrien} 112318334Speter#endif 112418334Speter 112550397Sobrien/* CONSTANT_POOL_BEFORE_FUNCTION may be defined as an expression with 1126117395Skan a nonzero value if the constant pool should be output before the 112750397Sobrien start of the function, or a zero value if the pool should output 112850397Sobrien after the end of the function. The default is to put it before the 112950397Sobrien start. */ 113050397Sobrien 113150397Sobrien#ifndef CONSTANT_POOL_BEFORE_FUNCTION 113250397Sobrien#define CONSTANT_POOL_BEFORE_FUNCTION 1 113350397Sobrien#endif 113450397Sobrien 113518334Speter/* Output assembler code for the constant pool of a function and associated 113618334Speter with defining the name of the function. DECL describes the function. 113718334Speter NAME is the function's name. For the constant pool, we use the current 113818334Speter constant pool data. */ 113918334Speter 114018334Spetervoid 114118334Speterassemble_start_function (decl, fnname) 114218334Speter tree decl; 114390075Sobrien const char *fnname; 114418334Speter{ 114518334Speter int align; 114618334Speter 114718334Speter /* The following code does not need preprocessing in the assembler. */ 114818334Speter 114918334Speter app_disable (); 115018334Speter 115150397Sobrien if (CONSTANT_POOL_BEFORE_FUNCTION) 115250397Sobrien output_constant_pool (fnname, decl); 115318334Speter 1154102780Skan resolve_unique_section (decl, 0, flag_function_sections); 115518334Speter function_section (decl); 115618334Speter 115718334Speter /* Tell assembler to move to target machine's alignment for functions. */ 115818334Speter align = floor_log2 (FUNCTION_BOUNDARY / BITS_PER_UNIT); 1159104752Skan if (align < force_align_functions_log) 1160104752Skan align = force_align_functions_log; 116118334Speter if (align > 0) 116290075Sobrien { 116390075Sobrien ASM_OUTPUT_ALIGN (asm_out_file, align); 116490075Sobrien } 116518334Speter 116690075Sobrien /* Handle a user-specified function alignment. 116790075Sobrien Note that we still need to align to FUNCTION_BOUNDARY, as above, 116890075Sobrien because ASM_OUTPUT_MAX_SKIP_ALIGN might not do any alignment at all. */ 1169117395Skan if (align_functions_log > align 1170117395Skan && cfun->function_frequency != FUNCTION_FREQUENCY_UNLIKELY_EXECUTED) 117190075Sobrien { 117290075Sobrien#ifdef ASM_OUTPUT_MAX_SKIP_ALIGN 117390075Sobrien ASM_OUTPUT_MAX_SKIP_ALIGN (asm_out_file, 1174117395Skan align_functions_log, align_functions - 1); 117590075Sobrien#else 117690075Sobrien ASM_OUTPUT_ALIGN (asm_out_file, align_functions_log); 117790075Sobrien#endif 117890075Sobrien } 117990075Sobrien 118018334Speter#ifdef ASM_OUTPUT_FUNCTION_PREFIX 118118334Speter ASM_OUTPUT_FUNCTION_PREFIX (asm_out_file, fnname); 118218334Speter#endif 118318334Speter 118490075Sobrien (*debug_hooks->begin_function) (decl); 118518334Speter 118618334Speter /* Make function name accessible from other files, if appropriate. */ 118718334Speter 118818334Speter if (TREE_PUBLIC (decl)) 118918334Speter { 119050397Sobrien if (! first_global_object_name) 119118334Speter { 119290075Sobrien const char *p; 119390075Sobrien char *name; 119418334Speter 1195117395Skan p = (* targetm.strip_name_encoding) (fnname); 1196117395Skan name = xstrdup (p); 119790075Sobrien 119850397Sobrien if (! DECL_WEAK (decl) && ! DECL_ONE_ONLY (decl)) 119990075Sobrien first_global_object_name = name; 120050397Sobrien else 120190075Sobrien weak_global_object_name = name; 120218334Speter } 120318334Speter 120496263Sobrien globalize_decl (decl); 1205117395Skan 1206117395Skan maybe_assemble_visibility (decl); 120718334Speter } 120818334Speter 120918334Speter /* Do any machine/system dependent processing of the function name */ 121018334Speter#ifdef ASM_DECLARE_FUNCTION_NAME 121118334Speter ASM_DECLARE_FUNCTION_NAME (asm_out_file, fnname, current_function_decl); 121218334Speter#else 121318334Speter /* Standard thing is just output label for the function. */ 121450397Sobrien ASM_OUTPUT_LABEL (asm_out_file, fnname); 121518334Speter#endif /* ASM_DECLARE_FUNCTION_NAME */ 121618334Speter} 121718334Speter 121818334Speter/* Output assembler code associated with defining the size of the 121918334Speter function. DECL describes the function. NAME is the function's name. */ 122018334Speter 122118334Spetervoid 122218334Speterassemble_end_function (decl, fnname) 122318334Speter tree decl; 122490075Sobrien const char *fnname; 122518334Speter{ 122618334Speter#ifdef ASM_DECLARE_FUNCTION_SIZE 122718334Speter ASM_DECLARE_FUNCTION_SIZE (asm_out_file, fnname, decl); 122818334Speter#endif 122950397Sobrien if (! CONSTANT_POOL_BEFORE_FUNCTION) 123050397Sobrien { 123150397Sobrien output_constant_pool (fnname, decl); 123250397Sobrien function_section (decl); /* need to switch back */ 123350397Sobrien } 123450397Sobrien 123550397Sobrien /* Output any constants which should appear after the function. */ 123650397Sobrien output_after_function_constants (); 123718334Speter} 123818334Speter 123918334Speter/* Assemble code to leave SIZE bytes of zeros. */ 124018334Speter 124118334Spetervoid 124218334Speterassemble_zeros (size) 124318334Speter int size; 124418334Speter{ 124552284Sobrien /* Do no output if -fsyntax-only. */ 124652284Sobrien if (flag_syntax_only) 124752284Sobrien return; 124852284Sobrien 124918334Speter#ifdef ASM_NO_SKIP_IN_TEXT 125018334Speter /* The `space' pseudo in the text section outputs nop insns rather than 0s, 125118334Speter so we must output 0s explicitly in the text section. */ 125218334Speter if (ASM_NO_SKIP_IN_TEXT && in_text_section ()) 125318334Speter { 125418334Speter int i; 125590075Sobrien for (i = 0; i < size; i++) 125690075Sobrien assemble_integer (const0_rtx, 1, BITS_PER_UNIT, 1); 125718334Speter } 125818334Speter else 125918334Speter#endif 126018334Speter if (size > 0) 126150397Sobrien ASM_OUTPUT_SKIP (asm_out_file, size); 126218334Speter} 126318334Speter 126418334Speter/* Assemble an alignment pseudo op for an ALIGN-bit boundary. */ 126518334Speter 126618334Spetervoid 126718334Speterassemble_align (align) 126818334Speter int align; 126918334Speter{ 127018334Speter if (align > BITS_PER_UNIT) 127190075Sobrien { 127290075Sobrien ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (align / BITS_PER_UNIT)); 127390075Sobrien } 127418334Speter} 127518334Speter 127618334Speter/* Assemble a string constant with the specified C string as contents. */ 127718334Speter 127818334Spetervoid 127918334Speterassemble_string (p, size) 128052284Sobrien const char *p; 128118334Speter int size; 128218334Speter{ 128318334Speter int pos = 0; 128418334Speter int maximum = 2000; 128518334Speter 128618334Speter /* If the string is very long, split it up. */ 128718334Speter 128818334Speter while (pos < size) 128918334Speter { 129018334Speter int thissize = size - pos; 129118334Speter if (thissize > maximum) 129218334Speter thissize = maximum; 129318334Speter 129450397Sobrien ASM_OUTPUT_ASCII (asm_out_file, p, thissize); 129518334Speter 129618334Speter pos += thissize; 129718334Speter p += thissize; 129818334Speter } 129918334Speter} 130018334Speter 130118334Speter 130290075Sobrien#if defined ASM_OUTPUT_ALIGNED_DECL_LOCAL 130390075Sobrien#define ASM_EMIT_LOCAL(decl, name, size, rounded) \ 130490075Sobrien ASM_OUTPUT_ALIGNED_DECL_LOCAL (asm_out_file, decl, name, size, DECL_ALIGN (decl)) 130590075Sobrien#else 130690075Sobrien#if defined ASM_OUTPUT_ALIGNED_LOCAL 130790075Sobrien#define ASM_EMIT_LOCAL(decl, name, size, rounded) \ 130890075Sobrien ASM_OUTPUT_ALIGNED_LOCAL (asm_out_file, name, size, DECL_ALIGN (decl)) 130990075Sobrien#else 131090075Sobrien#define ASM_EMIT_LOCAL(decl, name, size, rounded) \ 131190075Sobrien ASM_OUTPUT_LOCAL (asm_out_file, name, size, rounded) 131290075Sobrien#endif 131390075Sobrien#endif 131490075Sobrien 131590075Sobrien#if defined ASM_OUTPUT_ALIGNED_BSS 131690075Sobrien#define ASM_EMIT_BSS(decl, name, size, rounded) \ 131790075Sobrien ASM_OUTPUT_ALIGNED_BSS (asm_out_file, decl, name, size, DECL_ALIGN (decl)) 131890075Sobrien#else 131990075Sobrien#if defined ASM_OUTPUT_BSS 132090075Sobrien#define ASM_EMIT_BSS(decl, name, size, rounded) \ 132190075Sobrien ASM_OUTPUT_BSS (asm_out_file, decl, name, size, rounded) 132290075Sobrien#else 132390075Sobrien#undef ASM_EMIT_BSS 132490075Sobrien#endif 132590075Sobrien#endif 132690075Sobrien 132790075Sobrien#if defined ASM_OUTPUT_ALIGNED_DECL_COMMON 132890075Sobrien#define ASM_EMIT_COMMON(decl, name, size, rounded) \ 132990075Sobrien ASM_OUTPUT_ALIGNED_DECL_COMMON (asm_out_file, decl, name, size, DECL_ALIGN (decl)) 133090075Sobrien#else 133190075Sobrien#if defined ASM_OUTPUT_ALIGNED_COMMON 133290075Sobrien#define ASM_EMIT_COMMON(decl, name, size, rounded) \ 133390075Sobrien ASM_OUTPUT_ALIGNED_COMMON (asm_out_file, name, size, DECL_ALIGN (decl)) 133490075Sobrien#else 133590075Sobrien#define ASM_EMIT_COMMON(decl, name, size, rounded) \ 133690075Sobrien ASM_OUTPUT_COMMON (asm_out_file, name, size, rounded) 133790075Sobrien#endif 133890075Sobrien#endif 133990075Sobrien 1340117395Skanstatic bool 134190075Sobrienasm_emit_uninitialised (decl, name, size, rounded) 134290075Sobrien tree decl; 1343117395Skan const char *name; 134490075Sobrien int size ATTRIBUTE_UNUSED; 134590075Sobrien int rounded ATTRIBUTE_UNUSED; 134690075Sobrien{ 134790075Sobrien enum 134890075Sobrien { 134990075Sobrien asm_dest_common, 135090075Sobrien asm_dest_bss, 135190075Sobrien asm_dest_local 135290075Sobrien } 135390075Sobrien destination = asm_dest_local; 135490075Sobrien 1355117395Skan /* ??? We should handle .bss via select_section mechanisms rather than 1356117395Skan via special target hooks. That would eliminate this special case. */ 135790075Sobrien if (TREE_PUBLIC (decl)) 135890075Sobrien { 1359117395Skan if (!DECL_COMMON (decl)) 1360117395Skan#ifdef ASM_EMIT_BSS 136190075Sobrien destination = asm_dest_bss; 1362117395Skan#else 1363117395Skan return false; 1364117395Skan#endif 136590075Sobrien else 136690075Sobrien destination = asm_dest_common; 136790075Sobrien } 136890075Sobrien 136996263Sobrien if (destination == asm_dest_bss) 137096263Sobrien globalize_decl (decl); 1371102780Skan resolve_unique_section (decl, 0, flag_data_sections); 137296263Sobrien 137390075Sobrien if (flag_shared_data) 137490075Sobrien { 137590075Sobrien switch (destination) 137690075Sobrien { 137790075Sobrien#ifdef ASM_OUTPUT_SHARED_BSS 137890075Sobrien case asm_dest_bss: 137990075Sobrien ASM_OUTPUT_SHARED_BSS (asm_out_file, decl, name, size, rounded); 138090075Sobrien return; 138190075Sobrien#endif 138290075Sobrien#ifdef ASM_OUTPUT_SHARED_COMMON 138390075Sobrien case asm_dest_common: 138490075Sobrien ASM_OUTPUT_SHARED_COMMON (asm_out_file, name, size, rounded); 138590075Sobrien return; 138690075Sobrien#endif 138790075Sobrien#ifdef ASM_OUTPUT_SHARED_LOCAL 138890075Sobrien case asm_dest_local: 138990075Sobrien ASM_OUTPUT_SHARED_LOCAL (asm_out_file, name, size, rounded); 139090075Sobrien return; 139190075Sobrien#endif 139290075Sobrien default: 139390075Sobrien break; 139490075Sobrien } 139590075Sobrien } 139690075Sobrien 139790075Sobrien switch (destination) 139890075Sobrien { 139990075Sobrien#ifdef ASM_EMIT_BSS 140090075Sobrien case asm_dest_bss: 140190075Sobrien ASM_EMIT_BSS (decl, name, size, rounded); 140290075Sobrien break; 140390075Sobrien#endif 140490075Sobrien case asm_dest_common: 140590075Sobrien ASM_EMIT_COMMON (decl, name, size, rounded); 140690075Sobrien break; 140790075Sobrien case asm_dest_local: 140890075Sobrien ASM_EMIT_LOCAL (decl, name, size, rounded); 140990075Sobrien break; 141090075Sobrien default: 141190075Sobrien abort (); 141290075Sobrien } 141390075Sobrien 1414117395Skan return true; 141590075Sobrien} 141690075Sobrien 141718334Speter/* Assemble everything that is needed for a variable or function declaration. 141818334Speter Not used for automatic variables, and not used for function definitions. 141918334Speter Should not be called for variables of incomplete structure type. 142018334Speter 142118334Speter TOP_LEVEL is nonzero if this variable has file scope. 142218334Speter AT_END is nonzero if this is the special handling, at end of compilation, 142318334Speter to define things that have had only tentative definitions. 142418334Speter DONT_OUTPUT_DATA if nonzero means don't actually output the 142518334Speter initial value (that will be done by the caller). */ 142618334Speter 142718334Spetervoid 142818334Speterassemble_variable (decl, top_level, at_end, dont_output_data) 142918334Speter tree decl; 143052284Sobrien int top_level ATTRIBUTE_UNUSED; 143190075Sobrien int at_end ATTRIBUTE_UNUSED; 143218334Speter int dont_output_data; 143318334Speter{ 143490075Sobrien const char *name; 143550397Sobrien unsigned int align; 143618334Speter int reloc = 0; 143790075Sobrien rtx decl_rtl; 143818334Speter 143918334Speter last_assemble_variable_decl = 0; 144018334Speter 144118334Speter /* Normally no need to say anything here for external references, 144218334Speter since assemble_external is called by the language-specific code 144318334Speter when a declaration is first seen. */ 144418334Speter 144518334Speter if (DECL_EXTERNAL (decl)) 144618334Speter return; 144718334Speter 144818334Speter /* Output no assembler code for a function declaration. 144918334Speter Only definitions of functions output anything. */ 145018334Speter 145118334Speter if (TREE_CODE (decl) == FUNCTION_DECL) 145218334Speter return; 145318334Speter 145490075Sobrien /* Do nothing for global register variables. */ 145590075Sobrien if (DECL_RTL_SET_P (decl) && GET_CODE (DECL_RTL (decl)) == REG) 145690075Sobrien { 145790075Sobrien TREE_ASM_WRITTEN (decl) = 1; 145890075Sobrien return; 145990075Sobrien } 146090075Sobrien 146118334Speter /* If type was incomplete when the variable was declared, 146218334Speter see if it is complete now. */ 146318334Speter 146418334Speter if (DECL_SIZE (decl) == 0) 146518334Speter layout_decl (decl, 0); 146618334Speter 146718334Speter /* Still incomplete => don't allocate it; treat the tentative defn 146818334Speter (which is what it must have been) as an `extern' reference. */ 146918334Speter 147018334Speter if (!dont_output_data && DECL_SIZE (decl) == 0) 147118334Speter { 147218334Speter error_with_file_and_line (DECL_SOURCE_FILE (decl), 147318334Speter DECL_SOURCE_LINE (decl), 147418334Speter "storage size of `%s' isn't known", 147518334Speter IDENTIFIER_POINTER (DECL_NAME (decl))); 147618334Speter TREE_ASM_WRITTEN (decl) = 1; 147718334Speter return; 147818334Speter } 147918334Speter 148018334Speter /* The first declaration of a variable that comes through this function 148118334Speter decides whether it is global (in C, has external linkage) 148218334Speter or local (in C, has internal linkage). So do nothing more 148318334Speter if this function has already run. */ 148418334Speter 148518334Speter if (TREE_ASM_WRITTEN (decl)) 148618334Speter return; 148718334Speter 1488117395Skan /* Make sure targetm.encode_section_info is invoked before we set 1489117395Skan ASM_WRITTEN. */ 149090075Sobrien decl_rtl = DECL_RTL (decl); 149190075Sobrien 149218334Speter TREE_ASM_WRITTEN (decl) = 1; 149318334Speter 149452284Sobrien /* Do no output if -fsyntax-only. */ 149552284Sobrien if (flag_syntax_only) 149652284Sobrien return; 149752284Sobrien 149818334Speter app_disable (); 149918334Speter 150090075Sobrien if (! dont_output_data 150190075Sobrien && ! host_integerp (DECL_SIZE_UNIT (decl), 1)) 150218334Speter { 150390075Sobrien error_with_decl (decl, "size of variable `%s' is too large"); 150490075Sobrien return; 150518334Speter } 150618334Speter 150790075Sobrien name = XSTR (XEXP (decl_rtl, 0), 0); 150850397Sobrien if (TREE_PUBLIC (decl) && DECL_NAME (decl) 150950397Sobrien && ! first_global_object_name 151050397Sobrien && ! (DECL_COMMON (decl) && (DECL_INITIAL (decl) == 0 151150397Sobrien || DECL_INITIAL (decl) == error_mark_node)) 151250397Sobrien && ! DECL_WEAK (decl) 151350397Sobrien && ! DECL_ONE_ONLY (decl)) 151450397Sobrien { 151590075Sobrien const char *p; 151690075Sobrien char *xname; 151750397Sobrien 1518117395Skan p = (* targetm.strip_name_encoding) (name); 1519117395Skan xname = xstrdup (p); 152090075Sobrien first_global_object_name = xname; 152150397Sobrien } 152250397Sobrien 152350397Sobrien /* Compute the alignment of this data. */ 152450397Sobrien 152550397Sobrien align = DECL_ALIGN (decl); 152650397Sobrien 152750397Sobrien /* In the case for initialing an array whose length isn't specified, 152850397Sobrien where we have not yet been able to do the layout, 152950397Sobrien figure out the proper alignment now. */ 153050397Sobrien if (dont_output_data && DECL_SIZE (decl) == 0 153150397Sobrien && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE) 153250397Sobrien align = MAX (align, TYPE_ALIGN (TREE_TYPE (TREE_TYPE (decl)))); 153350397Sobrien 153450397Sobrien /* Some object file formats have a maximum alignment which they support. 153550397Sobrien In particular, a.out format supports a maximum alignment of 4. */ 153650397Sobrien#ifndef MAX_OFILE_ALIGNMENT 153750397Sobrien#define MAX_OFILE_ALIGNMENT BIGGEST_ALIGNMENT 153850397Sobrien#endif 153950397Sobrien if (align > MAX_OFILE_ALIGNMENT) 154050397Sobrien { 154150397Sobrien warning_with_decl (decl, 154290075Sobrien "alignment of `%s' is greater than maximum object file alignment. Using %d", 1543117395Skan MAX_OFILE_ALIGNMENT/BITS_PER_UNIT); 154450397Sobrien align = MAX_OFILE_ALIGNMENT; 154550397Sobrien } 154650397Sobrien 154750397Sobrien /* On some machines, it is good to increase alignment sometimes. */ 154890075Sobrien if (! DECL_USER_ALIGN (decl)) 154990075Sobrien { 155050397Sobrien#ifdef DATA_ALIGNMENT 155190075Sobrien align = DATA_ALIGNMENT (TREE_TYPE (decl), align); 155250397Sobrien#endif 155350397Sobrien#ifdef CONSTANT_ALIGNMENT 155490075Sobrien if (DECL_INITIAL (decl) != 0 && DECL_INITIAL (decl) != error_mark_node) 1555117395Skan align = CONSTANT_ALIGNMENT (DECL_INITIAL (decl), align); 155650397Sobrien#endif 155790075Sobrien } 155850397Sobrien 155950397Sobrien /* Reset the alignment in case we have made it tighter, so we can benefit 156050397Sobrien from it in get_pointer_alignment. */ 156150397Sobrien DECL_ALIGN (decl) = align; 156290075Sobrien set_mem_align (decl_rtl, align); 156350397Sobrien 1564117395Skan if (TREE_PUBLIC (decl)) 1565117395Skan maybe_assemble_visibility (decl); 1566117395Skan 1567117395Skan /* Output any data that we will need to use the address of. */ 1568117395Skan if (DECL_INITIAL (decl) == error_mark_node) 1569117395Skan reloc = contains_pointers_p (TREE_TYPE (decl)) ? 3 : 0; 1570117395Skan else if (DECL_INITIAL (decl)) 1571117395Skan reloc = output_addressed_constants (DECL_INITIAL (decl)); 1572117395Skan resolve_unique_section (decl, reloc, flag_data_sections); 1573117395Skan 157418334Speter /* Handle uninitialized definitions. */ 157518334Speter 1576117395Skan /* If the decl has been given an explicit section name, then it 1577117395Skan isn't common, and shouldn't be handled as such. */ 1578117395Skan if (DECL_SECTION_NAME (decl) || dont_output_data) 1579117395Skan ; 1580117395Skan /* We don't implement common thread-local data at present. */ 1581117395Skan else if (DECL_THREAD_LOCAL (decl)) 158218334Speter { 1583117395Skan if (DECL_COMMON (decl)) 1584117395Skan sorry ("thread-local COMMON data not implemented"); 1585117395Skan } 1586117395Skan else if (DECL_INITIAL (decl) == 0 1587117395Skan || DECL_INITIAL (decl) == error_mark_node 1588117395Skan || (flag_zero_initialized_in_bss 1589117395Skan /* Leave constant zeroes in .rodata so they can be shared. */ 1590117395Skan && !TREE_READONLY (decl) 1591117395Skan && initializer_zerop (DECL_INITIAL (decl)))) 1592117395Skan { 159390075Sobrien unsigned HOST_WIDE_INT size = tree_low_cst (DECL_SIZE_UNIT (decl), 1); 159490075Sobrien unsigned HOST_WIDE_INT rounded = size; 159518334Speter 159618334Speter /* Don't allocate zero bytes of common, 159718334Speter since that means "undefined external" in the linker. */ 159890075Sobrien if (size == 0) 159990075Sobrien rounded = 1; 160090075Sobrien 160118334Speter /* Round size up to multiple of BIGGEST_ALIGNMENT bits 160218334Speter so that each uninitialized object starts on such a boundary. */ 160318334Speter rounded += (BIGGEST_ALIGNMENT / BITS_PER_UNIT) - 1; 160418334Speter rounded = (rounded / (BIGGEST_ALIGNMENT / BITS_PER_UNIT) 160518334Speter * (BIGGEST_ALIGNMENT / BITS_PER_UNIT)); 160690075Sobrien 160790075Sobrien#if !defined(ASM_OUTPUT_ALIGNED_COMMON) && !defined(ASM_OUTPUT_ALIGNED_DECL_COMMON) && !defined(ASM_OUTPUT_ALIGNED_BSS) 160890075Sobrien if ((unsigned HOST_WIDE_INT) DECL_ALIGN (decl) / BITS_PER_UNIT > rounded) 1609117395Skan warning_with_decl 1610117395Skan (decl, "requested alignment for %s is greater than implemented alignment of %d",rounded); 161150397Sobrien#endif 161218334Speter 1613117395Skan /* If the target cannot output uninitialized but not common global data 1614117395Skan in .bss, then we have to use .data, so fall through. */ 1615117395Skan if (asm_emit_uninitialised (decl, name, size, rounded)) 1616117395Skan return; 161718334Speter } 161818334Speter 161950397Sobrien /* Handle initialized definitions. 162050397Sobrien Also handle uninitialized global definitions if -fno-common and the 162150397Sobrien target doesn't support ASM_OUTPUT_BSS. */ 162218334Speter 162318334Speter /* First make the assembler name(s) global if appropriate. */ 162418334Speter if (TREE_PUBLIC (decl) && DECL_NAME (decl)) 162596263Sobrien globalize_decl (decl); 162618334Speter 162750397Sobrien /* Switch to the appropriate section. */ 162850397Sobrien variable_section (decl, reloc); 162950397Sobrien 163018334Speter /* dbxout.c needs to know this. */ 163118334Speter if (in_text_section ()) 163218334Speter DECL_IN_TEXT_SECTION (decl) = 1; 163318334Speter 163450397Sobrien /* Output the alignment of this data. */ 163518334Speter if (align > BITS_PER_UNIT) 163690075Sobrien { 163790075Sobrien ASM_OUTPUT_ALIGN (asm_out_file, 163890075Sobrien floor_log2 (DECL_ALIGN (decl) / BITS_PER_UNIT)); 163990075Sobrien } 164018334Speter 164118334Speter /* Do any machine/system dependent processing of the object. */ 164218334Speter#ifdef ASM_DECLARE_OBJECT_NAME 164318334Speter last_assemble_variable_decl = decl; 164418334Speter ASM_DECLARE_OBJECT_NAME (asm_out_file, name, decl); 164518334Speter#else 164618334Speter /* Standard thing is just output label for the object. */ 164750397Sobrien ASM_OUTPUT_LABEL (asm_out_file, name); 164818334Speter#endif /* ASM_DECLARE_OBJECT_NAME */ 164918334Speter 165018334Speter if (!dont_output_data) 165118334Speter { 165296263Sobrien if (DECL_INITIAL (decl) && DECL_INITIAL (decl) != error_mark_node) 165318334Speter /* Output the actual data. */ 165490075Sobrien output_constant (DECL_INITIAL (decl), 165590075Sobrien tree_low_cst (DECL_SIZE_UNIT (decl), 1), 165690075Sobrien align); 165718334Speter else 165818334Speter /* Leave space for it. */ 165990075Sobrien assemble_zeros (tree_low_cst (DECL_SIZE_UNIT (decl), 1)); 166018334Speter } 166118334Speter} 166218334Speter 166318334Speter/* Return 1 if type TYPE contains any pointers. */ 166418334Speter 166518334Speterstatic int 166618334Spetercontains_pointers_p (type) 166718334Speter tree type; 166818334Speter{ 166918334Speter switch (TREE_CODE (type)) 167018334Speter { 167118334Speter case POINTER_TYPE: 167218334Speter case REFERENCE_TYPE: 167318334Speter /* I'm not sure whether OFFSET_TYPE needs this treatment, 167418334Speter so I'll play safe and return 1. */ 167518334Speter case OFFSET_TYPE: 167618334Speter return 1; 167718334Speter 167818334Speter case RECORD_TYPE: 167918334Speter case UNION_TYPE: 168018334Speter case QUAL_UNION_TYPE: 168118334Speter { 168218334Speter tree fields; 168318334Speter /* For a type that has fields, see if the fields have pointers. */ 168418334Speter for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields)) 168518334Speter if (TREE_CODE (fields) == FIELD_DECL 168618334Speter && contains_pointers_p (TREE_TYPE (fields))) 168718334Speter return 1; 168818334Speter return 0; 168918334Speter } 169018334Speter 169118334Speter case ARRAY_TYPE: 169218334Speter /* An array type contains pointers if its element type does. */ 169318334Speter return contains_pointers_p (TREE_TYPE (type)); 169418334Speter 169518334Speter default: 169618334Speter return 0; 169718334Speter } 169818334Speter} 169918334Speter 170018334Speter/* Output something to declare an external symbol to the assembler. 170118334Speter (Most assemblers don't need this, so we normally output nothing.) 170218334Speter Do nothing if DECL is not external. */ 170318334Speter 170418334Spetervoid 170518334Speterassemble_external (decl) 170652284Sobrien tree decl ATTRIBUTE_UNUSED; 170718334Speter{ 170890075Sobrien /* Because most platforms do not define ASM_OUTPUT_EXTERNAL, the 170990075Sobrien main body of this code is only rarely exercised. To provide some 171090075Sobrien testing, on all platforms, we make sure that the ASM_OUT_FILE is 171190075Sobrien open. If it's not, we should not be calling this function. */ 171290075Sobrien if (!asm_out_file) 171390075Sobrien abort (); 171490075Sobrien 171518334Speter#ifdef ASM_OUTPUT_EXTERNAL 171690075Sobrien if (DECL_P (decl) && DECL_EXTERNAL (decl) && TREE_PUBLIC (decl)) 171718334Speter { 171818334Speter rtx rtl = DECL_RTL (decl); 171918334Speter 172018334Speter if (GET_CODE (rtl) == MEM && GET_CODE (XEXP (rtl, 0)) == SYMBOL_REF 172118334Speter && ! SYMBOL_REF_USED (XEXP (rtl, 0))) 172218334Speter { 172318334Speter /* Some systems do require some output. */ 172418334Speter SYMBOL_REF_USED (XEXP (rtl, 0)) = 1; 172518334Speter ASM_OUTPUT_EXTERNAL (asm_out_file, decl, XSTR (XEXP (rtl, 0), 0)); 172618334Speter } 172718334Speter } 172818334Speter#endif 172918334Speter} 173018334Speter 173118334Speter/* Similar, for calling a library function FUN. */ 173218334Speter 173318334Spetervoid 173418334Speterassemble_external_libcall (fun) 173552284Sobrien rtx fun ATTRIBUTE_UNUSED; 173618334Speter{ 173718334Speter#ifdef ASM_OUTPUT_EXTERNAL_LIBCALL 173850397Sobrien /* Declare library function name external when first used, if nec. */ 173950397Sobrien if (! SYMBOL_REF_USED (fun)) 174018334Speter { 174150397Sobrien SYMBOL_REF_USED (fun) = 1; 174250397Sobrien ASM_OUTPUT_EXTERNAL_LIBCALL (asm_out_file, fun); 174318334Speter } 174418334Speter#endif 174518334Speter} 174618334Speter 174718334Speter/* Assemble a label named NAME. */ 174818334Speter 174918334Spetervoid 175018334Speterassemble_label (name) 175190075Sobrien const char *name; 175218334Speter{ 175350397Sobrien ASM_OUTPUT_LABEL (asm_out_file, name); 175418334Speter} 175518334Speter 175618334Speter/* Output to FILE a reference to the assembler name of a C-level name NAME. 175718334Speter If NAME starts with a *, the rest of NAME is output verbatim. 175818334Speter Otherwise NAME is transformed in an implementation-defined way 175918334Speter (usually by the addition of an underscore). 176018334Speter Many macros in the tm file are defined to call this function. */ 176118334Speter 176218334Spetervoid 176318334Speterassemble_name (file, name) 176418334Speter FILE *file; 176590075Sobrien const char *name; 176618334Speter{ 176790075Sobrien const char *real_name; 176850397Sobrien tree id; 176918334Speter 1770117395Skan real_name = (* targetm.strip_name_encoding) (name); 177118334Speter 177250397Sobrien id = maybe_get_identifier (real_name); 177350397Sobrien if (id) 177450397Sobrien TREE_SYMBOL_REFERENCED (id) = 1; 177518334Speter 177618334Speter if (name[0] == '*') 177750397Sobrien fputs (&name[1], file); 177818334Speter else 177950397Sobrien ASM_OUTPUT_LABELREF (file, name); 178018334Speter} 178118334Speter 178218334Speter/* Allocate SIZE bytes writable static space with a gensym name 178318334Speter and return an RTX to refer to its address. */ 178418334Speter 178518334Speterrtx 178618334Speterassemble_static_space (size) 178718334Speter int size; 178818334Speter{ 178918334Speter char name[12]; 179090075Sobrien const char *namestring; 179118334Speter rtx x; 179218334Speter 179318334Speter#if 0 179418334Speter if (flag_shared_data) 179518334Speter data_section (); 179618334Speter#endif 179718334Speter 179818334Speter ASM_GENERATE_INTERNAL_LABEL (name, "LF", const_labelno); 179918334Speter ++const_labelno; 180090075Sobrien namestring = ggc_strdup (name); 180118334Speter 180250397Sobrien x = gen_rtx_SYMBOL_REF (Pmode, namestring); 180318334Speter 180450397Sobrien#ifdef ASM_OUTPUT_ALIGNED_DECL_LOCAL 180550397Sobrien ASM_OUTPUT_ALIGNED_DECL_LOCAL (asm_out_file, NULL_TREE, name, size, 180650397Sobrien BIGGEST_ALIGNMENT); 180750397Sobrien#else 180818334Speter#ifdef ASM_OUTPUT_ALIGNED_LOCAL 180950397Sobrien ASM_OUTPUT_ALIGNED_LOCAL (asm_out_file, name, size, BIGGEST_ALIGNMENT); 181018334Speter#else 181150397Sobrien { 181250397Sobrien /* Round size up to multiple of BIGGEST_ALIGNMENT bits 181350397Sobrien so that each uninitialized object starts on such a boundary. */ 181490075Sobrien /* Variable `rounded' might or might not be used in ASM_OUTPUT_LOCAL. */ 181552284Sobrien int rounded ATTRIBUTE_UNUSED 181652284Sobrien = ((size + (BIGGEST_ALIGNMENT / BITS_PER_UNIT) - 1) 181752284Sobrien / (BIGGEST_ALIGNMENT / BITS_PER_UNIT) 181852284Sobrien * (BIGGEST_ALIGNMENT / BITS_PER_UNIT)); 181950397Sobrien ASM_OUTPUT_LOCAL (asm_out_file, name, size, rounded); 182050397Sobrien } 182118334Speter#endif 182250397Sobrien#endif 182318334Speter return x; 182418334Speter} 182518334Speter 182618334Speter/* Assemble the static constant template for function entry trampolines. 182718334Speter This is done at most once per compilation. 182818334Speter Returns an RTX for the address of the template. */ 182918334Speter 183048743Sobrien#ifdef TRAMPOLINE_TEMPLATE 183118334Speterrtx 183218334Speterassemble_trampoline_template () 183318334Speter{ 183418334Speter char label[256]; 183590075Sobrien const char *name; 183618334Speter int align; 183718334Speter 183818334Speter /* By default, put trampoline templates in read-only data section. */ 183918334Speter 184018334Speter#ifdef TRAMPOLINE_SECTION 184118334Speter TRAMPOLINE_SECTION (); 184218334Speter#else 184318334Speter readonly_data_section (); 184418334Speter#endif 184518334Speter 184618334Speter /* Write the assembler code to define one. */ 184750397Sobrien align = floor_log2 (TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT); 184818334Speter if (align > 0) 184990075Sobrien { 185090075Sobrien ASM_OUTPUT_ALIGN (asm_out_file, align); 185190075Sobrien } 185218334Speter 185318334Speter ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LTRAMP", 0); 185418334Speter TRAMPOLINE_TEMPLATE (asm_out_file); 185518334Speter 185618334Speter /* Record the rtl to refer to it. */ 185718334Speter ASM_GENERATE_INTERNAL_LABEL (label, "LTRAMP", 0); 185890075Sobrien name = ggc_strdup (label); 185950397Sobrien return gen_rtx_SYMBOL_REF (Pmode, name); 186018334Speter} 186148743Sobrien#endif 186218334Speter 186390075Sobrien/* A and B are either alignments or offsets. Return the minimum alignment 186490075Sobrien that may be assumed after adding the two together. */ 186518334Speter 186690075Sobrienstatic inline unsigned 186790075Sobrienmin_align (a, b) 186890075Sobrien unsigned int a, b; 186990075Sobrien{ 187090075Sobrien return (a | b) & -(a | b); 187190075Sobrien} 187218334Speter 187390075Sobrien/* Return the assembler directive for creating a given kind of integer 187490075Sobrien object. SIZE is the number of bytes in the object and ALIGNED_P 187590075Sobrien indicates whether it is known to be aligned. Return NULL if the 187690075Sobrien assembly dialect has no such directive. 187790075Sobrien 187890075Sobrien The returned string should be printed at the start of a new line and 187990075Sobrien be followed immediately by the object's initial value. */ 188090075Sobrien 188190075Sobrienconst char * 188290075Sobrieninteger_asm_op (size, aligned_p) 188318334Speter int size; 188490075Sobrien int aligned_p; 188518334Speter{ 188690075Sobrien struct asm_int_op *ops; 188718334Speter 188890075Sobrien if (aligned_p) 188990075Sobrien ops = &targetm.asm_out.aligned_op; 189090075Sobrien else 189190075Sobrien ops = &targetm.asm_out.unaligned_op; 189290075Sobrien 189318334Speter switch (size) 189418334Speter { 189518334Speter case 1: 189690075Sobrien return targetm.asm_out.byte_op; 189718334Speter case 2: 189890075Sobrien return ops->hi; 189918334Speter case 4: 190090075Sobrien return ops->si; 190118334Speter case 8: 190290075Sobrien return ops->di; 190318334Speter case 16: 190490075Sobrien return ops->ti; 190590075Sobrien default: 190690075Sobrien return NULL; 190718334Speter } 190890075Sobrien} 190918334Speter 191090075Sobrien/* Use directive OP to assemble an integer object X. Print OP at the 191190075Sobrien start of the line, followed immediately by the value of X. */ 191218334Speter 191390075Sobrienvoid 191490075Sobrienassemble_integer_with_op (op, x) 191590075Sobrien const char *op; 191690075Sobrien rtx x; 191790075Sobrien{ 191890075Sobrien fputs (op, asm_out_file); 191990075Sobrien output_addr_const (asm_out_file, x); 192090075Sobrien fputc ('\n', asm_out_file); 192190075Sobrien} 192218334Speter 192390075Sobrien/* The default implementation of the asm_out.integer target hook. */ 192418334Speter 192590075Sobrienbool 192690075Sobriendefault_assemble_integer (x, size, aligned_p) 192790075Sobrien rtx x ATTRIBUTE_UNUSED; 192890075Sobrien unsigned int size ATTRIBUTE_UNUSED; 192990075Sobrien int aligned_p ATTRIBUTE_UNUSED; 193090075Sobrien{ 193190075Sobrien const char *op = integer_asm_op (size, aligned_p); 193290075Sobrien return op && (assemble_integer_with_op (op, x), true); 193390075Sobrien} 193490075Sobrien 193590075Sobrien/* Assemble the integer constant X into an object of SIZE bytes. ALIGN is 193690075Sobrien the alignment of the integer in bits. Return 1 if we were able to output 1937117395Skan the constant, otherwise 0. If FORCE is nonzero, abort if we can't output 193890075Sobrien the constant. */ 193990075Sobrien 194090075Sobrienbool 194190075Sobrienassemble_integer (x, size, align, force) 194290075Sobrien rtx x; 194390075Sobrien unsigned int size; 194490075Sobrien unsigned int align; 194590075Sobrien int force; 194690075Sobrien{ 194790075Sobrien int aligned_p; 194890075Sobrien 194990075Sobrien aligned_p = (align >= MIN (size * BITS_PER_UNIT, BIGGEST_ALIGNMENT)); 195090075Sobrien 195190075Sobrien /* See if the target hook can handle this kind of object. */ 195290075Sobrien if ((*targetm.asm_out.integer) (x, size, aligned_p)) 195390075Sobrien return true; 195490075Sobrien 195590075Sobrien /* If the object is a multi-byte one, try splitting it up. Split 195690075Sobrien it into words it if is multi-word, otherwise split it into bytes. */ 195790075Sobrien if (size > 1) 195818334Speter { 195990075Sobrien enum machine_mode omode, imode; 196090075Sobrien unsigned int subalign; 196190075Sobrien unsigned int subsize, i; 196218334Speter 196390075Sobrien subsize = size > UNITS_PER_WORD? UNITS_PER_WORD : 1; 196490075Sobrien subalign = MIN (align, subsize * BITS_PER_UNIT); 196590075Sobrien omode = mode_for_size (subsize * BITS_PER_UNIT, MODE_INT, 0); 196690075Sobrien imode = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 0); 196790075Sobrien 196890075Sobrien for (i = 0; i < size; i += subsize) 196918334Speter { 197090075Sobrien rtx partial = simplify_subreg (omode, x, imode, i); 197190075Sobrien if (!partial || !assemble_integer (partial, subsize, subalign, 0)) 197218334Speter break; 197318334Speter } 197490075Sobrien if (i == size) 197590075Sobrien return true; 197618334Speter 197790075Sobrien /* If we've printed some of it, but not all of it, there's no going 197890075Sobrien back now. */ 197918334Speter if (i > 0) 198018334Speter abort (); 198118334Speter } 198218334Speter 198318334Speter if (force) 198418334Speter abort (); 198518334Speter 198690075Sobrien return false; 198718334Speter} 198818334Speter 198918334Spetervoid 199090075Sobrienassemble_real (d, mode, align) 199118334Speter REAL_VALUE_TYPE d; 199218334Speter enum machine_mode mode; 199390075Sobrien unsigned int align; 199418334Speter{ 199590075Sobrien long data[4]; 199690075Sobrien long l; 199790075Sobrien unsigned int nalign = min_align (align, 32); 199818334Speter 199990075Sobrien switch (BITS_PER_UNIT) 200018334Speter { 200190075Sobrien case 8: 200290075Sobrien switch (mode) 200390075Sobrien { 200490075Sobrien case SFmode: 200590075Sobrien REAL_VALUE_TO_TARGET_SINGLE (d, l); 200690075Sobrien assemble_integer (GEN_INT (l), 4, align, 1); 200790075Sobrien break; 200890075Sobrien case DFmode: 200990075Sobrien REAL_VALUE_TO_TARGET_DOUBLE (d, data); 201090075Sobrien assemble_integer (GEN_INT (data[0]), 4, align, 1); 201190075Sobrien assemble_integer (GEN_INT (data[1]), 4, nalign, 1); 201290075Sobrien break; 201390075Sobrien case XFmode: 201490075Sobrien REAL_VALUE_TO_TARGET_LONG_DOUBLE (d, data); 201590075Sobrien assemble_integer (GEN_INT (data[0]), 4, align, 1); 201690075Sobrien assemble_integer (GEN_INT (data[1]), 4, nalign, 1); 201790075Sobrien assemble_integer (GEN_INT (data[2]), 4, nalign, 1); 201890075Sobrien break; 201990075Sobrien case TFmode: 202090075Sobrien REAL_VALUE_TO_TARGET_LONG_DOUBLE (d, data); 202190075Sobrien assemble_integer (GEN_INT (data[0]), 4, align, 1); 202290075Sobrien assemble_integer (GEN_INT (data[1]), 4, nalign, 1); 202390075Sobrien assemble_integer (GEN_INT (data[2]), 4, nalign, 1); 202490075Sobrien assemble_integer (GEN_INT (data[3]), 4, nalign, 1); 202590075Sobrien break; 202690075Sobrien default: 202790075Sobrien abort (); 202890075Sobrien } 202918334Speter break; 203018334Speter 203190075Sobrien case 16: 203290075Sobrien switch (mode) 203390075Sobrien { 203490075Sobrien case HFmode: 203590075Sobrien REAL_VALUE_TO_TARGET_SINGLE (d, l); 203690075Sobrien assemble_integer (GEN_INT (l), 2, align, 1); 203790075Sobrien break; 203890075Sobrien case TQFmode: 203990075Sobrien REAL_VALUE_TO_TARGET_DOUBLE (d, data); 204090075Sobrien assemble_integer (GEN_INT (data[0]), 2, align, 1); 204190075Sobrien assemble_integer (GEN_INT (data[1]), 1, nalign, 1); 204290075Sobrien break; 204390075Sobrien default: 204490075Sobrien abort (); 204590075Sobrien } 204618334Speter break; 204718334Speter 204890075Sobrien case 32: 204990075Sobrien switch (mode) 205090075Sobrien { 205190075Sobrien case QFmode: 205290075Sobrien REAL_VALUE_TO_TARGET_SINGLE (d, l); 205390075Sobrien assemble_integer (GEN_INT (l), 1, align, 1); 205490075Sobrien break; 205590075Sobrien case HFmode: 205690075Sobrien REAL_VALUE_TO_TARGET_DOUBLE (d, data); 205790075Sobrien assemble_integer (GEN_INT (data[0]), 1, align, 1); 205890075Sobrien assemble_integer (GEN_INT (data[1]), 1, nalign, 1); 205990075Sobrien break; 206090075Sobrien default: 206190075Sobrien abort (); 206290075Sobrien } 206318334Speter break; 206418334Speter 206518334Speter default: 206618334Speter abort (); 206718334Speter } 206818334Speter} 206918334Speter 207018334Speter/* Given an expression EXP with a constant value, 207118334Speter reduce it to the sum of an assembler symbol and an integer. 207218334Speter Store them both in the structure *VALUE. 207318334Speter Abort if EXP does not reduce. */ 207418334Speter 2075117395Skanstruct addr_const GTY(()) 207618334Speter{ 207718334Speter rtx base; 207818334Speter HOST_WIDE_INT offset; 207918334Speter}; 208018334Speter 208118334Speterstatic void 208218334Speterdecode_addr_const (exp, value) 208318334Speter tree exp; 208418334Speter struct addr_const *value; 208518334Speter{ 208690075Sobrien tree target = TREE_OPERAND (exp, 0); 208790075Sobrien int offset = 0; 208890075Sobrien rtx x; 208918334Speter 209018334Speter while (1) 209118334Speter { 209218334Speter if (TREE_CODE (target) == COMPONENT_REF 209390075Sobrien && host_integerp (byte_position (TREE_OPERAND (target, 1)), 0)) 209490075Sobrien 209518334Speter { 209690075Sobrien offset += int_byte_position (TREE_OPERAND (target, 1)); 209718334Speter target = TREE_OPERAND (target, 0); 209818334Speter } 209990075Sobrien else if (TREE_CODE (target) == ARRAY_REF 210090075Sobrien || TREE_CODE (target) == ARRAY_RANGE_REF) 210118334Speter { 210290075Sobrien offset += (tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (target)), 1) 210390075Sobrien * tree_low_cst (TREE_OPERAND (target, 1), 0)); 210418334Speter target = TREE_OPERAND (target, 0); 210518334Speter } 210618334Speter else 210718334Speter break; 210818334Speter } 210918334Speter 211018334Speter switch (TREE_CODE (target)) 211118334Speter { 211218334Speter case VAR_DECL: 211318334Speter case FUNCTION_DECL: 211418334Speter x = DECL_RTL (target); 211518334Speter break; 211618334Speter 211718334Speter case LABEL_DECL: 211850397Sobrien x = gen_rtx_MEM (FUNCTION_MODE, 211950397Sobrien gen_rtx_LABEL_REF (VOIDmode, 212050397Sobrien label_rtx (TREE_OPERAND (exp, 0)))); 212118334Speter break; 212218334Speter 212318334Speter case REAL_CST: 212418334Speter case STRING_CST: 212518334Speter case COMPLEX_CST: 212618334Speter case CONSTRUCTOR: 212750397Sobrien case INTEGER_CST: 212890075Sobrien /* This constant should have been output already, but we can't simply 212990075Sobrien use TREE_CST_RTL since INTEGER_CST doesn't have one. */ 213090075Sobrien x = output_constant_def (target, 1); 213118334Speter break; 213218334Speter 213318334Speter default: 213418334Speter abort (); 213518334Speter } 213618334Speter 213750397Sobrien if (GET_CODE (x) != MEM) 213850397Sobrien abort (); 213950397Sobrien x = XEXP (x, 0); 214018334Speter 214118334Speter value->base = x; 214218334Speter value->offset = offset; 214318334Speter} 214418334Speter 214596263Sobrien/* We do RTX_UNSPEC + XINT (blah), so nothing can go after RTX_UNSPEC. */ 2146117395Skanenum kind { RTX_UNKNOWN, RTX_DOUBLE, RTX_VECTOR, RTX_INT, RTX_UNSPEC }; 2147117395Skanstruct rtx_const GTY(()) 214890075Sobrien{ 214990075Sobrien ENUM_BITFIELD(kind) kind : 16; 215090075Sobrien ENUM_BITFIELD(machine_mode) mode : 16; 2151117395Skan union rtx_const_un { 2152117395Skan REAL_VALUE_TYPE du; 2153117395Skan struct rtx_const_u_addr { 2154117395Skan rtx base; 2155117395Skan const char *symbol; 2156117395Skan HOST_WIDE_INT offset; 2157117395Skan } GTY ((tag ("1"))) addr; 2158117395Skan struct rtx_const_u_di { 2159117395Skan HOST_WIDE_INT high; 2160117395Skan HOST_WIDE_INT low; 2161117395Skan } GTY ((tag ("0"))) di; 216296263Sobrien 2163117395Skan /* The max vector size we have is 16 wide; two variants for 2164117395Skan integral and floating point vectors. */ 2165117395Skan struct rtx_const_int_vec { 2166117395Skan HOST_WIDE_INT high; 2167117395Skan HOST_WIDE_INT low; 2168117395Skan } GTY ((tag ("2"))) int_vec[16]; 2169117395Skan 2170117395Skan REAL_VALUE_TYPE GTY ((tag ("3"))) fp_vec[8]; 2171117395Skan 2172117395Skan } GTY ((desc ("%1.kind >= RTX_INT"), descbits ("1"))) un; 217390075Sobrien}; 217490075Sobrien 217518334Speter/* Uniquize all constants that appear in memory. 217618334Speter Each constant in memory thus far output is recorded 2177117395Skan in `const_hash_table'. */ 217818334Speter 2179117395Skanstruct constant_descriptor_tree GTY(()) 2180117395Skan{ 2181117395Skan /* More constant_descriptors with the same hash code. */ 2182117395Skan struct constant_descriptor_tree *next; 218318334Speter 2184117395Skan /* The label of the constant. */ 218590075Sobrien const char *label; 2186117395Skan 2187117395Skan /* A MEM for the constant. */ 218890075Sobrien rtx rtl; 2189117395Skan 2190117395Skan /* The value of the constant. */ 2191117395Skan tree value; 219218334Speter}; 219318334Speter 219418334Speter#define MAX_HASH_TABLE 1009 2195117395Skanstatic GTY(()) struct constant_descriptor_tree * 2196117395Skan const_hash_table[MAX_HASH_TABLE]; 219718334Speter 219890075Sobrien/* We maintain a hash table of STRING_CST values. Unless we are asked to force 219990075Sobrien out a string constant, we defer output of the constants until we know 220090075Sobrien they are actually used. This will be if something takes its address or if 220190075Sobrien there is a usage of the string in the RTL of a function. */ 220290075Sobrien 2203117395Skan#define STRHASH(x) htab_hash_pointer (x) 220490075Sobrien 2205117395Skanstruct deferred_string GTY(()) 220690075Sobrien{ 220790075Sobrien const char *label; 220890075Sobrien tree exp; 220990075Sobrien int labelno; 221090075Sobrien}; 221190075Sobrien 2212117395Skanstatic GTY ((param_is (struct deferred_string))) htab_t const_str_htab; 221390075Sobrien 221490075Sobrien/* Returns a hash code for X (which is a really a 221590075Sobrien struct deferred_string *). */ 221690075Sobrien 221790075Sobrienstatic hashval_t 221890075Sobrienconst_str_htab_hash (x) 221990075Sobrien const void *x; 222090075Sobrien{ 222190075Sobrien return STRHASH (((const struct deferred_string *) x)->label); 222290075Sobrien} 222390075Sobrien 2224117395Skan/* Returns nonzero if the value represented by X (which is really a 222590075Sobrien struct deferred_string *) is the same as that given by Y 222690075Sobrien (which is really a char *). */ 222790075Sobrien 222890075Sobrienstatic int 222990075Sobrienconst_str_htab_eq (x, y) 223090075Sobrien const void *x; 223190075Sobrien const void *y; 223290075Sobrien{ 223390075Sobrien return (((const struct deferred_string *) x)->label == (const char *) y); 223490075Sobrien} 223590075Sobrien 2236117395Skan/* Compute a hash code for a constant expression. */ 223790075Sobrien 2238117395Skanstatic unsigned int 2239117395Skanconst_hash (exp) 2240117395Skan tree exp; 224190075Sobrien{ 2242117395Skan return const_hash_1 (exp) % MAX_HASH_TABLE; 224390075Sobrien} 224490075Sobrien 2245117395Skanstatic unsigned int 2246117395Skanconst_hash_1 (exp) 224718334Speter tree exp; 224818334Speter{ 224990075Sobrien const char *p; 2250117395Skan unsigned int hi; 2251117395Skan int len, i; 225290075Sobrien enum tree_code code = TREE_CODE (exp); 225318334Speter 225450397Sobrien /* Either set P and LEN to the address and len of something to hash and 225550397Sobrien exit the switch or return a value. */ 225650397Sobrien 225750397Sobrien switch (code) 225818334Speter { 225950397Sobrien case INTEGER_CST: 226090075Sobrien p = (char *) &TREE_INT_CST (exp); 226190075Sobrien len = sizeof TREE_INT_CST (exp); 226250397Sobrien break; 226350397Sobrien 226450397Sobrien case REAL_CST: 2265117395Skan return real_hash (TREE_REAL_CST_PTR (exp)); 226618334Speter 226750397Sobrien case STRING_CST: 226850397Sobrien p = TREE_STRING_POINTER (exp); 226950397Sobrien len = TREE_STRING_LENGTH (exp); 227050397Sobrien break; 227118334Speter 227250397Sobrien case COMPLEX_CST: 2273117395Skan return (const_hash_1 (TREE_REALPART (exp)) * 5 2274117395Skan + const_hash_1 (TREE_IMAGPART (exp))); 227518334Speter 227650397Sobrien case CONSTRUCTOR: 227750397Sobrien if (TREE_CODE (TREE_TYPE (exp)) == SET_TYPE) 227818334Speter { 227990075Sobrien char *tmp; 228090075Sobrien 228150397Sobrien len = int_size_in_bytes (TREE_TYPE (exp)); 228290075Sobrien tmp = (char *) alloca (len); 228390075Sobrien get_set_constructor_bytes (exp, (unsigned char *) tmp, len); 228490075Sobrien p = tmp; 228550397Sobrien break; 228618334Speter } 228750397Sobrien else 228850397Sobrien { 228990075Sobrien tree link; 229018334Speter 2291117395Skan hi = 5 + int_size_in_bytes (TREE_TYPE (exp)); 229250397Sobrien 229350397Sobrien for (link = CONSTRUCTOR_ELTS (exp); link; link = TREE_CHAIN (link)) 229450397Sobrien if (TREE_VALUE (link)) 2295117395Skan hi = hi * 603 + const_hash_1 (TREE_VALUE (link)); 229650397Sobrien 229750397Sobrien return hi; 229850397Sobrien } 229950397Sobrien 230050397Sobrien case ADDR_EXPR: 2301102780Skan case FDESC_EXPR: 230250397Sobrien { 230350397Sobrien struct addr_const value; 230450397Sobrien 230550397Sobrien decode_addr_const (exp, &value); 230650397Sobrien if (GET_CODE (value.base) == SYMBOL_REF) 230750397Sobrien { 230850397Sobrien /* Don't hash the address of the SYMBOL_REF; 230950397Sobrien only use the offset and the symbol name. */ 231050397Sobrien hi = value.offset; 231150397Sobrien p = XSTR (value.base, 0); 231250397Sobrien for (i = 0; p[i] != 0; i++) 231350397Sobrien hi = ((hi * 613) + (unsigned) (p[i])); 231450397Sobrien } 231550397Sobrien else if (GET_CODE (value.base) == LABEL_REF) 231650397Sobrien hi = value.offset + CODE_LABEL_NUMBER (XEXP (value.base, 0)) * 13; 231790075Sobrien else 231890075Sobrien abort (); 231950397Sobrien } 232018334Speter return hi; 232150397Sobrien 232250397Sobrien case PLUS_EXPR: 232350397Sobrien case MINUS_EXPR: 2324117395Skan return (const_hash_1 (TREE_OPERAND (exp, 0)) * 9 2325117395Skan + const_hash_1 (TREE_OPERAND (exp, 1))); 232650397Sobrien 232750397Sobrien case NOP_EXPR: 232850397Sobrien case CONVERT_EXPR: 232950397Sobrien case NON_LVALUE_EXPR: 2330117395Skan return const_hash_1 (TREE_OPERAND (exp, 0)) * 7 + 2; 233190075Sobrien 233250397Sobrien default: 233390075Sobrien /* A language specific constant. Just hash the code. */ 2334117395Skan return code; 233518334Speter } 233618334Speter 233718334Speter /* Compute hashing function */ 233818334Speter hi = len; 233918334Speter for (i = 0; i < len; i++) 234050397Sobrien hi = ((hi * 613) + (unsigned) (p[i])); 234118334Speter 234218334Speter return hi; 234318334Speter} 234418334Speter 2345117395Skan/* Compare t1 and t2, and return 1 only if they are known to result in 2346117395Skan the same bit pattern on output. */ 2347117395Skan 234818334Speterstatic int 2349117395Skancompare_constant (t1, t2) 2350117395Skan tree t1; 2351117395Skan tree t2; 235218334Speter{ 2353117395Skan enum tree_code typecode; 235418334Speter 2355117395Skan if (t1 == NULL_TREE) 2356117395Skan return t2 == NULL_TREE; 2357117395Skan if (t2 == NULL_TREE) 2358117395Skan return 0; 235918334Speter 2360117395Skan if (TREE_CODE (t1) != TREE_CODE (t2)) 236118334Speter return 0; 236218334Speter 2363117395Skan switch (TREE_CODE (t1)) 236418334Speter { 236550397Sobrien case INTEGER_CST: 236618334Speter /* Integer constants are the same only if the same width of type. */ 2367117395Skan if (TYPE_PRECISION (TREE_TYPE (t1)) != TYPE_PRECISION (TREE_TYPE (t2))) 236818334Speter return 0; 2369117395Skan return tree_int_cst_equal (t1, t2); 237050397Sobrien 237150397Sobrien case REAL_CST: 237218334Speter /* Real constants are the same only if the same width of type. */ 2373117395Skan if (TYPE_PRECISION (TREE_TYPE (t1)) != TYPE_PRECISION (TREE_TYPE (t2))) 237418334Speter return 0; 237550397Sobrien 2376117395Skan return REAL_VALUES_IDENTICAL (TREE_REAL_CST (t1), TREE_REAL_CST (t2)); 237750397Sobrien 237850397Sobrien case STRING_CST: 237918334Speter if (flag_writable_strings) 238018334Speter return 0; 238150397Sobrien 2382117395Skan if (TYPE_MODE (TREE_TYPE (t1)) != TYPE_MODE (TREE_TYPE (t2))) 238350397Sobrien return 0; 238450397Sobrien 2385117395Skan return (TREE_STRING_LENGTH (t1) == TREE_STRING_LENGTH (t2) 2386117395Skan && ! memcmp (TREE_STRING_POINTER (t1), TREE_STRING_POINTER (t2), 2387117395Skan TREE_STRING_LENGTH (t1))); 238850397Sobrien 2389117395Skan case COMPLEX_CST: 2390117395Skan return (compare_constant (TREE_REALPART (t1), TREE_REALPART (t2)) 2391117395Skan && compare_constant (TREE_IMAGPART (t1), TREE_IMAGPART (t2))); 239250397Sobrien 2393117395Skan case CONSTRUCTOR: 2394117395Skan typecode = TREE_CODE (TREE_TYPE (t1)); 2395117395Skan if (typecode != TREE_CODE (TREE_TYPE (t2))) 239618334Speter return 0; 239718334Speter 2398117395Skan if (typecode == SET_TYPE) 239918334Speter { 2400117395Skan int len = int_size_in_bytes (TREE_TYPE (t2)); 2401117395Skan unsigned char *tmp1, *tmp2; 240250397Sobrien 2403117395Skan if (int_size_in_bytes (TREE_TYPE (t1)) != len) 240418334Speter return 0; 240550397Sobrien 2406117395Skan tmp1 = (unsigned char *) alloca (len); 2407117395Skan tmp2 = (unsigned char *) alloca (len); 2408117395Skan 2409117395Skan if (get_set_constructor_bytes (t1, tmp1, len) != NULL_TREE) 2410117395Skan return 0; 2411117395Skan if (get_set_constructor_bytes (t2, tmp2, len) != NULL_TREE) 2412117395Skan return 0; 2413117395Skan 2414117395Skan return memcmp (tmp1, tmp2, len) != 0; 241518334Speter } 241650397Sobrien else 241750397Sobrien { 2418117395Skan tree l1, l2; 241918334Speter 2420117395Skan if (typecode == ARRAY_TYPE) 242190075Sobrien { 2422117395Skan HOST_WIDE_INT size_1 = int_size_in_bytes (TREE_TYPE (t1)); 2423117395Skan /* For arrays, check that the sizes all match. */ 2424117395Skan if (TYPE_MODE (TREE_TYPE (t1)) != TYPE_MODE (TREE_TYPE (t2)) 2425117395Skan || size_1 == -1 2426117395Skan || size_1 != int_size_in_bytes (TREE_TYPE (t2))) 242790075Sobrien return 0; 242890075Sobrien } 2429117395Skan else 243018334Speter { 2431117395Skan /* For record and union constructors, require exact type 2432117395Skan equality. */ 2433117395Skan if (TREE_TYPE (t1) != TREE_TYPE (t2)) 243418334Speter return 0; 243518334Speter } 243650397Sobrien 2437117395Skan for (l1 = CONSTRUCTOR_ELTS (t1), l2 = CONSTRUCTOR_ELTS (t2); 2438117395Skan l1 && l2; 2439117395Skan l1 = TREE_CHAIN (l1), l2 = TREE_CHAIN (l2)) 244018334Speter { 2441117395Skan /* Check that each value is the same... */ 2442117395Skan if (! compare_constant (TREE_VALUE (l1), TREE_VALUE (l2))) 2443117395Skan return 0; 2444117395Skan /* ... and that they apply to the same fields! */ 2445117395Skan if (typecode == ARRAY_TYPE) 244650397Sobrien { 2447117395Skan if (! compare_constant (TREE_PURPOSE (l1), 2448117395Skan TREE_PURPOSE (l2))) 244950397Sobrien return 0; 245050397Sobrien } 245150397Sobrien else 245250397Sobrien { 2453117395Skan if (TREE_PURPOSE (l1) != TREE_PURPOSE (l2)) 245450397Sobrien return 0; 245550397Sobrien } 245618334Speter } 245750397Sobrien 2458117395Skan return l1 == NULL_TREE && l2 == NULL_TREE; 245918334Speter } 246018334Speter 246150397Sobrien case ADDR_EXPR: 2462102780Skan case FDESC_EXPR: 246350397Sobrien { 2464117395Skan struct addr_const value1, value2; 246550397Sobrien 2466117395Skan decode_addr_const (t1, &value1); 2467117395Skan decode_addr_const (t2, &value2); 2468117395Skan return (value1.offset == value2.offset 2469117395Skan && strcmp (XSTR (value1.base, 0), XSTR (value2.base, 0)) == 0); 247050397Sobrien } 247150397Sobrien 247250397Sobrien case PLUS_EXPR: 247350397Sobrien case MINUS_EXPR: 247452284Sobrien case RANGE_EXPR: 2475117395Skan return (compare_constant (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0)) 2476117395Skan && compare_constant(TREE_OPERAND (t1, 1), TREE_OPERAND (t2, 1))); 247750397Sobrien 247850397Sobrien case NOP_EXPR: 247950397Sobrien case CONVERT_EXPR: 248050397Sobrien case NON_LVALUE_EXPR: 2481117395Skan return compare_constant (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0)); 248250397Sobrien 248350397Sobrien default: 248490075Sobrien { 2485117395Skan tree nt1, nt2; 2486117395Skan nt1 = (*lang_hooks.expand_constant) (t1); 2487117395Skan nt2 = (*lang_hooks.expand_constant) (t2); 2488117395Skan if (nt1 != t1 || nt2 != t2) 2489117395Skan return compare_constant (nt1, nt2); 249090075Sobrien else 249190075Sobrien return 0; 249290075Sobrien } 249318334Speter } 249418334Speter 2495117395Skan /* Should not get here. */ 2496117395Skan abort (); 249718334Speter} 249818334Speter 249918334Speter/* Record a list of constant expressions that were passed to 250018334Speter output_constant_def but that could not be output right away. */ 250118334Speter 250218334Speterstruct deferred_constant 250318334Speter{ 250418334Speter struct deferred_constant *next; 250518334Speter tree exp; 250618334Speter int reloc; 250718334Speter int labelno; 250818334Speter}; 250918334Speter 251018334Speterstatic struct deferred_constant *deferred_constants; 251118334Speter 251250397Sobrien/* Another list of constants which should be output after the 251350397Sobrien function. */ 251450397Sobrienstatic struct deferred_constant *after_function_constants; 251550397Sobrien 251618334Speter/* Nonzero means defer output of addressed subconstants 251718334Speter (i.e., those for which output_constant_def is called.) */ 251818334Speterstatic int defer_addressed_constants_flag; 251918334Speter 252018334Speter/* Start deferring output of subconstants. */ 252118334Speter 252218334Spetervoid 252318334Speterdefer_addressed_constants () 252418334Speter{ 252518334Speter defer_addressed_constants_flag++; 252618334Speter} 252718334Speter 252818334Speter/* Stop deferring output of subconstants, 252918334Speter and output now all those that have been deferred. */ 253018334Speter 253118334Spetervoid 253218334Speteroutput_deferred_addressed_constants () 253318334Speter{ 253418334Speter struct deferred_constant *p, *next; 253518334Speter 253618334Speter defer_addressed_constants_flag--; 253718334Speter 253818334Speter if (defer_addressed_constants_flag > 0) 253918334Speter return; 254018334Speter 254118334Speter for (p = deferred_constants; p; p = next) 254218334Speter { 254318334Speter output_constant_def_contents (p->exp, p->reloc, p->labelno); 254418334Speter next = p->next; 254518334Speter free (p); 254618334Speter } 254718334Speter 254818334Speter deferred_constants = 0; 254918334Speter} 255018334Speter 255150397Sobrien/* Output any constants which should appear after a function. */ 255250397Sobrien 255350397Sobrienstatic void 255450397Sobrienoutput_after_function_constants () 255550397Sobrien{ 255650397Sobrien struct deferred_constant *p, *next; 255750397Sobrien 255850397Sobrien for (p = after_function_constants; p; p = next) 255950397Sobrien { 256050397Sobrien output_constant_def_contents (p->exp, p->reloc, p->labelno); 256150397Sobrien next = p->next; 256250397Sobrien free (p); 256350397Sobrien } 256450397Sobrien 256550397Sobrien after_function_constants = 0; 256650397Sobrien} 256750397Sobrien 2568117395Skan/* Make a copy of the whole tree structure for a constant. This 2569117395Skan handles the same types of nodes that compare_constant handles. */ 257018334Speter 257118334Speterstatic tree 257218334Spetercopy_constant (exp) 257318334Speter tree exp; 257418334Speter{ 257518334Speter switch (TREE_CODE (exp)) 257618334Speter { 257718334Speter case ADDR_EXPR: 257818334Speter /* For ADDR_EXPR, we do not want to copy the decl whose address 257918334Speter is requested. We do want to copy constants though. */ 258018334Speter if (TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 0))) == 'c') 258118334Speter return build1 (TREE_CODE (exp), TREE_TYPE (exp), 258218334Speter copy_constant (TREE_OPERAND (exp, 0))); 258318334Speter else 258418334Speter return copy_node (exp); 258518334Speter 258618334Speter case INTEGER_CST: 258718334Speter case REAL_CST: 258818334Speter case STRING_CST: 258918334Speter return copy_node (exp); 259018334Speter 259118334Speter case COMPLEX_CST: 259250397Sobrien return build_complex (TREE_TYPE (exp), 259350397Sobrien copy_constant (TREE_REALPART (exp)), 259418334Speter copy_constant (TREE_IMAGPART (exp))); 259518334Speter 259618334Speter case PLUS_EXPR: 259718334Speter case MINUS_EXPR: 259818334Speter return build (TREE_CODE (exp), TREE_TYPE (exp), 259918334Speter copy_constant (TREE_OPERAND (exp, 0)), 260018334Speter copy_constant (TREE_OPERAND (exp, 1))); 260118334Speter 260218334Speter case NOP_EXPR: 260318334Speter case CONVERT_EXPR: 260450397Sobrien case NON_LVALUE_EXPR: 260518334Speter return build1 (TREE_CODE (exp), TREE_TYPE (exp), 260618334Speter copy_constant (TREE_OPERAND (exp, 0))); 260718334Speter 260818334Speter case CONSTRUCTOR: 260918334Speter { 261018334Speter tree copy = copy_node (exp); 261118334Speter tree list = copy_list (CONSTRUCTOR_ELTS (exp)); 261218334Speter tree tail; 261318334Speter 261418334Speter CONSTRUCTOR_ELTS (copy) = list; 261518334Speter for (tail = list; tail; tail = TREE_CHAIN (tail)) 261618334Speter TREE_VALUE (tail) = copy_constant (TREE_VALUE (tail)); 261718334Speter if (TREE_CODE (TREE_TYPE (exp)) == SET_TYPE) 261818334Speter for (tail = list; tail; tail = TREE_CHAIN (tail)) 261918334Speter TREE_PURPOSE (tail) = copy_constant (TREE_PURPOSE (tail)); 262018334Speter 262118334Speter return copy; 262218334Speter } 262318334Speter 262418334Speter default: 2625117395Skan { 2626117395Skan tree t; 2627117395Skan t = (*lang_hooks.expand_constant) (exp); 2628117395Skan if (t != exp) 2629117395Skan return copy_constant (t); 2630117395Skan else 2631117395Skan abort (); 2632117395Skan } 263318334Speter } 263418334Speter} 263518334Speter 263618334Speter/* Return an rtx representing a reference to constant data in memory 263718334Speter for the constant expression EXP. 263818334Speter 263918334Speter If assembler code for such a constant has already been output, 264018334Speter return an rtx to refer to it. 264118334Speter Otherwise, output such a constant in memory (or defer it for later) 264218334Speter and generate an rtx for it. 264318334Speter 2644117395Skan If DEFER is nonzero, the output of string constants can be deferred 264590075Sobrien and output only if referenced in the function after all optimizations. 264690075Sobrien 264718334Speter The TREE_CST_RTL of EXP is set up to point to that rtx. 264818334Speter The const_hash_table records which constants already have label strings. */ 264918334Speter 265018334Speterrtx 265190075Sobrienoutput_constant_def (exp, defer) 265218334Speter tree exp; 265390075Sobrien int defer; 265418334Speter{ 265590075Sobrien int hash; 2656117395Skan struct constant_descriptor_tree *desc; 265790075Sobrien struct deferred_string **defstr; 265818334Speter char label[256]; 265918334Speter int reloc; 266090075Sobrien int found = 1; 266190075Sobrien int after_function = 0; 266290075Sobrien int labelno = -1; 266390075Sobrien rtx rtl; 266418334Speter 2665117395Skan /* We can't just use the saved RTL if this is a deferred string constant 2666117395Skan and we are not to defer anymore. */ 266790075Sobrien if (TREE_CODE (exp) != INTEGER_CST && TREE_CST_RTL (exp) 266890075Sobrien && (defer || !STRING_POOL_ADDRESS_P (XEXP (TREE_CST_RTL (exp), 0)))) 266918334Speter return TREE_CST_RTL (exp); 267018334Speter 267118334Speter /* Make sure any other constants whose addresses appear in EXP 267218334Speter are assigned label numbers. */ 267318334Speter 267418334Speter reloc = output_addressed_constants (exp); 267518334Speter 267618334Speter /* Compute hash code of EXP. Search the descriptors for that hash code 267718334Speter to see if any of them describes EXP. If yes, the descriptor records 267818334Speter the label number already assigned. */ 267918334Speter 2680117395Skan hash = const_hash (exp); 268190075Sobrien 268218334Speter for (desc = const_hash_table[hash]; desc; desc = desc->next) 2683117395Skan if (compare_constant (exp, desc->value)) 268490075Sobrien break; 268590075Sobrien 268690075Sobrien if (desc == 0) 268718334Speter { 268818334Speter /* No constant equal to EXP is known to have been output. 268918334Speter Make a constant descriptor to enter EXP in the hash table. 269018334Speter Assign the label number and record it in the descriptor for 269118334Speter future calls to this function to find. */ 269290075Sobrien 269318334Speter /* Create a string containing the label name, in LABEL. */ 269490075Sobrien labelno = const_labelno++; 269590075Sobrien ASM_GENERATE_INTERNAL_LABEL (label, "LC", labelno); 269618334Speter 2697117395Skan desc = ggc_alloc (sizeof (*desc)); 269818334Speter desc->next = const_hash_table[hash]; 269990075Sobrien desc->label = ggc_strdup (label); 2700117395Skan desc->value = copy_constant (exp); 270118334Speter const_hash_table[hash] = desc; 270290075Sobrien 270390075Sobrien /* We have a symbol name; construct the SYMBOL_REF and the MEM. */ 270490075Sobrien rtl = desc->rtl 270590075Sobrien = gen_rtx_MEM (TYPE_MODE (TREE_TYPE (exp)), 270690075Sobrien gen_rtx_SYMBOL_REF (Pmode, desc->label)); 270790075Sobrien 270890075Sobrien set_mem_attributes (rtl, exp, 1); 270990075Sobrien set_mem_alias_set (rtl, 0); 271090075Sobrien set_mem_alias_set (rtl, const_alias_set); 271190075Sobrien 271290075Sobrien found = 0; 271318334Speter } 271418334Speter else 271590075Sobrien rtl = desc->rtl; 271618334Speter 271790075Sobrien if (TREE_CODE (exp) != INTEGER_CST) 271890075Sobrien TREE_CST_RTL (exp) = rtl; 271918334Speter 272018334Speter /* Optionally set flags or add text to the name to record information 272118334Speter such as that it is a function name. If the name is changed, the macro 272218334Speter ASM_OUTPUT_LABELREF will have to know how to strip this information. */ 272390075Sobrien /* A previously-processed constant would already have section info 272490075Sobrien encoded in it. */ 272590075Sobrien if (! found) 272690075Sobrien { 2727117395Skan /* Take care not to invoke targetm.encode_section_info for 2728117395Skan constants which don't have a TREE_CST_RTL. */ 272996263Sobrien if (TREE_CODE (exp) != INTEGER_CST) 2730117395Skan (*targetm.encode_section_info) (exp, true); 2731117395Skan 273290075Sobrien desc->rtl = rtl; 273390075Sobrien desc->label = XSTR (XEXP (desc->rtl, 0), 0); 273490075Sobrien } 273518334Speter 273690075Sobrien#ifdef CONSTANT_AFTER_FUNCTION_P 273790075Sobrien if (current_function_decl != 0 273890075Sobrien && CONSTANT_AFTER_FUNCTION_P (exp)) 273990075Sobrien after_function = 1; 274090075Sobrien#endif 274190075Sobrien 274290075Sobrien if (found 274390075Sobrien && STRING_POOL_ADDRESS_P (XEXP (rtl, 0)) 274490075Sobrien && (!defer || defer_addressed_constants_flag || after_function)) 274590075Sobrien { 274690075Sobrien defstr = (struct deferred_string **) 274790075Sobrien htab_find_slot_with_hash (const_str_htab, desc->label, 274890075Sobrien STRHASH (desc->label), NO_INSERT); 274990075Sobrien if (defstr) 275090075Sobrien { 275190075Sobrien /* If the string is currently deferred but we need to output it now, 275290075Sobrien remove it from deferred string hash table. */ 275390075Sobrien found = 0; 275490075Sobrien labelno = (*defstr)->labelno; 275590075Sobrien STRING_POOL_ADDRESS_P (XEXP (rtl, 0)) = 0; 275690075Sobrien htab_clear_slot (const_str_htab, (void **) defstr); 275790075Sobrien } 275890075Sobrien } 275990075Sobrien 276018334Speter /* If this is the first time we've seen this particular constant, 276118334Speter output it (or defer its output for later). */ 276290075Sobrien if (! found) 276318334Speter { 276450397Sobrien if (defer_addressed_constants_flag || after_function) 276518334Speter { 276690075Sobrien struct deferred_constant *p 276790075Sobrien = (struct deferred_constant *) 276890075Sobrien xmalloc (sizeof (struct deferred_constant)); 276918334Speter 2770117395Skan p->exp = desc->value; 277118334Speter p->reloc = reloc; 277290075Sobrien p->labelno = labelno; 277350397Sobrien if (after_function) 277450397Sobrien { 277550397Sobrien p->next = after_function_constants; 277650397Sobrien after_function_constants = p; 277750397Sobrien } 277850397Sobrien else 277950397Sobrien { 278050397Sobrien p->next = deferred_constants; 278150397Sobrien deferred_constants = p; 278250397Sobrien } 278318334Speter } 278418334Speter else 278552284Sobrien { 278652284Sobrien /* Do no output if -fsyntax-only. */ 278752284Sobrien if (! flag_syntax_only) 278890075Sobrien { 278990075Sobrien if (TREE_CODE (exp) != STRING_CST 279090075Sobrien || !defer 279190075Sobrien || flag_writable_strings 279290075Sobrien || (defstr = (struct deferred_string **) 279390075Sobrien htab_find_slot_with_hash (const_str_htab, 279490075Sobrien desc->label, 279590075Sobrien STRHASH (desc->label), 279690075Sobrien INSERT)) == NULL) 279790075Sobrien output_constant_def_contents (exp, reloc, labelno); 279890075Sobrien else 279990075Sobrien { 280090075Sobrien struct deferred_string *p; 280190075Sobrien 280290075Sobrien p = (struct deferred_string *) 2803117395Skan ggc_alloc (sizeof (struct deferred_string)); 280490075Sobrien 2805117395Skan p->exp = desc->value; 280690075Sobrien p->label = desc->label; 280790075Sobrien p->labelno = labelno; 280890075Sobrien *defstr = p; 280990075Sobrien STRING_POOL_ADDRESS_P (XEXP (rtl, 0)) = 1; 281090075Sobrien } 281190075Sobrien } 281252284Sobrien } 281318334Speter } 281418334Speter 281590075Sobrien return rtl; 281618334Speter} 281718334Speter 281818334Speter/* Now output assembler code to define the label for EXP, 281918334Speter and follow it with the data of EXP. */ 282018334Speter 282118334Speterstatic void 282218334Speteroutput_constant_def_contents (exp, reloc, labelno) 282318334Speter tree exp; 282418334Speter int reloc; 282518334Speter int labelno; 282618334Speter{ 282718334Speter int align; 282818334Speter 282990075Sobrien /* Align the location counter as required by EXP's data type. */ 283090075Sobrien align = TYPE_ALIGN (TREE_TYPE (exp)); 283190075Sobrien#ifdef CONSTANT_ALIGNMENT 283290075Sobrien align = CONSTANT_ALIGNMENT (exp, align); 283390075Sobrien#endif 283490075Sobrien 283518334Speter if (IN_NAMED_SECTION (exp)) 283650397Sobrien named_section (exp, NULL, reloc); 283718334Speter else 2838117395Skan (*targetm.asm_out.select_section) (exp, reloc, align); 283918334Speter 284018334Speter if (align > BITS_PER_UNIT) 284190075Sobrien { 284290075Sobrien ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (align / BITS_PER_UNIT)); 284390075Sobrien } 284418334Speter 284518334Speter /* Output the label itself. */ 284618334Speter ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LC", labelno); 284718334Speter 284818334Speter /* Output the value of EXP. */ 284918334Speter output_constant (exp, 285018334Speter (TREE_CODE (exp) == STRING_CST 285190075Sobrien ? MAX (TREE_STRING_LENGTH (exp), 285290075Sobrien int_size_in_bytes (TREE_TYPE (exp))) 285390075Sobrien : int_size_in_bytes (TREE_TYPE (exp))), 285490075Sobrien align); 285518334Speter 285618334Speter} 285718334Speter 2858117395Skan/* Used in the hash tables to avoid outputting the same constant 2859117395Skan twice. Unlike 'struct constant_descriptor_tree', RTX constants 2860117395Skan are output once per function, not once per file; there seems 2861117395Skan to be no reason for the difference. */ 2862117395Skan 2863117395Skanstruct constant_descriptor_rtx GTY(()) 2864117395Skan{ 2865117395Skan /* More constant_descriptors with the same hash code. */ 2866117395Skan struct constant_descriptor_rtx *next; 2867117395Skan 2868117395Skan /* A MEM for the constant. */ 2869117395Skan rtx rtl; 2870117395Skan 2871117395Skan /* The value of the constant. */ 2872117395Skan struct rtx_const value; 2873117395Skan}; 2874117395Skan 287518334Speter/* Structure to represent sufficient information about a constant so that 287618334Speter it can be output when the constant pool is output, so that function 287718334Speter integration can be done, and to simplify handling on machines that reference 287818334Speter constant pool as base+displacement. */ 287918334Speter 2880117395Skanstruct pool_constant GTY(()) 288118334Speter{ 2882117395Skan struct constant_descriptor_rtx *desc; 2883117395Skan struct pool_constant *next; 2884117395Skan struct pool_constant *next_sym; 288590075Sobrien rtx constant; 288618334Speter enum machine_mode mode; 288718334Speter int labelno; 288890075Sobrien unsigned int align; 288990075Sobrien HOST_WIDE_INT offset; 289050397Sobrien int mark; 289118334Speter}; 289218334Speter 289318334Speter/* Hash code for a SYMBOL_REF with CONSTANT_POOL_ADDRESS_P true. 289418334Speter The argument is XSTR (... , 0) */ 289518334Speter 2896117395Skan#define SYMHASH(LABEL) (((unsigned long) (LABEL)) % MAX_RTX_HASH_TABLE) 289718334Speter 289890075Sobrien/* Initialize constant pool hashing for a new function. */ 289918334Speter 290018334Spetervoid 290190075Sobrieninit_varasm_status (f) 290290075Sobrien struct function *f; 290318334Speter{ 290490075Sobrien struct varasm_status *p; 2905117395Skan p = (struct varasm_status *) ggc_alloc (sizeof (struct varasm_status)); 290690075Sobrien f->varasm = p; 290790075Sobrien p->x_const_rtx_hash_table 2908117395Skan = ((struct constant_descriptor_rtx **) 2909117395Skan ggc_alloc_cleared (MAX_RTX_HASH_TABLE 2910117395Skan * sizeof (struct constant_descriptor_rtx *))); 291190075Sobrien p->x_const_rtx_sym_hash_table 291290075Sobrien = ((struct pool_constant **) 2913117395Skan ggc_alloc_cleared (MAX_RTX_HASH_TABLE 2914117395Skan * sizeof (struct pool_constant *))); 291518334Speter 291690075Sobrien p->x_first_pool = p->x_last_pool = 0; 291790075Sobrien p->x_pool_offset = 0; 291818334Speter} 291918334Speter 292018334Speter 292118334Speter/* Express an rtx for a constant integer (perhaps symbolic) 292218334Speter as the sum of a symbol or label plus an explicit integer. 292318334Speter They are stored into VALUE. */ 292418334Speter 292518334Speterstatic void 292618334Speterdecode_rtx_const (mode, x, value) 292718334Speter enum machine_mode mode; 292818334Speter rtx x; 292918334Speter struct rtx_const *value; 293018334Speter{ 293118334Speter /* Clear the whole structure, including any gaps. */ 293290075Sobrien memset (value, 0, sizeof (struct rtx_const)); 293318334Speter 293450397Sobrien value->kind = RTX_INT; /* Most usual kind. */ 293518334Speter value->mode = mode; 293618334Speter 293718334Speter switch (GET_CODE (x)) 293818334Speter { 293918334Speter case CONST_DOUBLE: 294018334Speter value->kind = RTX_DOUBLE; 294118334Speter if (GET_MODE (x) != VOIDmode) 294218334Speter { 2943117395Skan const REAL_VALUE_TYPE *r = CONST_DOUBLE_REAL_VALUE (x); 2944117395Skan 294518334Speter value->mode = GET_MODE (x); 2946117395Skan 2947117395Skan /* Copy the REAL_VALUE_TYPE by members so that we don't 2948117395Skan copy garbage from the original structure into our 2949117395Skan carefully cleaned hashing structure. */ 2950117395Skan value->un.du.class = r->class; 2951117395Skan value->un.du.sign = r->sign; 2952117395Skan switch (r->class) 2953117395Skan { 2954117395Skan case rvc_zero: 2955117395Skan case rvc_inf: 2956117395Skan break; 2957117395Skan case rvc_normal: 2958117395Skan value->un.du.exp = r->exp; 2959117395Skan /* FALLTHRU */ 2960117395Skan case rvc_nan: 2961117395Skan memcpy (value->un.du.sig, r->sig, sizeof (r->sig)); 2962117395Skan break; 2963117395Skan default: 2964117395Skan abort (); 2965117395Skan } 296618334Speter } 296718334Speter else 296818334Speter { 296918334Speter value->un.di.low = CONST_DOUBLE_LOW (x); 297018334Speter value->un.di.high = CONST_DOUBLE_HIGH (x); 297118334Speter } 297218334Speter break; 297318334Speter 297496263Sobrien case CONST_VECTOR: 297596263Sobrien { 297696263Sobrien int units, i; 297796263Sobrien 297896263Sobrien units = CONST_VECTOR_NUNITS (x); 297996263Sobrien value->kind = RTX_VECTOR; 298096263Sobrien value->mode = mode; 298196263Sobrien 2982117395Skan if (GET_MODE_CLASS (mode) == MODE_VECTOR_INT) 298396263Sobrien { 2984117395Skan for (i = 0; i < units; ++i) 298596263Sobrien { 2986117395Skan rtx elt = CONST_VECTOR_ELT (x, i); 2987117395Skan if (GET_CODE (elt) == CONST_INT) 2988117395Skan { 2989117395Skan value->un.int_vec[i].low = INTVAL (elt); 2990117395Skan value->un.int_vec[i].high = 0; 2991117395Skan } 2992117395Skan else 2993117395Skan { 2994117395Skan value->un.int_vec[i].low = CONST_DOUBLE_LOW (elt); 2995117395Skan value->un.int_vec[i].high = CONST_DOUBLE_HIGH (elt); 2996117395Skan } 299796263Sobrien } 2998117395Skan } 2999117395Skan else if (GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT) 3000117395Skan { 3001117395Skan for (i = 0; i < units; ++i) 300296263Sobrien { 3003117395Skan const REAL_VALUE_TYPE *r 3004117395Skan = CONST_DOUBLE_REAL_VALUE (CONST_VECTOR_ELT (x, i)); 3005117395Skan REAL_VALUE_TYPE *d = &value->un.fp_vec[i]; 3006117395Skan 3007117395Skan /* Copy the REAL_VALUE_TYPE by members so that we don't 3008117395Skan copy garbage from the original structure into our 3009117395Skan carefully cleaned hashing structure. */ 3010117395Skan d->class = r->class; 3011117395Skan d->sign = r->sign; 3012117395Skan switch (r->class) 3013117395Skan { 3014117395Skan case rvc_zero: 3015117395Skan case rvc_inf: 3016117395Skan break; 3017117395Skan case rvc_normal: 3018117395Skan d->exp = r->exp; 3019117395Skan /* FALLTHRU */ 3020117395Skan case rvc_nan: 3021117395Skan memcpy (d->sig, r->sig, sizeof (r->sig)); 3022117395Skan break; 3023117395Skan default: 3024117395Skan abort (); 3025117395Skan } 302696263Sobrien } 302796263Sobrien } 3028117395Skan else 3029117395Skan abort (); 303096263Sobrien } 303196263Sobrien break; 303296263Sobrien 303318334Speter case CONST_INT: 303418334Speter value->un.addr.offset = INTVAL (x); 303518334Speter break; 303618334Speter 303718334Speter case SYMBOL_REF: 303818334Speter case LABEL_REF: 303918334Speter case PC: 304018334Speter value->un.addr.base = x; 304118334Speter break; 304218334Speter 304318334Speter case CONST: 304418334Speter x = XEXP (x, 0); 304590075Sobrien if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 1)) == CONST_INT) 304618334Speter { 304718334Speter value->un.addr.base = XEXP (x, 0); 304818334Speter value->un.addr.offset = INTVAL (XEXP (x, 1)); 304918334Speter } 305090075Sobrien else if (GET_CODE (x) == MINUS && GET_CODE (XEXP (x, 1)) == CONST_INT) 305118334Speter { 305218334Speter value->un.addr.base = XEXP (x, 0); 305318334Speter value->un.addr.offset = - INTVAL (XEXP (x, 1)); 305418334Speter } 305518334Speter else 305690075Sobrien { 305790075Sobrien value->un.addr.base = x; 305890075Sobrien value->un.addr.offset = 0; 305990075Sobrien } 306018334Speter break; 306118334Speter 306218334Speter default: 306396263Sobrien value->kind = RTX_UNKNOWN; 306496263Sobrien break; 306518334Speter } 306618334Speter 306796263Sobrien if (value->kind == RTX_INT && value->un.addr.base != 0 306896263Sobrien && GET_CODE (value->un.addr.base) == UNSPEC) 3069117395Skan { 307096263Sobrien /* For a simple UNSPEC, the base is set to the 307196263Sobrien operand, the kind field is set to the index of 3072117395Skan the unspec expression. 307396263Sobrien Together with the code below, in case that 3074117395Skan the operand is a SYMBOL_REF or LABEL_REF, 3075117395Skan the address of the string or the code_label 307696263Sobrien is taken as base. */ 307796263Sobrien if (XVECLEN (value->un.addr.base, 0) == 1) 3078117395Skan { 307996263Sobrien value->kind = RTX_UNSPEC + XINT (value->un.addr.base, 1); 308096263Sobrien value->un.addr.base = XVECEXP (value->un.addr.base, 0, 0); 308196263Sobrien } 308296263Sobrien } 308396263Sobrien 3084117395Skan if (value->kind >= RTX_INT && value->un.addr.base != 0) 308518334Speter switch (GET_CODE (value->un.addr.base)) 308618334Speter { 308718334Speter case SYMBOL_REF: 308890075Sobrien /* Use the string's address, not the SYMBOL_REF's address, 308990075Sobrien for the sake of addresses of library routines. */ 3090117395Skan value->un.addr.symbol = XSTR (value->un.addr.base, 0); 3091117395Skan value->un.addr.base = NULL_RTX; 309290075Sobrien break; 309390075Sobrien 309418334Speter case LABEL_REF: 309590075Sobrien /* For a LABEL_REF, compare labels. */ 309618334Speter value->un.addr.base = XEXP (value->un.addr.base, 0); 309790075Sobrien 309850397Sobrien default: 309950397Sobrien break; 310018334Speter } 310118334Speter} 310218334Speter 310318334Speter/* Given a MINUS expression, simplify it if both sides 310418334Speter include the same symbol. */ 310518334Speter 310618334Speterrtx 310718334Spetersimplify_subtraction (x) 310818334Speter rtx x; 310918334Speter{ 311018334Speter struct rtx_const val0, val1; 311118334Speter 311218334Speter decode_rtx_const (GET_MODE (x), XEXP (x, 0), &val0); 311318334Speter decode_rtx_const (GET_MODE (x), XEXP (x, 1), &val1); 311418334Speter 3115117395Skan if (val0.kind >= RTX_INT 311696263Sobrien && val0.kind == val1.kind 3117117395Skan && val0.un.addr.base == val1.un.addr.base 3118117395Skan && val0.un.addr.symbol == val1.un.addr.symbol) 311918334Speter return GEN_INT (val0.un.addr.offset - val1.un.addr.offset); 312096263Sobrien 312118334Speter return x; 312218334Speter} 312318334Speter 312418334Speter/* Compute a hash code for a constant RTL expression. */ 312518334Speter 3126117395Skanstatic unsigned int 312718334Speterconst_hash_rtx (mode, x) 312818334Speter enum machine_mode mode; 312918334Speter rtx x; 313018334Speter{ 3131117395Skan union { 3132117395Skan struct rtx_const value; 3133117395Skan unsigned int data[sizeof(struct rtx_const) / sizeof (unsigned int)]; 3134117395Skan } u; 3135117395Skan 3136117395Skan unsigned int hi; 313790075Sobrien size_t i; 313818334Speter 3139117395Skan decode_rtx_const (mode, x, &u.value); 314018334Speter 314118334Speter /* Compute hashing function */ 314218334Speter hi = 0; 3143117395Skan for (i = 0; i < ARRAY_SIZE (u.data); i++) 3144117395Skan hi = hi * 613 + u.data[i]; 314518334Speter 3146117395Skan return hi % MAX_RTX_HASH_TABLE; 314718334Speter} 314818334Speter 314918334Speter/* Compare a constant rtl object X with a constant-descriptor DESC. 315018334Speter Return 1 if DESC describes a constant with the same value as X. */ 315118334Speter 315218334Speterstatic int 315318334Spetercompare_constant_rtx (mode, x, desc) 315418334Speter enum machine_mode mode; 315518334Speter rtx x; 3156117395Skan struct constant_descriptor_rtx *desc; 315718334Speter{ 315818334Speter struct rtx_const value; 315918334Speter 316018334Speter decode_rtx_const (mode, x, &value); 316118334Speter 316218334Speter /* Compare constant contents. */ 3163117395Skan return memcmp (&value, &desc->value, sizeof (struct rtx_const)) == 0; 316418334Speter} 316518334Speter 316618334Speter/* Construct a constant descriptor for the rtl-expression X. 316718334Speter It is up to the caller to enter the descriptor in the hash table. */ 316818334Speter 3169117395Skanstatic struct constant_descriptor_rtx * 317018334Speterrecord_constant_rtx (mode, x) 317118334Speter enum machine_mode mode; 317218334Speter rtx x; 317318334Speter{ 3174117395Skan struct constant_descriptor_rtx *ptr; 317518334Speter 3176117395Skan ptr = (struct constant_descriptor_rtx *) ggc_alloc (sizeof (*ptr)); 3177117395Skan decode_rtx_const (mode, x, &ptr->value); 317818334Speter 317990075Sobrien return ptr; 318090075Sobrien} 318190075Sobrien 318290075Sobrien/* Given a constant rtx X, return a MEM for the location in memory at which 318390075Sobrien this constant has been placed. Return 0 if it not has been placed yet. */ 318418334Speter 318590075Sobrienrtx 318690075Sobrienmem_for_const_double (x) 318790075Sobrien rtx x; 318890075Sobrien{ 318990075Sobrien enum machine_mode mode = GET_MODE (x); 3190117395Skan struct constant_descriptor_rtx *desc; 319118334Speter 319290075Sobrien for (desc = const_rtx_hash_table[const_hash_rtx (mode, x)]; desc; 319390075Sobrien desc = desc->next) 319490075Sobrien if (compare_constant_rtx (mode, x, desc)) 319590075Sobrien return desc->rtl; 319690075Sobrien 319790075Sobrien return 0; 319818334Speter} 3199117395Skan 320018334Speter/* Given a constant rtx X, make (or find) a memory constant for its value 320118334Speter and return a MEM rtx to refer to it in memory. */ 320218334Speter 320318334Speterrtx 320418334Speterforce_const_mem (mode, x) 320518334Speter enum machine_mode mode; 320618334Speter rtx x; 320718334Speter{ 320890075Sobrien int hash; 3209117395Skan struct constant_descriptor_rtx *desc; 321018334Speter char label[256]; 321118334Speter rtx def; 321290075Sobrien struct pool_constant *pool; 321390075Sobrien unsigned int align; 321418334Speter 3215117395Skan /* If we're not allowed to drop X into the constant pool, don't. */ 3216117395Skan if ((*targetm.cannot_force_const_mem) (x)) 3217117395Skan return NULL_RTX; 3218117395Skan 321918334Speter /* Compute hash code of X. Search the descriptors for that hash code 322090075Sobrien to see if any of them describes X. If yes, we have an rtx to use. */ 322118334Speter hash = const_hash_rtx (mode, x); 322218334Speter for (desc = const_rtx_hash_table[hash]; desc; desc = desc->next) 322318334Speter if (compare_constant_rtx (mode, x, desc)) 322490075Sobrien return desc->rtl; 322518334Speter 322690075Sobrien /* No constant equal to X is known to have been output. 322790075Sobrien Make a constant descriptor to enter X in the hash table 322890075Sobrien and make a MEM for it. */ 322990075Sobrien desc = record_constant_rtx (mode, x); 323090075Sobrien desc->next = const_rtx_hash_table[hash]; 323190075Sobrien const_rtx_hash_table[hash] = desc; 3232117395Skan 323390075Sobrien /* Align the location counter as required by EXP's data type. */ 323490075Sobrien align = GET_MODE_ALIGNMENT (mode == VOIDmode ? word_mode : mode); 323550397Sobrien#ifdef CONSTANT_ALIGNMENT 3236117395Skan align = CONSTANT_ALIGNMENT (make_tree ((*lang_hooks.types.type_for_mode) 3237117395Skan (mode, 0), x), align); 323850397Sobrien#endif 323918334Speter 324090075Sobrien pool_offset += (align / BITS_PER_UNIT) - 1; 324190075Sobrien pool_offset &= ~ ((align / BITS_PER_UNIT) - 1); 324218334Speter 324390075Sobrien if (GET_CODE (x) == LABEL_REF) 324490075Sobrien LABEL_PRESERVE_P (XEXP (x, 0)) = 1; 324518334Speter 324690075Sobrien /* Allocate a pool constant descriptor, fill it in, and chain it in. */ 324790075Sobrien pool = (struct pool_constant *) ggc_alloc (sizeof (struct pool_constant)); 324890075Sobrien pool->desc = desc; 324990075Sobrien pool->constant = x; 325090075Sobrien pool->mode = mode; 325190075Sobrien pool->labelno = const_labelno; 325290075Sobrien pool->align = align; 325390075Sobrien pool->offset = pool_offset; 325490075Sobrien pool->mark = 1; 325590075Sobrien pool->next = 0; 325650397Sobrien 325790075Sobrien if (last_pool == 0) 325890075Sobrien first_pool = pool; 325990075Sobrien else 326090075Sobrien last_pool->next = pool; 3261117395Skan 326290075Sobrien last_pool = pool; 326390075Sobrien pool_offset += GET_MODE_SIZE (mode); 326418334Speter 326590075Sobrien /* Create a string containing the label name, in LABEL. */ 326690075Sobrien ASM_GENERATE_INTERNAL_LABEL (label, "LC", const_labelno); 326774722Sobrien 326890075Sobrien ++const_labelno; 326974722Sobrien 327090075Sobrien /* Construct the SYMBOL_REF and the MEM. */ 327118334Speter 327290075Sobrien pool->desc->rtl = def 327390075Sobrien = gen_rtx_MEM (mode, gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (label))); 327490075Sobrien set_mem_alias_set (def, const_alias_set); 3275117395Skan set_mem_attributes (def, (*lang_hooks.types.type_for_mode) (mode, 0), 1); 327690075Sobrien RTX_UNCHANGING_P (def) = 1; 327718334Speter 327890075Sobrien /* Add label to symbol hash table. */ 327990075Sobrien hash = SYMHASH (XSTR (XEXP (def, 0), 0)); 328090075Sobrien pool->next_sym = const_rtx_sym_hash_table[hash]; 328190075Sobrien const_rtx_sym_hash_table[hash] = pool; 328218334Speter 328318334Speter /* Mark the symbol_ref as belonging to this constants pool. */ 328418334Speter CONSTANT_POOL_ADDRESS_P (XEXP (def, 0)) = 1; 328518334Speter current_function_uses_const_pool = 1; 328618334Speter 328718334Speter return def; 328818334Speter} 328918334Speter 329018334Speter/* Given a SYMBOL_REF with CONSTANT_POOL_ADDRESS_P true, return a pointer to 329118334Speter the corresponding pool_constant structure. */ 329218334Speter 329318334Speterstatic struct pool_constant * 329490075Sobrienfind_pool_constant (f, addr) 329590075Sobrien struct function *f; 329618334Speter rtx addr; 329718334Speter{ 329890075Sobrien struct pool_constant *pool; 329990075Sobrien const char *label = XSTR (addr, 0); 330018334Speter 330190075Sobrien for (pool = f->varasm->x_const_rtx_sym_hash_table[SYMHASH (label)]; pool; 330290075Sobrien pool = pool->next_sym) 330390075Sobrien if (XSTR (XEXP (pool->desc->rtl, 0), 0) == label) 330490075Sobrien return pool; 330518334Speter 330618334Speter abort (); 330718334Speter} 330818334Speter 330918334Speter/* Given a constant pool SYMBOL_REF, return the corresponding constant. */ 331018334Speter 331118334Speterrtx 331218334Speterget_pool_constant (addr) 331318334Speter rtx addr; 331418334Speter{ 331590075Sobrien return (find_pool_constant (cfun, addr))->constant; 331618334Speter} 331718334Speter 331896263Sobrien/* Given a constant pool SYMBOL_REF, return the corresponding constant 331996263Sobrien and whether it has been output or not. */ 332096263Sobrien 332196263Sobrienrtx 332296263Sobrienget_pool_constant_mark (addr, pmarked) 332396263Sobrien rtx addr; 332496263Sobrien bool *pmarked; 332596263Sobrien{ 332696263Sobrien struct pool_constant *pool = find_pool_constant (cfun, addr); 332796263Sobrien *pmarked = (pool->mark != 0); 332896263Sobrien return pool->constant; 332996263Sobrien} 333096263Sobrien 333190075Sobrien/* Likewise, but for the constant pool of a specific function. */ 333290075Sobrien 333390075Sobrienrtx 333490075Sobrienget_pool_constant_for_function (f, addr) 333590075Sobrien struct function *f; 333690075Sobrien rtx addr; 333790075Sobrien{ 333890075Sobrien return (find_pool_constant (f, addr))->constant; 333990075Sobrien} 334090075Sobrien 334118334Speter/* Similar, return the mode. */ 334218334Speter 334318334Speterenum machine_mode 334418334Speterget_pool_mode (addr) 334518334Speter rtx addr; 334618334Speter{ 334790075Sobrien return (find_pool_constant (cfun, addr))->mode; 334818334Speter} 334918334Speter 335090075Sobrienenum machine_mode 335190075Sobrienget_pool_mode_for_function (f, addr) 335290075Sobrien struct function *f; 335390075Sobrien rtx addr; 335490075Sobrien{ 335590075Sobrien return (find_pool_constant (f, addr))->mode; 335690075Sobrien} 335790075Sobrien 335818334Speter/* Similar, return the offset in the constant pool. */ 335918334Speter 336018334Speterint 336118334Speterget_pool_offset (addr) 336218334Speter rtx addr; 336318334Speter{ 336490075Sobrien return (find_pool_constant (cfun, addr))->offset; 336518334Speter} 336618334Speter 336718334Speter/* Return the size of the constant pool. */ 336818334Speter 336918334Speterint 337018334Speterget_pool_size () 337118334Speter{ 337218334Speter return pool_offset; 337318334Speter} 337418334Speter 337518334Speter/* Write all the constants in the constant pool. */ 337618334Speter 337718334Spetervoid 337818334Speteroutput_constant_pool (fnname, fndecl) 3379117395Skan const char *fnname ATTRIBUTE_UNUSED; 3380117395Skan tree fndecl ATTRIBUTE_UNUSED; 338118334Speter{ 338218334Speter struct pool_constant *pool; 338318334Speter rtx x; 3384117395Skan REAL_VALUE_TYPE r; 338518334Speter 338650397Sobrien /* It is possible for gcc to call force_const_mem and then to later 338750397Sobrien discard the instructions which refer to the constant. In such a 338850397Sobrien case we do not need to output the constant. */ 338952284Sobrien mark_constant_pool (); 339050397Sobrien 339118334Speter#ifdef ASM_OUTPUT_POOL_PROLOGUE 339218334Speter ASM_OUTPUT_POOL_PROLOGUE (asm_out_file, fnname, fndecl, pool_offset); 339318334Speter#endif 339418334Speter 339518334Speter for (pool = first_pool; pool; pool = pool->next) 339618334Speter { 339790075Sobrien rtx tmp; 339890075Sobrien 339918334Speter x = pool->constant; 340018334Speter 340150397Sobrien if (! pool->mark) 340250397Sobrien continue; 340350397Sobrien 340418334Speter /* See if X is a LABEL_REF (or a CONST referring to a LABEL_REF) 340518334Speter whose CODE_LABEL has been deleted. This can occur if a jump table 340618334Speter is eliminated by optimization. If so, write a constant of zero 340718334Speter instead. Note that this can also happen by turning the 340818334Speter CODE_LABEL into a NOTE. */ 340990075Sobrien /* ??? This seems completely and utterly wrong. Certainly it's 341090075Sobrien not true for NOTE_INSN_DELETED_LABEL, but I disbelieve proper 341190075Sobrien functioning even with INSN_DELETED_P and friends. */ 341218334Speter 341390075Sobrien tmp = x; 341490075Sobrien switch (GET_CODE (x)) 341590075Sobrien { 341690075Sobrien case CONST: 341790075Sobrien if (GET_CODE (XEXP (x, 0)) != PLUS 341890075Sobrien || GET_CODE (XEXP (XEXP (x, 0), 0)) != LABEL_REF) 341990075Sobrien break; 342090075Sobrien tmp = XEXP (XEXP (x, 0), 0); 342190075Sobrien /* FALLTHRU */ 342290075Sobrien 342390075Sobrien case LABEL_REF: 342490075Sobrien tmp = XEXP (x, 0); 342590075Sobrien if (INSN_DELETED_P (tmp) 342690075Sobrien || (GET_CODE (tmp) == NOTE 342790075Sobrien && NOTE_LINE_NUMBER (tmp) == NOTE_INSN_DELETED)) 342890075Sobrien { 342990075Sobrien abort (); 343090075Sobrien x = const0_rtx; 343190075Sobrien } 343290075Sobrien break; 343390075Sobrien 343490075Sobrien default: 343590075Sobrien break; 343690075Sobrien } 343790075Sobrien 343818334Speter /* First switch to correct section. */ 3439117395Skan (*targetm.asm_out.select_rtx_section) (pool->mode, x, pool->align); 344018334Speter 344118334Speter#ifdef ASM_OUTPUT_SPECIAL_POOL_ENTRY 344218334Speter ASM_OUTPUT_SPECIAL_POOL_ENTRY (asm_out_file, x, pool->mode, 344318334Speter pool->align, pool->labelno, done); 344418334Speter#endif 344518334Speter 344690075Sobrien assemble_align (pool->align); 344718334Speter 344818334Speter /* Output the label. */ 344918334Speter ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, "LC", pool->labelno); 345018334Speter 345118334Speter /* Output the value of the constant itself. */ 345218334Speter switch (GET_MODE_CLASS (pool->mode)) 345318334Speter { 345418334Speter case MODE_FLOAT: 345518334Speter if (GET_CODE (x) != CONST_DOUBLE) 345618334Speter abort (); 345718334Speter 3458117395Skan REAL_VALUE_FROM_CONST_DOUBLE (r, x); 3459117395Skan assemble_real (r, pool->mode, pool->align); 346018334Speter break; 346118334Speter 346218334Speter case MODE_INT: 346318334Speter case MODE_PARTIAL_INT: 346490075Sobrien assemble_integer (x, GET_MODE_SIZE (pool->mode), pool->align, 1); 346518334Speter break; 346618334Speter 346796263Sobrien case MODE_VECTOR_FLOAT: 346896263Sobrien { 346996263Sobrien int i, units; 347096263Sobrien rtx elt; 347196263Sobrien 347296263Sobrien if (GET_CODE (x) != CONST_VECTOR) 347396263Sobrien abort (); 347496263Sobrien 347596263Sobrien units = CONST_VECTOR_NUNITS (x); 347696263Sobrien 347796263Sobrien for (i = 0; i < units; i++) 347896263Sobrien { 347996263Sobrien elt = CONST_VECTOR_ELT (x, i); 3480117395Skan REAL_VALUE_FROM_CONST_DOUBLE (r, elt); 3481117395Skan assemble_real (r, GET_MODE_INNER (pool->mode), pool->align); 348296263Sobrien } 348396263Sobrien } 348496263Sobrien break; 348596263Sobrien 3486117395Skan case MODE_VECTOR_INT: 348796263Sobrien { 348896263Sobrien int i, units; 348996263Sobrien rtx elt; 349096263Sobrien 349196263Sobrien if (GET_CODE (x) != CONST_VECTOR) 349296263Sobrien abort (); 349396263Sobrien 349496263Sobrien units = CONST_VECTOR_NUNITS (x); 349596263Sobrien 349696263Sobrien for (i = 0; i < units; i++) 349796263Sobrien { 349896263Sobrien elt = CONST_VECTOR_ELT (x, i); 349996263Sobrien assemble_integer (elt, GET_MODE_UNIT_SIZE (pool->mode), 350096263Sobrien pool->align, 1); 350196263Sobrien } 350296263Sobrien } 350396263Sobrien break; 350496263Sobrien 350518334Speter default: 350618334Speter abort (); 350718334Speter } 350818334Speter 3509117395Skan /* Make sure all constants in SECTION_MERGE and not SECTION_STRINGS 3510117395Skan sections have proper size. */ 3511117395Skan if (pool->align > GET_MODE_BITSIZE (pool->mode) 3512117395Skan && in_section == in_named 3513117395Skan && get_named_section_flags (in_named_name) & SECTION_MERGE) 3514117395Skan assemble_align (pool->align); 3515117395Skan 351650397Sobrien#ifdef ASM_OUTPUT_SPECIAL_POOL_ENTRY 351718334Speter done: ; 351850397Sobrien#endif 351918334Speter } 352018334Speter 352150397Sobrien#ifdef ASM_OUTPUT_POOL_EPILOGUE 352250397Sobrien ASM_OUTPUT_POOL_EPILOGUE (asm_out_file, fnname, fndecl, pool_offset); 352350397Sobrien#endif 352450397Sobrien 352518334Speter /* Done with this pool. */ 352618334Speter first_pool = last_pool = 0; 352718334Speter} 352850397Sobrien 352950397Sobrien/* Look through the instructions for this function, and mark all the 353090075Sobrien entries in the constant pool which are actually being used. 353190075Sobrien Emit used deferred strings. */ 353250397Sobrien 353350397Sobrienstatic void 353450397Sobrienmark_constant_pool () 353550397Sobrien{ 353690075Sobrien rtx insn; 3537117395Skan rtx link; 353850397Sobrien struct pool_constant *pool; 353950397Sobrien 354090075Sobrien if (first_pool == 0 && htab_elements (const_str_htab) == 0) 354150397Sobrien return; 354250397Sobrien 354350397Sobrien for (pool = first_pool; pool; pool = pool->next) 354450397Sobrien pool->mark = 0; 354550397Sobrien 354650397Sobrien for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) 354790075Sobrien if (INSN_P (insn)) 354850397Sobrien mark_constants (PATTERN (insn)); 354950397Sobrien 3550117395Skan for (link = current_function_epilogue_delay_list; 3551117395Skan link; 3552117395Skan link = XEXP (link, 1)) 3553117395Skan { 3554117395Skan insn = XEXP (link, 0); 3555117395Skan 3556117395Skan if (INSN_P (insn)) 3557117395Skan mark_constants (PATTERN (insn)); 3558117395Skan } 355990075Sobrien} 356052284Sobrien 356190075Sobrien/* Look through appropriate parts of X, marking all entries in the 356290075Sobrien constant pool which are actually being used. Entries that are only 356390075Sobrien referenced by other constants are also marked as used. Emit 356490075Sobrien deferred strings that are used. */ 356552284Sobrien 356650397Sobrienstatic void 356750397Sobrienmark_constants (x) 356890075Sobrien rtx x; 356950397Sobrien{ 357090075Sobrien int i; 357190075Sobrien const char *format_ptr; 357250397Sobrien 357350397Sobrien if (x == 0) 357450397Sobrien return; 357550397Sobrien 357650397Sobrien if (GET_CODE (x) == SYMBOL_REF) 357750397Sobrien { 357890075Sobrien mark_constant (&x, NULL); 357950397Sobrien return; 358050397Sobrien } 358150397Sobrien 358250397Sobrien /* Insns may appear inside a SEQUENCE. Only check the patterns of 358350397Sobrien insns, not any notes that may be attached. We don't want to mark 358450397Sobrien a constant just because it happens to appear in a REG_EQUIV note. */ 358590075Sobrien if (INSN_P (x)) 358650397Sobrien { 358750397Sobrien mark_constants (PATTERN (x)); 358850397Sobrien return; 358950397Sobrien } 359050397Sobrien 359150397Sobrien format_ptr = GET_RTX_FORMAT (GET_CODE (x)); 359250397Sobrien 359350397Sobrien for (i = 0; i < GET_RTX_LENGTH (GET_CODE (x)); i++) 359450397Sobrien { 359550397Sobrien switch (*format_ptr++) 359650397Sobrien { 359750397Sobrien case 'e': 359850397Sobrien mark_constants (XEXP (x, i)); 359950397Sobrien break; 360050397Sobrien 360150397Sobrien case 'E': 360250397Sobrien if (XVEC (x, i) != 0) 360350397Sobrien { 360490075Sobrien int j; 360550397Sobrien 360650397Sobrien for (j = 0; j < XVECLEN (x, i); j++) 360750397Sobrien mark_constants (XVECEXP (x, i, j)); 360850397Sobrien } 360950397Sobrien break; 361050397Sobrien 361150397Sobrien case 'S': 361250397Sobrien case 's': 361350397Sobrien case '0': 361450397Sobrien case 'i': 361550397Sobrien case 'w': 361650397Sobrien case 'n': 361750397Sobrien case 'u': 3618117395Skan case 'B': 361950397Sobrien break; 362050397Sobrien 362150397Sobrien default: 362250397Sobrien abort (); 362350397Sobrien } 362450397Sobrien } 362550397Sobrien} 362690075Sobrien 362790075Sobrien/* Given a SYMBOL_REF CURRENT_RTX, mark it and all constants it refers 362890075Sobrien to as used. Emit referenced deferred strings. This function can 362990075Sobrien be used with for_each_rtx to mark all SYMBOL_REFs in an rtx. */ 363090075Sobrien 363190075Sobrienstatic int 363290075Sobrienmark_constant (current_rtx, data) 363390075Sobrien rtx *current_rtx; 363490075Sobrien void *data ATTRIBUTE_UNUSED; 363590075Sobrien{ 363690075Sobrien rtx x = *current_rtx; 363790075Sobrien 363890075Sobrien if (x == NULL_RTX) 363990075Sobrien return 0; 364090075Sobrien 364190075Sobrien else if (GET_CODE (x) == SYMBOL_REF) 364290075Sobrien { 364390075Sobrien if (CONSTANT_POOL_ADDRESS_P (x)) 364490075Sobrien { 364590075Sobrien struct pool_constant *pool = find_pool_constant (cfun, x); 3646117395Skan if (pool->mark == 0) 3647117395Skan { 3648117395Skan pool->mark = 1; 3649117395Skan for_each_rtx (&(pool->constant), &mark_constant, NULL); 3650117395Skan } 365190075Sobrien else 365290075Sobrien return -1; 365390075Sobrien } 365490075Sobrien else if (STRING_POOL_ADDRESS_P (x)) 365590075Sobrien { 365690075Sobrien struct deferred_string **defstr; 365790075Sobrien 365890075Sobrien defstr = (struct deferred_string **) 365990075Sobrien htab_find_slot_with_hash (const_str_htab, XSTR (x, 0), 366090075Sobrien STRHASH (XSTR (x, 0)), NO_INSERT); 366190075Sobrien if (defstr) 366290075Sobrien { 366390075Sobrien struct deferred_string *p = *defstr; 366490075Sobrien 366590075Sobrien STRING_POOL_ADDRESS_P (x) = 0; 366690075Sobrien output_constant_def_contents (p->exp, 0, p->labelno); 366790075Sobrien htab_clear_slot (const_str_htab, (void **) defstr); 366890075Sobrien } 366990075Sobrien } 367090075Sobrien } 367190075Sobrien return 0; 367290075Sobrien} 367318334Speter 367418334Speter/* Find all the constants whose addresses are referenced inside of EXP, 367518334Speter and make sure assembler code with a label has been output for each one. 367618334Speter Indicate whether an ADDR_EXPR has been encountered. */ 367718334Speter 367818334Speterstatic int 367918334Speteroutput_addressed_constants (exp) 368018334Speter tree exp; 368118334Speter{ 3682117395Skan int reloc = 0, reloc2; 368390075Sobrien tree tem; 368418334Speter 368590075Sobrien /* Give the front-end a chance to convert VALUE to something that 368690075Sobrien looks more like a constant to the back-end. */ 368790075Sobrien exp = (*lang_hooks.expand_constant) (exp); 368890075Sobrien 368918334Speter switch (TREE_CODE (exp)) 369018334Speter { 369118334Speter case ADDR_EXPR: 3692102780Skan case FDESC_EXPR: 369390075Sobrien /* Go inside any operations that get_inner_reference can handle and see 369490075Sobrien if what's inside is a constant: no need to do anything here for 369590075Sobrien addresses of variables or functions. */ 369690075Sobrien for (tem = TREE_OPERAND (exp, 0); handled_component_p (tem); 369790075Sobrien tem = TREE_OPERAND (tem, 0)) 369890075Sobrien ; 369918334Speter 370090075Sobrien if (TREE_CODE_CLASS (TREE_CODE (tem)) == 'c' 3701117395Skan || TREE_CODE (tem) == CONSTRUCTOR) 3702117395Skan output_constant_def (tem, 0); 370318334Speter 370490075Sobrien if (TREE_PUBLIC (tem)) 370590075Sobrien reloc |= 2; 370690075Sobrien else 370790075Sobrien reloc |= 1; 370818334Speter break; 370918334Speter 371018334Speter case PLUS_EXPR: 371118334Speter reloc = output_addressed_constants (TREE_OPERAND (exp, 0)); 371218334Speter reloc |= output_addressed_constants (TREE_OPERAND (exp, 1)); 371318334Speter break; 371418334Speter 3715117395Skan case MINUS_EXPR: 3716117395Skan reloc = output_addressed_constants (TREE_OPERAND (exp, 0)); 3717117395Skan reloc2 = output_addressed_constants (TREE_OPERAND (exp, 1)); 3718117395Skan /* The difference of two local labels is computable at link time. */ 3719117395Skan if (reloc == 1 && reloc2 == 1) 3720117395Skan reloc = 0; 3721117395Skan else 3722117395Skan reloc |= reloc2; 3723117395Skan break; 3724117395Skan 372518334Speter case NOP_EXPR: 372618334Speter case CONVERT_EXPR: 372718334Speter case NON_LVALUE_EXPR: 372818334Speter reloc = output_addressed_constants (TREE_OPERAND (exp, 0)); 372918334Speter break; 373018334Speter 373118334Speter case CONSTRUCTOR: 373290075Sobrien for (tem = CONSTRUCTOR_ELTS (exp); tem; tem = TREE_CHAIN (tem)) 373390075Sobrien if (TREE_VALUE (tem) != 0) 3734117395Skan reloc |= output_addressed_constants (TREE_VALUE (tem)); 373590075Sobrien 373618334Speter break; 373718334Speter 373850397Sobrien default: 373918334Speter break; 374018334Speter } 374118334Speter return reloc; 374218334Speter} 374318334Speter 374490075Sobrien/* Return nonzero if VALUE is a valid constant-valued expression 374590075Sobrien for use in initializing a static variable; one that can be an 374690075Sobrien element of a "constant" initializer. 374790075Sobrien 374890075Sobrien Return null_pointer_node if the value is absolute; 374990075Sobrien if it is relocatable, return the variable that determines the relocation. 375090075Sobrien We assume that VALUE has been folded as much as possible; 375190075Sobrien therefore, we do not need to check for such things as 375290075Sobrien arithmetic-combinations of integers. */ 375390075Sobrien 375490075Sobrientree 375590075Sobrieninitializer_constant_valid_p (value, endtype) 375690075Sobrien tree value; 375790075Sobrien tree endtype; 375890075Sobrien{ 375990075Sobrien /* Give the front-end a chance to convert VALUE to something that 376090075Sobrien looks more like a constant to the back-end. */ 376190075Sobrien value = (*lang_hooks.expand_constant) (value); 376290075Sobrien 376390075Sobrien switch (TREE_CODE (value)) 376490075Sobrien { 376590075Sobrien case CONSTRUCTOR: 376690075Sobrien if ((TREE_CODE (TREE_TYPE (value)) == UNION_TYPE 376790075Sobrien || TREE_CODE (TREE_TYPE (value)) == RECORD_TYPE) 376890075Sobrien && TREE_CONSTANT (value) 376990075Sobrien && CONSTRUCTOR_ELTS (value)) 377090075Sobrien return 377190075Sobrien initializer_constant_valid_p (TREE_VALUE (CONSTRUCTOR_ELTS (value)), 377290075Sobrien endtype); 377390075Sobrien 377490075Sobrien return TREE_STATIC (value) ? null_pointer_node : 0; 377590075Sobrien 377690075Sobrien case INTEGER_CST: 377796263Sobrien case VECTOR_CST: 377890075Sobrien case REAL_CST: 377990075Sobrien case STRING_CST: 378090075Sobrien case COMPLEX_CST: 378190075Sobrien return null_pointer_node; 378290075Sobrien 378390075Sobrien case ADDR_EXPR: 378490075Sobrien case FDESC_EXPR: 378590075Sobrien return staticp (TREE_OPERAND (value, 0)) ? TREE_OPERAND (value, 0) : 0; 378690075Sobrien 378790075Sobrien case VIEW_CONVERT_EXPR: 378890075Sobrien case NON_LVALUE_EXPR: 378990075Sobrien return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype); 379090075Sobrien 379190075Sobrien case CONVERT_EXPR: 379290075Sobrien case NOP_EXPR: 379390075Sobrien /* Allow conversions between pointer types. */ 379490075Sobrien if (POINTER_TYPE_P (TREE_TYPE (value)) 379590075Sobrien && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (value, 0)))) 379690075Sobrien return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype); 379790075Sobrien 379890075Sobrien /* Allow conversions between real types. */ 379990075Sobrien if (FLOAT_TYPE_P (TREE_TYPE (value)) 380090075Sobrien && FLOAT_TYPE_P (TREE_TYPE (TREE_OPERAND (value, 0)))) 380190075Sobrien return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype); 380290075Sobrien 380390075Sobrien /* Allow length-preserving conversions between integer types. */ 380490075Sobrien if (INTEGRAL_TYPE_P (TREE_TYPE (value)) 380590075Sobrien && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (value, 0))) 380690075Sobrien && (TYPE_PRECISION (TREE_TYPE (value)) 380790075Sobrien == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (value, 0))))) 380890075Sobrien return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype); 380990075Sobrien 381090075Sobrien /* Allow conversions between other integer types only if 381190075Sobrien explicit value. */ 381290075Sobrien if (INTEGRAL_TYPE_P (TREE_TYPE (value)) 381390075Sobrien && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (value, 0)))) 381490075Sobrien { 381590075Sobrien tree inner = initializer_constant_valid_p (TREE_OPERAND (value, 0), 381690075Sobrien endtype); 381790075Sobrien if (inner == null_pointer_node) 381890075Sobrien return null_pointer_node; 381990075Sobrien break; 382090075Sobrien } 382190075Sobrien 382290075Sobrien /* Allow (int) &foo provided int is as wide as a pointer. */ 382390075Sobrien if (INTEGRAL_TYPE_P (TREE_TYPE (value)) 382490075Sobrien && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (value, 0))) 382590075Sobrien && (TYPE_PRECISION (TREE_TYPE (value)) 382690075Sobrien >= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (value, 0))))) 382790075Sobrien return initializer_constant_valid_p (TREE_OPERAND (value, 0), 382890075Sobrien endtype); 382990075Sobrien 383090075Sobrien /* Likewise conversions from int to pointers, but also allow 383190075Sobrien conversions from 0. */ 383290075Sobrien if (POINTER_TYPE_P (TREE_TYPE (value)) 383390075Sobrien && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (value, 0)))) 383490075Sobrien { 383590075Sobrien if (integer_zerop (TREE_OPERAND (value, 0))) 383690075Sobrien return null_pointer_node; 383790075Sobrien else if (TYPE_PRECISION (TREE_TYPE (value)) 383890075Sobrien <= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (value, 0)))) 383990075Sobrien return initializer_constant_valid_p (TREE_OPERAND (value, 0), 384090075Sobrien endtype); 384190075Sobrien } 384290075Sobrien 384390075Sobrien /* Allow conversions to union types if the value inside is okay. */ 384490075Sobrien if (TREE_CODE (TREE_TYPE (value)) == UNION_TYPE) 384590075Sobrien return initializer_constant_valid_p (TREE_OPERAND (value, 0), 384690075Sobrien endtype); 384790075Sobrien break; 384890075Sobrien 384990075Sobrien case PLUS_EXPR: 385090075Sobrien if (! INTEGRAL_TYPE_P (endtype) 385190075Sobrien || TYPE_PRECISION (endtype) >= POINTER_SIZE) 3852117395Skan { 385390075Sobrien tree valid0 = initializer_constant_valid_p (TREE_OPERAND (value, 0), 385490075Sobrien endtype); 385590075Sobrien tree valid1 = initializer_constant_valid_p (TREE_OPERAND (value, 1), 385690075Sobrien endtype); 385790075Sobrien /* If either term is absolute, use the other terms relocation. */ 385890075Sobrien if (valid0 == null_pointer_node) 385990075Sobrien return valid1; 386090075Sobrien if (valid1 == null_pointer_node) 386190075Sobrien return valid0; 3862117395Skan } 386390075Sobrien break; 386490075Sobrien 386590075Sobrien case MINUS_EXPR: 386690075Sobrien if (! INTEGRAL_TYPE_P (endtype) 386790075Sobrien || TYPE_PRECISION (endtype) >= POINTER_SIZE) 386890075Sobrien { 386990075Sobrien tree valid0 = initializer_constant_valid_p (TREE_OPERAND (value, 0), 387090075Sobrien endtype); 387190075Sobrien tree valid1 = initializer_constant_valid_p (TREE_OPERAND (value, 1), 387290075Sobrien endtype); 387390075Sobrien /* Win if second argument is absolute. */ 387490075Sobrien if (valid1 == null_pointer_node) 387590075Sobrien return valid0; 387690075Sobrien /* Win if both arguments have the same relocation. 387790075Sobrien Then the value is absolute. */ 387890075Sobrien if (valid0 == valid1 && valid0 != 0) 387990075Sobrien return null_pointer_node; 388090075Sobrien 388190075Sobrien /* Since GCC guarantees that string constants are unique in the 388290075Sobrien generated code, a subtraction between two copies of the same 388390075Sobrien constant string is absolute. */ 388490075Sobrien if (valid0 && TREE_CODE (valid0) == STRING_CST && 388590075Sobrien valid1 && TREE_CODE (valid1) == STRING_CST && 388690075Sobrien TREE_STRING_POINTER (valid0) == TREE_STRING_POINTER (valid1)) 388790075Sobrien return null_pointer_node; 388890075Sobrien } 388990075Sobrien 389090075Sobrien /* Support differences between labels. */ 389190075Sobrien if (INTEGRAL_TYPE_P (endtype)) 389290075Sobrien { 389390075Sobrien tree op0, op1; 389490075Sobrien op0 = TREE_OPERAND (value, 0); 389590075Sobrien op1 = TREE_OPERAND (value, 1); 389690075Sobrien 389796263Sobrien /* Like STRIP_NOPS except allow the operand mode to widen. 389896263Sobrien This works around a feature of fold that simplfies 389996263Sobrien (int)(p1 - p2) to ((int)p1 - (int)p2) under the theory 390096263Sobrien that the narrower operation is cheaper. */ 390196263Sobrien 390296263Sobrien while (TREE_CODE (op0) == NOP_EXPR 390396263Sobrien || TREE_CODE (op0) == CONVERT_EXPR 390496263Sobrien || TREE_CODE (op0) == NON_LVALUE_EXPR) 390596263Sobrien { 390696263Sobrien tree inner = TREE_OPERAND (op0, 0); 390796263Sobrien if (inner == error_mark_node 390896263Sobrien || ! INTEGRAL_MODE_P (TYPE_MODE (TREE_TYPE (inner))) 390996263Sobrien || (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (op0))) 391096263Sobrien > GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (inner))))) 391196263Sobrien break; 391296263Sobrien op0 = inner; 391396263Sobrien } 391496263Sobrien 391596263Sobrien while (TREE_CODE (op1) == NOP_EXPR 391696263Sobrien || TREE_CODE (op1) == CONVERT_EXPR 391796263Sobrien || TREE_CODE (op1) == NON_LVALUE_EXPR) 391896263Sobrien { 391996263Sobrien tree inner = TREE_OPERAND (op1, 0); 392096263Sobrien if (inner == error_mark_node 392196263Sobrien || ! INTEGRAL_MODE_P (TYPE_MODE (TREE_TYPE (inner))) 392296263Sobrien || (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (op1))) 392396263Sobrien > GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (inner))))) 392496263Sobrien break; 392596263Sobrien op1 = inner; 392696263Sobrien } 392796263Sobrien 392890075Sobrien if (TREE_CODE (op0) == ADDR_EXPR 392990075Sobrien && TREE_CODE (TREE_OPERAND (op0, 0)) == LABEL_DECL 393090075Sobrien && TREE_CODE (op1) == ADDR_EXPR 393190075Sobrien && TREE_CODE (TREE_OPERAND (op1, 0)) == LABEL_DECL) 393290075Sobrien return null_pointer_node; 393390075Sobrien } 393490075Sobrien break; 393590075Sobrien 393690075Sobrien default: 393790075Sobrien break; 393890075Sobrien } 393990075Sobrien 394090075Sobrien return 0; 394190075Sobrien} 394290075Sobrien 394318334Speter/* Output assembler code for constant EXP to FILE, with no label. 394418334Speter This includes the pseudo-op such as ".int" or ".byte", and a newline. 394518334Speter Assumes output_addressed_constants has been done on EXP already. 394618334Speter 394718334Speter Generate exactly SIZE bytes of assembler data, padding at the end 394818334Speter with zeros if necessary. SIZE must always be specified. 394918334Speter 395018334Speter SIZE is important for structure constructors, 395118334Speter since trailing members may have been omitted from the constructor. 395218334Speter It is also important for initialization of arrays from string constants 395318334Speter since the full length of the string constant might not be wanted. 395418334Speter It is also needed for initialization of unions, where the initializer's 395518334Speter type is just one member, and that may not be as long as the union. 395618334Speter 395718334Speter There a case in which we would fail to output exactly SIZE bytes: 395818334Speter for a structure constructor that wants to produce more than SIZE bytes. 395990075Sobrien But such constructors will never be generated for any possible input. 396018334Speter 396190075Sobrien ALIGN is the alignment of the data in bits. */ 396290075Sobrien 396318334Spetervoid 396490075Sobrienoutput_constant (exp, size, align) 396590075Sobrien tree exp; 396690075Sobrien HOST_WIDE_INT size; 396790075Sobrien unsigned int align; 396818334Speter{ 396990075Sobrien enum tree_code code; 397090075Sobrien HOST_WIDE_INT thissize; 397118334Speter 397290075Sobrien /* Some front-ends use constants other than the standard language-indepdent 397390075Sobrien varieties, but which may still be output directly. Give the front-end a 397490075Sobrien chance to convert EXP to a language-independent representation. */ 397590075Sobrien exp = (*lang_hooks.expand_constant) (exp); 397652284Sobrien 397752284Sobrien if (size == 0 || flag_syntax_only) 397818334Speter return; 397918334Speter 398090075Sobrien /* Eliminate any conversions since we'll be outputting the underlying 398190075Sobrien constant. */ 398290075Sobrien while (TREE_CODE (exp) == NOP_EXPR || TREE_CODE (exp) == CONVERT_EXPR 398390075Sobrien || TREE_CODE (exp) == NON_LVALUE_EXPR 398490075Sobrien || TREE_CODE (exp) == VIEW_CONVERT_EXPR) 398518334Speter exp = TREE_OPERAND (exp, 0); 398618334Speter 398790075Sobrien code = TREE_CODE (TREE_TYPE (exp)); 398890075Sobrien thissize = int_size_in_bytes (TREE_TYPE (exp)); 398990075Sobrien 399018334Speter /* Allow a constructor with no elements for any data type. 399118334Speter This means to fill the space with zeros. */ 399218334Speter if (TREE_CODE (exp) == CONSTRUCTOR && CONSTRUCTOR_ELTS (exp) == 0) 399318334Speter { 399450397Sobrien assemble_zeros (size); 399518334Speter return; 399618334Speter } 399718334Speter 399890075Sobrien if (TREE_CODE (exp) == FDESC_EXPR) 399990075Sobrien { 400090075Sobrien#ifdef ASM_OUTPUT_FDESC 400190075Sobrien HOST_WIDE_INT part = tree_low_cst (TREE_OPERAND (exp, 1), 0); 400290075Sobrien tree decl = TREE_OPERAND (exp, 0); 400390075Sobrien ASM_OUTPUT_FDESC (asm_out_file, decl, part); 400490075Sobrien#else 400590075Sobrien abort (); 400690075Sobrien#endif 400790075Sobrien return; 400890075Sobrien } 400990075Sobrien 401090075Sobrien /* Now output the underlying data. If we've handling the padding, return. 401190075Sobrien Otherwise, break and ensure THISSIZE is the size written. */ 401218334Speter switch (code) 401318334Speter { 401418334Speter case CHAR_TYPE: 401518334Speter case BOOLEAN_TYPE: 401618334Speter case INTEGER_TYPE: 401718334Speter case ENUMERAL_TYPE: 401818334Speter case POINTER_TYPE: 401918334Speter case REFERENCE_TYPE: 402018334Speter if (! assemble_integer (expand_expr (exp, NULL_RTX, VOIDmode, 402118334Speter EXPAND_INITIALIZER), 402290075Sobrien size, align, 0)) 402318334Speter error ("initializer for integer value is too complicated"); 402418334Speter break; 402518334Speter 402618334Speter case REAL_TYPE: 402718334Speter if (TREE_CODE (exp) != REAL_CST) 402818334Speter error ("initializer for floating value is not a floating constant"); 402918334Speter 403018334Speter assemble_real (TREE_REAL_CST (exp), 403190075Sobrien mode_for_size (size * BITS_PER_UNIT, MODE_FLOAT, 0), 403290075Sobrien align); 403318334Speter break; 403418334Speter 403518334Speter case COMPLEX_TYPE: 403690075Sobrien output_constant (TREE_REALPART (exp), thissize / 2, align); 403790075Sobrien output_constant (TREE_IMAGPART (exp), thissize / 2, 403890075Sobrien min_align (align, BITS_PER_UNIT * (thissize / 2))); 403918334Speter break; 404018334Speter 404118334Speter case ARRAY_TYPE: 404296263Sobrien case VECTOR_TYPE: 404318334Speter if (TREE_CODE (exp) == CONSTRUCTOR) 404418334Speter { 404590075Sobrien output_constructor (exp, size, align); 404618334Speter return; 404718334Speter } 404818334Speter else if (TREE_CODE (exp) == STRING_CST) 404918334Speter { 405090075Sobrien thissize = MIN (TREE_STRING_LENGTH (exp), size); 405190075Sobrien assemble_string (TREE_STRING_POINTER (exp), thissize); 405218334Speter } 405318334Speter else 405418334Speter abort (); 405518334Speter break; 405618334Speter 405718334Speter case RECORD_TYPE: 405818334Speter case UNION_TYPE: 405918334Speter if (TREE_CODE (exp) == CONSTRUCTOR) 406090075Sobrien output_constructor (exp, size, align); 406118334Speter else 406218334Speter abort (); 406318334Speter return; 406418334Speter 406518334Speter case SET_TYPE: 406618334Speter if (TREE_CODE (exp) == INTEGER_CST) 406718334Speter assemble_integer (expand_expr (exp, NULL_RTX, 406818334Speter VOIDmode, EXPAND_INITIALIZER), 4069117395Skan thissize, align, 1); 407018334Speter else if (TREE_CODE (exp) == CONSTRUCTOR) 407118334Speter { 407290075Sobrien unsigned char *buffer = (unsigned char *) alloca (thissize); 407390075Sobrien if (get_set_constructor_bytes (exp, buffer, thissize)) 407418334Speter abort (); 407590075Sobrien assemble_string ((char *) buffer, thissize); 407618334Speter } 407718334Speter else 407818334Speter error ("unknown set constructor type"); 407918334Speter return; 408050397Sobrien 408190075Sobrien case ERROR_MARK: 408290075Sobrien return; 408390075Sobrien 408450397Sobrien default: 408590075Sobrien abort (); 408618334Speter } 408718334Speter 408890075Sobrien size -= thissize; 408918334Speter if (size > 0) 409018334Speter assemble_zeros (size); 409118334Speter} 409218334Speter 409318334Speter 409490075Sobrien/* Subroutine of output_constructor, used for computing the size of 409590075Sobrien arrays of unspecified length. VAL must be a CONSTRUCTOR of an array 409690075Sobrien type with an unspecified upper bound. */ 409790075Sobrien 409890075Sobrienstatic unsigned HOST_WIDE_INT 409990075Sobrienarray_size_for_constructor (val) 410090075Sobrien tree val; 410190075Sobrien{ 410290075Sobrien tree max_index, i; 410390075Sobrien 410490075Sobrien /* This code used to attempt to handle string constants that are not 410590075Sobrien arrays of single-bytes, but nothing else does, so there's no point in 410690075Sobrien doing it here. */ 410790075Sobrien if (TREE_CODE (val) == STRING_CST) 410890075Sobrien return TREE_STRING_LENGTH (val); 410990075Sobrien 411090075Sobrien max_index = NULL_TREE; 4111117395Skan for (i = CONSTRUCTOR_ELTS (val); i; i = TREE_CHAIN (i)) 411290075Sobrien { 411390075Sobrien tree index = TREE_PURPOSE (i); 411490075Sobrien 411590075Sobrien if (TREE_CODE (index) == RANGE_EXPR) 411690075Sobrien index = TREE_OPERAND (index, 1); 411790075Sobrien if (max_index == NULL_TREE || tree_int_cst_lt (max_index, index)) 411890075Sobrien max_index = index; 411990075Sobrien } 412090075Sobrien 412190075Sobrien if (max_index == NULL_TREE) 412290075Sobrien return 0; 412390075Sobrien 412490075Sobrien /* Compute the total number of array elements. */ 412590075Sobrien i = size_binop (MINUS_EXPR, convert (sizetype, max_index), 412690075Sobrien convert (sizetype, 412790075Sobrien TYPE_MIN_VALUE (TYPE_DOMAIN (TREE_TYPE (val))))); 412890075Sobrien i = size_binop (PLUS_EXPR, i, convert (sizetype, integer_one_node)); 412990075Sobrien 413090075Sobrien /* Multiply by the array element unit size to find number of bytes. */ 413190075Sobrien i = size_binop (MULT_EXPR, i, TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (val)))); 413290075Sobrien 413390075Sobrien return tree_low_cst (i, 1); 413490075Sobrien} 413590075Sobrien 413690075Sobrien/* Subroutine of output_constant, used for CONSTRUCTORs (aggregate constants). 413718334Speter Generate at least SIZE bytes, padding if necessary. */ 413818334Speter 413918334Speterstatic void 414090075Sobrienoutput_constructor (exp, size, align) 414118334Speter tree exp; 414290075Sobrien HOST_WIDE_INT size; 414390075Sobrien unsigned int align; 414418334Speter{ 414590075Sobrien tree type = TREE_TYPE (exp); 414690075Sobrien tree link, field = 0; 414790075Sobrien tree min_index = 0; 414818334Speter /* Number of bytes output or skipped so far. 414918334Speter In other words, current position within the constructor. */ 415090075Sobrien HOST_WIDE_INT total_bytes = 0; 415118334Speter /* Non-zero means BYTE contains part of a byte, to be output. */ 415218334Speter int byte_buffer_in_use = 0; 415390075Sobrien int byte = 0; 415418334Speter 415518334Speter if (HOST_BITS_PER_WIDE_INT < BITS_PER_UNIT) 415618334Speter abort (); 415718334Speter 415890075Sobrien if (TREE_CODE (type) == RECORD_TYPE) 415990075Sobrien field = TYPE_FIELDS (type); 416018334Speter 416190075Sobrien if (TREE_CODE (type) == ARRAY_TYPE 416290075Sobrien && TYPE_DOMAIN (type) != 0) 416390075Sobrien min_index = TYPE_MIN_VALUE (TYPE_DOMAIN (type)); 416418334Speter 416518334Speter /* As LINK goes through the elements of the constant, 416618334Speter FIELD goes through the structure fields, if the constant is a structure. 416718334Speter if the constant is a union, then we override this, 416818334Speter by getting the field from the TREE_LIST element. 416952284Sobrien But the constant could also be an array. Then FIELD is zero. 417052284Sobrien 417152284Sobrien There is always a maximum of one element in the chain LINK for unions 417252284Sobrien (even if the initializer in a source program incorrectly contains 417390075Sobrien more one). */ 417418334Speter for (link = CONSTRUCTOR_ELTS (exp); 417518334Speter link; 417618334Speter link = TREE_CHAIN (link), 417718334Speter field = field ? TREE_CHAIN (field) : 0) 417818334Speter { 417918334Speter tree val = TREE_VALUE (link); 418018334Speter tree index = 0; 418118334Speter 418290075Sobrien /* The element in a union constructor specifies the proper field 418390075Sobrien or index. */ 418490075Sobrien if ((TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE 418590075Sobrien || TREE_CODE (type) == QUAL_UNION_TYPE) 418690075Sobrien && TREE_PURPOSE (link) != 0) 418790075Sobrien field = TREE_PURPOSE (link); 418818334Speter 418990075Sobrien else if (TREE_CODE (type) == ARRAY_TYPE) 419018334Speter index = TREE_PURPOSE (link); 419118334Speter 419218334Speter /* Eliminate the marker that makes a cast not be an lvalue. */ 419318334Speter if (val != 0) 419418334Speter STRIP_NOPS (val); 419518334Speter 419650397Sobrien if (index && TREE_CODE (index) == RANGE_EXPR) 419718334Speter { 419890075Sobrien unsigned HOST_WIDE_INT fieldsize 419990075Sobrien = int_size_in_bytes (TREE_TYPE (type)); 420090075Sobrien HOST_WIDE_INT lo_index = tree_low_cst (TREE_OPERAND (index, 0), 0); 420190075Sobrien HOST_WIDE_INT hi_index = tree_low_cst (TREE_OPERAND (index, 1), 0); 420250397Sobrien HOST_WIDE_INT index; 420390075Sobrien unsigned int align2 = min_align (align, fieldsize * BITS_PER_UNIT); 420490075Sobrien 420550397Sobrien for (index = lo_index; index <= hi_index; index++) 420650397Sobrien { 420750397Sobrien /* Output the element's initial value. */ 420850397Sobrien if (val == 0) 420950397Sobrien assemble_zeros (fieldsize); 421050397Sobrien else 421190075Sobrien output_constant (val, fieldsize, align2); 421250397Sobrien 421350397Sobrien /* Count its size. */ 421450397Sobrien total_bytes += fieldsize; 421550397Sobrien } 421650397Sobrien } 421750397Sobrien else if (field == 0 || !DECL_BIT_FIELD (field)) 421850397Sobrien { 421918334Speter /* An element that is not a bit-field. */ 422018334Speter 422190075Sobrien unsigned HOST_WIDE_INT fieldsize; 422218334Speter /* Since this structure is static, 422318334Speter we know the positions are constant. */ 422490075Sobrien HOST_WIDE_INT pos = field ? int_byte_position (field) : 0; 422590075Sobrien unsigned int align2; 422690075Sobrien 422718334Speter if (index != 0) 422890075Sobrien pos = (tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (val)), 1) 422990075Sobrien * (tree_low_cst (index, 0) - tree_low_cst (min_index, 0))); 423018334Speter 423118334Speter /* Output any buffered-up bit-fields preceding this element. */ 423218334Speter if (byte_buffer_in_use) 423318334Speter { 423490075Sobrien assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1); 423518334Speter total_bytes++; 423618334Speter byte_buffer_in_use = 0; 423718334Speter } 423818334Speter 423918334Speter /* Advance to offset of this element. 424018334Speter Note no alignment needed in an array, since that is guaranteed 424118334Speter if each element has the proper size. */ 424290075Sobrien if ((field != 0 || index != 0) && pos != total_bytes) 424318334Speter { 424490075Sobrien assemble_zeros (pos - total_bytes); 424590075Sobrien total_bytes = pos; 424618334Speter } 424718334Speter 424890075Sobrien /* Find the alignment of this element. */ 424990075Sobrien align2 = min_align (align, BITS_PER_UNIT * pos); 425090075Sobrien 425118334Speter /* Determine size this element should occupy. */ 425218334Speter if (field) 425318334Speter { 425490075Sobrien fieldsize = 0; 425590075Sobrien 425690075Sobrien /* If this is an array with an unspecified upper bound, 425790075Sobrien the initializer determines the size. */ 425890075Sobrien /* ??? This ought to only checked if DECL_SIZE_UNIT is NULL, 425990075Sobrien but we cannot do this until the deprecated support for 426090075Sobrien initializing zero-length array members is removed. */ 426190075Sobrien if (TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE 426290075Sobrien && TYPE_DOMAIN (TREE_TYPE (field)) 426390075Sobrien && ! TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (field)))) 426418334Speter { 426590075Sobrien fieldsize = array_size_for_constructor (val); 426690075Sobrien /* Given a non-empty initialization, this field had 426790075Sobrien better be last. */ 426890075Sobrien if (fieldsize != 0 && TREE_CHAIN (field) != NULL_TREE) 426990075Sobrien abort (); 427018334Speter } 427190075Sobrien else if (DECL_SIZE_UNIT (field)) 427218334Speter { 427390075Sobrien /* ??? This can't be right. If the decl size overflows 427490075Sobrien a host integer we will silently emit no data. */ 427590075Sobrien if (host_integerp (DECL_SIZE_UNIT (field), 1)) 427690075Sobrien fieldsize = tree_low_cst (DECL_SIZE_UNIT (field), 1); 427718334Speter } 427818334Speter } 427918334Speter else 428090075Sobrien fieldsize = int_size_in_bytes (TREE_TYPE (type)); 428118334Speter 428218334Speter /* Output the element's initial value. */ 428318334Speter if (val == 0) 428418334Speter assemble_zeros (fieldsize); 428518334Speter else 428690075Sobrien output_constant (val, fieldsize, align2); 428718334Speter 428818334Speter /* Count its size. */ 428918334Speter total_bytes += fieldsize; 429018334Speter } 429118334Speter else if (val != 0 && TREE_CODE (val) != INTEGER_CST) 429218334Speter error ("invalid initial value for member `%s'", 429318334Speter IDENTIFIER_POINTER (DECL_NAME (field))); 429418334Speter else 429518334Speter { 429618334Speter /* Element that is a bit-field. */ 429718334Speter 429890075Sobrien HOST_WIDE_INT next_offset = int_bit_position (field); 429990075Sobrien HOST_WIDE_INT end_offset 430090075Sobrien = (next_offset + tree_low_cst (DECL_SIZE (field), 1)); 430118334Speter 430218334Speter if (val == 0) 430318334Speter val = integer_zero_node; 430418334Speter 430518334Speter /* If this field does not start in this (or, next) byte, 430618334Speter skip some bytes. */ 430718334Speter if (next_offset / BITS_PER_UNIT != total_bytes) 430818334Speter { 430918334Speter /* Output remnant of any bit field in previous bytes. */ 431018334Speter if (byte_buffer_in_use) 431118334Speter { 431290075Sobrien assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1); 431318334Speter total_bytes++; 431418334Speter byte_buffer_in_use = 0; 431518334Speter } 431618334Speter 431718334Speter /* If still not at proper byte, advance to there. */ 431818334Speter if (next_offset / BITS_PER_UNIT != total_bytes) 431918334Speter { 432018334Speter assemble_zeros (next_offset / BITS_PER_UNIT - total_bytes); 432118334Speter total_bytes = next_offset / BITS_PER_UNIT; 432218334Speter } 432318334Speter } 432418334Speter 432518334Speter if (! byte_buffer_in_use) 432618334Speter byte = 0; 432718334Speter 432818334Speter /* We must split the element into pieces that fall within 432918334Speter separate bytes, and combine each byte with previous or 433018334Speter following bit-fields. */ 433118334Speter 433218334Speter /* next_offset is the offset n fbits from the beginning of 433318334Speter the structure to the next bit of this element to be processed. 433418334Speter end_offset is the offset of the first bit past the end of 433518334Speter this element. */ 433618334Speter while (next_offset < end_offset) 433718334Speter { 433818334Speter int this_time; 433918334Speter int shift; 434018334Speter HOST_WIDE_INT value; 434190075Sobrien HOST_WIDE_INT next_byte = next_offset / BITS_PER_UNIT; 434290075Sobrien HOST_WIDE_INT next_bit = next_offset % BITS_PER_UNIT; 434318334Speter 434418334Speter /* Advance from byte to byte 434518334Speter within this element when necessary. */ 434618334Speter while (next_byte != total_bytes) 434718334Speter { 434890075Sobrien assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1); 434918334Speter total_bytes++; 435018334Speter byte = 0; 435118334Speter } 435218334Speter 435318334Speter /* Number of bits we can process at once 435418334Speter (all part of the same byte). */ 435518334Speter this_time = MIN (end_offset - next_offset, 435618334Speter BITS_PER_UNIT - next_bit); 435718334Speter if (BYTES_BIG_ENDIAN) 435818334Speter { 435918334Speter /* On big-endian machine, take the most significant bits 436018334Speter first (of the bits that are significant) 436118334Speter and put them into bytes from the most significant end. */ 436218334Speter shift = end_offset - next_offset - this_time; 436390075Sobrien 436418334Speter /* Don't try to take a bunch of bits that cross 436590075Sobrien the word boundary in the INTEGER_CST. We can 436690075Sobrien only select bits from the LOW or HIGH part 436790075Sobrien not from both. */ 436818334Speter if (shift < HOST_BITS_PER_WIDE_INT 436918334Speter && shift + this_time > HOST_BITS_PER_WIDE_INT) 437018334Speter { 437190075Sobrien this_time = shift + this_time - HOST_BITS_PER_WIDE_INT; 437218334Speter shift = HOST_BITS_PER_WIDE_INT; 437318334Speter } 437418334Speter 437518334Speter /* Now get the bits from the appropriate constant word. */ 437618334Speter if (shift < HOST_BITS_PER_WIDE_INT) 437790075Sobrien value = TREE_INT_CST_LOW (val); 437818334Speter else if (shift < 2 * HOST_BITS_PER_WIDE_INT) 437918334Speter { 438018334Speter value = TREE_INT_CST_HIGH (val); 438118334Speter shift -= HOST_BITS_PER_WIDE_INT; 438218334Speter } 438318334Speter else 438418334Speter abort (); 438590075Sobrien 438690075Sobrien /* Get the result. This works only when: 438790075Sobrien 1 <= this_time <= HOST_BITS_PER_WIDE_INT. */ 438818334Speter byte |= (((value >> shift) 438990075Sobrien & (((HOST_WIDE_INT) 2 << (this_time - 1)) - 1)) 439018334Speter << (BITS_PER_UNIT - this_time - next_bit)); 439118334Speter } 439218334Speter else 439318334Speter { 439418334Speter /* On little-endian machines, 439518334Speter take first the least significant bits of the value 439618334Speter and pack them starting at the least significant 439718334Speter bits of the bytes. */ 439890075Sobrien shift = next_offset - int_bit_position (field); 439990075Sobrien 440018334Speter /* Don't try to take a bunch of bits that cross 440190075Sobrien the word boundary in the INTEGER_CST. We can 440290075Sobrien only select bits from the LOW or HIGH part 440390075Sobrien not from both. */ 440418334Speter if (shift < HOST_BITS_PER_WIDE_INT 440518334Speter && shift + this_time > HOST_BITS_PER_WIDE_INT) 440690075Sobrien this_time = (HOST_BITS_PER_WIDE_INT - shift); 440718334Speter 440818334Speter /* Now get the bits from the appropriate constant word. */ 440950397Sobrien if (shift < HOST_BITS_PER_WIDE_INT) 441018334Speter value = TREE_INT_CST_LOW (val); 441118334Speter else if (shift < 2 * HOST_BITS_PER_WIDE_INT) 441218334Speter { 441318334Speter value = TREE_INT_CST_HIGH (val); 441418334Speter shift -= HOST_BITS_PER_WIDE_INT; 441518334Speter } 441618334Speter else 441718334Speter abort (); 441890075Sobrien 441990075Sobrien /* Get the result. This works only when: 442090075Sobrien 1 <= this_time <= HOST_BITS_PER_WIDE_INT. */ 442118334Speter byte |= (((value >> shift) 442290075Sobrien & (((HOST_WIDE_INT) 2 << (this_time - 1)) - 1)) 442318334Speter << next_bit); 442418334Speter } 442590075Sobrien 442618334Speter next_offset += this_time; 442718334Speter byte_buffer_in_use = 1; 442818334Speter } 442918334Speter } 443018334Speter } 443190075Sobrien 443218334Speter if (byte_buffer_in_use) 443318334Speter { 443490075Sobrien assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1); 443518334Speter total_bytes++; 443618334Speter } 443790075Sobrien 443818334Speter if (total_bytes < size) 443918334Speter assemble_zeros (size - total_bytes); 444018334Speter} 444118334Speter 444296263Sobrien/* This TREE_LIST contains any weak symbol declarations waiting 444396263Sobrien to be emitted. */ 4444117395Skanstatic GTY(()) tree weak_decls; 444590075Sobrien 444696263Sobrien/* Mark DECL as weak. */ 444796263Sobrien 444896263Sobrienstatic void 444996263Sobrienmark_weak (decl) 445096263Sobrien tree decl; 445190075Sobrien{ 445296263Sobrien DECL_WEAK (decl) = 1; 445390075Sobrien 445496263Sobrien if (DECL_RTL_SET_P (decl) 445596263Sobrien && GET_CODE (DECL_RTL (decl)) == MEM 445696263Sobrien && XEXP (DECL_RTL (decl), 0) 445796263Sobrien && GET_CODE (XEXP (DECL_RTL (decl), 0)) == SYMBOL_REF) 445896263Sobrien SYMBOL_REF_WEAK (XEXP (DECL_RTL (decl), 0)) = 1; 445996263Sobrien} 4460117395Skan 446196263Sobrien/* Merge weak status between NEWDECL and OLDDECL. */ 446290075Sobrien 446396263Sobrienvoid 446496263Sobrienmerge_weak (newdecl, olddecl) 446596263Sobrien tree newdecl; 446696263Sobrien tree olddecl; 446718334Speter{ 446896263Sobrien if (DECL_WEAK (newdecl) == DECL_WEAK (olddecl)) 446996263Sobrien return; 447018334Speter 447196263Sobrien if (DECL_WEAK (newdecl)) 447296263Sobrien { 447396263Sobrien tree wd; 4474117395Skan 447596263Sobrien /* NEWDECL is weak, but OLDDECL is not. */ 447618334Speter 447796263Sobrien /* If we already output the OLDDECL, we're in trouble; we can't 447896263Sobrien go back and make it weak. This error cannot caught in 447996263Sobrien declare_weak because the NEWDECL and OLDDECL was not yet 448096263Sobrien been merged; therefore, TREE_ASM_WRITTEN was not set. */ 4481102780Skan if (TREE_ASM_WRITTEN (olddecl)) 4482117395Skan error_with_decl (newdecl, 448396263Sobrien "weak declaration of `%s' must precede definition"); 4484102780Skan 4485102780Skan /* If we've already generated rtl referencing OLDDECL, we may 4486102780Skan have done so in a way that will not function properly with 4487102780Skan a weak symbol. */ 4488102780Skan else if (TREE_USED (olddecl) 4489102780Skan && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (olddecl))) 4490102780Skan warning_with_decl (newdecl, "weak declaration of `%s' after first use results in unspecified behavior"); 4491102780Skan 449296263Sobrien if (SUPPORTS_WEAK) 449396263Sobrien { 449496263Sobrien /* We put the NEWDECL on the weak_decls list at some point. 449596263Sobrien Replace it with the OLDDECL. */ 449696263Sobrien for (wd = weak_decls; wd; wd = TREE_CHAIN (wd)) 449796263Sobrien if (TREE_VALUE (wd) == newdecl) 449896263Sobrien { 449996263Sobrien TREE_VALUE (wd) = olddecl; 450096263Sobrien break; 450196263Sobrien } 450296263Sobrien /* We may not find the entry on the list. If NEWDECL is a 450396263Sobrien weak alias, then we will have already called 450496263Sobrien globalize_decl to remove the entry; in that case, we do 450596263Sobrien not need to do anything. */ 450696263Sobrien } 450752284Sobrien 450896263Sobrien /* Make the OLDDECL weak; it's OLDDECL that we'll be keeping. */ 450996263Sobrien mark_weak (olddecl); 451096263Sobrien } 451196263Sobrien else 451296263Sobrien /* OLDDECL was weak, but NEWDECL was not explicitly marked as 451396263Sobrien weak. Just update NEWDECL to indicate that it's weak too. */ 451496263Sobrien mark_weak (newdecl); 451552284Sobrien} 451618334Speter 451718334Speter/* Declare DECL to be a weak symbol. */ 451818334Speter 451918334Spetervoid 452018334Speterdeclare_weak (decl) 452118334Speter tree decl; 452218334Speter{ 452318334Speter if (! TREE_PUBLIC (decl)) 452418334Speter error_with_decl (decl, "weak declaration of `%s' must be public"); 452596263Sobrien else if (TREE_CODE (decl) == FUNCTION_DECL && TREE_ASM_WRITTEN (decl)) 452618334Speter error_with_decl (decl, "weak declaration of `%s' must precede definition"); 452718334Speter else if (SUPPORTS_WEAK) 452896263Sobrien { 452996263Sobrien if (! DECL_WEAK (decl)) 453096263Sobrien weak_decls = tree_cons (NULL, decl, weak_decls); 453196263Sobrien } 453290075Sobrien else 453390075Sobrien warning_with_decl (decl, "weak declaration of `%s' not supported"); 453490075Sobrien 453596263Sobrien mark_weak (decl); 453618334Speter} 453718334Speter 453818334Speter/* Emit any pending weak declarations. */ 453918334Speter 454018334Spetervoid 454118334Speterweak_finish () 454218334Speter{ 454396263Sobrien tree t; 454496263Sobrien 4545117395Skan for (t = weak_decls; t; t = TREE_CHAIN (t)) 454618334Speter { 454796263Sobrien tree decl = TREE_VALUE (t); 454896263Sobrien const char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); 454996263Sobrien 455096263Sobrien if (! TREE_USED (decl)) 455196263Sobrien continue; 455296263Sobrien 455396263Sobrien#ifdef ASM_WEAKEN_DECL 455496263Sobrien ASM_WEAKEN_DECL (asm_out_file, decl, name, NULL); 455590075Sobrien#else 455690075Sobrien#ifdef ASM_WEAKEN_LABEL 455796263Sobrien ASM_WEAKEN_LABEL (asm_out_file, name); 455896263Sobrien#else 455996263Sobrien#ifdef ASM_OUTPUT_WEAK_ALIAS 456096263Sobrien warning ("only weak aliases are supported in this configuration"); 456196263Sobrien return; 456290075Sobrien#endif 456390075Sobrien#endif 456496263Sobrien#endif 456518334Speter } 456618334Speter} 456718334Speter 456896263Sobrien/* Emit the assembly bits to indicate that DECL is globally visible. */ 456996263Sobrien 457052284Sobrienstatic void 457196263Sobrienglobalize_decl (decl) 457296263Sobrien tree decl; 457352284Sobrien{ 457496263Sobrien const char *name = XSTR (XEXP (DECL_RTL (decl), 0), 0); 457590075Sobrien 457696263Sobrien#if defined (ASM_WEAKEN_LABEL) || defined (ASM_WEAKEN_DECL) 457796263Sobrien if (DECL_WEAK (decl)) 457852284Sobrien { 457996263Sobrien tree *p, t; 458096263Sobrien 458196263Sobrien#ifdef ASM_WEAKEN_DECL 458296263Sobrien ASM_WEAKEN_DECL (asm_out_file, decl, name, 0); 458396263Sobrien#else 458496263Sobrien ASM_WEAKEN_LABEL (asm_out_file, name); 458596263Sobrien#endif 458696263Sobrien 458796263Sobrien /* Remove this function from the pending weak list so that 458896263Sobrien we do not emit multiple .weak directives for it. */ 458996263Sobrien for (p = &weak_decls; (t = *p) ; ) 459096263Sobrien { 459196263Sobrien if (DECL_ASSEMBLER_NAME (decl) == DECL_ASSEMBLER_NAME (TREE_VALUE (t))) 459296263Sobrien *p = TREE_CHAIN (t); 459396263Sobrien else 459496263Sobrien p = &TREE_CHAIN (t); 459596263Sobrien } 459696263Sobrien return; 459752284Sobrien } 459896263Sobrien#endif 459996263Sobrien 4600117395Skan (*targetm.asm_out.globalize_label) (asm_out_file, name); 460152284Sobrien} 460252284Sobrien 460390075Sobrien/* Emit an assembler directive to make the symbol for DECL an alias to 460490075Sobrien the symbol for TARGET. */ 460590075Sobrien 460618334Spetervoid 460718334Speterassemble_alias (decl, target) 460852284Sobrien tree decl, target ATTRIBUTE_UNUSED; 460918334Speter{ 461090075Sobrien const char *name; 461118334Speter 461290075Sobrien /* We must force creation of DECL_RTL for debug info generation, even though 461390075Sobrien we don't use it here. */ 461490075Sobrien make_decl_rtl (decl, NULL); 461518334Speter 461690075Sobrien name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); 461790075Sobrien 461850397Sobrien#ifdef ASM_OUTPUT_DEF 461918334Speter /* Make name accessible from other files, if appropriate. */ 4620117395Skan 462118334Speter if (TREE_PUBLIC (decl)) 4622117395Skan { 4623117395Skan globalize_decl (decl); 4624117395Skan maybe_assemble_visibility (decl); 4625117395Skan } 462618334Speter 462790075Sobrien#ifdef ASM_OUTPUT_DEF_FROM_DECLS 462890075Sobrien ASM_OUTPUT_DEF_FROM_DECLS (asm_out_file, decl, target); 462990075Sobrien#else 463018334Speter ASM_OUTPUT_DEF (asm_out_file, name, IDENTIFIER_POINTER (target)); 463190075Sobrien#endif 463296263Sobrien#else /* !ASM_OUTPUT_DEF */ 463396263Sobrien#if defined (ASM_OUTPUT_WEAK_ALIAS) || defined (ASM_WEAKEN_DECL) 463450397Sobrien if (! DECL_WEAK (decl)) 463550397Sobrien warning ("only weak aliases are supported in this configuration"); 463650397Sobrien 463796263Sobrien#ifdef ASM_WEAKEN_DECL 463896263Sobrien ASM_WEAKEN_DECL (asm_out_file, decl, name, IDENTIFIER_POINTER (target)); 463996263Sobrien#else 464050397Sobrien ASM_OUTPUT_WEAK_ALIAS (asm_out_file, name, IDENTIFIER_POINTER (target)); 464196263Sobrien#endif 464250397Sobrien#else 464350397Sobrien warning ("alias definitions not supported in this configuration; ignored"); 464418334Speter#endif 464550397Sobrien#endif 4646102780Skan 4647102780Skan TREE_USED (decl) = 1; 4648102780Skan TREE_ASM_WRITTEN (decl) = 1; 4649102780Skan TREE_ASM_WRITTEN (DECL_ASSEMBLER_NAME (decl)) = 1; 465018334Speter} 465150397Sobrien 4652117395Skan/* Emit an assembler directive to set symbol for DECL visibility to 4653117395Skan the visibility type VIS, which must not be VISIBILITY_DEFAULT. */ 4654117395Skan 4655117395Skanvoid 4656117395Skandefault_assemble_visibility (decl, vis) 4657117395Skan tree decl; 4658117395Skan int vis; 4659117395Skan{ 4660117395Skan static const char * const visibility_types[] = { 4661117395Skan NULL, "internal", "hidden", "protected" 4662117395Skan }; 4663117395Skan 4664117395Skan const char *name, *type; 4665117395Skan 4666117395Skan name = (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))); 4667117395Skan type = visibility_types[vis]; 4668117395Skan 4669117395Skan#ifdef HAVE_GAS_HIDDEN 4670117395Skan fprintf (asm_out_file, "\t.%s\t", type); 4671117395Skan assemble_name (asm_out_file, name); 4672117395Skan fprintf (asm_out_file, "\n"); 4673117395Skan#else 4674117395Skan warning ("visibility attribute not supported in this configuration; ignored"); 4675117395Skan#endif 4676117395Skan} 4677117395Skan 4678117395Skan/* A helper function to call assemble_visibility when needed for a decl. */ 4679117395Skan 4680117395Skanstatic void 4681117395Skanmaybe_assemble_visibility (decl) 4682117395Skan tree decl; 4683117395Skan{ 4684117395Skan enum symbol_visibility vis = decl_visibility (decl); 4685117395Skan 4686117395Skan if (vis != VISIBILITY_DEFAULT) 4687117395Skan (* targetm.asm_out.visibility) (decl, vis); 4688117395Skan} 4689117395Skan 469050397Sobrien/* Returns 1 if the target configuration supports defining public symbols 469150397Sobrien so that one of them will be chosen at link time instead of generating a 469250397Sobrien multiply-defined symbol error, whether through the use of weak symbols or 469350397Sobrien a target-specific mechanism for having duplicates discarded. */ 469450397Sobrien 469550397Sobrienint 469650397Sobriensupports_one_only () 469750397Sobrien{ 469850397Sobrien if (SUPPORTS_ONE_ONLY) 469950397Sobrien return 1; 470050397Sobrien return SUPPORTS_WEAK; 470150397Sobrien} 470250397Sobrien 470350397Sobrien/* Set up DECL as a public symbol that can be defined in multiple 470450397Sobrien translation units without generating a linker error. */ 470550397Sobrien 470650397Sobrienvoid 470750397Sobrienmake_decl_one_only (decl) 470850397Sobrien tree decl; 470950397Sobrien{ 471050397Sobrien if (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != FUNCTION_DECL) 471150397Sobrien abort (); 471250397Sobrien 471350397Sobrien TREE_PUBLIC (decl) = 1; 471450397Sobrien 471550397Sobrien if (TREE_CODE (decl) == VAR_DECL 471650397Sobrien && (DECL_INITIAL (decl) == 0 || DECL_INITIAL (decl) == error_mark_node)) 471750397Sobrien DECL_COMMON (decl) = 1; 471850397Sobrien else if (SUPPORTS_ONE_ONLY) 471950397Sobrien { 472050397Sobrien#ifdef MAKE_DECL_ONE_ONLY 472150397Sobrien MAKE_DECL_ONE_ONLY (decl); 472250397Sobrien#endif 472350397Sobrien DECL_ONE_ONLY (decl) = 1; 472450397Sobrien } 472550397Sobrien else if (SUPPORTS_WEAK) 472650397Sobrien DECL_WEAK (decl) = 1; 472750397Sobrien else 472850397Sobrien abort (); 472950397Sobrien} 473090075Sobrien 473190075Sobrienvoid 473290075Sobrieninit_varasm_once () 473390075Sobrien{ 4734117395Skan const_str_htab = htab_create_ggc (128, const_str_htab_hash, 4735117395Skan const_str_htab_eq, NULL); 473690075Sobrien in_named_htab = htab_create (31, in_named_entry_hash, 473790075Sobrien in_named_entry_eq, NULL); 473890075Sobrien 473990075Sobrien const_alias_set = new_alias_set (); 474090075Sobrien} 474190075Sobrien 4742117395Skanenum tls_model 4743117395Skandecl_tls_model (decl) 4744117395Skan tree decl; 4745117395Skan{ 4746117395Skan enum tls_model kind; 4747117395Skan tree attr = lookup_attribute ("tls_model", DECL_ATTRIBUTES (decl)); 4748117395Skan bool is_local; 4749117395Skan 4750117395Skan if (attr) 4751117395Skan { 4752117395Skan attr = TREE_VALUE (TREE_VALUE (attr)); 4753117395Skan if (TREE_CODE (attr) != STRING_CST) 4754117395Skan abort (); 4755117395Skan if (!strcmp (TREE_STRING_POINTER (attr), "local-exec")) 4756117395Skan kind = TLS_MODEL_LOCAL_EXEC; 4757117395Skan else if (!strcmp (TREE_STRING_POINTER (attr), "initial-exec")) 4758117395Skan kind = TLS_MODEL_INITIAL_EXEC; 4759117395Skan else if (!strcmp (TREE_STRING_POINTER (attr), "local-dynamic")) 4760117395Skan kind = optimize ? TLS_MODEL_LOCAL_DYNAMIC : TLS_MODEL_GLOBAL_DYNAMIC; 4761117395Skan else if (!strcmp (TREE_STRING_POINTER (attr), "global-dynamic")) 4762117395Skan kind = TLS_MODEL_GLOBAL_DYNAMIC; 4763117395Skan else 4764117395Skan abort (); 4765117395Skan return kind; 4766117395Skan } 4767117395Skan 4768117395Skan is_local = (*targetm.binds_local_p) (decl); 4769117395Skan if (!flag_pic) 4770117395Skan { 4771117395Skan if (is_local) 4772117395Skan kind = TLS_MODEL_LOCAL_EXEC; 4773117395Skan else 4774117395Skan kind = TLS_MODEL_INITIAL_EXEC; 4775117395Skan } 4776117395Skan /* Local dynamic is inefficient when we're not combining the 4777117395Skan parts of the address. */ 4778117395Skan else if (optimize && is_local) 4779117395Skan kind = TLS_MODEL_LOCAL_DYNAMIC; 4780117395Skan else 4781117395Skan kind = TLS_MODEL_GLOBAL_DYNAMIC; 4782117395Skan if (kind < flag_tls_default) 4783117395Skan kind = flag_tls_default; 4784117395Skan 4785117395Skan return kind; 4786117395Skan} 4787117395Skan 4788117395Skanenum symbol_visibility 4789117395Skandecl_visibility (decl) 4790117395Skan tree decl; 4791117395Skan{ 4792117395Skan tree attr = lookup_attribute ("visibility", DECL_ATTRIBUTES (decl)); 4793117395Skan 4794117395Skan if (attr) 4795117395Skan { 4796117395Skan const char *which = TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (attr))); 4797117395Skan 4798117395Skan if (strcmp (which, "default") == 0) 4799117395Skan return VISIBILITY_DEFAULT; 4800117395Skan if (strcmp (which, "internal") == 0) 4801117395Skan return VISIBILITY_INTERNAL; 4802117395Skan if (strcmp (which, "hidden") == 0) 4803117395Skan return VISIBILITY_HIDDEN; 4804117395Skan if (strcmp (which, "protected") == 0) 4805117395Skan return VISIBILITY_PROTECTED; 4806117395Skan 4807117395Skan abort (); 4808117395Skan } 4809117395Skan 4810117395Skan return VISIBILITY_DEFAULT; 4811117395Skan} 4812117395Skan 481390075Sobrien/* Select a set of attributes for section NAME based on the properties 481490075Sobrien of DECL and whether or not RELOC indicates that DECL's initializer 481590075Sobrien might contain runtime relocations. 481690075Sobrien 481790075Sobrien We make the section read-only and executable for a function decl, 481890075Sobrien read-only for a const data decl, and writable for a non-const data decl. */ 481990075Sobrien 482090075Sobrienunsigned int 482190075Sobriendefault_section_type_flags (decl, name, reloc) 482290075Sobrien tree decl; 482390075Sobrien const char *name; 482490075Sobrien int reloc; 482590075Sobrien{ 4826117395Skan return default_section_type_flags_1 (decl, name, reloc, flag_pic); 4827117395Skan} 4828117395Skan 4829117395Skanunsigned int 4830117395Skandefault_section_type_flags_1 (decl, name, reloc, shlib) 4831117395Skan tree decl; 4832117395Skan const char *name; 4833117395Skan int reloc; 4834117395Skan int shlib; 4835117395Skan{ 483690075Sobrien unsigned int flags; 483790075Sobrien 483890075Sobrien if (decl && TREE_CODE (decl) == FUNCTION_DECL) 483990075Sobrien flags = SECTION_CODE; 4840117395Skan else if (decl && decl_readonly_section_1 (decl, reloc, shlib)) 484190075Sobrien flags = 0; 484290075Sobrien else 484390075Sobrien flags = SECTION_WRITE; 484490075Sobrien 484590075Sobrien if (decl && DECL_ONE_ONLY (decl)) 484690075Sobrien flags |= SECTION_LINKONCE; 484790075Sobrien 4848117395Skan if (decl && TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL (decl)) 4849117395Skan flags |= SECTION_TLS | SECTION_WRITE; 4850117395Skan 485190075Sobrien if (strcmp (name, ".bss") == 0 485290075Sobrien || strncmp (name, ".bss.", 5) == 0 485390075Sobrien || strncmp (name, ".gnu.linkonce.b.", 16) == 0 485490075Sobrien || strcmp (name, ".sbss") == 0 485590075Sobrien || strncmp (name, ".sbss.", 6) == 0 4856117395Skan || strncmp (name, ".gnu.linkonce.sb.", 17) == 0 4857117395Skan || strcmp (name, ".tbss") == 0 4858117395Skan || strncmp (name, ".gnu.linkonce.tb.", 17) == 0) 485990075Sobrien flags |= SECTION_BSS; 486090075Sobrien 4861117395Skan if (strcmp (name, ".tdata") == 0 4862117395Skan || strcmp (name, ".tbss") == 0 4863117395Skan || strncmp (name, ".gnu.linkonce.td.", 17) == 0 4864117395Skan || strncmp (name, ".gnu.linkonce.tb.", 17) == 0) 4865117395Skan flags |= SECTION_TLS; 4866117395Skan 4867117395Skan /* These three sections have special ELF types. They are neither 4868117395Skan SHT_PROGBITS nor SHT_NOBITS, so when changing sections we don't 4869117395Skan want to print a section type (@progbits or @nobits). If someone 4870117395Skan is silly enough to emit code or TLS variables to one of these 4871117395Skan sections, then don't handle them specially. */ 4872117395Skan if (!(flags & (SECTION_CODE | SECTION_BSS | SECTION_TLS)) 4873117395Skan && (strcmp (name, ".init_array") == 0 4874117395Skan || strcmp (name, ".fini_array") == 0 4875117395Skan || strcmp (name, ".preinit_array") == 0)) 4876117395Skan flags |= SECTION_NOTYPE; 4877117395Skan 487890075Sobrien return flags; 487990075Sobrien} 488090075Sobrien 488190075Sobrien/* Output assembly to switch to section NAME with attribute FLAGS. 488290075Sobrien Four variants for common object file formats. */ 488390075Sobrien 488490075Sobrienvoid 488590075Sobriendefault_no_named_section (name, flags) 488690075Sobrien const char *name ATTRIBUTE_UNUSED; 488790075Sobrien unsigned int flags ATTRIBUTE_UNUSED; 488890075Sobrien{ 488990075Sobrien /* Some object formats don't support named sections at all. The 489090075Sobrien front-end should already have flagged this as an error. */ 489190075Sobrien abort (); 489290075Sobrien} 489390075Sobrien 489490075Sobrienvoid 489590075Sobriendefault_elf_asm_named_section (name, flags) 489690075Sobrien const char *name; 489790075Sobrien unsigned int flags; 489890075Sobrien{ 489990075Sobrien char flagchars[10], *f = flagchars; 490090075Sobrien 490190075Sobrien if (! named_section_first_declaration (name)) 490290075Sobrien { 490390075Sobrien fprintf (asm_out_file, "\t.section\t%s\n", name); 490490075Sobrien return; 490590075Sobrien } 490690075Sobrien 490790075Sobrien if (!(flags & SECTION_DEBUG)) 490890075Sobrien *f++ = 'a'; 490990075Sobrien if (flags & SECTION_WRITE) 491090075Sobrien *f++ = 'w'; 491190075Sobrien if (flags & SECTION_CODE) 491290075Sobrien *f++ = 'x'; 491390075Sobrien if (flags & SECTION_SMALL) 491490075Sobrien *f++ = 's'; 491590075Sobrien if (flags & SECTION_MERGE) 491690075Sobrien *f++ = 'M'; 491790075Sobrien if (flags & SECTION_STRINGS) 491890075Sobrien *f++ = 'S'; 4919117395Skan if (flags & SECTION_TLS) 4920117395Skan *f++ = 'T'; 492190075Sobrien *f = '\0'; 492290075Sobrien 4923117395Skan fprintf (asm_out_file, "\t.section\t%s,\"%s\"", name, flagchars); 492490075Sobrien 4925117395Skan if (!(flags & SECTION_NOTYPE)) 4926117395Skan { 4927117395Skan const char *type; 4928117395Skan 4929117395Skan if (flags & SECTION_BSS) 4930117395Skan type = "nobits"; 4931117395Skan else 4932117395Skan type = "progbits"; 4933117395Skan 4934117395Skan fprintf (asm_out_file, ",@%s", type); 4935117395Skan 4936117395Skan if (flags & SECTION_ENTSIZE) 4937117395Skan fprintf (asm_out_file, ",%d", flags & SECTION_ENTSIZE); 4938117395Skan } 4939117395Skan 4940117395Skan putc ('\n', asm_out_file); 494190075Sobrien} 494290075Sobrien 494390075Sobrienvoid 494490075Sobriendefault_coff_asm_named_section (name, flags) 494590075Sobrien const char *name; 494690075Sobrien unsigned int flags; 494790075Sobrien{ 494890075Sobrien char flagchars[8], *f = flagchars; 494990075Sobrien 495090075Sobrien if (flags & SECTION_WRITE) 495190075Sobrien *f++ = 'w'; 495290075Sobrien if (flags & SECTION_CODE) 495390075Sobrien *f++ = 'x'; 495490075Sobrien *f = '\0'; 495590075Sobrien 495690075Sobrien fprintf (asm_out_file, "\t.section\t%s,\"%s\"\n", name, flagchars); 495790075Sobrien} 495890075Sobrien 495990075Sobrienvoid 496090075Sobriendefault_pe_asm_named_section (name, flags) 496190075Sobrien const char *name; 496290075Sobrien unsigned int flags; 496390075Sobrien{ 496490075Sobrien default_coff_asm_named_section (name, flags); 496590075Sobrien 496690075Sobrien if (flags & SECTION_LINKONCE) 496790075Sobrien { 496890075Sobrien /* Functions may have been compiled at various levels of 496990075Sobrien optimization so we can't use `same_size' here. 497090075Sobrien Instead, have the linker pick one. */ 497190075Sobrien fprintf (asm_out_file, "\t.linkonce %s\n", 497290075Sobrien (flags & SECTION_CODE ? "discard" : "same_size")); 497390075Sobrien } 497490075Sobrien} 497590075Sobrien 497690075Sobrien/* Used for vtable gc in GNU binutils. Record that the pointer at OFFSET 497790075Sobrien from SYMBOL is used in all classes derived from SYMBOL. */ 497890075Sobrien 497990075Sobrienvoid 498090075Sobrienassemble_vtable_entry (symbol, offset) 498190075Sobrien rtx symbol; 498290075Sobrien HOST_WIDE_INT offset; 498390075Sobrien{ 498490075Sobrien fputs ("\t.vtable_entry ", asm_out_file); 498590075Sobrien output_addr_const (asm_out_file, symbol); 498690075Sobrien fputs (", ", asm_out_file); 498790075Sobrien fprintf (asm_out_file, HOST_WIDE_INT_PRINT_DEC, offset); 498890075Sobrien fputc ('\n', asm_out_file); 498990075Sobrien} 499090075Sobrien 499190075Sobrien/* Used for vtable gc in GNU binutils. Record the class hierarchy by noting 499290075Sobrien that the vtable symbol CHILD is derived from the vtable symbol PARENT. */ 499390075Sobrien 499490075Sobrienvoid 499590075Sobrienassemble_vtable_inherit (child, parent) 499690075Sobrien rtx child, parent; 499790075Sobrien{ 499890075Sobrien fputs ("\t.vtable_inherit ", asm_out_file); 499990075Sobrien output_addr_const (asm_out_file, child); 500090075Sobrien fputs (", ", asm_out_file); 500190075Sobrien output_addr_const (asm_out_file, parent); 500290075Sobrien fputc ('\n', asm_out_file); 500390075Sobrien} 5004117395Skan 5005117395Skan/* The lame default section selector. */ 5006117395Skan 5007117395Skanvoid 5008117395Skandefault_select_section (decl, reloc, align) 5009117395Skan tree decl; 5010117395Skan int reloc; 5011117395Skan unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED; 5012117395Skan{ 5013117395Skan bool readonly = false; 5014117395Skan 5015117395Skan if (DECL_P (decl)) 5016117395Skan { 5017117395Skan if (decl_readonly_section (decl, reloc)) 5018117395Skan readonly = true; 5019117395Skan } 5020117395Skan else if (TREE_CODE (decl) == CONSTRUCTOR) 5021117395Skan { 5022117395Skan if (! ((flag_pic && reloc) 5023117395Skan || !TREE_READONLY (decl) 5024117395Skan || TREE_SIDE_EFFECTS (decl) 5025117395Skan || !TREE_CONSTANT (decl))) 5026117395Skan readonly = true; 5027117395Skan } 5028117395Skan else if (TREE_CODE (decl) == STRING_CST) 5029117395Skan readonly = !flag_writable_strings; 5030117395Skan else if (! (flag_pic && reloc)) 5031117395Skan readonly = true; 5032117395Skan 5033117395Skan if (readonly) 5034117395Skan readonly_data_section (); 5035117395Skan else 5036117395Skan data_section (); 5037117395Skan} 5038117395Skan 5039117395Skan/* A helper function for default_elf_select_section and 5040117395Skan default_elf_unique_section. Categorizes the DECL. */ 5041117395Skan 5042117395Skanenum section_category 5043117395Skan{ 5044117395Skan SECCAT_TEXT, 5045117395Skan 5046117395Skan SECCAT_RODATA, 5047117395Skan SECCAT_RODATA_MERGE_STR, 5048117395Skan SECCAT_RODATA_MERGE_STR_INIT, 5049117395Skan SECCAT_RODATA_MERGE_CONST, 5050117395Skan SECCAT_SRODATA, 5051117395Skan 5052117395Skan SECCAT_DATA, 5053117395Skan 5054117395Skan /* To optimize loading of shared programs, define following subsections 5055117395Skan of data section: 5056117395Skan _REL Contains data that has relocations, so they get grouped 5057117395Skan together and dynamic linker will visit fewer pages in memory. 5058117395Skan _RO Contains data that is otherwise read-only. This is useful 5059117395Skan with prelinking as most relocations won't be dynamically 5060117395Skan linked and thus stay read only. 5061117395Skan _LOCAL Marks data containing relocations only to local objects. 5062117395Skan These relocations will get fully resolved by prelinking. */ 5063117395Skan SECCAT_DATA_REL, 5064117395Skan SECCAT_DATA_REL_LOCAL, 5065117395Skan SECCAT_DATA_REL_RO, 5066117395Skan SECCAT_DATA_REL_RO_LOCAL, 5067117395Skan 5068117395Skan SECCAT_SDATA, 5069117395Skan SECCAT_TDATA, 5070117395Skan 5071117395Skan SECCAT_BSS, 5072117395Skan SECCAT_SBSS, 5073117395Skan SECCAT_TBSS 5074117395Skan}; 5075117395Skan 5076117395Skanstatic enum section_category 5077117395Skancategorize_decl_for_section PARAMS ((tree, int, int)); 5078117395Skan 5079117395Skanstatic enum section_category 5080117395Skancategorize_decl_for_section (decl, reloc, shlib) 5081117395Skan tree decl; 5082117395Skan int reloc; 5083117395Skan int shlib; 5084117395Skan{ 5085117395Skan enum section_category ret; 5086117395Skan 5087117395Skan if (TREE_CODE (decl) == FUNCTION_DECL) 5088117395Skan return SECCAT_TEXT; 5089117395Skan else if (TREE_CODE (decl) == STRING_CST) 5090117395Skan { 5091117395Skan if (flag_writable_strings) 5092117395Skan return SECCAT_DATA; 5093117395Skan else 5094117395Skan return SECCAT_RODATA_MERGE_STR; 5095117395Skan } 5096117395Skan else if (TREE_CODE (decl) == VAR_DECL) 5097117395Skan { 5098117395Skan if (DECL_INITIAL (decl) == NULL 5099117395Skan || DECL_INITIAL (decl) == error_mark_node) 5100117395Skan ret = SECCAT_BSS; 5101117395Skan else if (! TREE_READONLY (decl) 5102117395Skan || TREE_SIDE_EFFECTS (decl) 5103117395Skan || ! TREE_CONSTANT (DECL_INITIAL (decl))) 5104117395Skan { 5105117395Skan if (shlib && (reloc & 2)) 5106117395Skan ret = SECCAT_DATA_REL; 5107117395Skan else if (shlib && reloc) 5108117395Skan ret = SECCAT_DATA_REL_LOCAL; 5109117395Skan else 5110117395Skan ret = SECCAT_DATA; 5111117395Skan } 5112117395Skan else if (shlib && (reloc & 2)) 5113117395Skan ret = SECCAT_DATA_REL_RO; 5114117395Skan else if (shlib && reloc) 5115117395Skan ret = SECCAT_DATA_REL_RO_LOCAL; 5116117395Skan else if (reloc || flag_merge_constants < 2) 5117117395Skan /* C and C++ don't allow different variables to share the same 5118117395Skan location. -fmerge-all-constants allows even that (at the 5119117395Skan expense of not conforming). */ 5120117395Skan ret = SECCAT_RODATA; 5121117395Skan else if (TREE_CODE (DECL_INITIAL (decl)) == STRING_CST) 5122117395Skan ret = SECCAT_RODATA_MERGE_STR_INIT; 5123117395Skan else 5124117395Skan ret = SECCAT_RODATA_MERGE_CONST; 5125117395Skan } 5126117395Skan else if (TREE_CODE (decl) == CONSTRUCTOR) 5127117395Skan { 5128117395Skan if ((shlib && reloc) 5129117395Skan || TREE_SIDE_EFFECTS (decl) 5130117395Skan || ! TREE_CONSTANT (decl)) 5131117395Skan ret = SECCAT_DATA; 5132117395Skan else 5133117395Skan ret = SECCAT_RODATA; 5134117395Skan } 5135117395Skan else 5136117395Skan ret = SECCAT_RODATA; 5137117395Skan 5138117395Skan /* There are no read-only thread-local sections. */ 5139117395Skan if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL (decl)) 5140117395Skan { 5141117395Skan if (ret == SECCAT_BSS) 5142117395Skan ret = SECCAT_TBSS; 5143117395Skan else 5144117395Skan ret = SECCAT_TDATA; 5145117395Skan } 5146117395Skan 5147117395Skan /* If the target uses small data sections, select it. */ 5148117395Skan else if ((*targetm.in_small_data_p) (decl)) 5149117395Skan { 5150117395Skan if (ret == SECCAT_BSS) 5151117395Skan ret = SECCAT_SBSS; 5152117395Skan else if (targetm.have_srodata_section && ret == SECCAT_RODATA) 5153117395Skan ret = SECCAT_SRODATA; 5154117395Skan else 5155117395Skan ret = SECCAT_SDATA; 5156117395Skan } 5157117395Skan 5158117395Skan return ret; 5159117395Skan} 5160117395Skan 5161117395Skanbool 5162117395Skandecl_readonly_section (decl, reloc) 5163117395Skan tree decl; 5164117395Skan int reloc; 5165117395Skan{ 5166117395Skan return decl_readonly_section_1 (decl, reloc, flag_pic); 5167117395Skan} 5168117395Skan 5169117395Skanbool 5170117395Skandecl_readonly_section_1 (decl, reloc, shlib) 5171117395Skan tree decl; 5172117395Skan int reloc; 5173117395Skan int shlib; 5174117395Skan{ 5175117395Skan switch (categorize_decl_for_section (decl, reloc, shlib)) 5176117395Skan { 5177117395Skan case SECCAT_RODATA: 5178117395Skan case SECCAT_RODATA_MERGE_STR: 5179117395Skan case SECCAT_RODATA_MERGE_STR_INIT: 5180117395Skan case SECCAT_RODATA_MERGE_CONST: 5181117395Skan case SECCAT_SRODATA: 5182117395Skan return true; 5183117395Skan break; 5184117395Skan default: 5185117395Skan return false; 5186117395Skan break; 5187117395Skan } 5188117395Skan} 5189117395Skan 5190117395Skan/* Select a section based on the above categorization. */ 5191117395Skan 5192117395Skanvoid 5193117395Skandefault_elf_select_section (decl, reloc, align) 5194117395Skan tree decl; 5195117395Skan int reloc; 5196117395Skan unsigned HOST_WIDE_INT align; 5197117395Skan{ 5198117395Skan default_elf_select_section_1 (decl, reloc, align, flag_pic); 5199117395Skan} 5200117395Skan 5201117395Skanvoid 5202117395Skandefault_elf_select_section_1 (decl, reloc, align, shlib) 5203117395Skan tree decl; 5204117395Skan int reloc; 5205117395Skan unsigned HOST_WIDE_INT align; 5206117395Skan int shlib; 5207117395Skan{ 5208117395Skan switch (categorize_decl_for_section (decl, reloc, shlib)) 5209117395Skan { 5210117395Skan case SECCAT_TEXT: 5211117395Skan /* We're not supposed to be called on FUNCTION_DECLs. */ 5212117395Skan abort (); 5213117395Skan case SECCAT_RODATA: 5214117395Skan readonly_data_section (); 5215117395Skan break; 5216117395Skan case SECCAT_RODATA_MERGE_STR: 5217117395Skan mergeable_string_section (decl, align, 0); 5218117395Skan break; 5219117395Skan case SECCAT_RODATA_MERGE_STR_INIT: 5220117395Skan mergeable_string_section (DECL_INITIAL (decl), align, 0); 5221117395Skan break; 5222117395Skan case SECCAT_RODATA_MERGE_CONST: 5223117395Skan mergeable_constant_section (DECL_MODE (decl), align, 0); 5224117395Skan break; 5225117395Skan case SECCAT_SRODATA: 5226117395Skan named_section (NULL_TREE, ".sdata2", reloc); 5227117395Skan break; 5228117395Skan case SECCAT_DATA: 5229117395Skan data_section (); 5230117395Skan break; 5231117395Skan case SECCAT_DATA_REL: 5232117395Skan named_section (NULL_TREE, ".data.rel", reloc); 5233117395Skan break; 5234117395Skan case SECCAT_DATA_REL_LOCAL: 5235117395Skan named_section (NULL_TREE, ".data.rel.local", reloc); 5236117395Skan break; 5237117395Skan case SECCAT_DATA_REL_RO: 5238117395Skan named_section (NULL_TREE, ".data.rel.ro", reloc); 5239117395Skan break; 5240117395Skan case SECCAT_DATA_REL_RO_LOCAL: 5241117395Skan named_section (NULL_TREE, ".data.rel.ro.local", reloc); 5242117395Skan break; 5243117395Skan case SECCAT_SDATA: 5244117395Skan named_section (NULL_TREE, ".sdata", reloc); 5245117395Skan break; 5246117395Skan case SECCAT_TDATA: 5247117395Skan named_section (NULL_TREE, ".tdata", reloc); 5248117395Skan break; 5249117395Skan case SECCAT_BSS: 5250117395Skan#ifdef BSS_SECTION_ASM_OP 5251117395Skan bss_section (); 5252117395Skan#else 5253117395Skan named_section (NULL_TREE, ".bss", reloc); 5254117395Skan#endif 5255117395Skan break; 5256117395Skan case SECCAT_SBSS: 5257117395Skan named_section (NULL_TREE, ".sbss", reloc); 5258117395Skan break; 5259117395Skan case SECCAT_TBSS: 5260117395Skan named_section (NULL_TREE, ".tbss", reloc); 5261117395Skan break; 5262117395Skan default: 5263117395Skan abort (); 5264117395Skan } 5265117395Skan} 5266117395Skan 5267117395Skan/* Construct a unique section name based on the decl name and the 5268117395Skan categorization performed above. */ 5269117395Skan 5270117395Skanvoid 5271117395Skandefault_unique_section (decl, reloc) 5272117395Skan tree decl; 5273117395Skan int reloc; 5274117395Skan{ 5275117395Skan default_unique_section_1 (decl, reloc, flag_pic); 5276117395Skan} 5277117395Skan 5278117395Skanvoid 5279117395Skandefault_unique_section_1 (decl, reloc, shlib) 5280117395Skan tree decl; 5281117395Skan int reloc; 5282117395Skan int shlib; 5283117395Skan{ 5284117395Skan bool one_only = DECL_ONE_ONLY (decl); 5285117395Skan const char *prefix, *name; 5286117395Skan size_t nlen, plen; 5287117395Skan char *string; 5288117395Skan 5289117395Skan switch (categorize_decl_for_section (decl, reloc, shlib)) 5290117395Skan { 5291117395Skan case SECCAT_TEXT: 5292117395Skan prefix = one_only ? ".gnu.linkonce.t." : ".text."; 5293117395Skan break; 5294117395Skan case SECCAT_RODATA: 5295117395Skan case SECCAT_RODATA_MERGE_STR: 5296117395Skan case SECCAT_RODATA_MERGE_STR_INIT: 5297117395Skan case SECCAT_RODATA_MERGE_CONST: 5298117395Skan prefix = one_only ? ".gnu.linkonce.r." : ".rodata."; 5299117395Skan break; 5300117395Skan case SECCAT_SRODATA: 5301117395Skan prefix = one_only ? ".gnu.linkonce.s2." : ".sdata2."; 5302117395Skan break; 5303117395Skan case SECCAT_DATA: 5304117395Skan case SECCAT_DATA_REL: 5305117395Skan case SECCAT_DATA_REL_LOCAL: 5306117395Skan case SECCAT_DATA_REL_RO: 5307117395Skan case SECCAT_DATA_REL_RO_LOCAL: 5308117395Skan prefix = one_only ? ".gnu.linkonce.d." : ".data."; 5309117395Skan break; 5310117395Skan case SECCAT_SDATA: 5311117395Skan prefix = one_only ? ".gnu.linkonce.s." : ".sdata."; 5312117395Skan break; 5313117395Skan case SECCAT_BSS: 5314117395Skan prefix = one_only ? ".gnu.linkonce.b." : ".bss."; 5315117395Skan break; 5316117395Skan case SECCAT_SBSS: 5317117395Skan prefix = one_only ? ".gnu.linkonce.sb." : ".sbss."; 5318117395Skan break; 5319117395Skan case SECCAT_TDATA: 5320117395Skan prefix = one_only ? ".gnu.linkonce.td." : ".tdata."; 5321117395Skan break; 5322117395Skan case SECCAT_TBSS: 5323117395Skan prefix = one_only ? ".gnu.linkonce.tb." : ".tbss."; 5324117395Skan break; 5325117395Skan default: 5326117395Skan abort (); 5327117395Skan } 5328117395Skan plen = strlen (prefix); 5329117395Skan 5330117395Skan name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); 5331117395Skan name = (* targetm.strip_name_encoding) (name); 5332117395Skan nlen = strlen (name); 5333117395Skan 5334117395Skan string = alloca (nlen + plen + 1); 5335117395Skan memcpy (string, prefix, plen); 5336117395Skan memcpy (string + plen, name, nlen + 1); 5337117395Skan 5338117395Skan DECL_SECTION_NAME (decl) = build_string (nlen + plen, string); 5339117395Skan} 5340117395Skan 5341117395Skanvoid 5342117395Skandefault_select_rtx_section (mode, x, align) 5343117395Skan enum machine_mode mode ATTRIBUTE_UNUSED; 5344117395Skan rtx x; 5345117395Skan unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED; 5346117395Skan{ 5347117395Skan if (flag_pic) 5348117395Skan switch (GET_CODE (x)) 5349117395Skan { 5350117395Skan case CONST: 5351117395Skan case SYMBOL_REF: 5352117395Skan case LABEL_REF: 5353117395Skan data_section (); 5354117395Skan return; 5355117395Skan 5356117395Skan default: 5357117395Skan break; 5358117395Skan } 5359117395Skan 5360117395Skan readonly_data_section (); 5361117395Skan} 5362117395Skan 5363117395Skanvoid 5364117395Skandefault_elf_select_rtx_section (mode, x, align) 5365117395Skan enum machine_mode mode; 5366117395Skan rtx x; 5367117395Skan unsigned HOST_WIDE_INT align; 5368117395Skan{ 5369117395Skan /* ??? Handle small data here somehow. */ 5370117395Skan 5371117395Skan if (flag_pic) 5372117395Skan switch (GET_CODE (x)) 5373117395Skan { 5374117395Skan case CONST: 5375117395Skan case SYMBOL_REF: 5376117395Skan named_section (NULL_TREE, ".data.rel.ro", 3); 5377117395Skan return; 5378117395Skan 5379117395Skan case LABEL_REF: 5380117395Skan named_section (NULL_TREE, ".data.rel.ro.local", 1); 5381117395Skan return; 5382117395Skan 5383117395Skan default: 5384117395Skan break; 5385117395Skan } 5386117395Skan 5387117395Skan mergeable_constant_section (mode, align, 0); 5388117395Skan} 5389117395Skan 5390117395Skan/* By default, we do nothing for encode_section_info, so we need not 5391117395Skan do anything but discard the '*' marker. */ 5392117395Skan 5393117395Skanconst char * 5394117395Skandefault_strip_name_encoding (str) 5395117395Skan const char *str; 5396117395Skan{ 5397117395Skan return str + (*str == '*'); 5398117395Skan} 5399117395Skan 5400117395Skan/* Assume ELF-ish defaults, since that's pretty much the most liberal 5401117395Skan wrt cross-module name binding. */ 5402117395Skan 5403117395Skanbool 5404117395Skandefault_binds_local_p (exp) 5405117395Skan tree exp; 5406117395Skan{ 5407117395Skan return default_binds_local_p_1 (exp, flag_pic); 5408117395Skan} 5409117395Skan 5410117395Skanbool 5411117395Skandefault_binds_local_p_1 (exp, shlib) 5412117395Skan tree exp; 5413117395Skan int shlib; 5414117395Skan{ 5415117395Skan bool local_p; 5416117395Skan 5417117395Skan /* A non-decl is an entry in the constant pool. */ 5418117395Skan if (!DECL_P (exp)) 5419117395Skan local_p = true; 5420117395Skan /* Static variables are always local. */ 5421117395Skan else if (! TREE_PUBLIC (exp)) 5422117395Skan local_p = true; 5423117395Skan /* A variable is local if the user tells us so. */ 5424117395Skan else if (decl_visibility (exp) != VISIBILITY_DEFAULT) 5425117395Skan local_p = true; 5426117395Skan /* Otherwise, variables defined outside this object may not be local. */ 5427117395Skan else if (DECL_EXTERNAL (exp)) 5428117395Skan local_p = false; 5429117395Skan /* Linkonce and weak data are never local. */ 5430117395Skan else if (DECL_ONE_ONLY (exp) || DECL_WEAK (exp)) 5431117395Skan local_p = false; 5432117395Skan /* If PIC, then assume that any global name can be overridden by 5433117395Skan symbols resolved from other modules. */ 5434117395Skan else if (shlib) 5435117395Skan local_p = false; 5436117395Skan /* Uninitialized COMMON variable may be unified with symbols 5437117395Skan resolved from other modules. */ 5438117395Skan else if (DECL_COMMON (exp) 5439117395Skan && (DECL_INITIAL (exp) == NULL 5440117395Skan || DECL_INITIAL (exp) == error_mark_node)) 5441117395Skan local_p = false; 5442117395Skan /* Otherwise we're left with initialized (or non-common) global data 5443117395Skan which is of necessity defined locally. */ 5444117395Skan else 5445117395Skan local_p = true; 5446117395Skan 5447117395Skan return local_p; 5448117395Skan} 5449117395Skan 5450117395Skan/* Default function to output code that will globalize a label. A 5451117395Skan target must define GLOBAL_ASM_OP or provide it's own function to 5452117395Skan globalize a label. */ 5453117395Skan#ifdef GLOBAL_ASM_OP 5454117395Skanvoid 5455117395Skandefault_globalize_label (stream, name) 5456117395Skan FILE * stream; 5457117395Skan const char *name; 5458117395Skan{ 5459117395Skan fputs (GLOBAL_ASM_OP, stream); 5460117395Skan assemble_name (stream, name); 5461117395Skan putc ('\n', stream); 5462117395Skan} 5463117395Skan#endif /* GLOBAL_ASM_OP */ 5464117395Skan 5465117395Skan#include "gt-varasm.h" 5466