138fd1498Szrj /* Output variables, constants and external declarations, for GNU compiler.
238fd1498Szrj Copyright (C) 1987-2018 Free Software Foundation, Inc.
338fd1498Szrj
438fd1498Szrj This file is part of GCC.
538fd1498Szrj
638fd1498Szrj GCC is free software; you can redistribute it and/or modify it under
738fd1498Szrj the terms of the GNU General Public License as published by the Free
838fd1498Szrj Software Foundation; either version 3, or (at your option) any later
938fd1498Szrj version.
1038fd1498Szrj
1138fd1498Szrj GCC is distributed in the hope that it will be useful, but WITHOUT ANY
1238fd1498Szrj WARRANTY; without even the implied warranty of MERCHANTABILITY or
1338fd1498Szrj FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
1438fd1498Szrj for more details.
1538fd1498Szrj
1638fd1498Szrj You should have received a copy of the GNU General Public License
1738fd1498Szrj along with GCC; see the file COPYING3. If not see
1838fd1498Szrj <http://www.gnu.org/licenses/>. */
1938fd1498Szrj
2038fd1498Szrj
2138fd1498Szrj /* This file handles generation of all the assembler code
2238fd1498Szrj *except* the instructions of a function.
2338fd1498Szrj This includes declarations of variables and their initial values.
2438fd1498Szrj
2538fd1498Szrj We also output the assembler code for constants stored in memory
2638fd1498Szrj and are responsible for combining constants with the same value. */
2738fd1498Szrj
2838fd1498Szrj #include "config.h"
2938fd1498Szrj #include "system.h"
3038fd1498Szrj #include "coretypes.h"
3138fd1498Szrj #include "backend.h"
3238fd1498Szrj #include "target.h"
3338fd1498Szrj #include "rtl.h"
3438fd1498Szrj #include "tree.h"
3538fd1498Szrj #include "predict.h"
3638fd1498Szrj #include "memmodel.h"
3738fd1498Szrj #include "tm_p.h"
3838fd1498Szrj #include "stringpool.h"
3938fd1498Szrj #include "regs.h"
4038fd1498Szrj #include "emit-rtl.h"
4138fd1498Szrj #include "cgraph.h"
4238fd1498Szrj #include "diagnostic-core.h"
4338fd1498Szrj #include "fold-const.h"
4438fd1498Szrj #include "stor-layout.h"
4538fd1498Szrj #include "varasm.h"
4638fd1498Szrj #include "flags.h"
4738fd1498Szrj #include "stmt.h"
4838fd1498Szrj #include "expr.h"
4938fd1498Szrj #include "expmed.h"
5038fd1498Szrj #include "output.h"
5138fd1498Szrj #include "langhooks.h"
5238fd1498Szrj #include "debug.h"
5338fd1498Szrj #include "common/common-target.h"
5438fd1498Szrj #include "stringpool.h"
5538fd1498Szrj #include "attribs.h"
5638fd1498Szrj #include "asan.h"
5738fd1498Szrj #include "rtl-iter.h"
5838fd1498Szrj #include "file-prefix-map.h" /* remap_debug_filename() */
5938fd1498Szrj
6038fd1498Szrj #ifdef XCOFF_DEBUGGING_INFO
6138fd1498Szrj #include "xcoffout.h" /* Needed for external data declarations. */
6238fd1498Szrj #endif
6338fd1498Szrj
6438fd1498Szrj /* The (assembler) name of the first globally-visible object output. */
6538fd1498Szrj extern GTY(()) const char *first_global_object_name;
6638fd1498Szrj extern GTY(()) const char *weak_global_object_name;
6738fd1498Szrj
6838fd1498Szrj const char *first_global_object_name;
6938fd1498Szrj const char *weak_global_object_name;
7038fd1498Szrj
7138fd1498Szrj struct addr_const;
7238fd1498Szrj struct constant_descriptor_rtx;
7338fd1498Szrj struct rtx_constant_pool;
7438fd1498Szrj
7538fd1498Szrj #define n_deferred_constants (crtl->varasm.deferred_constants)
7638fd1498Szrj
7738fd1498Szrj /* Number for making the label on the next
7838fd1498Szrj constant that is stored in memory. */
7938fd1498Szrj
8038fd1498Szrj static GTY(()) int const_labelno;
8138fd1498Szrj
8238fd1498Szrj /* Carry information from ASM_DECLARE_OBJECT_NAME
8338fd1498Szrj to ASM_FINISH_DECLARE_OBJECT. */
8438fd1498Szrj
8538fd1498Szrj int size_directive_output;
8638fd1498Szrj
8738fd1498Szrj /* The last decl for which assemble_variable was called,
8838fd1498Szrj if it did ASM_DECLARE_OBJECT_NAME.
8938fd1498Szrj If the last call to assemble_variable didn't do that,
9038fd1498Szrj this holds 0. */
9138fd1498Szrj
9238fd1498Szrj tree last_assemble_variable_decl;
9338fd1498Szrj
9438fd1498Szrj /* The following global variable indicates if the first basic block
9538fd1498Szrj in a function belongs to the cold partition or not. */
9638fd1498Szrj
9738fd1498Szrj bool first_function_block_is_cold;
9838fd1498Szrj
9938fd1498Szrj /* Whether we saw any functions with no_split_stack. */
10038fd1498Szrj
10138fd1498Szrj static bool saw_no_split_stack;
10238fd1498Szrj
10338fd1498Szrj static const char *strip_reg_name (const char *);
10438fd1498Szrj static int contains_pointers_p (tree);
10538fd1498Szrj #ifdef ASM_OUTPUT_EXTERNAL
10638fd1498Szrj static bool incorporeal_function_p (tree);
10738fd1498Szrj #endif
10838fd1498Szrj static void decode_addr_const (tree, struct addr_const *);
10938fd1498Szrj static hashval_t const_hash_1 (const tree);
11038fd1498Szrj static int compare_constant (const tree, const tree);
11138fd1498Szrj static void output_constant_def_contents (rtx);
11238fd1498Szrj static void output_addressed_constants (tree);
11338fd1498Szrj static unsigned HOST_WIDE_INT output_constant (tree, unsigned HOST_WIDE_INT,
11438fd1498Szrj unsigned int, bool);
11538fd1498Szrj static void globalize_decl (tree);
11638fd1498Szrj static bool decl_readonly_section_1 (enum section_category);
11738fd1498Szrj #ifdef BSS_SECTION_ASM_OP
11838fd1498Szrj #ifdef ASM_OUTPUT_ALIGNED_BSS
11938fd1498Szrj static void asm_output_aligned_bss (FILE *, tree, const char *,
12038fd1498Szrj unsigned HOST_WIDE_INT, int)
12138fd1498Szrj ATTRIBUTE_UNUSED;
12238fd1498Szrj #endif
12338fd1498Szrj #endif /* BSS_SECTION_ASM_OP */
12438fd1498Szrj static void mark_weak (tree);
12538fd1498Szrj static void output_constant_pool (const char *, tree);
12638fd1498Szrj static void handle_vtv_comdat_section (section *, const_tree);
12738fd1498Szrj
12838fd1498Szrj /* Well-known sections, each one associated with some sort of *_ASM_OP. */
12938fd1498Szrj section *text_section;
13038fd1498Szrj section *data_section;
13138fd1498Szrj section *readonly_data_section;
13238fd1498Szrj section *sdata_section;
13338fd1498Szrj section *ctors_section;
13438fd1498Szrj section *dtors_section;
13538fd1498Szrj section *bss_section;
13638fd1498Szrj section *sbss_section;
13738fd1498Szrj
13838fd1498Szrj /* Various forms of common section. All are guaranteed to be nonnull. */
13938fd1498Szrj section *tls_comm_section;
14038fd1498Szrj section *comm_section;
14138fd1498Szrj section *lcomm_section;
14238fd1498Szrj
14338fd1498Szrj /* A SECTION_NOSWITCH section used for declaring global BSS variables.
14438fd1498Szrj May be null. */
14538fd1498Szrj section *bss_noswitch_section;
14638fd1498Szrj
14738fd1498Szrj /* The section that holds the main exception table, when known. The section
14838fd1498Szrj is set either by the target's init_sections hook or by the first call to
14938fd1498Szrj switch_to_exception_section. */
15038fd1498Szrj section *exception_section;
15138fd1498Szrj
15238fd1498Szrj /* The section that holds the DWARF2 frame unwind information, when known.
15338fd1498Szrj The section is set either by the target's init_sections hook or by the
15438fd1498Szrj first call to switch_to_eh_frame_section. */
15538fd1498Szrj section *eh_frame_section;
15638fd1498Szrj
15738fd1498Szrj /* asm_out_file's current section. This is NULL if no section has yet
15838fd1498Szrj been selected or if we lose track of what the current section is. */
15938fd1498Szrj section *in_section;
16038fd1498Szrj
16138fd1498Szrj /* True if code for the current function is currently being directed
16238fd1498Szrj at the cold section. */
16338fd1498Szrj bool in_cold_section_p;
16438fd1498Szrj
16538fd1498Szrj /* The following global holds the "function name" for the code in the
16638fd1498Szrj cold section of a function, if hot/cold function splitting is enabled
16738fd1498Szrj and there was actually code that went into the cold section. A
16838fd1498Szrj pseudo function name is needed for the cold section of code for some
16938fd1498Szrj debugging tools that perform symbolization. */
17038fd1498Szrj tree cold_function_name = NULL_TREE;
17138fd1498Szrj
17238fd1498Szrj /* A linked list of all the unnamed sections. */
17338fd1498Szrj static GTY(()) section *unnamed_sections;
17438fd1498Szrj
17538fd1498Szrj /* Return a nonzero value if DECL has a section attribute. */
17638fd1498Szrj #define IN_NAMED_SECTION(DECL) \
17738fd1498Szrj (VAR_OR_FUNCTION_DECL_P (DECL) && DECL_SECTION_NAME (DECL) != NULL)
17838fd1498Szrj
17938fd1498Szrj struct section_hasher : ggc_ptr_hash<section>
18038fd1498Szrj {
18138fd1498Szrj typedef const char *compare_type;
18238fd1498Szrj
18338fd1498Szrj static hashval_t hash (section *);
18438fd1498Szrj static bool equal (section *, const char *);
18538fd1498Szrj };
18638fd1498Szrj
18738fd1498Szrj /* Hash table of named sections. */
18838fd1498Szrj static GTY(()) hash_table<section_hasher> *section_htab;
18938fd1498Szrj
19038fd1498Szrj struct object_block_hasher : ggc_ptr_hash<object_block>
19138fd1498Szrj {
19238fd1498Szrj typedef const section *compare_type;
19338fd1498Szrj
19438fd1498Szrj static hashval_t hash (object_block *);
19538fd1498Szrj static bool equal (object_block *, const section *);
19638fd1498Szrj };
19738fd1498Szrj
19838fd1498Szrj /* A table of object_blocks, indexed by section. */
19938fd1498Szrj static GTY(()) hash_table<object_block_hasher> *object_block_htab;
20038fd1498Szrj
20138fd1498Szrj /* The next number to use for internal anchor labels. */
20238fd1498Szrj static GTY(()) int anchor_labelno;
20338fd1498Szrj
20438fd1498Szrj /* A pool of constants that can be shared between functions. */
20538fd1498Szrj static GTY(()) struct rtx_constant_pool *shared_constant_pool;
20638fd1498Szrj
20738fd1498Szrj /* Helper routines for maintaining section_htab. */
20838fd1498Szrj
20938fd1498Szrj bool
equal(section * old,const char * new_name)21038fd1498Szrj section_hasher::equal (section *old, const char *new_name)
21138fd1498Szrj {
21238fd1498Szrj return strcmp (old->named.name, new_name) == 0;
21338fd1498Szrj }
21438fd1498Szrj
21538fd1498Szrj hashval_t
hash(section * old)21638fd1498Szrj section_hasher::hash (section *old)
21738fd1498Szrj {
21838fd1498Szrj return htab_hash_string (old->named.name);
21938fd1498Szrj }
22038fd1498Szrj
22138fd1498Szrj /* Return a hash value for section SECT. */
22238fd1498Szrj
22338fd1498Szrj static hashval_t
hash_section(section * sect)22438fd1498Szrj hash_section (section *sect)
22538fd1498Szrj {
22638fd1498Szrj if (sect->common.flags & SECTION_NAMED)
22738fd1498Szrj return htab_hash_string (sect->named.name);
22838fd1498Szrj return sect->common.flags & ~SECTION_DECLARED;
22938fd1498Szrj }
23038fd1498Szrj
23138fd1498Szrj /* Helper routines for maintaining object_block_htab. */
23238fd1498Szrj
23338fd1498Szrj inline bool
equal(object_block * old,const section * new_section)23438fd1498Szrj object_block_hasher::equal (object_block *old, const section *new_section)
23538fd1498Szrj {
23638fd1498Szrj return old->sect == new_section;
23738fd1498Szrj }
23838fd1498Szrj
23938fd1498Szrj hashval_t
hash(object_block * old)24038fd1498Szrj object_block_hasher::hash (object_block *old)
24138fd1498Szrj {
24238fd1498Szrj return hash_section (old->sect);
24338fd1498Szrj }
24438fd1498Szrj
24538fd1498Szrj /* Return a new unnamed section with the given fields. */
24638fd1498Szrj
24738fd1498Szrj section *
get_unnamed_section(unsigned int flags,void (* callback)(const void *),const void * data)24838fd1498Szrj get_unnamed_section (unsigned int flags, void (*callback) (const void *),
24938fd1498Szrj const void *data)
25038fd1498Szrj {
25138fd1498Szrj section *sect;
25238fd1498Szrj
25338fd1498Szrj sect = ggc_alloc<section> ();
25438fd1498Szrj sect->unnamed.common.flags = flags | SECTION_UNNAMED;
25538fd1498Szrj sect->unnamed.callback = callback;
25638fd1498Szrj sect->unnamed.data = data;
25738fd1498Szrj sect->unnamed.next = unnamed_sections;
25838fd1498Szrj
25938fd1498Szrj unnamed_sections = sect;
26038fd1498Szrj return sect;
26138fd1498Szrj }
26238fd1498Szrj
26338fd1498Szrj /* Return a SECTION_NOSWITCH section with the given fields. */
26438fd1498Szrj
26538fd1498Szrj static section *
get_noswitch_section(unsigned int flags,noswitch_section_callback callback)26638fd1498Szrj get_noswitch_section (unsigned int flags, noswitch_section_callback callback)
26738fd1498Szrj {
26838fd1498Szrj section *sect;
26938fd1498Szrj
27038fd1498Szrj sect = ggc_alloc<section> ();
27138fd1498Szrj sect->noswitch.common.flags = flags | SECTION_NOSWITCH;
27238fd1498Szrj sect->noswitch.callback = callback;
27338fd1498Szrj
27438fd1498Szrj return sect;
27538fd1498Szrj }
27638fd1498Szrj
27738fd1498Szrj /* Return the named section structure associated with NAME. Create
27838fd1498Szrj a new section with the given fields if no such structure exists. */
27938fd1498Szrj
28038fd1498Szrj section *
get_section(const char * name,unsigned int flags,tree decl)28138fd1498Szrj get_section (const char *name, unsigned int flags, tree decl)
28238fd1498Szrj {
28338fd1498Szrj section *sect, **slot;
28438fd1498Szrj
28538fd1498Szrj slot = section_htab->find_slot_with_hash (name, htab_hash_string (name),
28638fd1498Szrj INSERT);
28738fd1498Szrj flags |= SECTION_NAMED;
28838fd1498Szrj if (*slot == NULL)
28938fd1498Szrj {
29038fd1498Szrj sect = ggc_alloc<section> ();
29138fd1498Szrj sect->named.common.flags = flags;
29238fd1498Szrj sect->named.name = ggc_strdup (name);
29338fd1498Szrj sect->named.decl = decl;
29438fd1498Szrj *slot = sect;
29538fd1498Szrj }
29638fd1498Szrj else
29738fd1498Szrj {
29838fd1498Szrj sect = *slot;
299*58e805e6Szrj /* It is fine if one of the sections has SECTION_NOTYPE as long as
300*58e805e6Szrj the other has none of the contrary flags (see the logic at the end
301*58e805e6Szrj of default_section_type_flags, below). */
302*58e805e6Szrj if (((sect->common.flags ^ flags) & SECTION_NOTYPE)
303*58e805e6Szrj && !((sect->common.flags | flags)
304*58e805e6Szrj & (SECTION_CODE | SECTION_BSS | SECTION_TLS | SECTION_ENTSIZE
305*58e805e6Szrj | (HAVE_COMDAT_GROUP ? SECTION_LINKONCE : 0))))
306*58e805e6Szrj {
307*58e805e6Szrj sect->common.flags |= SECTION_NOTYPE;
308*58e805e6Szrj flags |= SECTION_NOTYPE;
309*58e805e6Szrj }
31038fd1498Szrj if ((sect->common.flags & ~SECTION_DECLARED) != flags
31138fd1498Szrj && ((sect->common.flags | flags) & SECTION_OVERRIDE) == 0)
31238fd1498Szrj {
31338fd1498Szrj /* It is fine if one of the section flags is
31438fd1498Szrj SECTION_WRITE | SECTION_RELRO and the other has none of these
31538fd1498Szrj flags (i.e. read-only) in named sections and either the
31638fd1498Szrj section hasn't been declared yet or has been declared as writable.
31738fd1498Szrj In that case just make sure the resulting flags are
31838fd1498Szrj SECTION_WRITE | SECTION_RELRO, ie. writable only because of
31938fd1498Szrj relocations. */
32038fd1498Szrj if (((sect->common.flags ^ flags) & (SECTION_WRITE | SECTION_RELRO))
32138fd1498Szrj == (SECTION_WRITE | SECTION_RELRO)
32238fd1498Szrj && (sect->common.flags
32338fd1498Szrj & ~(SECTION_DECLARED | SECTION_WRITE | SECTION_RELRO))
32438fd1498Szrj == (flags & ~(SECTION_WRITE | SECTION_RELRO))
32538fd1498Szrj && ((sect->common.flags & SECTION_DECLARED) == 0
32638fd1498Szrj || (sect->common.flags & SECTION_WRITE)))
32738fd1498Szrj {
32838fd1498Szrj sect->common.flags |= (SECTION_WRITE | SECTION_RELRO);
32938fd1498Szrj return sect;
33038fd1498Szrj }
33138fd1498Szrj /* Sanity check user variables for flag changes. */
33238fd1498Szrj if (sect->named.decl != NULL
33338fd1498Szrj && DECL_P (sect->named.decl)
33438fd1498Szrj && decl != sect->named.decl)
33538fd1498Szrj {
33638fd1498Szrj if (decl != NULL && DECL_P (decl))
33738fd1498Szrj error ("%+qD causes a section type conflict with %qD",
33838fd1498Szrj decl, sect->named.decl);
33938fd1498Szrj else
34038fd1498Szrj error ("section type conflict with %qD", sect->named.decl);
34138fd1498Szrj inform (DECL_SOURCE_LOCATION (sect->named.decl),
34238fd1498Szrj "%qD was declared here", sect->named.decl);
34338fd1498Szrj }
34438fd1498Szrj else if (decl != NULL && DECL_P (decl))
34538fd1498Szrj error ("%+qD causes a section type conflict", decl);
34638fd1498Szrj else
34738fd1498Szrj error ("section type conflict");
34838fd1498Szrj /* Make sure we don't error about one section multiple times. */
34938fd1498Szrj sect->common.flags |= SECTION_OVERRIDE;
35038fd1498Szrj }
35138fd1498Szrj }
35238fd1498Szrj return sect;
35338fd1498Szrj }
35438fd1498Szrj
35538fd1498Szrj /* Return true if the current compilation mode benefits from having
35638fd1498Szrj objects grouped into blocks. */
35738fd1498Szrj
35838fd1498Szrj static bool
use_object_blocks_p(void)35938fd1498Szrj use_object_blocks_p (void)
36038fd1498Szrj {
36138fd1498Szrj return flag_section_anchors;
36238fd1498Szrj }
36338fd1498Szrj
36438fd1498Szrj /* Return the object_block structure for section SECT. Create a new
36538fd1498Szrj structure if we haven't created one already. Return null if SECT
36638fd1498Szrj itself is null. */
36738fd1498Szrj
36838fd1498Szrj static struct object_block *
get_block_for_section(section * sect)36938fd1498Szrj get_block_for_section (section *sect)
37038fd1498Szrj {
37138fd1498Szrj struct object_block *block;
37238fd1498Szrj
37338fd1498Szrj if (sect == NULL)
37438fd1498Szrj return NULL;
37538fd1498Szrj
37638fd1498Szrj object_block **slot
37738fd1498Szrj = object_block_htab->find_slot_with_hash (sect, hash_section (sect),
37838fd1498Szrj INSERT);
37938fd1498Szrj block = *slot;
38038fd1498Szrj if (block == NULL)
38138fd1498Szrj {
38238fd1498Szrj block = ggc_cleared_alloc<object_block> ();
38338fd1498Szrj block->sect = sect;
38438fd1498Szrj *slot = block;
38538fd1498Szrj }
38638fd1498Szrj return block;
38738fd1498Szrj }
38838fd1498Szrj
38938fd1498Szrj /* Create a symbol with label LABEL and place it at byte offset
39038fd1498Szrj OFFSET in BLOCK. OFFSET can be negative if the symbol's offset
39138fd1498Szrj is not yet known. LABEL must be a garbage-collected string. */
39238fd1498Szrj
39338fd1498Szrj static rtx
create_block_symbol(const char * label,struct object_block * block,HOST_WIDE_INT offset)39438fd1498Szrj create_block_symbol (const char *label, struct object_block *block,
39538fd1498Szrj HOST_WIDE_INT offset)
39638fd1498Szrj {
39738fd1498Szrj rtx symbol;
39838fd1498Szrj unsigned int size;
39938fd1498Szrj
40038fd1498Szrj /* Create the extended SYMBOL_REF. */
40138fd1498Szrj size = RTX_HDR_SIZE + sizeof (struct block_symbol);
40238fd1498Szrj symbol = (rtx) ggc_internal_alloc (size);
40338fd1498Szrj
40438fd1498Szrj /* Initialize the normal SYMBOL_REF fields. */
40538fd1498Szrj memset (symbol, 0, size);
40638fd1498Szrj PUT_CODE (symbol, SYMBOL_REF);
40738fd1498Szrj PUT_MODE (symbol, Pmode);
40838fd1498Szrj XSTR (symbol, 0) = label;
40938fd1498Szrj SYMBOL_REF_FLAGS (symbol) = SYMBOL_FLAG_HAS_BLOCK_INFO;
41038fd1498Szrj
41138fd1498Szrj /* Initialize the block_symbol stuff. */
41238fd1498Szrj SYMBOL_REF_BLOCK (symbol) = block;
41338fd1498Szrj SYMBOL_REF_BLOCK_OFFSET (symbol) = offset;
41438fd1498Szrj
41538fd1498Szrj return symbol;
41638fd1498Szrj }
41738fd1498Szrj
41838fd1498Szrj /* Return a section with a particular name and with whatever SECTION_*
41938fd1498Szrj flags section_type_flags deems appropriate. The name of the section
42038fd1498Szrj is taken from NAME if nonnull, otherwise it is taken from DECL's
42138fd1498Szrj DECL_SECTION_NAME. DECL is the decl associated with the section
42238fd1498Szrj (see the section comment for details) and RELOC is as for
42338fd1498Szrj section_type_flags. */
42438fd1498Szrj
42538fd1498Szrj section *
get_named_section(tree decl,const char * name,int reloc)42638fd1498Szrj get_named_section (tree decl, const char *name, int reloc)
42738fd1498Szrj {
42838fd1498Szrj unsigned int flags;
42938fd1498Szrj
43038fd1498Szrj if (name == NULL)
43138fd1498Szrj {
43238fd1498Szrj gcc_assert (decl && DECL_P (decl) && DECL_SECTION_NAME (decl));
43338fd1498Szrj name = DECL_SECTION_NAME (decl);
43438fd1498Szrj }
43538fd1498Szrj
43638fd1498Szrj flags = targetm.section_type_flags (decl, name, reloc);
43738fd1498Szrj return get_section (name, flags, decl);
43838fd1498Szrj }
43938fd1498Szrj
44038fd1498Szrj /* Worker for resolve_unique_section. */
44138fd1498Szrj
44238fd1498Szrj static bool
set_implicit_section(struct symtab_node * n,void * data ATTRIBUTE_UNUSED)44338fd1498Szrj set_implicit_section (struct symtab_node *n, void *data ATTRIBUTE_UNUSED)
44438fd1498Szrj {
44538fd1498Szrj n->implicit_section = true;
44638fd1498Szrj return false;
44738fd1498Szrj }
44838fd1498Szrj
44938fd1498Szrj /* If required, set DECL_SECTION_NAME to a unique name. */
45038fd1498Szrj
45138fd1498Szrj void
resolve_unique_section(tree decl,int reloc ATTRIBUTE_UNUSED,int flag_function_or_data_sections)45238fd1498Szrj resolve_unique_section (tree decl, int reloc ATTRIBUTE_UNUSED,
45338fd1498Szrj int flag_function_or_data_sections)
45438fd1498Szrj {
45538fd1498Szrj if (DECL_SECTION_NAME (decl) == NULL
45638fd1498Szrj && targetm_common.have_named_sections
45738fd1498Szrj && (flag_function_or_data_sections
45838fd1498Szrj || DECL_COMDAT_GROUP (decl)))
45938fd1498Szrj {
46038fd1498Szrj targetm.asm_out.unique_section (decl, reloc);
46138fd1498Szrj if (DECL_SECTION_NAME (decl))
46238fd1498Szrj symtab_node::get (decl)->call_for_symbol_and_aliases
46338fd1498Szrj (set_implicit_section, NULL, true);
46438fd1498Szrj }
46538fd1498Szrj }
46638fd1498Szrj
46738fd1498Szrj #ifdef BSS_SECTION_ASM_OP
46838fd1498Szrj
46938fd1498Szrj #ifdef ASM_OUTPUT_ALIGNED_BSS
47038fd1498Szrj
47138fd1498Szrj /* Utility function for targets to use in implementing
47238fd1498Szrj ASM_OUTPUT_ALIGNED_BSS.
47338fd1498Szrj ??? It is believed that this function will work in most cases so such
47438fd1498Szrj support is localized here. */
47538fd1498Szrj
47638fd1498Szrj static void
asm_output_aligned_bss(FILE * file,tree decl ATTRIBUTE_UNUSED,const char * name,unsigned HOST_WIDE_INT size,int align)47738fd1498Szrj asm_output_aligned_bss (FILE *file, tree decl ATTRIBUTE_UNUSED,
47838fd1498Szrj const char *name, unsigned HOST_WIDE_INT size,
47938fd1498Szrj int align)
48038fd1498Szrj {
48138fd1498Szrj switch_to_section (bss_section);
48238fd1498Szrj ASM_OUTPUT_ALIGN (file, floor_log2 (align / BITS_PER_UNIT));
48338fd1498Szrj #ifdef ASM_DECLARE_OBJECT_NAME
48438fd1498Szrj last_assemble_variable_decl = decl;
48538fd1498Szrj ASM_DECLARE_OBJECT_NAME (file, name, decl);
48638fd1498Szrj #else
48738fd1498Szrj /* Standard thing is just output label for the object. */
48838fd1498Szrj ASM_OUTPUT_LABEL (file, name);
48938fd1498Szrj #endif /* ASM_DECLARE_OBJECT_NAME */
49038fd1498Szrj ASM_OUTPUT_SKIP (file, size ? size : 1);
49138fd1498Szrj }
49238fd1498Szrj
49338fd1498Szrj #endif
49438fd1498Szrj
49538fd1498Szrj #endif /* BSS_SECTION_ASM_OP */
49638fd1498Szrj
49738fd1498Szrj #ifndef USE_SELECT_SECTION_FOR_FUNCTIONS
49838fd1498Szrj /* Return the hot section for function DECL. Return text_section for
49938fd1498Szrj null DECLs. */
50038fd1498Szrj
50138fd1498Szrj static section *
hot_function_section(tree decl)50238fd1498Szrj hot_function_section (tree decl)
50338fd1498Szrj {
50438fd1498Szrj if (decl != NULL_TREE
50538fd1498Szrj && DECL_SECTION_NAME (decl) != NULL
50638fd1498Szrj && targetm_common.have_named_sections)
50738fd1498Szrj return get_named_section (decl, NULL, 0);
50838fd1498Szrj else
50938fd1498Szrj return text_section;
51038fd1498Szrj }
51138fd1498Szrj #endif
51238fd1498Szrj
51338fd1498Szrj /* Return section for TEXT_SECTION_NAME if DECL or DECL_SECTION_NAME (DECL)
51438fd1498Szrj is NULL.
51538fd1498Szrj
51638fd1498Szrj When DECL_SECTION_NAME is non-NULL and it is implicit section and
51738fd1498Szrj NAMED_SECTION_SUFFIX is non-NULL, then produce section called
51838fd1498Szrj concatenate the name with NAMED_SECTION_SUFFIX.
51938fd1498Szrj Otherwise produce "TEXT_SECTION_NAME.IMPLICIT_NAME". */
52038fd1498Szrj
52138fd1498Szrj section *
get_named_text_section(tree decl,const char * text_section_name,const char * named_section_suffix)52238fd1498Szrj get_named_text_section (tree decl,
52338fd1498Szrj const char *text_section_name,
52438fd1498Szrj const char *named_section_suffix)
52538fd1498Szrj {
52638fd1498Szrj if (decl && DECL_SECTION_NAME (decl))
52738fd1498Szrj {
52838fd1498Szrj if (named_section_suffix)
52938fd1498Szrj {
53038fd1498Szrj const char *dsn = DECL_SECTION_NAME (decl);
53138fd1498Szrj const char *stripped_name;
53238fd1498Szrj char *name, *buffer;
53338fd1498Szrj
53438fd1498Szrj name = (char *) alloca (strlen (dsn) + 1);
53538fd1498Szrj memcpy (name, dsn,
53638fd1498Szrj strlen (dsn) + 1);
53738fd1498Szrj
53838fd1498Szrj stripped_name = targetm.strip_name_encoding (name);
53938fd1498Szrj
54038fd1498Szrj buffer = ACONCAT ((stripped_name, named_section_suffix, NULL));
54138fd1498Szrj return get_named_section (decl, buffer, 0);
54238fd1498Szrj }
54338fd1498Szrj else if (symtab_node::get (decl)->implicit_section)
54438fd1498Szrj {
54538fd1498Szrj const char *name;
54638fd1498Szrj
54738fd1498Szrj /* Do not try to split gnu_linkonce functions. This gets somewhat
54838fd1498Szrj slipperly. */
54938fd1498Szrj if (DECL_COMDAT_GROUP (decl) && !HAVE_COMDAT_GROUP)
55038fd1498Szrj return NULL;
55138fd1498Szrj name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
55238fd1498Szrj name = targetm.strip_name_encoding (name);
55338fd1498Szrj return get_named_section (decl, ACONCAT ((text_section_name, ".",
55438fd1498Szrj name, NULL)), 0);
55538fd1498Szrj }
55638fd1498Szrj else
55738fd1498Szrj return NULL;
55838fd1498Szrj }
55938fd1498Szrj return get_named_section (decl, text_section_name, 0);
56038fd1498Szrj }
56138fd1498Szrj
56238fd1498Szrj /* Choose named function section based on its frequency. */
56338fd1498Szrj
56438fd1498Szrj section *
default_function_section(tree decl,enum node_frequency freq,bool startup,bool exit)56538fd1498Szrj default_function_section (tree decl, enum node_frequency freq,
56638fd1498Szrj bool startup, bool exit)
56738fd1498Szrj {
56838fd1498Szrj #if defined HAVE_LD_EH_GC_SECTIONS && defined HAVE_LD_EH_GC_SECTIONS_BUG
56938fd1498Szrj /* Old GNU linkers have buggy --gc-section support, which sometimes
57038fd1498Szrj results in .gcc_except_table* sections being garbage collected. */
57138fd1498Szrj if (decl
57238fd1498Szrj && symtab_node::get (decl)->implicit_section)
57338fd1498Szrj return NULL;
57438fd1498Szrj #endif
57538fd1498Szrj
57638fd1498Szrj if (!flag_reorder_functions
57738fd1498Szrj || !targetm_common.have_named_sections)
57838fd1498Szrj return NULL;
57938fd1498Szrj /* Startup code should go to startup subsection unless it is
58038fd1498Szrj unlikely executed (this happens especially with function splitting
58138fd1498Szrj where we can split away unnecessary parts of static constructors. */
58238fd1498Szrj if (startup && freq != NODE_FREQUENCY_UNLIKELY_EXECUTED)
58338fd1498Szrj {
58438fd1498Szrj /* If we do have a profile or(and) LTO phase is executed, we do not need
58538fd1498Szrj these ELF section. */
58638fd1498Szrj if (!in_lto_p || !flag_profile_values)
58738fd1498Szrj return get_named_text_section (decl, ".text.startup", NULL);
58838fd1498Szrj else
58938fd1498Szrj return NULL;
59038fd1498Szrj }
59138fd1498Szrj
59238fd1498Szrj /* Similarly for exit. */
59338fd1498Szrj if (exit && freq != NODE_FREQUENCY_UNLIKELY_EXECUTED)
59438fd1498Szrj return get_named_text_section (decl, ".text.exit", NULL);
59538fd1498Szrj
59638fd1498Szrj /* Group cold functions together, similarly for hot code. */
59738fd1498Szrj switch (freq)
59838fd1498Szrj {
59938fd1498Szrj case NODE_FREQUENCY_UNLIKELY_EXECUTED:
60038fd1498Szrj return get_named_text_section (decl, ".text.unlikely", NULL);
60138fd1498Szrj case NODE_FREQUENCY_HOT:
60238fd1498Szrj /* If we do have a profile or(and) LTO phase is executed, we do not need
60338fd1498Szrj these ELF section. */
60438fd1498Szrj if (!in_lto_p || !flag_profile_values)
60538fd1498Szrj return get_named_text_section (decl, ".text.hot", NULL);
60638fd1498Szrj /* FALLTHRU */
60738fd1498Szrj default:
60838fd1498Szrj return NULL;
60938fd1498Szrj }
61038fd1498Szrj }
61138fd1498Szrj
61238fd1498Szrj /* Return the section for function DECL.
61338fd1498Szrj
61438fd1498Szrj If DECL is NULL_TREE, return the text section. We can be passed
61538fd1498Szrj NULL_TREE under some circumstances by dbxout.c at least.
61638fd1498Szrj
61738fd1498Szrj If FORCE_COLD is true, return cold function section ignoring
61838fd1498Szrj the frequency info of cgraph_node. */
61938fd1498Szrj
62038fd1498Szrj static section *
function_section_1(tree decl,bool force_cold)62138fd1498Szrj function_section_1 (tree decl, bool force_cold)
62238fd1498Szrj {
62338fd1498Szrj section *section = NULL;
62438fd1498Szrj enum node_frequency freq = NODE_FREQUENCY_NORMAL;
62538fd1498Szrj bool startup = false, exit = false;
62638fd1498Szrj
62738fd1498Szrj if (decl)
62838fd1498Szrj {
62938fd1498Szrj struct cgraph_node *node = cgraph_node::get (decl);
63038fd1498Szrj
63138fd1498Szrj if (node)
63238fd1498Szrj {
63338fd1498Szrj freq = node->frequency;
63438fd1498Szrj startup = node->only_called_at_startup;
63538fd1498Szrj exit = node->only_called_at_exit;
63638fd1498Szrj }
63738fd1498Szrj }
63838fd1498Szrj if (force_cold)
63938fd1498Szrj freq = NODE_FREQUENCY_UNLIKELY_EXECUTED;
64038fd1498Szrj
64138fd1498Szrj #ifdef USE_SELECT_SECTION_FOR_FUNCTIONS
64238fd1498Szrj if (decl != NULL_TREE
64338fd1498Szrj && DECL_SECTION_NAME (decl) != NULL)
64438fd1498Szrj {
64538fd1498Szrj if (targetm.asm_out.function_section)
64638fd1498Szrj section = targetm.asm_out.function_section (decl, freq,
64738fd1498Szrj startup, exit);
64838fd1498Szrj if (section)
64938fd1498Szrj return section;
65038fd1498Szrj return get_named_section (decl, NULL, 0);
65138fd1498Szrj }
65238fd1498Szrj else
65338fd1498Szrj return targetm.asm_out.select_section
65438fd1498Szrj (decl, freq == NODE_FREQUENCY_UNLIKELY_EXECUTED,
65538fd1498Szrj symtab_node::get (decl)->definition_alignment ());
65638fd1498Szrj #else
65738fd1498Szrj if (targetm.asm_out.function_section)
65838fd1498Szrj section = targetm.asm_out.function_section (decl, freq, startup, exit);
65938fd1498Szrj if (section)
66038fd1498Szrj return section;
66138fd1498Szrj return hot_function_section (decl);
66238fd1498Szrj #endif
66338fd1498Szrj }
66438fd1498Szrj
66538fd1498Szrj /* Return the section for function DECL.
66638fd1498Szrj
66738fd1498Szrj If DECL is NULL_TREE, return the text section. We can be passed
66838fd1498Szrj NULL_TREE under some circumstances by dbxout.c at least. */
66938fd1498Szrj
67038fd1498Szrj section *
function_section(tree decl)67138fd1498Szrj function_section (tree decl)
67238fd1498Szrj {
67338fd1498Szrj /* Handle cases where function splitting code decides
67438fd1498Szrj to put function entry point into unlikely executed section
67538fd1498Szrj despite the fact that the function itself is not cold
67638fd1498Szrj (i.e. it is called rarely but contains a hot loop that is
67738fd1498Szrj better to live in hot subsection for the code locality). */
67838fd1498Szrj return function_section_1 (decl,
67938fd1498Szrj first_function_block_is_cold);
68038fd1498Szrj }
68138fd1498Szrj
68238fd1498Szrj /* Return the section for the current function, take IN_COLD_SECTION_P
68338fd1498Szrj into account. */
68438fd1498Szrj
68538fd1498Szrj section *
current_function_section(void)68638fd1498Szrj current_function_section (void)
68738fd1498Szrj {
68838fd1498Szrj return function_section_1 (current_function_decl, in_cold_section_p);
68938fd1498Szrj }
69038fd1498Szrj
69138fd1498Szrj /* Tell assembler to switch to unlikely-to-be-executed text section. */
69238fd1498Szrj
69338fd1498Szrj section *
unlikely_text_section(void)69438fd1498Szrj unlikely_text_section (void)
69538fd1498Szrj {
69638fd1498Szrj return function_section_1 (current_function_decl, true);
69738fd1498Szrj }
69838fd1498Szrj
69938fd1498Szrj /* When called within a function context, return true if the function
70038fd1498Szrj has been assigned a cold text section and if SECT is that section.
70138fd1498Szrj When called outside a function context, return true if SECT is the
70238fd1498Szrj default cold section. */
70338fd1498Szrj
70438fd1498Szrj bool
unlikely_text_section_p(section * sect)70538fd1498Szrj unlikely_text_section_p (section *sect)
70638fd1498Szrj {
70738fd1498Szrj return sect == function_section_1 (current_function_decl, true);
70838fd1498Szrj }
70938fd1498Szrj
71038fd1498Szrj /* Switch to the other function partition (if inside of hot section
71138fd1498Szrj into cold section, otherwise into the hot section). */
71238fd1498Szrj
71338fd1498Szrj void
switch_to_other_text_partition(void)71438fd1498Szrj switch_to_other_text_partition (void)
71538fd1498Szrj {
71638fd1498Szrj in_cold_section_p = !in_cold_section_p;
71738fd1498Szrj switch_to_section (current_function_section ());
71838fd1498Szrj }
71938fd1498Szrj
72038fd1498Szrj /* Return the read-only data section associated with function DECL. */
72138fd1498Szrj
72238fd1498Szrj section *
default_function_rodata_section(tree decl)72338fd1498Szrj default_function_rodata_section (tree decl)
72438fd1498Szrj {
72538fd1498Szrj if (decl != NULL_TREE && DECL_SECTION_NAME (decl))
72638fd1498Szrj {
72738fd1498Szrj const char *name = DECL_SECTION_NAME (decl);
72838fd1498Szrj
72938fd1498Szrj if (DECL_COMDAT_GROUP (decl) && HAVE_COMDAT_GROUP)
73038fd1498Szrj {
73138fd1498Szrj const char *dot;
73238fd1498Szrj size_t len;
73338fd1498Szrj char* rname;
73438fd1498Szrj
73538fd1498Szrj dot = strchr (name + 1, '.');
73638fd1498Szrj if (!dot)
73738fd1498Szrj dot = name;
73838fd1498Szrj len = strlen (dot) + 8;
73938fd1498Szrj rname = (char *) alloca (len);
74038fd1498Szrj
74138fd1498Szrj strcpy (rname, ".rodata");
74238fd1498Szrj strcat (rname, dot);
74338fd1498Szrj return get_section (rname, SECTION_LINKONCE, decl);
74438fd1498Szrj }
74538fd1498Szrj /* For .gnu.linkonce.t.foo we want to use .gnu.linkonce.r.foo. */
74638fd1498Szrj else if (DECL_COMDAT_GROUP (decl)
74738fd1498Szrj && strncmp (name, ".gnu.linkonce.t.", 16) == 0)
74838fd1498Szrj {
74938fd1498Szrj size_t len = strlen (name) + 1;
75038fd1498Szrj char *rname = (char *) alloca (len);
75138fd1498Szrj
75238fd1498Szrj memcpy (rname, name, len);
75338fd1498Szrj rname[14] = 'r';
75438fd1498Szrj return get_section (rname, SECTION_LINKONCE, decl);
75538fd1498Szrj }
75638fd1498Szrj /* For .text.foo we want to use .rodata.foo. */
75738fd1498Szrj else if (flag_function_sections && flag_data_sections
75838fd1498Szrj && strncmp (name, ".text.", 6) == 0)
75938fd1498Szrj {
76038fd1498Szrj size_t len = strlen (name) + 1;
76138fd1498Szrj char *rname = (char *) alloca (len + 2);
76238fd1498Szrj
76338fd1498Szrj memcpy (rname, ".rodata", 7);
76438fd1498Szrj memcpy (rname + 7, name + 5, len - 5);
76538fd1498Szrj return get_section (rname, 0, decl);
76638fd1498Szrj }
76738fd1498Szrj }
76838fd1498Szrj
76938fd1498Szrj return readonly_data_section;
77038fd1498Szrj }
77138fd1498Szrj
77238fd1498Szrj /* Return the read-only data section associated with function DECL
77338fd1498Szrj for targets where that section should be always the single
77438fd1498Szrj readonly data section. */
77538fd1498Szrj
77638fd1498Szrj section *
default_no_function_rodata_section(tree decl ATTRIBUTE_UNUSED)77738fd1498Szrj default_no_function_rodata_section (tree decl ATTRIBUTE_UNUSED)
77838fd1498Szrj {
77938fd1498Szrj return readonly_data_section;
78038fd1498Szrj }
78138fd1498Szrj
78238fd1498Szrj /* A subroutine of mergeable_string_section and mergeable_constant_section. */
78338fd1498Szrj
78438fd1498Szrj static const char *
function_mergeable_rodata_prefix(void)78538fd1498Szrj function_mergeable_rodata_prefix (void)
78638fd1498Szrj {
78738fd1498Szrj section *s = targetm.asm_out.function_rodata_section (current_function_decl);
78838fd1498Szrj if (SECTION_STYLE (s) == SECTION_NAMED)
78938fd1498Szrj return s->named.name;
79038fd1498Szrj else
79138fd1498Szrj return targetm.asm_out.mergeable_rodata_prefix;
79238fd1498Szrj }
79338fd1498Szrj
79438fd1498Szrj /* Return the section to use for string merging. */
79538fd1498Szrj
79638fd1498Szrj static section *
mergeable_string_section(tree decl ATTRIBUTE_UNUSED,unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED,unsigned int flags ATTRIBUTE_UNUSED)79738fd1498Szrj mergeable_string_section (tree decl ATTRIBUTE_UNUSED,
79838fd1498Szrj unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED,
79938fd1498Szrj unsigned int flags ATTRIBUTE_UNUSED)
80038fd1498Szrj {
80138fd1498Szrj HOST_WIDE_INT len;
80238fd1498Szrj
80338fd1498Szrj if (HAVE_GAS_SHF_MERGE && flag_merge_constants
80438fd1498Szrj && TREE_CODE (decl) == STRING_CST
80538fd1498Szrj && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
80638fd1498Szrj && align <= 256
80738fd1498Szrj && (len = int_size_in_bytes (TREE_TYPE (decl))) > 0
80838fd1498Szrj && TREE_STRING_LENGTH (decl) >= len)
80938fd1498Szrj {
81038fd1498Szrj scalar_int_mode mode;
81138fd1498Szrj unsigned int modesize;
81238fd1498Szrj const char *str;
81338fd1498Szrj HOST_WIDE_INT i;
81438fd1498Szrj int j, unit;
81538fd1498Szrj const char *prefix = function_mergeable_rodata_prefix ();
81638fd1498Szrj char *name = (char *) alloca (strlen (prefix) + 30);
81738fd1498Szrj
81838fd1498Szrj mode = SCALAR_INT_TYPE_MODE (TREE_TYPE (TREE_TYPE (decl)));
81938fd1498Szrj modesize = GET_MODE_BITSIZE (mode);
82038fd1498Szrj if (modesize >= 8 && modesize <= 256
82138fd1498Szrj && (modesize & (modesize - 1)) == 0)
82238fd1498Szrj {
82338fd1498Szrj if (align < modesize)
82438fd1498Szrj align = modesize;
82538fd1498Szrj
82638fd1498Szrj str = TREE_STRING_POINTER (decl);
82738fd1498Szrj unit = GET_MODE_SIZE (mode);
82838fd1498Szrj
82938fd1498Szrj /* Check for embedded NUL characters. */
83038fd1498Szrj for (i = 0; i < len; i += unit)
83138fd1498Szrj {
83238fd1498Szrj for (j = 0; j < unit; j++)
83338fd1498Szrj if (str[i + j] != '\0')
83438fd1498Szrj break;
83538fd1498Szrj if (j == unit)
83638fd1498Szrj break;
83738fd1498Szrj }
83838fd1498Szrj if (i == len - unit)
83938fd1498Szrj {
84038fd1498Szrj sprintf (name, "%s.str%d.%d", prefix,
84138fd1498Szrj modesize / 8, (int) (align / 8));
84238fd1498Szrj flags |= (modesize / 8) | SECTION_MERGE | SECTION_STRINGS;
84338fd1498Szrj return get_section (name, flags, NULL);
84438fd1498Szrj }
84538fd1498Szrj }
84638fd1498Szrj }
84738fd1498Szrj
84838fd1498Szrj return readonly_data_section;
84938fd1498Szrj }
85038fd1498Szrj
85138fd1498Szrj /* Return the section to use for constant merging. */
85238fd1498Szrj
85338fd1498Szrj section *
mergeable_constant_section(machine_mode mode ATTRIBUTE_UNUSED,unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED,unsigned int flags ATTRIBUTE_UNUSED)85438fd1498Szrj mergeable_constant_section (machine_mode mode ATTRIBUTE_UNUSED,
85538fd1498Szrj unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED,
85638fd1498Szrj unsigned int flags ATTRIBUTE_UNUSED)
85738fd1498Szrj {
85838fd1498Szrj if (HAVE_GAS_SHF_MERGE && flag_merge_constants
85938fd1498Szrj && mode != VOIDmode
86038fd1498Szrj && mode != BLKmode
86138fd1498Szrj && known_le (GET_MODE_BITSIZE (mode), align)
86238fd1498Szrj && align >= 8
86338fd1498Szrj && align <= 256
86438fd1498Szrj && (align & (align - 1)) == 0)
86538fd1498Szrj {
86638fd1498Szrj const char *prefix = function_mergeable_rodata_prefix ();
86738fd1498Szrj char *name = (char *) alloca (strlen (prefix) + 30);
86838fd1498Szrj
86938fd1498Szrj sprintf (name, "%s.cst%d", prefix, (int) (align / 8));
87038fd1498Szrj flags |= (align / 8) | SECTION_MERGE;
87138fd1498Szrj return get_section (name, flags, NULL);
87238fd1498Szrj }
87338fd1498Szrj return readonly_data_section;
87438fd1498Szrj }
87538fd1498Szrj
87638fd1498Szrj /* Given NAME, a putative register name, discard any customary prefixes. */
87738fd1498Szrj
87838fd1498Szrj static const char *
strip_reg_name(const char * name)87938fd1498Szrj strip_reg_name (const char *name)
88038fd1498Szrj {
88138fd1498Szrj #ifdef REGISTER_PREFIX
88238fd1498Szrj if (!strncmp (name, REGISTER_PREFIX, strlen (REGISTER_PREFIX)))
88338fd1498Szrj name += strlen (REGISTER_PREFIX);
88438fd1498Szrj #endif
88538fd1498Szrj if (name[0] == '%' || name[0] == '#')
88638fd1498Szrj name++;
88738fd1498Szrj return name;
88838fd1498Szrj }
88938fd1498Szrj
89038fd1498Szrj /* The user has asked for a DECL to have a particular name. Set (or
89138fd1498Szrj change) it in such a way that we don't prefix an underscore to
89238fd1498Szrj it. */
89338fd1498Szrj void
set_user_assembler_name(tree decl,const char * name)89438fd1498Szrj set_user_assembler_name (tree decl, const char *name)
89538fd1498Szrj {
89638fd1498Szrj char *starred = (char *) alloca (strlen (name) + 2);
89738fd1498Szrj starred[0] = '*';
89838fd1498Szrj strcpy (starred + 1, name);
89938fd1498Szrj symtab->change_decl_assembler_name (decl, get_identifier (starred));
90038fd1498Szrj SET_DECL_RTL (decl, NULL_RTX);
90138fd1498Szrj }
90238fd1498Szrj
90338fd1498Szrj /* Decode an `asm' spec for a declaration as a register name.
90438fd1498Szrj Return the register number, or -1 if nothing specified,
90538fd1498Szrj or -2 if the ASMSPEC is not `cc' or `memory' and is not recognized,
90638fd1498Szrj or -3 if ASMSPEC is `cc' and is not recognized,
90738fd1498Szrj or -4 if ASMSPEC is `memory' and is not recognized.
90838fd1498Szrj Accept an exact spelling or a decimal number.
90938fd1498Szrj Prefixes such as % are optional. */
91038fd1498Szrj
91138fd1498Szrj int
decode_reg_name_and_count(const char * asmspec,int * pnregs)91238fd1498Szrj decode_reg_name_and_count (const char *asmspec, int *pnregs)
91338fd1498Szrj {
91438fd1498Szrj /* Presume just one register is clobbered. */
91538fd1498Szrj *pnregs = 1;
91638fd1498Szrj
91738fd1498Szrj if (asmspec != 0)
91838fd1498Szrj {
91938fd1498Szrj int i;
92038fd1498Szrj
92138fd1498Szrj /* Get rid of confusing prefixes. */
92238fd1498Szrj asmspec = strip_reg_name (asmspec);
92338fd1498Szrj
92438fd1498Szrj /* Allow a decimal number as a "register name". */
92538fd1498Szrj for (i = strlen (asmspec) - 1; i >= 0; i--)
92638fd1498Szrj if (! ISDIGIT (asmspec[i]))
92738fd1498Szrj break;
92838fd1498Szrj if (asmspec[0] != 0 && i < 0)
92938fd1498Szrj {
93038fd1498Szrj i = atoi (asmspec);
93138fd1498Szrj if (i < FIRST_PSEUDO_REGISTER && i >= 0 && reg_names[i][0])
93238fd1498Szrj return i;
93338fd1498Szrj else
93438fd1498Szrj return -2;
93538fd1498Szrj }
93638fd1498Szrj
93738fd1498Szrj for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
93838fd1498Szrj if (reg_names[i][0]
93938fd1498Szrj && ! strcmp (asmspec, strip_reg_name (reg_names[i])))
94038fd1498Szrj return i;
94138fd1498Szrj
94238fd1498Szrj #ifdef OVERLAPPING_REGISTER_NAMES
94338fd1498Szrj {
94438fd1498Szrj static const struct
94538fd1498Szrj {
94638fd1498Szrj const char *const name;
94738fd1498Szrj const int number;
94838fd1498Szrj const int nregs;
94938fd1498Szrj } table[] = OVERLAPPING_REGISTER_NAMES;
95038fd1498Szrj
95138fd1498Szrj for (i = 0; i < (int) ARRAY_SIZE (table); i++)
95238fd1498Szrj if (table[i].name[0]
95338fd1498Szrj && ! strcmp (asmspec, table[i].name))
95438fd1498Szrj {
95538fd1498Szrj *pnregs = table[i].nregs;
95638fd1498Szrj return table[i].number;
95738fd1498Szrj }
95838fd1498Szrj }
95938fd1498Szrj #endif /* OVERLAPPING_REGISTER_NAMES */
96038fd1498Szrj
96138fd1498Szrj #ifdef ADDITIONAL_REGISTER_NAMES
96238fd1498Szrj {
96338fd1498Szrj static const struct { const char *const name; const int number; } table[]
96438fd1498Szrj = ADDITIONAL_REGISTER_NAMES;
96538fd1498Szrj
96638fd1498Szrj for (i = 0; i < (int) ARRAY_SIZE (table); i++)
96738fd1498Szrj if (table[i].name[0]
96838fd1498Szrj && ! strcmp (asmspec, table[i].name)
96938fd1498Szrj && reg_names[table[i].number][0])
97038fd1498Szrj return table[i].number;
97138fd1498Szrj }
97238fd1498Szrj #endif /* ADDITIONAL_REGISTER_NAMES */
97338fd1498Szrj
97438fd1498Szrj if (!strcmp (asmspec, "memory"))
97538fd1498Szrj return -4;
97638fd1498Szrj
97738fd1498Szrj if (!strcmp (asmspec, "cc"))
97838fd1498Szrj return -3;
97938fd1498Szrj
98038fd1498Szrj return -2;
98138fd1498Szrj }
98238fd1498Szrj
98338fd1498Szrj return -1;
98438fd1498Szrj }
98538fd1498Szrj
98638fd1498Szrj int
decode_reg_name(const char * name)98738fd1498Szrj decode_reg_name (const char *name)
98838fd1498Szrj {
98938fd1498Szrj int count;
99038fd1498Szrj return decode_reg_name_and_count (name, &count);
99138fd1498Szrj }
99238fd1498Szrj
99338fd1498Szrj
99438fd1498Szrj /* Return true if DECL's initializer is suitable for a BSS section. */
99538fd1498Szrj
99638fd1498Szrj bool
bss_initializer_p(const_tree decl,bool named)99738fd1498Szrj bss_initializer_p (const_tree decl, bool named)
99838fd1498Szrj {
99938fd1498Szrj /* Do not put non-common constants into the .bss section, they belong in
100038fd1498Szrj a readonly section, except when NAMED is true. */
100138fd1498Szrj return ((!TREE_READONLY (decl) || DECL_COMMON (decl) || named)
100238fd1498Szrj && (DECL_INITIAL (decl) == NULL
100338fd1498Szrj /* In LTO we have no errors in program; error_mark_node is used
100438fd1498Szrj to mark offlined constructors. */
100538fd1498Szrj || (DECL_INITIAL (decl) == error_mark_node
100638fd1498Szrj && !in_lto_p)
100738fd1498Szrj || (flag_zero_initialized_in_bss
100838fd1498Szrj && initializer_zerop (DECL_INITIAL (decl)))));
100938fd1498Szrj }
101038fd1498Szrj
101138fd1498Szrj /* Compute the alignment of variable specified by DECL.
101238fd1498Szrj DONT_OUTPUT_DATA is from assemble_variable. */
101338fd1498Szrj
101438fd1498Szrj void
align_variable(tree decl,bool dont_output_data)101538fd1498Szrj align_variable (tree decl, bool dont_output_data)
101638fd1498Szrj {
101738fd1498Szrj unsigned int align = DECL_ALIGN (decl);
101838fd1498Szrj
101938fd1498Szrj /* In the case for initialing an array whose length isn't specified,
102038fd1498Szrj where we have not yet been able to do the layout,
102138fd1498Szrj figure out the proper alignment now. */
102238fd1498Szrj if (dont_output_data && DECL_SIZE (decl) == 0
102338fd1498Szrj && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
102438fd1498Szrj align = MAX (align, TYPE_ALIGN (TREE_TYPE (TREE_TYPE (decl))));
102538fd1498Szrj
102638fd1498Szrj /* Some object file formats have a maximum alignment which they support.
102738fd1498Szrj In particular, a.out format supports a maximum alignment of 4. */
102838fd1498Szrj if (align > MAX_OFILE_ALIGNMENT)
102938fd1498Szrj {
103038fd1498Szrj error ("alignment of %q+D is greater than maximum object "
103138fd1498Szrj "file alignment %d", decl,
103238fd1498Szrj MAX_OFILE_ALIGNMENT/BITS_PER_UNIT);
103338fd1498Szrj align = MAX_OFILE_ALIGNMENT;
103438fd1498Szrj }
103538fd1498Szrj
103638fd1498Szrj if (! DECL_USER_ALIGN (decl))
103738fd1498Szrj {
103838fd1498Szrj #ifdef DATA_ABI_ALIGNMENT
103938fd1498Szrj unsigned int data_abi_align
104038fd1498Szrj = DATA_ABI_ALIGNMENT (TREE_TYPE (decl), align);
104138fd1498Szrj /* For backwards compatibility, don't assume the ABI alignment for
104238fd1498Szrj TLS variables. */
104338fd1498Szrj if (! DECL_THREAD_LOCAL_P (decl) || data_abi_align <= BITS_PER_WORD)
104438fd1498Szrj align = data_abi_align;
104538fd1498Szrj #endif
104638fd1498Szrj
104738fd1498Szrj /* On some machines, it is good to increase alignment sometimes.
104838fd1498Szrj But as DECL_ALIGN is used both for actually emitting the variable
104938fd1498Szrj and for code accessing the variable as guaranteed alignment, we
105038fd1498Szrj can only increase the alignment if it is a performance optimization
105138fd1498Szrj if the references to it must bind to the current definition. */
105238fd1498Szrj if (decl_binds_to_current_def_p (decl)
105338fd1498Szrj && !DECL_VIRTUAL_P (decl))
105438fd1498Szrj {
105538fd1498Szrj #ifdef DATA_ALIGNMENT
105638fd1498Szrj unsigned int data_align = DATA_ALIGNMENT (TREE_TYPE (decl), align);
105738fd1498Szrj /* Don't increase alignment too much for TLS variables - TLS space
105838fd1498Szrj is too precious. */
105938fd1498Szrj if (! DECL_THREAD_LOCAL_P (decl) || data_align <= BITS_PER_WORD)
106038fd1498Szrj align = data_align;
106138fd1498Szrj #endif
106238fd1498Szrj if (DECL_INITIAL (decl) != 0
106338fd1498Szrj /* In LTO we have no errors in program; error_mark_node is used
106438fd1498Szrj to mark offlined constructors. */
106538fd1498Szrj && (in_lto_p || DECL_INITIAL (decl) != error_mark_node))
106638fd1498Szrj {
106738fd1498Szrj unsigned int const_align
106838fd1498Szrj = targetm.constant_alignment (DECL_INITIAL (decl), align);
106938fd1498Szrj /* Don't increase alignment too much for TLS variables - TLS
107038fd1498Szrj space is too precious. */
107138fd1498Szrj if (! DECL_THREAD_LOCAL_P (decl) || const_align <= BITS_PER_WORD)
107238fd1498Szrj align = const_align;
107338fd1498Szrj }
107438fd1498Szrj }
107538fd1498Szrj }
107638fd1498Szrj
107738fd1498Szrj /* Reset the alignment in case we have made it tighter, so we can benefit
107838fd1498Szrj from it in get_pointer_alignment. */
107938fd1498Szrj SET_DECL_ALIGN (decl, align);
108038fd1498Szrj }
108138fd1498Szrj
108238fd1498Szrj /* Return DECL_ALIGN (decl), possibly increased for optimization purposes
108338fd1498Szrj beyond what align_variable returned. */
108438fd1498Szrj
108538fd1498Szrj static unsigned int
get_variable_align(tree decl)108638fd1498Szrj get_variable_align (tree decl)
108738fd1498Szrj {
108838fd1498Szrj unsigned int align = DECL_ALIGN (decl);
108938fd1498Szrj
109038fd1498Szrj /* For user aligned vars or static vars align_variable already did
109138fd1498Szrj everything. */
109238fd1498Szrj if (DECL_USER_ALIGN (decl) || !TREE_PUBLIC (decl))
109338fd1498Szrj return align;
109438fd1498Szrj
109538fd1498Szrj #ifdef DATA_ABI_ALIGNMENT
109638fd1498Szrj if (DECL_THREAD_LOCAL_P (decl))
109738fd1498Szrj align = DATA_ABI_ALIGNMENT (TREE_TYPE (decl), align);
109838fd1498Szrj #endif
109938fd1498Szrj
110038fd1498Szrj /* For decls that bind to the current definition, align_variable
110138fd1498Szrj did also everything, except for not assuming ABI required alignment
110238fd1498Szrj of TLS variables. For other vars, increase the alignment here
110338fd1498Szrj as an optimization. */
110438fd1498Szrj if (!decl_binds_to_current_def_p (decl))
110538fd1498Szrj {
110638fd1498Szrj /* On some machines, it is good to increase alignment sometimes. */
110738fd1498Szrj #ifdef DATA_ALIGNMENT
110838fd1498Szrj unsigned int data_align = DATA_ALIGNMENT (TREE_TYPE (decl), align);
110938fd1498Szrj /* Don't increase alignment too much for TLS variables - TLS space
111038fd1498Szrj is too precious. */
111138fd1498Szrj if (! DECL_THREAD_LOCAL_P (decl) || data_align <= BITS_PER_WORD)
111238fd1498Szrj align = data_align;
111338fd1498Szrj #endif
111438fd1498Szrj if (DECL_INITIAL (decl) != 0
111538fd1498Szrj /* In LTO we have no errors in program; error_mark_node is used
111638fd1498Szrj to mark offlined constructors. */
111738fd1498Szrj && (in_lto_p || DECL_INITIAL (decl) != error_mark_node))
111838fd1498Szrj {
111938fd1498Szrj unsigned int const_align
112038fd1498Szrj = targetm.constant_alignment (DECL_INITIAL (decl), align);
112138fd1498Szrj /* Don't increase alignment too much for TLS variables - TLS space
112238fd1498Szrj is too precious. */
112338fd1498Szrj if (! DECL_THREAD_LOCAL_P (decl) || const_align <= BITS_PER_WORD)
112438fd1498Szrj align = const_align;
112538fd1498Szrj }
112638fd1498Szrj }
112738fd1498Szrj
112838fd1498Szrj return align;
112938fd1498Szrj }
113038fd1498Szrj
113138fd1498Szrj /* Return the section into which the given VAR_DECL or CONST_DECL
113238fd1498Szrj should be placed. PREFER_NOSWITCH_P is true if a noswitch
113338fd1498Szrj section should be used wherever possible. */
113438fd1498Szrj
113538fd1498Szrj section *
get_variable_section(tree decl,bool prefer_noswitch_p)113638fd1498Szrj get_variable_section (tree decl, bool prefer_noswitch_p)
113738fd1498Szrj {
113838fd1498Szrj addr_space_t as = ADDR_SPACE_GENERIC;
113938fd1498Szrj int reloc;
114038fd1498Szrj varpool_node *vnode = varpool_node::get (decl);
114138fd1498Szrj if (vnode)
114238fd1498Szrj {
114338fd1498Szrj vnode = vnode->ultimate_alias_target ();
114438fd1498Szrj decl = vnode->decl;
114538fd1498Szrj }
114638fd1498Szrj
114738fd1498Szrj if (TREE_TYPE (decl) != error_mark_node)
114838fd1498Szrj as = TYPE_ADDR_SPACE (TREE_TYPE (decl));
114938fd1498Szrj
115038fd1498Szrj /* We need the constructor to figure out reloc flag. */
115138fd1498Szrj if (vnode)
115238fd1498Szrj vnode->get_constructor ();
115338fd1498Szrj
115438fd1498Szrj if (DECL_COMMON (decl))
115538fd1498Szrj {
115638fd1498Szrj /* If the decl has been given an explicit section name, or it resides
115738fd1498Szrj in a non-generic address space, then it isn't common, and shouldn't
115838fd1498Szrj be handled as such. */
115938fd1498Szrj gcc_assert (DECL_SECTION_NAME (decl) == NULL
116038fd1498Szrj && ADDR_SPACE_GENERIC_P (as));
116138fd1498Szrj if (DECL_THREAD_LOCAL_P (decl))
116238fd1498Szrj return tls_comm_section;
116338fd1498Szrj else if (TREE_PUBLIC (decl) && bss_initializer_p (decl))
116438fd1498Szrj return comm_section;
116538fd1498Szrj }
116638fd1498Szrj
116738fd1498Szrj if (DECL_INITIAL (decl) == error_mark_node)
116838fd1498Szrj reloc = contains_pointers_p (TREE_TYPE (decl)) ? 3 : 0;
116938fd1498Szrj else if (DECL_INITIAL (decl))
117038fd1498Szrj reloc = compute_reloc_for_constant (DECL_INITIAL (decl));
117138fd1498Szrj else
117238fd1498Szrj reloc = 0;
117338fd1498Szrj
117438fd1498Szrj resolve_unique_section (decl, reloc, flag_data_sections);
117538fd1498Szrj if (IN_NAMED_SECTION (decl))
117638fd1498Szrj {
117738fd1498Szrj section *sect = get_named_section (decl, NULL, reloc);
117838fd1498Szrj
117938fd1498Szrj if ((sect->common.flags & SECTION_BSS)
118038fd1498Szrj && !bss_initializer_p (decl, true))
118138fd1498Szrj {
118238fd1498Szrj error_at (DECL_SOURCE_LOCATION (decl),
118338fd1498Szrj "only zero initializers are allowed in section %qs",
118438fd1498Szrj sect->named.name);
118538fd1498Szrj DECL_INITIAL (decl) = error_mark_node;
118638fd1498Szrj }
118738fd1498Szrj return sect;
118838fd1498Szrj }
118938fd1498Szrj
119038fd1498Szrj if (ADDR_SPACE_GENERIC_P (as)
119138fd1498Szrj && !DECL_THREAD_LOCAL_P (decl)
119238fd1498Szrj && !(prefer_noswitch_p && targetm.have_switchable_bss_sections)
119338fd1498Szrj && bss_initializer_p (decl))
119438fd1498Szrj {
119538fd1498Szrj if (!TREE_PUBLIC (decl)
119638fd1498Szrj && !((flag_sanitize & SANITIZE_ADDRESS)
119738fd1498Szrj && asan_protect_global (decl)))
119838fd1498Szrj return lcomm_section;
119938fd1498Szrj if (bss_noswitch_section)
120038fd1498Szrj return bss_noswitch_section;
120138fd1498Szrj }
120238fd1498Szrj
120338fd1498Szrj return targetm.asm_out.select_section (decl, reloc,
120438fd1498Szrj get_variable_align (decl));
120538fd1498Szrj }
120638fd1498Szrj
120738fd1498Szrj /* Return the block into which object_block DECL should be placed. */
120838fd1498Szrj
120938fd1498Szrj static struct object_block *
get_block_for_decl(tree decl)121038fd1498Szrj get_block_for_decl (tree decl)
121138fd1498Szrj {
121238fd1498Szrj section *sect;
121338fd1498Szrj
121438fd1498Szrj if (VAR_P (decl))
121538fd1498Szrj {
121638fd1498Szrj /* The object must be defined in this translation unit. */
121738fd1498Szrj if (DECL_EXTERNAL (decl))
121838fd1498Szrj return NULL;
121938fd1498Szrj
122038fd1498Szrj /* There's no point using object blocks for something that is
122138fd1498Szrj isolated by definition. */
122238fd1498Szrj if (DECL_COMDAT_GROUP (decl))
122338fd1498Szrj return NULL;
122438fd1498Szrj }
122538fd1498Szrj
122638fd1498Szrj /* We can only calculate block offsets if the decl has a known
122738fd1498Szrj constant size. */
122838fd1498Szrj if (DECL_SIZE_UNIT (decl) == NULL)
122938fd1498Szrj return NULL;
123038fd1498Szrj if (!tree_fits_uhwi_p (DECL_SIZE_UNIT (decl)))
123138fd1498Szrj return NULL;
123238fd1498Szrj
123338fd1498Szrj /* Find out which section should contain DECL. We cannot put it into
123438fd1498Szrj an object block if it requires a standalone definition. */
123538fd1498Szrj if (VAR_P (decl))
123638fd1498Szrj align_variable (decl, 0);
123738fd1498Szrj sect = get_variable_section (decl, true);
123838fd1498Szrj if (SECTION_STYLE (sect) == SECTION_NOSWITCH)
123938fd1498Szrj return NULL;
124038fd1498Szrj
124138fd1498Szrj return get_block_for_section (sect);
124238fd1498Szrj }
124338fd1498Szrj
124438fd1498Szrj /* Make sure block symbol SYMBOL is in block BLOCK. */
124538fd1498Szrj
124638fd1498Szrj static void
change_symbol_block(rtx symbol,struct object_block * block)124738fd1498Szrj change_symbol_block (rtx symbol, struct object_block *block)
124838fd1498Szrj {
124938fd1498Szrj if (block != SYMBOL_REF_BLOCK (symbol))
125038fd1498Szrj {
125138fd1498Szrj gcc_assert (SYMBOL_REF_BLOCK_OFFSET (symbol) < 0);
125238fd1498Szrj SYMBOL_REF_BLOCK (symbol) = block;
125338fd1498Szrj }
125438fd1498Szrj }
125538fd1498Szrj
125638fd1498Szrj /* Return true if it is possible to put DECL in an object_block. */
125738fd1498Szrj
125838fd1498Szrj static bool
use_blocks_for_decl_p(tree decl)125938fd1498Szrj use_blocks_for_decl_p (tree decl)
126038fd1498Szrj {
126138fd1498Szrj struct symtab_node *snode;
126238fd1498Szrj
126338fd1498Szrj /* Only data DECLs can be placed into object blocks. */
126438fd1498Szrj if (!VAR_P (decl) && TREE_CODE (decl) != CONST_DECL)
126538fd1498Szrj return false;
126638fd1498Szrj
126738fd1498Szrj /* DECL_INITIAL (decl) set to decl is a hack used for some decls that
126838fd1498Szrj are never used from code directly and we never want object block handling
126938fd1498Szrj for those. */
127038fd1498Szrj if (DECL_INITIAL (decl) == decl)
127138fd1498Szrj return false;
127238fd1498Szrj
127338fd1498Szrj /* If this decl is an alias, then we don't want to emit a
127438fd1498Szrj definition. */
127538fd1498Szrj if (VAR_P (decl)
127638fd1498Szrj && (snode = symtab_node::get (decl)) != NULL
127738fd1498Szrj && snode->alias)
127838fd1498Szrj return false;
127938fd1498Szrj
128038fd1498Szrj return targetm.use_blocks_for_decl_p (decl);
128138fd1498Szrj }
128238fd1498Szrj
128338fd1498Szrj /* Follow the IDENTIFIER_TRANSPARENT_ALIAS chain starting at *ALIAS
128438fd1498Szrj until we find an identifier that is not itself a transparent alias.
128538fd1498Szrj Modify the alias passed to it by reference (and all aliases on the
128638fd1498Szrj way to the ultimate target), such that they do not have to be
128738fd1498Szrj followed again, and return the ultimate target of the alias
128838fd1498Szrj chain. */
128938fd1498Szrj
129038fd1498Szrj static inline tree
ultimate_transparent_alias_target(tree * alias)129138fd1498Szrj ultimate_transparent_alias_target (tree *alias)
129238fd1498Szrj {
129338fd1498Szrj tree target = *alias;
129438fd1498Szrj
129538fd1498Szrj if (IDENTIFIER_TRANSPARENT_ALIAS (target))
129638fd1498Szrj {
129738fd1498Szrj gcc_assert (TREE_CHAIN (target));
129838fd1498Szrj target = ultimate_transparent_alias_target (&TREE_CHAIN (target));
129938fd1498Szrj gcc_assert (! IDENTIFIER_TRANSPARENT_ALIAS (target)
130038fd1498Szrj && ! TREE_CHAIN (target));
130138fd1498Szrj *alias = target;
130238fd1498Szrj }
130338fd1498Szrj
130438fd1498Szrj return target;
130538fd1498Szrj }
130638fd1498Szrj
130738fd1498Szrj /* Create the DECL_RTL for a VAR_DECL or FUNCTION_DECL. DECL should
130838fd1498Szrj have static storage duration. In other words, it should not be an
130938fd1498Szrj automatic variable, including PARM_DECLs.
131038fd1498Szrj
131138fd1498Szrj There is, however, one exception: this function handles variables
131238fd1498Szrj explicitly placed in a particular register by the user.
131338fd1498Szrj
131438fd1498Szrj This is never called for PARM_DECL nodes. */
131538fd1498Szrj
131638fd1498Szrj void
make_decl_rtl(tree decl)131738fd1498Szrj make_decl_rtl (tree decl)
131838fd1498Szrj {
131938fd1498Szrj const char *name = 0;
132038fd1498Szrj int reg_number;
132138fd1498Szrj tree id;
132238fd1498Szrj rtx x;
132338fd1498Szrj
132438fd1498Szrj /* Check that we are not being given an automatic variable. */
132538fd1498Szrj gcc_assert (TREE_CODE (decl) != PARM_DECL
132638fd1498Szrj && TREE_CODE (decl) != RESULT_DECL);
132738fd1498Szrj
132838fd1498Szrj /* A weak alias has TREE_PUBLIC set but not the other bits. */
132938fd1498Szrj gcc_assert (!VAR_P (decl)
133038fd1498Szrj || TREE_STATIC (decl)
133138fd1498Szrj || TREE_PUBLIC (decl)
133238fd1498Szrj || DECL_EXTERNAL (decl)
133338fd1498Szrj || DECL_REGISTER (decl));
133438fd1498Szrj
133538fd1498Szrj /* And that we were not given a type or a label. */
133638fd1498Szrj gcc_assert (TREE_CODE (decl) != TYPE_DECL
133738fd1498Szrj && TREE_CODE (decl) != LABEL_DECL);
133838fd1498Szrj
133938fd1498Szrj /* For a duplicate declaration, we can be called twice on the
134038fd1498Szrj same DECL node. Don't discard the RTL already made. */
134138fd1498Szrj if (DECL_RTL_SET_P (decl))
134238fd1498Szrj {
134338fd1498Szrj /* If the old RTL had the wrong mode, fix the mode. */
134438fd1498Szrj x = DECL_RTL (decl);
134538fd1498Szrj if (GET_MODE (x) != DECL_MODE (decl))
134638fd1498Szrj SET_DECL_RTL (decl, adjust_address_nv (x, DECL_MODE (decl), 0));
134738fd1498Szrj
134838fd1498Szrj if (TREE_CODE (decl) != FUNCTION_DECL && DECL_REGISTER (decl))
134938fd1498Szrj return;
135038fd1498Szrj
135138fd1498Szrj /* ??? Another way to do this would be to maintain a hashed
135238fd1498Szrj table of such critters. Instead of adding stuff to a DECL
135338fd1498Szrj to give certain attributes to it, we could use an external
135438fd1498Szrj hash map from DECL to set of attributes. */
135538fd1498Szrj
135638fd1498Szrj /* Let the target reassign the RTL if it wants.
135738fd1498Szrj This is necessary, for example, when one machine specific
135838fd1498Szrj decl attribute overrides another. */
135938fd1498Szrj targetm.encode_section_info (decl, DECL_RTL (decl), false);
136038fd1498Szrj
136138fd1498Szrj /* If the symbol has a SYMBOL_REF_BLOCK field, update it based
136238fd1498Szrj on the new decl information. */
136338fd1498Szrj if (MEM_P (x)
136438fd1498Szrj && GET_CODE (XEXP (x, 0)) == SYMBOL_REF
136538fd1498Szrj && SYMBOL_REF_HAS_BLOCK_INFO_P (XEXP (x, 0)))
136638fd1498Szrj change_symbol_block (XEXP (x, 0), get_block_for_decl (decl));
136738fd1498Szrj
136838fd1498Szrj return;
136938fd1498Szrj }
137038fd1498Szrj
137138fd1498Szrj /* If this variable belongs to the global constant pool, retrieve the
137238fd1498Szrj pre-computed RTL or recompute it in LTO mode. */
137338fd1498Szrj if (VAR_P (decl) && DECL_IN_CONSTANT_POOL (decl))
137438fd1498Szrj {
137538fd1498Szrj SET_DECL_RTL (decl, output_constant_def (DECL_INITIAL (decl), 1));
137638fd1498Szrj return;
137738fd1498Szrj }
137838fd1498Szrj
137938fd1498Szrj id = DECL_ASSEMBLER_NAME (decl);
138038fd1498Szrj if (TREE_CODE (decl) == FUNCTION_DECL
138138fd1498Szrj && cgraph_node::get (decl)
138238fd1498Szrj && cgraph_node::get (decl)->instrumentation_clone)
138338fd1498Szrj ultimate_transparent_alias_target (&id);
138438fd1498Szrj name = IDENTIFIER_POINTER (id);
138538fd1498Szrj
138638fd1498Szrj if (name[0] != '*' && TREE_CODE (decl) != FUNCTION_DECL
138738fd1498Szrj && DECL_REGISTER (decl))
138838fd1498Szrj {
138938fd1498Szrj error ("register name not specified for %q+D", decl);
139038fd1498Szrj }
139138fd1498Szrj else if (TREE_CODE (decl) != FUNCTION_DECL && DECL_REGISTER (decl))
139238fd1498Szrj {
139338fd1498Szrj const char *asmspec = name+1;
139438fd1498Szrj machine_mode mode = DECL_MODE (decl);
139538fd1498Szrj reg_number = decode_reg_name (asmspec);
139638fd1498Szrj /* First detect errors in declaring global registers. */
139738fd1498Szrj if (reg_number == -1)
139838fd1498Szrj error ("register name not specified for %q+D", decl);
139938fd1498Szrj else if (reg_number < 0)
140038fd1498Szrj error ("invalid register name for %q+D", decl);
140138fd1498Szrj else if (mode == BLKmode)
140238fd1498Szrj error ("data type of %q+D isn%'t suitable for a register",
140338fd1498Szrj decl);
140438fd1498Szrj else if (!in_hard_reg_set_p (accessible_reg_set, mode, reg_number))
140538fd1498Szrj error ("the register specified for %q+D cannot be accessed"
140638fd1498Szrj " by the current target", decl);
140738fd1498Szrj else if (!in_hard_reg_set_p (operand_reg_set, mode, reg_number))
140838fd1498Szrj error ("the register specified for %q+D is not general enough"
140938fd1498Szrj " to be used as a register variable", decl);
141038fd1498Szrj else if (!targetm.hard_regno_mode_ok (reg_number, mode))
141138fd1498Szrj error ("register specified for %q+D isn%'t suitable for data type",
141238fd1498Szrj decl);
141338fd1498Szrj /* Now handle properly declared static register variables. */
141438fd1498Szrj else
141538fd1498Szrj {
141638fd1498Szrj int nregs;
141738fd1498Szrj
141838fd1498Szrj if (DECL_INITIAL (decl) != 0 && TREE_STATIC (decl))
141938fd1498Szrj {
142038fd1498Szrj DECL_INITIAL (decl) = 0;
142138fd1498Szrj error ("global register variable has initial value");
142238fd1498Szrj }
142338fd1498Szrj if (TREE_THIS_VOLATILE (decl))
142438fd1498Szrj warning (OPT_Wvolatile_register_var,
142538fd1498Szrj "optimization may eliminate reads and/or "
142638fd1498Szrj "writes to register variables");
142738fd1498Szrj
142838fd1498Szrj /* If the user specified one of the eliminables registers here,
142938fd1498Szrj e.g., FRAME_POINTER_REGNUM, we don't want to get this variable
143038fd1498Szrj confused with that register and be eliminated. This usage is
143138fd1498Szrj somewhat suspect... */
143238fd1498Szrj
143338fd1498Szrj SET_DECL_RTL (decl, gen_raw_REG (mode, reg_number));
143438fd1498Szrj ORIGINAL_REGNO (DECL_RTL (decl)) = reg_number;
143538fd1498Szrj REG_USERVAR_P (DECL_RTL (decl)) = 1;
143638fd1498Szrj
143738fd1498Szrj if (TREE_STATIC (decl))
143838fd1498Szrj {
143938fd1498Szrj /* Make this register global, so not usable for anything
144038fd1498Szrj else. */
144138fd1498Szrj #ifdef ASM_DECLARE_REGISTER_GLOBAL
144238fd1498Szrj name = IDENTIFIER_POINTER (DECL_NAME (decl));
144338fd1498Szrj ASM_DECLARE_REGISTER_GLOBAL (asm_out_file, decl, reg_number, name);
144438fd1498Szrj #endif
144538fd1498Szrj nregs = hard_regno_nregs (reg_number, mode);
144638fd1498Szrj while (nregs > 0)
144738fd1498Szrj globalize_reg (decl, reg_number + --nregs);
144838fd1498Szrj }
144938fd1498Szrj
145038fd1498Szrj /* As a register variable, it has no section. */
145138fd1498Szrj return;
145238fd1498Szrj }
145338fd1498Szrj /* Avoid internal errors from invalid register
145438fd1498Szrj specifications. */
145538fd1498Szrj SET_DECL_ASSEMBLER_NAME (decl, NULL_TREE);
145638fd1498Szrj DECL_HARD_REGISTER (decl) = 0;
145738fd1498Szrj /* Also avoid SSA inconsistencies by pretending this is an external
145838fd1498Szrj decl now. */
145938fd1498Szrj DECL_EXTERNAL (decl) = 1;
146038fd1498Szrj return;
146138fd1498Szrj }
146238fd1498Szrj /* Now handle ordinary static variables and functions (in memory).
146338fd1498Szrj Also handle vars declared register invalidly. */
146438fd1498Szrj else if (name[0] == '*')
146538fd1498Szrj {
146638fd1498Szrj #ifdef REGISTER_PREFIX
146738fd1498Szrj if (strlen (REGISTER_PREFIX) != 0)
146838fd1498Szrj {
146938fd1498Szrj reg_number = decode_reg_name (name);
147038fd1498Szrj if (reg_number >= 0 || reg_number == -3)
147138fd1498Szrj error ("register name given for non-register variable %q+D", decl);
147238fd1498Szrj }
147338fd1498Szrj #endif
147438fd1498Szrj }
147538fd1498Szrj
147638fd1498Szrj /* Specifying a section attribute on a variable forces it into a
147738fd1498Szrj non-.bss section, and thus it cannot be common. */
147838fd1498Szrj /* FIXME: In general this code should not be necessary because
147938fd1498Szrj visibility pass is doing the same work. But notice_global_symbol
148038fd1498Szrj is called early and it needs to make DECL_RTL to get the name.
148138fd1498Szrj we take care of recomputing the DECL_RTL after visibility is changed. */
148238fd1498Szrj if (VAR_P (decl)
148338fd1498Szrj && (TREE_STATIC (decl) || DECL_EXTERNAL (decl))
148438fd1498Szrj && DECL_SECTION_NAME (decl) != NULL
148538fd1498Szrj && DECL_INITIAL (decl) == NULL_TREE
148638fd1498Szrj && DECL_COMMON (decl))
148738fd1498Szrj DECL_COMMON (decl) = 0;
148838fd1498Szrj
148938fd1498Szrj /* Variables can't be both common and weak. */
149038fd1498Szrj if (VAR_P (decl) && DECL_WEAK (decl))
149138fd1498Szrj DECL_COMMON (decl) = 0;
149238fd1498Szrj
149338fd1498Szrj if (use_object_blocks_p () && use_blocks_for_decl_p (decl))
149438fd1498Szrj x = create_block_symbol (name, get_block_for_decl (decl), -1);
149538fd1498Szrj else
149638fd1498Szrj {
149738fd1498Szrj machine_mode address_mode = Pmode;
149838fd1498Szrj if (TREE_TYPE (decl) != error_mark_node)
149938fd1498Szrj {
150038fd1498Szrj addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (decl));
150138fd1498Szrj address_mode = targetm.addr_space.address_mode (as);
150238fd1498Szrj }
150338fd1498Szrj x = gen_rtx_SYMBOL_REF (address_mode, name);
150438fd1498Szrj }
150538fd1498Szrj SYMBOL_REF_WEAK (x) = DECL_WEAK (decl);
150638fd1498Szrj SET_SYMBOL_REF_DECL (x, decl);
150738fd1498Szrj
150838fd1498Szrj x = gen_rtx_MEM (DECL_MODE (decl), x);
150938fd1498Szrj if (TREE_CODE (decl) != FUNCTION_DECL)
151038fd1498Szrj set_mem_attributes (x, decl, 1);
151138fd1498Szrj SET_DECL_RTL (decl, x);
151238fd1498Szrj
151338fd1498Szrj /* Optionally set flags or add text to the name to record information
151438fd1498Szrj such as that it is a function name.
151538fd1498Szrj If the name is changed, the macro ASM_OUTPUT_LABELREF
151638fd1498Szrj will have to know how to strip this information. */
151738fd1498Szrj targetm.encode_section_info (decl, DECL_RTL (decl), true);
151838fd1498Szrj }
151938fd1498Szrj
152038fd1498Szrj /* Like make_decl_rtl, but inhibit creation of new alias sets when
152138fd1498Szrj calling make_decl_rtl. Also, reset DECL_RTL before returning the
152238fd1498Szrj rtl. */
152338fd1498Szrj
152438fd1498Szrj rtx
make_decl_rtl_for_debug(tree decl)152538fd1498Szrj make_decl_rtl_for_debug (tree decl)
152638fd1498Szrj {
152738fd1498Szrj unsigned int save_aliasing_flag;
152838fd1498Szrj rtx rtl;
152938fd1498Szrj
153038fd1498Szrj if (DECL_RTL_SET_P (decl))
153138fd1498Szrj return DECL_RTL (decl);
153238fd1498Szrj
153338fd1498Szrj /* Kludge alert! Somewhere down the call chain, make_decl_rtl will
153438fd1498Szrj call new_alias_set. If running with -fcompare-debug, sometimes
153538fd1498Szrj we do not want to create alias sets that will throw the alias
153638fd1498Szrj numbers off in the comparison dumps. So... clearing
153738fd1498Szrj flag_strict_aliasing will keep new_alias_set() from creating a
153838fd1498Szrj new set. */
153938fd1498Szrj save_aliasing_flag = flag_strict_aliasing;
154038fd1498Szrj flag_strict_aliasing = 0;
154138fd1498Szrj
154238fd1498Szrj rtl = DECL_RTL (decl);
154338fd1498Szrj /* Reset DECL_RTL back, as various parts of the compiler expects
154438fd1498Szrj DECL_RTL set meaning it is actually going to be output. */
154538fd1498Szrj SET_DECL_RTL (decl, NULL);
154638fd1498Szrj
154738fd1498Szrj flag_strict_aliasing = save_aliasing_flag;
154838fd1498Szrj return rtl;
154938fd1498Szrj }
155038fd1498Szrj
155138fd1498Szrj /* Output a string of literal assembler code
155238fd1498Szrj for an `asm' keyword used between functions. */
155338fd1498Szrj
155438fd1498Szrj void
assemble_asm(tree string)155538fd1498Szrj assemble_asm (tree string)
155638fd1498Szrj {
155738fd1498Szrj const char *p;
155838fd1498Szrj app_enable ();
155938fd1498Szrj
156038fd1498Szrj if (TREE_CODE (string) == ADDR_EXPR)
156138fd1498Szrj string = TREE_OPERAND (string, 0);
156238fd1498Szrj
156338fd1498Szrj p = TREE_STRING_POINTER (string);
156438fd1498Szrj fprintf (asm_out_file, "%s%s\n", p[0] == '\t' ? "" : "\t", p);
156538fd1498Szrj }
156638fd1498Szrj
156738fd1498Szrj /* Write the address of the entity given by SYMBOL to SEC. */
156838fd1498Szrj void
assemble_addr_to_section(rtx symbol,section * sec)156938fd1498Szrj assemble_addr_to_section (rtx symbol, section *sec)
157038fd1498Szrj {
157138fd1498Szrj switch_to_section (sec);
157238fd1498Szrj assemble_align (POINTER_SIZE);
157338fd1498Szrj assemble_integer (symbol, POINTER_SIZE_UNITS, POINTER_SIZE, 1);
157438fd1498Szrj }
157538fd1498Szrj
157638fd1498Szrj /* Return the numbered .ctors.N (if CONSTRUCTOR_P) or .dtors.N (if
157738fd1498Szrj not) section for PRIORITY. */
157838fd1498Szrj section *
get_cdtor_priority_section(int priority,bool constructor_p)157938fd1498Szrj get_cdtor_priority_section (int priority, bool constructor_p)
158038fd1498Szrj {
158138fd1498Szrj /* Buffer conservatively large enough for the full range of a 32-bit
158238fd1498Szrj int plus the text below. */
158338fd1498Szrj char buf[18];
158438fd1498Szrj
158538fd1498Szrj /* ??? This only works reliably with the GNU linker. */
158638fd1498Szrj sprintf (buf, "%s.%.5u",
158738fd1498Szrj constructor_p ? ".ctors" : ".dtors",
158838fd1498Szrj /* Invert the numbering so the linker puts us in the proper
158938fd1498Szrj order; constructors are run from right to left, and the
159038fd1498Szrj linker sorts in increasing order. */
159138fd1498Szrj MAX_INIT_PRIORITY - priority);
159238fd1498Szrj return get_section (buf, SECTION_WRITE, NULL);
159338fd1498Szrj }
159438fd1498Szrj
159538fd1498Szrj void
default_named_section_asm_out_destructor(rtx symbol,int priority)159638fd1498Szrj default_named_section_asm_out_destructor (rtx symbol, int priority)
159738fd1498Szrj {
159838fd1498Szrj section *sec;
159938fd1498Szrj
160038fd1498Szrj if (priority != DEFAULT_INIT_PRIORITY)
160138fd1498Szrj sec = get_cdtor_priority_section (priority,
160238fd1498Szrj /*constructor_p=*/false);
160338fd1498Szrj else
160438fd1498Szrj sec = get_section (".dtors", SECTION_WRITE, NULL);
160538fd1498Szrj
160638fd1498Szrj assemble_addr_to_section (symbol, sec);
160738fd1498Szrj }
160838fd1498Szrj
160938fd1498Szrj #ifdef DTORS_SECTION_ASM_OP
161038fd1498Szrj void
default_dtor_section_asm_out_destructor(rtx symbol,int priority ATTRIBUTE_UNUSED)161138fd1498Szrj default_dtor_section_asm_out_destructor (rtx symbol,
161238fd1498Szrj int priority ATTRIBUTE_UNUSED)
161338fd1498Szrj {
161438fd1498Szrj assemble_addr_to_section (symbol, dtors_section);
161538fd1498Szrj }
161638fd1498Szrj #endif
161738fd1498Szrj
161838fd1498Szrj void
default_named_section_asm_out_constructor(rtx symbol,int priority)161938fd1498Szrj default_named_section_asm_out_constructor (rtx symbol, int priority)
162038fd1498Szrj {
162138fd1498Szrj section *sec;
162238fd1498Szrj
162338fd1498Szrj if (priority != DEFAULT_INIT_PRIORITY)
162438fd1498Szrj sec = get_cdtor_priority_section (priority,
162538fd1498Szrj /*constructor_p=*/true);
162638fd1498Szrj else
162738fd1498Szrj sec = get_section (".ctors", SECTION_WRITE, NULL);
162838fd1498Szrj
162938fd1498Szrj assemble_addr_to_section (symbol, sec);
163038fd1498Szrj }
163138fd1498Szrj
163238fd1498Szrj #ifdef CTORS_SECTION_ASM_OP
163338fd1498Szrj void
default_ctor_section_asm_out_constructor(rtx symbol,int priority ATTRIBUTE_UNUSED)163438fd1498Szrj default_ctor_section_asm_out_constructor (rtx symbol,
163538fd1498Szrj int priority ATTRIBUTE_UNUSED)
163638fd1498Szrj {
163738fd1498Szrj assemble_addr_to_section (symbol, ctors_section);
163838fd1498Szrj }
163938fd1498Szrj #endif
164038fd1498Szrj
164138fd1498Szrj /* CONSTANT_POOL_BEFORE_FUNCTION may be defined as an expression with
164238fd1498Szrj a nonzero value if the constant pool should be output before the
164338fd1498Szrj start of the function, or a zero value if the pool should output
164438fd1498Szrj after the end of the function. The default is to put it before the
164538fd1498Szrj start. */
164638fd1498Szrj
164738fd1498Szrj #ifndef CONSTANT_POOL_BEFORE_FUNCTION
164838fd1498Szrj #define CONSTANT_POOL_BEFORE_FUNCTION 1
164938fd1498Szrj #endif
165038fd1498Szrj
165138fd1498Szrj /* DECL is an object (either VAR_DECL or FUNCTION_DECL) which is going
165238fd1498Szrj to be output to assembler.
165338fd1498Szrj Set first_global_object_name and weak_global_object_name as appropriate. */
165438fd1498Szrj
165538fd1498Szrj void
notice_global_symbol(tree decl)165638fd1498Szrj notice_global_symbol (tree decl)
165738fd1498Szrj {
165838fd1498Szrj const char **t = &first_global_object_name;
165938fd1498Szrj
166038fd1498Szrj if (first_global_object_name
166138fd1498Szrj || !TREE_PUBLIC (decl)
166238fd1498Szrj || DECL_EXTERNAL (decl)
166338fd1498Szrj || !DECL_NAME (decl)
166438fd1498Szrj || (VAR_P (decl) && DECL_HARD_REGISTER (decl))
166538fd1498Szrj || (TREE_CODE (decl) != FUNCTION_DECL
166638fd1498Szrj && (!VAR_P (decl)
166738fd1498Szrj || (DECL_COMMON (decl)
166838fd1498Szrj && (DECL_INITIAL (decl) == 0
166938fd1498Szrj || DECL_INITIAL (decl) == error_mark_node)))))
167038fd1498Szrj return;
167138fd1498Szrj
167238fd1498Szrj /* We win when global object is found, but it is useful to know about weak
167338fd1498Szrj symbol as well so we can produce nicer unique names. */
167438fd1498Szrj if (DECL_WEAK (decl) || DECL_ONE_ONLY (decl) || flag_shlib)
167538fd1498Szrj t = &weak_global_object_name;
167638fd1498Szrj
167738fd1498Szrj if (!*t)
167838fd1498Szrj {
167938fd1498Szrj tree id = DECL_ASSEMBLER_NAME (decl);
168038fd1498Szrj ultimate_transparent_alias_target (&id);
168138fd1498Szrj *t = ggc_strdup (targetm.strip_name_encoding (IDENTIFIER_POINTER (id)));
168238fd1498Szrj }
168338fd1498Szrj }
168438fd1498Szrj
168538fd1498Szrj /* If not using flag_reorder_blocks_and_partition, decide early whether the
168638fd1498Szrj current function goes into the cold section, so that targets can use
168738fd1498Szrj current_function_section during RTL expansion. DECL describes the
168838fd1498Szrj function. */
168938fd1498Szrj
169038fd1498Szrj void
decide_function_section(tree decl)169138fd1498Szrj decide_function_section (tree decl)
169238fd1498Szrj {
169338fd1498Szrj first_function_block_is_cold = false;
169438fd1498Szrj
169538fd1498Szrj if (DECL_SECTION_NAME (decl))
169638fd1498Szrj {
169738fd1498Szrj struct cgraph_node *node = cgraph_node::get (current_function_decl);
169838fd1498Szrj /* Calls to function_section rely on first_function_block_is_cold
169938fd1498Szrj being accurate. */
170038fd1498Szrj first_function_block_is_cold = (node
170138fd1498Szrj && node->frequency
170238fd1498Szrj == NODE_FREQUENCY_UNLIKELY_EXECUTED);
170338fd1498Szrj }
170438fd1498Szrj
170538fd1498Szrj in_cold_section_p = first_function_block_is_cold;
170638fd1498Szrj }
170738fd1498Szrj
170838fd1498Szrj /* Get the function's name, as described by its RTL. This may be
170938fd1498Szrj different from the DECL_NAME name used in the source file. */
171038fd1498Szrj const char *
get_fnname_from_decl(tree decl)171138fd1498Szrj get_fnname_from_decl (tree decl)
171238fd1498Szrj {
171338fd1498Szrj rtx x = DECL_RTL (decl);
171438fd1498Szrj gcc_assert (MEM_P (x));
171538fd1498Szrj x = XEXP (x, 0);
171638fd1498Szrj gcc_assert (GET_CODE (x) == SYMBOL_REF);
171738fd1498Szrj return XSTR (x, 0);
171838fd1498Szrj }
171938fd1498Szrj
172038fd1498Szrj /* Output assembler code for the constant pool of a function and associated
172138fd1498Szrj with defining the name of the function. DECL describes the function.
172238fd1498Szrj NAME is the function's name. For the constant pool, we use the current
172338fd1498Szrj constant pool data. */
172438fd1498Szrj
172538fd1498Szrj void
assemble_start_function(tree decl,const char * fnname)172638fd1498Szrj assemble_start_function (tree decl, const char *fnname)
172738fd1498Szrj {
172838fd1498Szrj int align;
172938fd1498Szrj char tmp_label[100];
173038fd1498Szrj bool hot_label_written = false;
173138fd1498Szrj
173238fd1498Szrj if (crtl->has_bb_partition)
173338fd1498Szrj {
173438fd1498Szrj ASM_GENERATE_INTERNAL_LABEL (tmp_label, "LHOTB", const_labelno);
173538fd1498Szrj crtl->subsections.hot_section_label = ggc_strdup (tmp_label);
173638fd1498Szrj ASM_GENERATE_INTERNAL_LABEL (tmp_label, "LCOLDB", const_labelno);
173738fd1498Szrj crtl->subsections.cold_section_label = ggc_strdup (tmp_label);
173838fd1498Szrj ASM_GENERATE_INTERNAL_LABEL (tmp_label, "LHOTE", const_labelno);
173938fd1498Szrj crtl->subsections.hot_section_end_label = ggc_strdup (tmp_label);
174038fd1498Szrj ASM_GENERATE_INTERNAL_LABEL (tmp_label, "LCOLDE", const_labelno);
174138fd1498Szrj crtl->subsections.cold_section_end_label = ggc_strdup (tmp_label);
174238fd1498Szrj const_labelno++;
174338fd1498Szrj cold_function_name = NULL_TREE;
174438fd1498Szrj }
174538fd1498Szrj else
174638fd1498Szrj {
174738fd1498Szrj crtl->subsections.hot_section_label = NULL;
174838fd1498Szrj crtl->subsections.cold_section_label = NULL;
174938fd1498Szrj crtl->subsections.hot_section_end_label = NULL;
175038fd1498Szrj crtl->subsections.cold_section_end_label = NULL;
175138fd1498Szrj }
175238fd1498Szrj
175338fd1498Szrj /* The following code does not need preprocessing in the assembler. */
175438fd1498Szrj
175538fd1498Szrj app_disable ();
175638fd1498Szrj
175738fd1498Szrj if (CONSTANT_POOL_BEFORE_FUNCTION)
175838fd1498Szrj output_constant_pool (fnname, decl);
175938fd1498Szrj
176038fd1498Szrj align = symtab_node::get (decl)->definition_alignment ();
176138fd1498Szrj
176238fd1498Szrj /* Make sure the not and cold text (code) sections are properly
176338fd1498Szrj aligned. This is necessary here in the case where the function
176438fd1498Szrj has both hot and cold sections, because we don't want to re-set
176538fd1498Szrj the alignment when the section switch happens mid-function. */
176638fd1498Szrj
176738fd1498Szrj if (crtl->has_bb_partition)
176838fd1498Szrj {
176938fd1498Szrj first_function_block_is_cold = false;
177038fd1498Szrj
177138fd1498Szrj switch_to_section (unlikely_text_section ());
177238fd1498Szrj assemble_align (align);
177338fd1498Szrj ASM_OUTPUT_LABEL (asm_out_file, crtl->subsections.cold_section_label);
177438fd1498Szrj
177538fd1498Szrj /* When the function starts with a cold section, we need to explicitly
177638fd1498Szrj align the hot section and write out the hot section label.
177738fd1498Szrj But if the current function is a thunk, we do not have a CFG. */
177838fd1498Szrj if (!cfun->is_thunk
177938fd1498Szrj && BB_PARTITION (ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb) == BB_COLD_PARTITION)
178038fd1498Szrj {
178138fd1498Szrj switch_to_section (text_section);
178238fd1498Szrj assemble_align (align);
178338fd1498Szrj ASM_OUTPUT_LABEL (asm_out_file, crtl->subsections.hot_section_label);
178438fd1498Szrj hot_label_written = true;
178538fd1498Szrj first_function_block_is_cold = true;
178638fd1498Szrj }
178738fd1498Szrj in_cold_section_p = first_function_block_is_cold;
178838fd1498Szrj }
178938fd1498Szrj
179038fd1498Szrj
179138fd1498Szrj /* Switch to the correct text section for the start of the function. */
179238fd1498Szrj
179338fd1498Szrj switch_to_section (function_section (decl));
179438fd1498Szrj if (crtl->has_bb_partition && !hot_label_written)
179538fd1498Szrj ASM_OUTPUT_LABEL (asm_out_file, crtl->subsections.hot_section_label);
179638fd1498Szrj
179738fd1498Szrj /* Tell assembler to move to target machine's alignment for functions. */
179838fd1498Szrj align = floor_log2 (align / BITS_PER_UNIT);
179938fd1498Szrj if (align > 0)
180038fd1498Szrj {
180138fd1498Szrj ASM_OUTPUT_ALIGN (asm_out_file, align);
180238fd1498Szrj }
180338fd1498Szrj
180438fd1498Szrj /* Handle a user-specified function alignment.
180538fd1498Szrj Note that we still need to align to DECL_ALIGN, as above,
180638fd1498Szrj because ASM_OUTPUT_MAX_SKIP_ALIGN might not do any alignment at all. */
180738fd1498Szrj if (! DECL_USER_ALIGN (decl)
180838fd1498Szrj && align_functions_log > align
180938fd1498Szrj && optimize_function_for_speed_p (cfun))
181038fd1498Szrj {
181138fd1498Szrj #ifdef ASM_OUTPUT_MAX_SKIP_ALIGN
181238fd1498Szrj int align_log = align_functions_log;
181338fd1498Szrj #endif
181438fd1498Szrj int max_skip = align_functions - 1;
181538fd1498Szrj if (flag_limit_function_alignment && crtl->max_insn_address > 0
181638fd1498Szrj && max_skip >= crtl->max_insn_address)
181738fd1498Szrj max_skip = crtl->max_insn_address - 1;
181838fd1498Szrj
181938fd1498Szrj #ifdef ASM_OUTPUT_MAX_SKIP_ALIGN
182038fd1498Szrj ASM_OUTPUT_MAX_SKIP_ALIGN (asm_out_file, align_log, max_skip);
182138fd1498Szrj #else
182238fd1498Szrj ASM_OUTPUT_ALIGN (asm_out_file, align_functions_log);
182338fd1498Szrj #endif
182438fd1498Szrj }
182538fd1498Szrj
182638fd1498Szrj #ifdef ASM_OUTPUT_FUNCTION_PREFIX
182738fd1498Szrj ASM_OUTPUT_FUNCTION_PREFIX (asm_out_file, fnname);
182838fd1498Szrj #endif
182938fd1498Szrj
183038fd1498Szrj if (!DECL_IGNORED_P (decl))
183138fd1498Szrj (*debug_hooks->begin_function) (decl);
183238fd1498Szrj
183338fd1498Szrj /* Make function name accessible from other files, if appropriate. */
183438fd1498Szrj
183538fd1498Szrj if (TREE_PUBLIC (decl)
183638fd1498Szrj || (cgraph_node::get (decl)->instrumentation_clone
183738fd1498Szrj && cgraph_node::get (decl)->instrumented_version
183838fd1498Szrj && TREE_PUBLIC (cgraph_node::get (decl)->instrumented_version->decl)))
183938fd1498Szrj {
184038fd1498Szrj notice_global_symbol (decl);
184138fd1498Szrj
184238fd1498Szrj globalize_decl (decl);
184338fd1498Szrj
184438fd1498Szrj maybe_assemble_visibility (decl);
184538fd1498Szrj }
184638fd1498Szrj
184738fd1498Szrj if (DECL_PRESERVE_P (decl))
184838fd1498Szrj targetm.asm_out.mark_decl_preserved (fnname);
184938fd1498Szrj
185038fd1498Szrj unsigned HOST_WIDE_INT patch_area_size = function_entry_patch_area_size;
185138fd1498Szrj unsigned HOST_WIDE_INT patch_area_entry = function_entry_patch_area_start;
185238fd1498Szrj
185338fd1498Szrj tree patchable_function_entry_attr
185438fd1498Szrj = lookup_attribute ("patchable_function_entry", DECL_ATTRIBUTES (decl));
185538fd1498Szrj if (patchable_function_entry_attr)
185638fd1498Szrj {
185738fd1498Szrj tree pp_val = TREE_VALUE (patchable_function_entry_attr);
185838fd1498Szrj tree patchable_function_entry_value1 = TREE_VALUE (pp_val);
185938fd1498Szrj
186038fd1498Szrj if (tree_fits_uhwi_p (patchable_function_entry_value1))
186138fd1498Szrj patch_area_size = tree_to_uhwi (patchable_function_entry_value1);
186238fd1498Szrj else
186338fd1498Szrj gcc_unreachable ();
186438fd1498Szrj
186538fd1498Szrj patch_area_entry = 0;
186638fd1498Szrj if (list_length (pp_val) > 1)
186738fd1498Szrj {
186838fd1498Szrj tree patchable_function_entry_value2 =
186938fd1498Szrj TREE_VALUE (TREE_CHAIN (pp_val));
187038fd1498Szrj
187138fd1498Szrj if (tree_fits_uhwi_p (patchable_function_entry_value2))
187238fd1498Szrj patch_area_entry = tree_to_uhwi (patchable_function_entry_value2);
187338fd1498Szrj else
187438fd1498Szrj gcc_unreachable ();
187538fd1498Szrj }
187638fd1498Szrj }
187738fd1498Szrj
187838fd1498Szrj if (patch_area_entry > patch_area_size)
187938fd1498Szrj {
188038fd1498Szrj if (patch_area_size > 0)
188138fd1498Szrj warning (OPT_Wattributes, "Patchable function entry > size");
188238fd1498Szrj patch_area_entry = 0;
188338fd1498Szrj }
188438fd1498Szrj
188538fd1498Szrj /* Emit the patching area before the entry label, if any. */
188638fd1498Szrj if (patch_area_entry > 0)
188738fd1498Szrj targetm.asm_out.print_patchable_function_entry (asm_out_file,
188838fd1498Szrj patch_area_entry, true);
188938fd1498Szrj
189038fd1498Szrj /* Do any machine/system dependent processing of the function name. */
189138fd1498Szrj #ifdef ASM_DECLARE_FUNCTION_NAME
189238fd1498Szrj ASM_DECLARE_FUNCTION_NAME (asm_out_file, fnname, current_function_decl);
189338fd1498Szrj #else
189438fd1498Szrj /* Standard thing is just output label for the function. */
189538fd1498Szrj ASM_OUTPUT_FUNCTION_LABEL (asm_out_file, fnname, current_function_decl);
189638fd1498Szrj #endif /* ASM_DECLARE_FUNCTION_NAME */
189738fd1498Szrj
189838fd1498Szrj /* And the area after the label. Record it if we haven't done so yet. */
189938fd1498Szrj if (patch_area_size > patch_area_entry)
190038fd1498Szrj targetm.asm_out.print_patchable_function_entry (asm_out_file,
190138fd1498Szrj patch_area_size-patch_area_entry,
190238fd1498Szrj patch_area_entry == 0);
190338fd1498Szrj
190438fd1498Szrj if (lookup_attribute ("no_split_stack", DECL_ATTRIBUTES (decl)))
190538fd1498Szrj saw_no_split_stack = true;
190638fd1498Szrj }
190738fd1498Szrj
190838fd1498Szrj /* Output assembler code associated with defining the size of the
190938fd1498Szrj function. DECL describes the function. NAME is the function's name. */
191038fd1498Szrj
191138fd1498Szrj void
assemble_end_function(tree decl,const char * fnname ATTRIBUTE_UNUSED)191238fd1498Szrj assemble_end_function (tree decl, const char *fnname ATTRIBUTE_UNUSED)
191338fd1498Szrj {
191438fd1498Szrj #ifdef ASM_DECLARE_FUNCTION_SIZE
191538fd1498Szrj /* We could have switched section in the middle of the function. */
191638fd1498Szrj if (crtl->has_bb_partition)
191738fd1498Szrj switch_to_section (function_section (decl));
191838fd1498Szrj ASM_DECLARE_FUNCTION_SIZE (asm_out_file, fnname, decl);
191938fd1498Szrj #endif
192038fd1498Szrj if (! CONSTANT_POOL_BEFORE_FUNCTION)
192138fd1498Szrj {
192238fd1498Szrj output_constant_pool (fnname, decl);
192338fd1498Szrj switch_to_section (function_section (decl)); /* need to switch back */
192438fd1498Szrj }
192538fd1498Szrj /* Output labels for end of hot/cold text sections (to be used by
192638fd1498Szrj debug info.) */
192738fd1498Szrj if (crtl->has_bb_partition)
192838fd1498Szrj {
192938fd1498Szrj section *save_text_section;
193038fd1498Szrj
193138fd1498Szrj save_text_section = in_section;
193238fd1498Szrj switch_to_section (unlikely_text_section ());
193338fd1498Szrj #ifdef ASM_DECLARE_COLD_FUNCTION_SIZE
193438fd1498Szrj if (cold_function_name != NULL_TREE)
193538fd1498Szrj ASM_DECLARE_COLD_FUNCTION_SIZE (asm_out_file,
193638fd1498Szrj IDENTIFIER_POINTER (cold_function_name),
193738fd1498Szrj decl);
193838fd1498Szrj #endif
193938fd1498Szrj ASM_OUTPUT_LABEL (asm_out_file, crtl->subsections.cold_section_end_label);
194038fd1498Szrj if (first_function_block_is_cold)
194138fd1498Szrj switch_to_section (text_section);
194238fd1498Szrj else
194338fd1498Szrj switch_to_section (function_section (decl));
194438fd1498Szrj ASM_OUTPUT_LABEL (asm_out_file, crtl->subsections.hot_section_end_label);
194538fd1498Szrj switch_to_section (save_text_section);
194638fd1498Szrj }
194738fd1498Szrj }
194838fd1498Szrj
194938fd1498Szrj /* Assemble code to leave SIZE bytes of zeros. */
195038fd1498Szrj
195138fd1498Szrj void
assemble_zeros(unsigned HOST_WIDE_INT size)195238fd1498Szrj assemble_zeros (unsigned HOST_WIDE_INT size)
195338fd1498Szrj {
195438fd1498Szrj /* Do no output if -fsyntax-only. */
195538fd1498Szrj if (flag_syntax_only)
195638fd1498Szrj return;
195738fd1498Szrj
195838fd1498Szrj #ifdef ASM_NO_SKIP_IN_TEXT
195938fd1498Szrj /* The `space' pseudo in the text section outputs nop insns rather than 0s,
196038fd1498Szrj so we must output 0s explicitly in the text section. */
196138fd1498Szrj if (ASM_NO_SKIP_IN_TEXT && (in_section->common.flags & SECTION_CODE) != 0)
196238fd1498Szrj {
196338fd1498Szrj unsigned HOST_WIDE_INT i;
196438fd1498Szrj for (i = 0; i < size; i++)
196538fd1498Szrj assemble_integer (const0_rtx, 1, BITS_PER_UNIT, 1);
196638fd1498Szrj }
196738fd1498Szrj else
196838fd1498Szrj #endif
196938fd1498Szrj if (size > 0)
197038fd1498Szrj ASM_OUTPUT_SKIP (asm_out_file, size);
197138fd1498Szrj }
197238fd1498Szrj
197338fd1498Szrj /* Assemble an alignment pseudo op for an ALIGN-bit boundary. */
197438fd1498Szrj
197538fd1498Szrj void
assemble_align(int align)197638fd1498Szrj assemble_align (int align)
197738fd1498Szrj {
197838fd1498Szrj if (align > BITS_PER_UNIT)
197938fd1498Szrj {
198038fd1498Szrj ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (align / BITS_PER_UNIT));
198138fd1498Szrj }
198238fd1498Szrj }
198338fd1498Szrj
198438fd1498Szrj /* Assemble a string constant with the specified C string as contents. */
198538fd1498Szrj
198638fd1498Szrj void
assemble_string(const char * p,int size)198738fd1498Szrj assemble_string (const char *p, int size)
198838fd1498Szrj {
198938fd1498Szrj int pos = 0;
199038fd1498Szrj int maximum = 2000;
199138fd1498Szrj
199238fd1498Szrj /* If the string is very long, split it up. */
199338fd1498Szrj
199438fd1498Szrj while (pos < size)
199538fd1498Szrj {
199638fd1498Szrj int thissize = size - pos;
199738fd1498Szrj if (thissize > maximum)
199838fd1498Szrj thissize = maximum;
199938fd1498Szrj
200038fd1498Szrj ASM_OUTPUT_ASCII (asm_out_file, p, thissize);
200138fd1498Szrj
200238fd1498Szrj pos += thissize;
200338fd1498Szrj p += thissize;
200438fd1498Szrj }
200538fd1498Szrj }
200638fd1498Szrj
200738fd1498Szrj
200838fd1498Szrj /* A noswitch_section_callback for lcomm_section. */
200938fd1498Szrj
201038fd1498Szrj static bool
emit_local(tree decl ATTRIBUTE_UNUSED,const char * name ATTRIBUTE_UNUSED,unsigned HOST_WIDE_INT size ATTRIBUTE_UNUSED,unsigned HOST_WIDE_INT rounded ATTRIBUTE_UNUSED)201138fd1498Szrj emit_local (tree decl ATTRIBUTE_UNUSED,
201238fd1498Szrj const char *name ATTRIBUTE_UNUSED,
201338fd1498Szrj unsigned HOST_WIDE_INT size ATTRIBUTE_UNUSED,
201438fd1498Szrj unsigned HOST_WIDE_INT rounded ATTRIBUTE_UNUSED)
201538fd1498Szrj {
201638fd1498Szrj #if defined ASM_OUTPUT_ALIGNED_DECL_LOCAL
201738fd1498Szrj unsigned int align = symtab_node::get (decl)->definition_alignment ();
201838fd1498Szrj ASM_OUTPUT_ALIGNED_DECL_LOCAL (asm_out_file, decl, name,
201938fd1498Szrj size, align);
202038fd1498Szrj return true;
202138fd1498Szrj #elif defined ASM_OUTPUT_ALIGNED_LOCAL
202238fd1498Szrj unsigned int align = symtab_node::get (decl)->definition_alignment ();
202338fd1498Szrj ASM_OUTPUT_ALIGNED_LOCAL (asm_out_file, name, size, align);
202438fd1498Szrj return true;
202538fd1498Szrj #else
202638fd1498Szrj ASM_OUTPUT_LOCAL (asm_out_file, name, size, rounded);
202738fd1498Szrj return false;
202838fd1498Szrj #endif
202938fd1498Szrj }
203038fd1498Szrj
203138fd1498Szrj /* A noswitch_section_callback for bss_noswitch_section. */
203238fd1498Szrj
203338fd1498Szrj #if defined ASM_OUTPUT_ALIGNED_BSS
203438fd1498Szrj static bool
emit_bss(tree decl ATTRIBUTE_UNUSED,const char * name ATTRIBUTE_UNUSED,unsigned HOST_WIDE_INT size ATTRIBUTE_UNUSED,unsigned HOST_WIDE_INT rounded ATTRIBUTE_UNUSED)203538fd1498Szrj emit_bss (tree decl ATTRIBUTE_UNUSED,
203638fd1498Szrj const char *name ATTRIBUTE_UNUSED,
203738fd1498Szrj unsigned HOST_WIDE_INT size ATTRIBUTE_UNUSED,
203838fd1498Szrj unsigned HOST_WIDE_INT rounded ATTRIBUTE_UNUSED)
203938fd1498Szrj {
204038fd1498Szrj ASM_OUTPUT_ALIGNED_BSS (asm_out_file, decl, name, size,
204138fd1498Szrj get_variable_align (decl));
204238fd1498Szrj return true;
204338fd1498Szrj }
204438fd1498Szrj #endif
204538fd1498Szrj
204638fd1498Szrj /* A noswitch_section_callback for comm_section. */
204738fd1498Szrj
204838fd1498Szrj static bool
emit_common(tree decl ATTRIBUTE_UNUSED,const char * name ATTRIBUTE_UNUSED,unsigned HOST_WIDE_INT size ATTRIBUTE_UNUSED,unsigned HOST_WIDE_INT rounded ATTRIBUTE_UNUSED)204938fd1498Szrj emit_common (tree decl ATTRIBUTE_UNUSED,
205038fd1498Szrj const char *name ATTRIBUTE_UNUSED,
205138fd1498Szrj unsigned HOST_WIDE_INT size ATTRIBUTE_UNUSED,
205238fd1498Szrj unsigned HOST_WIDE_INT rounded ATTRIBUTE_UNUSED)
205338fd1498Szrj {
205438fd1498Szrj #if defined ASM_OUTPUT_ALIGNED_DECL_COMMON
205538fd1498Szrj ASM_OUTPUT_ALIGNED_DECL_COMMON (asm_out_file, decl, name,
205638fd1498Szrj size, get_variable_align (decl));
205738fd1498Szrj return true;
205838fd1498Szrj #elif defined ASM_OUTPUT_ALIGNED_COMMON
205938fd1498Szrj ASM_OUTPUT_ALIGNED_COMMON (asm_out_file, name, size,
206038fd1498Szrj get_variable_align (decl));
206138fd1498Szrj return true;
206238fd1498Szrj #else
206338fd1498Szrj ASM_OUTPUT_COMMON (asm_out_file, name, size, rounded);
206438fd1498Szrj return false;
206538fd1498Szrj #endif
206638fd1498Szrj }
206738fd1498Szrj
206838fd1498Szrj /* A noswitch_section_callback for tls_comm_section. */
206938fd1498Szrj
207038fd1498Szrj static bool
emit_tls_common(tree decl ATTRIBUTE_UNUSED,const char * name ATTRIBUTE_UNUSED,unsigned HOST_WIDE_INT size ATTRIBUTE_UNUSED,unsigned HOST_WIDE_INT rounded ATTRIBUTE_UNUSED)207138fd1498Szrj emit_tls_common (tree decl ATTRIBUTE_UNUSED,
207238fd1498Szrj const char *name ATTRIBUTE_UNUSED,
207338fd1498Szrj unsigned HOST_WIDE_INT size ATTRIBUTE_UNUSED,
207438fd1498Szrj unsigned HOST_WIDE_INT rounded ATTRIBUTE_UNUSED)
207538fd1498Szrj {
207638fd1498Szrj #ifdef ASM_OUTPUT_TLS_COMMON
207738fd1498Szrj ASM_OUTPUT_TLS_COMMON (asm_out_file, decl, name, size);
207838fd1498Szrj return true;
207938fd1498Szrj #else
208038fd1498Szrj sorry ("thread-local COMMON data not implemented");
208138fd1498Szrj return true;
208238fd1498Szrj #endif
208338fd1498Szrj }
208438fd1498Szrj
208538fd1498Szrj /* Assemble DECL given that it belongs in SECTION_NOSWITCH section SECT.
208638fd1498Szrj NAME is the name of DECL's SYMBOL_REF. */
208738fd1498Szrj
208838fd1498Szrj static void
assemble_noswitch_variable(tree decl,const char * name,section * sect,unsigned int align)208938fd1498Szrj assemble_noswitch_variable (tree decl, const char *name, section *sect,
209038fd1498Szrj unsigned int align)
209138fd1498Szrj {
209238fd1498Szrj unsigned HOST_WIDE_INT size, rounded;
209338fd1498Szrj
209438fd1498Szrj size = tree_to_uhwi (DECL_SIZE_UNIT (decl));
209538fd1498Szrj rounded = size;
209638fd1498Szrj
209738fd1498Szrj if ((flag_sanitize & SANITIZE_ADDRESS) && asan_protect_global (decl))
209838fd1498Szrj size += asan_red_zone_size (size);
209938fd1498Szrj
210038fd1498Szrj /* Don't allocate zero bytes of common,
210138fd1498Szrj since that means "undefined external" in the linker. */
210238fd1498Szrj if (size == 0)
210338fd1498Szrj rounded = 1;
210438fd1498Szrj
210538fd1498Szrj /* Round size up to multiple of BIGGEST_ALIGNMENT bits
210638fd1498Szrj so that each uninitialized object starts on such a boundary. */
210738fd1498Szrj rounded += (BIGGEST_ALIGNMENT / BITS_PER_UNIT) - 1;
210838fd1498Szrj rounded = (rounded / (BIGGEST_ALIGNMENT / BITS_PER_UNIT)
210938fd1498Szrj * (BIGGEST_ALIGNMENT / BITS_PER_UNIT));
211038fd1498Szrj
211138fd1498Szrj if (!sect->noswitch.callback (decl, name, size, rounded)
211238fd1498Szrj && (unsigned HOST_WIDE_INT) (align / BITS_PER_UNIT) > rounded)
211338fd1498Szrj error ("requested alignment for %q+D is greater than "
211438fd1498Szrj "implemented alignment of %wu", decl, rounded);
211538fd1498Szrj }
211638fd1498Szrj
211738fd1498Szrj /* A subroutine of assemble_variable. Output the label and contents of
211838fd1498Szrj DECL, whose address is a SYMBOL_REF with name NAME. DONT_OUTPUT_DATA
211938fd1498Szrj is as for assemble_variable. */
212038fd1498Szrj
212138fd1498Szrj static void
assemble_variable_contents(tree decl,const char * name,bool dont_output_data)212238fd1498Szrj assemble_variable_contents (tree decl, const char *name,
212338fd1498Szrj bool dont_output_data)
212438fd1498Szrj {
212538fd1498Szrj /* Do any machine/system dependent processing of the object. */
212638fd1498Szrj #ifdef ASM_DECLARE_OBJECT_NAME
212738fd1498Szrj last_assemble_variable_decl = decl;
212838fd1498Szrj ASM_DECLARE_OBJECT_NAME (asm_out_file, name, decl);
212938fd1498Szrj #else
213038fd1498Szrj /* Standard thing is just output label for the object. */
213138fd1498Szrj ASM_OUTPUT_LABEL (asm_out_file, name);
213238fd1498Szrj #endif /* ASM_DECLARE_OBJECT_NAME */
213338fd1498Szrj
213438fd1498Szrj if (!dont_output_data)
213538fd1498Szrj {
213638fd1498Szrj /* Caller is supposed to use varpool_get_constructor when it wants
213738fd1498Szrj to output the body. */
213838fd1498Szrj gcc_assert (!in_lto_p || DECL_INITIAL (decl) != error_mark_node);
213938fd1498Szrj if (DECL_INITIAL (decl)
214038fd1498Szrj && DECL_INITIAL (decl) != error_mark_node
214138fd1498Szrj && !initializer_zerop (DECL_INITIAL (decl)))
214238fd1498Szrj /* Output the actual data. */
214338fd1498Szrj output_constant (DECL_INITIAL (decl),
214438fd1498Szrj tree_to_uhwi (DECL_SIZE_UNIT (decl)),
214538fd1498Szrj get_variable_align (decl),
214638fd1498Szrj false);
214738fd1498Szrj else
214838fd1498Szrj /* Leave space for it. */
214938fd1498Szrj assemble_zeros (tree_to_uhwi (DECL_SIZE_UNIT (decl)));
215038fd1498Szrj targetm.asm_out.decl_end ();
215138fd1498Szrj }
215238fd1498Szrj }
215338fd1498Szrj
215438fd1498Szrj /* Write out assembly for the variable DECL, which is not defined in
215538fd1498Szrj the current translation unit. */
215638fd1498Szrj void
assemble_undefined_decl(tree decl)215738fd1498Szrj assemble_undefined_decl (tree decl)
215838fd1498Szrj {
215938fd1498Szrj const char *name = XSTR (XEXP (DECL_RTL (decl), 0), 0);
216038fd1498Szrj targetm.asm_out.assemble_undefined_decl (asm_out_file, name, decl);
216138fd1498Szrj }
216238fd1498Szrj
216338fd1498Szrj /* Assemble everything that is needed for a variable or function declaration.
216438fd1498Szrj Not used for automatic variables, and not used for function definitions.
216538fd1498Szrj Should not be called for variables of incomplete structure type.
216638fd1498Szrj
216738fd1498Szrj TOP_LEVEL is nonzero if this variable has file scope.
216838fd1498Szrj AT_END is nonzero if this is the special handling, at end of compilation,
216938fd1498Szrj to define things that have had only tentative definitions.
217038fd1498Szrj DONT_OUTPUT_DATA if nonzero means don't actually output the
217138fd1498Szrj initial value (that will be done by the caller). */
217238fd1498Szrj
217338fd1498Szrj void
assemble_variable(tree decl,int top_level ATTRIBUTE_UNUSED,int at_end ATTRIBUTE_UNUSED,int dont_output_data)217438fd1498Szrj assemble_variable (tree decl, int top_level ATTRIBUTE_UNUSED,
217538fd1498Szrj int at_end ATTRIBUTE_UNUSED, int dont_output_data)
217638fd1498Szrj {
217738fd1498Szrj const char *name;
217838fd1498Szrj rtx decl_rtl, symbol;
217938fd1498Szrj section *sect;
218038fd1498Szrj unsigned int align;
218138fd1498Szrj bool asan_protected = false;
218238fd1498Szrj
218338fd1498Szrj /* This function is supposed to handle VARIABLES. Ensure we have one. */
218438fd1498Szrj gcc_assert (VAR_P (decl));
218538fd1498Szrj
218638fd1498Szrj /* Emulated TLS had better not get this far. */
218738fd1498Szrj gcc_checking_assert (targetm.have_tls || !DECL_THREAD_LOCAL_P (decl));
218838fd1498Szrj
218938fd1498Szrj last_assemble_variable_decl = 0;
219038fd1498Szrj
219138fd1498Szrj /* Normally no need to say anything here for external references,
219238fd1498Szrj since assemble_external is called by the language-specific code
219338fd1498Szrj when a declaration is first seen. */
219438fd1498Szrj
219538fd1498Szrj if (DECL_EXTERNAL (decl))
219638fd1498Szrj return;
219738fd1498Szrj
219838fd1498Szrj /* Do nothing for global register variables. */
219938fd1498Szrj if (DECL_RTL_SET_P (decl) && REG_P (DECL_RTL (decl)))
220038fd1498Szrj {
220138fd1498Szrj TREE_ASM_WRITTEN (decl) = 1;
220238fd1498Szrj return;
220338fd1498Szrj }
220438fd1498Szrj
220538fd1498Szrj /* If type was incomplete when the variable was declared,
220638fd1498Szrj see if it is complete now. */
220738fd1498Szrj
220838fd1498Szrj if (DECL_SIZE (decl) == 0)
220938fd1498Szrj layout_decl (decl, 0);
221038fd1498Szrj
221138fd1498Szrj /* Still incomplete => don't allocate it; treat the tentative defn
221238fd1498Szrj (which is what it must have been) as an `extern' reference. */
221338fd1498Szrj
221438fd1498Szrj if (!dont_output_data && DECL_SIZE (decl) == 0)
221538fd1498Szrj {
221638fd1498Szrj error ("storage size of %q+D isn%'t known", decl);
221738fd1498Szrj TREE_ASM_WRITTEN (decl) = 1;
221838fd1498Szrj return;
221938fd1498Szrj }
222038fd1498Szrj
222138fd1498Szrj /* The first declaration of a variable that comes through this function
222238fd1498Szrj decides whether it is global (in C, has external linkage)
222338fd1498Szrj or local (in C, has internal linkage). So do nothing more
222438fd1498Szrj if this function has already run. */
222538fd1498Szrj
222638fd1498Szrj if (TREE_ASM_WRITTEN (decl))
222738fd1498Szrj return;
222838fd1498Szrj
222938fd1498Szrj /* Make sure targetm.encode_section_info is invoked before we set
223038fd1498Szrj ASM_WRITTEN. */
223138fd1498Szrj decl_rtl = DECL_RTL (decl);
223238fd1498Szrj
223338fd1498Szrj TREE_ASM_WRITTEN (decl) = 1;
223438fd1498Szrj
223538fd1498Szrj /* Do no output if -fsyntax-only. */
223638fd1498Szrj if (flag_syntax_only)
223738fd1498Szrj return;
223838fd1498Szrj
223938fd1498Szrj if (! dont_output_data
224038fd1498Szrj && ! valid_constant_size_p (DECL_SIZE_UNIT (decl)))
224138fd1498Szrj {
224238fd1498Szrj error ("size of variable %q+D is too large", decl);
224338fd1498Szrj return;
224438fd1498Szrj }
224538fd1498Szrj
224638fd1498Szrj gcc_assert (MEM_P (decl_rtl));
224738fd1498Szrj gcc_assert (GET_CODE (XEXP (decl_rtl, 0)) == SYMBOL_REF);
224838fd1498Szrj symbol = XEXP (decl_rtl, 0);
224938fd1498Szrj
225038fd1498Szrj /* If this symbol belongs to the tree constant pool, output the constant
225138fd1498Szrj if it hasn't already been written. */
225238fd1498Szrj if (TREE_CONSTANT_POOL_ADDRESS_P (symbol))
225338fd1498Szrj {
225438fd1498Szrj tree decl = SYMBOL_REF_DECL (symbol);
225538fd1498Szrj if (!TREE_ASM_WRITTEN (DECL_INITIAL (decl)))
225638fd1498Szrj output_constant_def_contents (symbol);
225738fd1498Szrj return;
225838fd1498Szrj }
225938fd1498Szrj
226038fd1498Szrj app_disable ();
226138fd1498Szrj
226238fd1498Szrj name = XSTR (symbol, 0);
226338fd1498Szrj if (TREE_PUBLIC (decl) && DECL_NAME (decl))
226438fd1498Szrj notice_global_symbol (decl);
226538fd1498Szrj
226638fd1498Szrj /* Compute the alignment of this data. */
226738fd1498Szrj
226838fd1498Szrj align_variable (decl, dont_output_data);
226938fd1498Szrj
227038fd1498Szrj if ((flag_sanitize & SANITIZE_ADDRESS)
227138fd1498Szrj && asan_protect_global (decl))
227238fd1498Szrj {
227338fd1498Szrj asan_protected = true;
227438fd1498Szrj SET_DECL_ALIGN (decl, MAX (DECL_ALIGN (decl),
227538fd1498Szrj ASAN_RED_ZONE_SIZE * BITS_PER_UNIT));
227638fd1498Szrj }
227738fd1498Szrj
227838fd1498Szrj set_mem_align (decl_rtl, DECL_ALIGN (decl));
227938fd1498Szrj
228038fd1498Szrj align = get_variable_align (decl);
228138fd1498Szrj
228238fd1498Szrj if (TREE_PUBLIC (decl))
228338fd1498Szrj maybe_assemble_visibility (decl);
228438fd1498Szrj
228538fd1498Szrj if (DECL_PRESERVE_P (decl))
228638fd1498Szrj targetm.asm_out.mark_decl_preserved (name);
228738fd1498Szrj
228838fd1498Szrj /* First make the assembler name(s) global if appropriate. */
228938fd1498Szrj sect = get_variable_section (decl, false);
229038fd1498Szrj if (TREE_PUBLIC (decl)
229138fd1498Szrj && (sect->common.flags & SECTION_COMMON) == 0)
229238fd1498Szrj globalize_decl (decl);
229338fd1498Szrj
229438fd1498Szrj /* Output any data that we will need to use the address of. */
229538fd1498Szrj if (DECL_INITIAL (decl) && DECL_INITIAL (decl) != error_mark_node)
229638fd1498Szrj output_addressed_constants (DECL_INITIAL (decl));
229738fd1498Szrj
229838fd1498Szrj /* dbxout.c needs to know this. */
229938fd1498Szrj if (sect && (sect->common.flags & SECTION_CODE) != 0)
230038fd1498Szrj DECL_IN_TEXT_SECTION (decl) = 1;
230138fd1498Szrj
230238fd1498Szrj /* If the decl is part of an object_block, make sure that the decl
230338fd1498Szrj has been positioned within its block, but do not write out its
230438fd1498Szrj definition yet. output_object_blocks will do that later. */
230538fd1498Szrj if (SYMBOL_REF_HAS_BLOCK_INFO_P (symbol) && SYMBOL_REF_BLOCK (symbol))
230638fd1498Szrj {
230738fd1498Szrj gcc_assert (!dont_output_data);
230838fd1498Szrj place_block_symbol (symbol);
230938fd1498Szrj }
231038fd1498Szrj else if (SECTION_STYLE (sect) == SECTION_NOSWITCH)
231138fd1498Szrj assemble_noswitch_variable (decl, name, sect, align);
231238fd1498Szrj else
231338fd1498Szrj {
231438fd1498Szrj /* Special-case handling of vtv comdat sections. */
231538fd1498Szrj if (sect->named.name
231638fd1498Szrj && (strcmp (sect->named.name, ".vtable_map_vars") == 0))
231738fd1498Szrj handle_vtv_comdat_section (sect, decl);
231838fd1498Szrj else
231938fd1498Szrj switch_to_section (sect);
232038fd1498Szrj if (align > BITS_PER_UNIT)
232138fd1498Szrj ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (align / BITS_PER_UNIT));
232238fd1498Szrj assemble_variable_contents (decl, name, dont_output_data);
232338fd1498Szrj if (asan_protected)
232438fd1498Szrj {
232538fd1498Szrj unsigned HOST_WIDE_INT int size
232638fd1498Szrj = tree_to_uhwi (DECL_SIZE_UNIT (decl));
232738fd1498Szrj assemble_zeros (asan_red_zone_size (size));
232838fd1498Szrj }
232938fd1498Szrj }
233038fd1498Szrj }
233138fd1498Szrj
233238fd1498Szrj
233338fd1498Szrj /* Given a function declaration (FN_DECL), this function assembles the
233438fd1498Szrj function into the .preinit_array section. */
233538fd1498Szrj
233638fd1498Szrj void
assemble_vtv_preinit_initializer(tree fn_decl)233738fd1498Szrj assemble_vtv_preinit_initializer (tree fn_decl)
233838fd1498Szrj {
233938fd1498Szrj section *sect;
234038fd1498Szrj unsigned flags = SECTION_WRITE;
234138fd1498Szrj rtx symbol = XEXP (DECL_RTL (fn_decl), 0);
234238fd1498Szrj
234338fd1498Szrj flags |= SECTION_NOTYPE;
234438fd1498Szrj sect = get_section (".preinit_array", flags, fn_decl);
234538fd1498Szrj switch_to_section (sect);
234638fd1498Szrj assemble_addr_to_section (symbol, sect);
234738fd1498Szrj }
234838fd1498Szrj
234938fd1498Szrj /* Return 1 if type TYPE contains any pointers. */
235038fd1498Szrj
235138fd1498Szrj static int
contains_pointers_p(tree type)235238fd1498Szrj contains_pointers_p (tree type)
235338fd1498Szrj {
235438fd1498Szrj switch (TREE_CODE (type))
235538fd1498Szrj {
235638fd1498Szrj case POINTER_TYPE:
235738fd1498Szrj case REFERENCE_TYPE:
235838fd1498Szrj /* I'm not sure whether OFFSET_TYPE needs this treatment,
235938fd1498Szrj so I'll play safe and return 1. */
236038fd1498Szrj case OFFSET_TYPE:
236138fd1498Szrj return 1;
236238fd1498Szrj
236338fd1498Szrj case RECORD_TYPE:
236438fd1498Szrj case UNION_TYPE:
236538fd1498Szrj case QUAL_UNION_TYPE:
236638fd1498Szrj {
236738fd1498Szrj tree fields;
236838fd1498Szrj /* For a type that has fields, see if the fields have pointers. */
236938fd1498Szrj for (fields = TYPE_FIELDS (type); fields; fields = DECL_CHAIN (fields))
237038fd1498Szrj if (TREE_CODE (fields) == FIELD_DECL
237138fd1498Szrj && contains_pointers_p (TREE_TYPE (fields)))
237238fd1498Szrj return 1;
237338fd1498Szrj return 0;
237438fd1498Szrj }
237538fd1498Szrj
237638fd1498Szrj case ARRAY_TYPE:
237738fd1498Szrj /* An array type contains pointers if its element type does. */
237838fd1498Szrj return contains_pointers_p (TREE_TYPE (type));
237938fd1498Szrj
238038fd1498Szrj default:
238138fd1498Szrj return 0;
238238fd1498Szrj }
238338fd1498Szrj }
238438fd1498Szrj
238538fd1498Szrj /* We delay assemble_external processing until
238638fd1498Szrj the compilation unit is finalized. This is the best we can do for
238738fd1498Szrj right now (i.e. stage 3 of GCC 4.0) - the right thing is to delay
238838fd1498Szrj it all the way to final. See PR 17982 for further discussion. */
238938fd1498Szrj static GTY(()) tree pending_assemble_externals;
239038fd1498Szrj
239138fd1498Szrj #ifdef ASM_OUTPUT_EXTERNAL
239238fd1498Szrj /* Some targets delay some output to final using TARGET_ASM_FILE_END.
239338fd1498Szrj As a result, assemble_external can be called after the list of externals
239438fd1498Szrj is processed and the pointer set destroyed. */
239538fd1498Szrj static bool pending_assemble_externals_processed;
239638fd1498Szrj
239738fd1498Szrj /* Avoid O(external_decls**2) lookups in the pending_assemble_externals
239838fd1498Szrj TREE_LIST in assemble_external. */
239938fd1498Szrj static hash_set<tree> *pending_assemble_externals_set;
240038fd1498Szrj
240138fd1498Szrj /* True if DECL is a function decl for which no out-of-line copy exists.
240238fd1498Szrj It is assumed that DECL's assembler name has been set. */
240338fd1498Szrj
240438fd1498Szrj static bool
incorporeal_function_p(tree decl)240538fd1498Szrj incorporeal_function_p (tree decl)
240638fd1498Szrj {
240738fd1498Szrj if (TREE_CODE (decl) == FUNCTION_DECL && DECL_BUILT_IN (decl))
240838fd1498Szrj {
240938fd1498Szrj const char *name;
241038fd1498Szrj
241138fd1498Szrj if (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL
241238fd1498Szrj && ALLOCA_FUNCTION_CODE_P (DECL_FUNCTION_CODE (decl)))
241338fd1498Szrj return true;
241438fd1498Szrj
241538fd1498Szrj name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
241638fd1498Szrj /* Atomic or sync builtins which have survived this far will be
241738fd1498Szrj resolved externally and therefore are not incorporeal. */
241838fd1498Szrj if (strncmp (name, "__builtin_", 10) == 0)
241938fd1498Szrj return true;
242038fd1498Szrj }
242138fd1498Szrj return false;
242238fd1498Szrj }
242338fd1498Szrj
242438fd1498Szrj /* Actually do the tests to determine if this is necessary, and invoke
242538fd1498Szrj ASM_OUTPUT_EXTERNAL. */
242638fd1498Szrj static void
assemble_external_real(tree decl)242738fd1498Szrj assemble_external_real (tree decl)
242838fd1498Szrj {
242938fd1498Szrj rtx rtl = DECL_RTL (decl);
243038fd1498Szrj
243138fd1498Szrj if (MEM_P (rtl) && GET_CODE (XEXP (rtl, 0)) == SYMBOL_REF
243238fd1498Szrj && !SYMBOL_REF_USED (XEXP (rtl, 0))
243338fd1498Szrj && !incorporeal_function_p (decl))
243438fd1498Szrj {
243538fd1498Szrj /* Some systems do require some output. */
243638fd1498Szrj SYMBOL_REF_USED (XEXP (rtl, 0)) = 1;
243738fd1498Szrj ASM_OUTPUT_EXTERNAL (asm_out_file, decl, XSTR (XEXP (rtl, 0), 0));
243838fd1498Szrj }
243938fd1498Szrj }
244038fd1498Szrj #endif
244138fd1498Szrj
244238fd1498Szrj void
process_pending_assemble_externals(void)244338fd1498Szrj process_pending_assemble_externals (void)
244438fd1498Szrj {
244538fd1498Szrj #ifdef ASM_OUTPUT_EXTERNAL
244638fd1498Szrj tree list;
244738fd1498Szrj for (list = pending_assemble_externals; list; list = TREE_CHAIN (list))
244838fd1498Szrj assemble_external_real (TREE_VALUE (list));
244938fd1498Szrj
245038fd1498Szrj pending_assemble_externals = 0;
245138fd1498Szrj pending_assemble_externals_processed = true;
245238fd1498Szrj delete pending_assemble_externals_set;
245338fd1498Szrj #endif
245438fd1498Szrj }
245538fd1498Szrj
245638fd1498Szrj /* This TREE_LIST contains any weak symbol declarations waiting
245738fd1498Szrj to be emitted. */
245838fd1498Szrj static GTY(()) tree weak_decls;
245938fd1498Szrj
246038fd1498Szrj /* Output something to declare an external symbol to the assembler,
246138fd1498Szrj and qualifiers such as weakness. (Most assemblers don't need
246238fd1498Szrj extern declaration, so we normally output nothing.) Do nothing if
246338fd1498Szrj DECL is not external. */
246438fd1498Szrj
246538fd1498Szrj void
assemble_external(tree decl ATTRIBUTE_UNUSED)246638fd1498Szrj assemble_external (tree decl ATTRIBUTE_UNUSED)
246738fd1498Szrj {
246838fd1498Szrj /* Make sure that the ASM_OUT_FILE is open.
246938fd1498Szrj If it's not, we should not be calling this function. */
247038fd1498Szrj gcc_assert (asm_out_file);
247138fd1498Szrj
247238fd1498Szrj /* In a perfect world, the following condition would be true.
247338fd1498Szrj Sadly, the Go front end emit assembly *from the front end*,
247438fd1498Szrj bypassing the call graph. See PR52739. Fix before GCC 4.8. */
247538fd1498Szrj #if 0
247638fd1498Szrj /* This function should only be called if we are expanding, or have
247738fd1498Szrj expanded, to RTL.
247838fd1498Szrj Ideally, only final.c would be calling this function, but it is
247938fd1498Szrj not clear whether that would break things somehow. See PR 17982
248038fd1498Szrj for further discussion. */
248138fd1498Szrj gcc_assert (state == EXPANSION
248238fd1498Szrj || state == FINISHED);
248338fd1498Szrj #endif
248438fd1498Szrj
248538fd1498Szrj if (!DECL_P (decl) || !DECL_EXTERNAL (decl) || !TREE_PUBLIC (decl))
248638fd1498Szrj return;
248738fd1498Szrj
248838fd1498Szrj /* We want to output annotation for weak and external symbols at
248938fd1498Szrj very last to check if they are references or not. */
249038fd1498Szrj
249138fd1498Szrj if (TARGET_SUPPORTS_WEAK
249238fd1498Szrj && DECL_WEAK (decl)
249338fd1498Szrj /* TREE_STATIC is a weird and abused creature which is not
249438fd1498Szrj generally the right test for whether an entity has been
249538fd1498Szrj locally emitted, inlined or otherwise not-really-extern, but
249638fd1498Szrj for declarations that can be weak, it happens to be
249738fd1498Szrj match. */
249838fd1498Szrj && !TREE_STATIC (decl)
249938fd1498Szrj && lookup_attribute ("weak", DECL_ATTRIBUTES (decl))
250038fd1498Szrj && value_member (decl, weak_decls) == NULL_TREE)
250138fd1498Szrj weak_decls = tree_cons (NULL, decl, weak_decls);
250238fd1498Szrj
250338fd1498Szrj #ifdef ASM_OUTPUT_EXTERNAL
250438fd1498Szrj if (pending_assemble_externals_processed)
250538fd1498Szrj {
250638fd1498Szrj assemble_external_real (decl);
250738fd1498Szrj return;
250838fd1498Szrj }
250938fd1498Szrj
251038fd1498Szrj if (! pending_assemble_externals_set->add (decl))
251138fd1498Szrj pending_assemble_externals = tree_cons (NULL, decl,
251238fd1498Szrj pending_assemble_externals);
251338fd1498Szrj #endif
251438fd1498Szrj }
251538fd1498Szrj
251638fd1498Szrj /* Similar, for calling a library function FUN. */
251738fd1498Szrj
251838fd1498Szrj void
assemble_external_libcall(rtx fun)251938fd1498Szrj assemble_external_libcall (rtx fun)
252038fd1498Szrj {
252138fd1498Szrj /* Declare library function name external when first used, if nec. */
252238fd1498Szrj if (! SYMBOL_REF_USED (fun))
252338fd1498Szrj {
252438fd1498Szrj SYMBOL_REF_USED (fun) = 1;
252538fd1498Szrj targetm.asm_out.external_libcall (fun);
252638fd1498Szrj }
252738fd1498Szrj }
252838fd1498Szrj
252938fd1498Szrj /* Assemble a label named NAME. */
253038fd1498Szrj
253138fd1498Szrj void
assemble_label(FILE * file,const char * name)253238fd1498Szrj assemble_label (FILE *file, const char *name)
253338fd1498Szrj {
253438fd1498Szrj ASM_OUTPUT_LABEL (file, name);
253538fd1498Szrj }
253638fd1498Szrj
253738fd1498Szrj /* Set the symbol_referenced flag for ID. */
253838fd1498Szrj void
mark_referenced(tree id)253938fd1498Szrj mark_referenced (tree id)
254038fd1498Szrj {
254138fd1498Szrj TREE_SYMBOL_REFERENCED (id) = 1;
254238fd1498Szrj }
254338fd1498Szrj
254438fd1498Szrj /* Set the symbol_referenced flag for DECL and notify callgraph. */
254538fd1498Szrj void
mark_decl_referenced(tree decl)254638fd1498Szrj mark_decl_referenced (tree decl)
254738fd1498Szrj {
254838fd1498Szrj if (TREE_CODE (decl) == FUNCTION_DECL)
254938fd1498Szrj {
255038fd1498Szrj /* Extern inline functions don't become needed when referenced.
255138fd1498Szrj If we know a method will be emitted in other TU and no new
255238fd1498Szrj functions can be marked reachable, just use the external
255338fd1498Szrj definition. */
255438fd1498Szrj struct cgraph_node *node = cgraph_node::get_create (decl);
255538fd1498Szrj if (!DECL_EXTERNAL (decl)
255638fd1498Szrj && !node->definition)
255738fd1498Szrj node->mark_force_output ();
255838fd1498Szrj }
255938fd1498Szrj else if (VAR_P (decl))
256038fd1498Szrj {
256138fd1498Szrj varpool_node *node = varpool_node::get_create (decl);
256238fd1498Szrj /* C++ frontend use mark_decl_references to force COMDAT variables
256338fd1498Szrj to be output that might appear dead otherwise. */
256438fd1498Szrj node->force_output = true;
256538fd1498Szrj }
256638fd1498Szrj /* else do nothing - we can get various sorts of CST nodes here,
256738fd1498Szrj which do not need to be marked. */
256838fd1498Szrj }
256938fd1498Szrj
257038fd1498Szrj
257138fd1498Szrj /* Output to FILE (an assembly file) a reference to NAME. If NAME
257238fd1498Szrj starts with a *, the rest of NAME is output verbatim. Otherwise
257338fd1498Szrj NAME is transformed in a target-specific way (usually by the
257438fd1498Szrj addition of an underscore). */
257538fd1498Szrj
257638fd1498Szrj void
assemble_name_raw(FILE * file,const char * name)257738fd1498Szrj assemble_name_raw (FILE *file, const char *name)
257838fd1498Szrj {
257938fd1498Szrj if (name[0] == '*')
258038fd1498Szrj fputs (&name[1], file);
258138fd1498Szrj else
258238fd1498Szrj ASM_OUTPUT_LABELREF (file, name);
258338fd1498Szrj }
258438fd1498Szrj
258538fd1498Szrj /* Like assemble_name_raw, but should be used when NAME might refer to
258638fd1498Szrj an entity that is also represented as a tree (like a function or
258738fd1498Szrj variable). If NAME does refer to such an entity, that entity will
258838fd1498Szrj be marked as referenced. */
258938fd1498Szrj
259038fd1498Szrj void
assemble_name(FILE * file,const char * name)259138fd1498Szrj assemble_name (FILE *file, const char *name)
259238fd1498Szrj {
259338fd1498Szrj const char *real_name;
259438fd1498Szrj tree id;
259538fd1498Szrj
259638fd1498Szrj real_name = targetm.strip_name_encoding (name);
259738fd1498Szrj
259838fd1498Szrj id = maybe_get_identifier (real_name);
259938fd1498Szrj if (id)
260038fd1498Szrj {
260138fd1498Szrj tree id_orig = id;
260238fd1498Szrj
260338fd1498Szrj mark_referenced (id);
260438fd1498Szrj ultimate_transparent_alias_target (&id);
260538fd1498Szrj if (id != id_orig)
260638fd1498Szrj name = IDENTIFIER_POINTER (id);
260738fd1498Szrj gcc_assert (! TREE_CHAIN (id));
260838fd1498Szrj }
260938fd1498Szrj
261038fd1498Szrj assemble_name_raw (file, name);
261138fd1498Szrj }
261238fd1498Szrj
261338fd1498Szrj /* Allocate SIZE bytes writable static space with a gensym name
261438fd1498Szrj and return an RTX to refer to its address. */
261538fd1498Szrj
261638fd1498Szrj rtx
assemble_static_space(unsigned HOST_WIDE_INT size)261738fd1498Szrj assemble_static_space (unsigned HOST_WIDE_INT size)
261838fd1498Szrj {
261938fd1498Szrj char name[17];
262038fd1498Szrj const char *namestring;
262138fd1498Szrj rtx x;
262238fd1498Szrj
262338fd1498Szrj ASM_GENERATE_INTERNAL_LABEL (name, "LF", const_labelno);
262438fd1498Szrj ++const_labelno;
262538fd1498Szrj namestring = ggc_strdup (name);
262638fd1498Szrj
262738fd1498Szrj x = gen_rtx_SYMBOL_REF (Pmode, namestring);
262838fd1498Szrj SYMBOL_REF_FLAGS (x) = SYMBOL_FLAG_LOCAL;
262938fd1498Szrj
263038fd1498Szrj #ifdef ASM_OUTPUT_ALIGNED_DECL_LOCAL
263138fd1498Szrj ASM_OUTPUT_ALIGNED_DECL_LOCAL (asm_out_file, NULL_TREE, name, size,
263238fd1498Szrj BIGGEST_ALIGNMENT);
263338fd1498Szrj #else
263438fd1498Szrj #ifdef ASM_OUTPUT_ALIGNED_LOCAL
263538fd1498Szrj ASM_OUTPUT_ALIGNED_LOCAL (asm_out_file, name, size, BIGGEST_ALIGNMENT);
263638fd1498Szrj #else
263738fd1498Szrj {
263838fd1498Szrj /* Round size up to multiple of BIGGEST_ALIGNMENT bits
263938fd1498Szrj so that each uninitialized object starts on such a boundary. */
264038fd1498Szrj /* Variable `rounded' might or might not be used in ASM_OUTPUT_LOCAL. */
264138fd1498Szrj unsigned HOST_WIDE_INT rounded ATTRIBUTE_UNUSED
264238fd1498Szrj = ((size + (BIGGEST_ALIGNMENT / BITS_PER_UNIT) - 1)
264338fd1498Szrj / (BIGGEST_ALIGNMENT / BITS_PER_UNIT)
264438fd1498Szrj * (BIGGEST_ALIGNMENT / BITS_PER_UNIT));
264538fd1498Szrj ASM_OUTPUT_LOCAL (asm_out_file, name, size, rounded);
264638fd1498Szrj }
264738fd1498Szrj #endif
264838fd1498Szrj #endif
264938fd1498Szrj return x;
265038fd1498Szrj }
265138fd1498Szrj
265238fd1498Szrj /* Assemble the static constant template for function entry trampolines.
265338fd1498Szrj This is done at most once per compilation.
265438fd1498Szrj Returns an RTX for the address of the template. */
265538fd1498Szrj
265638fd1498Szrj static GTY(()) rtx initial_trampoline;
265738fd1498Szrj
265838fd1498Szrj rtx
assemble_trampoline_template(void)265938fd1498Szrj assemble_trampoline_template (void)
266038fd1498Szrj {
266138fd1498Szrj char label[256];
266238fd1498Szrj const char *name;
266338fd1498Szrj int align;
266438fd1498Szrj rtx symbol;
266538fd1498Szrj
266638fd1498Szrj gcc_assert (targetm.asm_out.trampoline_template != NULL);
266738fd1498Szrj
266838fd1498Szrj if (initial_trampoline)
266938fd1498Szrj return initial_trampoline;
267038fd1498Szrj
267138fd1498Szrj /* By default, put trampoline templates in read-only data section. */
267238fd1498Szrj
267338fd1498Szrj #ifdef TRAMPOLINE_SECTION
267438fd1498Szrj switch_to_section (TRAMPOLINE_SECTION);
267538fd1498Szrj #else
267638fd1498Szrj switch_to_section (readonly_data_section);
267738fd1498Szrj #endif
267838fd1498Szrj
267938fd1498Szrj /* Write the assembler code to define one. */
268038fd1498Szrj align = floor_log2 (TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT);
268138fd1498Szrj if (align > 0)
268238fd1498Szrj ASM_OUTPUT_ALIGN (asm_out_file, align);
268338fd1498Szrj
268438fd1498Szrj targetm.asm_out.internal_label (asm_out_file, "LTRAMP", 0);
268538fd1498Szrj targetm.asm_out.trampoline_template (asm_out_file);
268638fd1498Szrj
268738fd1498Szrj /* Record the rtl to refer to it. */
268838fd1498Szrj ASM_GENERATE_INTERNAL_LABEL (label, "LTRAMP", 0);
268938fd1498Szrj name = ggc_strdup (label);
269038fd1498Szrj symbol = gen_rtx_SYMBOL_REF (Pmode, name);
269138fd1498Szrj SYMBOL_REF_FLAGS (symbol) = SYMBOL_FLAG_LOCAL;
269238fd1498Szrj
269338fd1498Szrj initial_trampoline = gen_const_mem (BLKmode, symbol);
269438fd1498Szrj set_mem_align (initial_trampoline, TRAMPOLINE_ALIGNMENT);
269538fd1498Szrj set_mem_size (initial_trampoline, TRAMPOLINE_SIZE);
269638fd1498Szrj
269738fd1498Szrj return initial_trampoline;
269838fd1498Szrj }
269938fd1498Szrj
270038fd1498Szrj /* A and B are either alignments or offsets. Return the minimum alignment
270138fd1498Szrj that may be assumed after adding the two together. */
270238fd1498Szrj
270338fd1498Szrj static inline unsigned
min_align(unsigned int a,unsigned int b)270438fd1498Szrj min_align (unsigned int a, unsigned int b)
270538fd1498Szrj {
270638fd1498Szrj return least_bit_hwi (a | b);
270738fd1498Szrj }
270838fd1498Szrj
270938fd1498Szrj /* Return the assembler directive for creating a given kind of integer
271038fd1498Szrj object. SIZE is the number of bytes in the object and ALIGNED_P
271138fd1498Szrj indicates whether it is known to be aligned. Return NULL if the
271238fd1498Szrj assembly dialect has no such directive.
271338fd1498Szrj
271438fd1498Szrj The returned string should be printed at the start of a new line and
271538fd1498Szrj be followed immediately by the object's initial value. */
271638fd1498Szrj
271738fd1498Szrj const char *
integer_asm_op(int size,int aligned_p)271838fd1498Szrj integer_asm_op (int size, int aligned_p)
271938fd1498Szrj {
272038fd1498Szrj struct asm_int_op *ops;
272138fd1498Szrj
272238fd1498Szrj if (aligned_p)
272338fd1498Szrj ops = &targetm.asm_out.aligned_op;
272438fd1498Szrj else
272538fd1498Szrj ops = &targetm.asm_out.unaligned_op;
272638fd1498Szrj
272738fd1498Szrj switch (size)
272838fd1498Szrj {
272938fd1498Szrj case 1:
273038fd1498Szrj return targetm.asm_out.byte_op;
273138fd1498Szrj case 2:
273238fd1498Szrj return ops->hi;
273338fd1498Szrj case 4:
273438fd1498Szrj return ops->si;
273538fd1498Szrj case 8:
273638fd1498Szrj return ops->di;
273738fd1498Szrj case 16:
273838fd1498Szrj return ops->ti;
273938fd1498Szrj default:
274038fd1498Szrj return NULL;
274138fd1498Szrj }
274238fd1498Szrj }
274338fd1498Szrj
274438fd1498Szrj /* Use directive OP to assemble an integer object X. Print OP at the
274538fd1498Szrj start of the line, followed immediately by the value of X. */
274638fd1498Szrj
274738fd1498Szrj void
assemble_integer_with_op(const char * op,rtx x)274838fd1498Szrj assemble_integer_with_op (const char *op, rtx x)
274938fd1498Szrj {
275038fd1498Szrj fputs (op, asm_out_file);
275138fd1498Szrj output_addr_const (asm_out_file, x);
275238fd1498Szrj fputc ('\n', asm_out_file);
275338fd1498Szrj }
275438fd1498Szrj
275538fd1498Szrj /* The default implementation of the asm_out.integer target hook. */
275638fd1498Szrj
275738fd1498Szrj bool
default_assemble_integer(rtx x ATTRIBUTE_UNUSED,unsigned int size ATTRIBUTE_UNUSED,int aligned_p ATTRIBUTE_UNUSED)275838fd1498Szrj default_assemble_integer (rtx x ATTRIBUTE_UNUSED,
275938fd1498Szrj unsigned int size ATTRIBUTE_UNUSED,
276038fd1498Szrj int aligned_p ATTRIBUTE_UNUSED)
276138fd1498Szrj {
276238fd1498Szrj const char *op = integer_asm_op (size, aligned_p);
276338fd1498Szrj /* Avoid GAS bugs for large values. Specifically negative values whose
276438fd1498Szrj absolute value fits in a bfd_vma, but not in a bfd_signed_vma. */
276538fd1498Szrj if (size > UNITS_PER_WORD && size > POINTER_SIZE_UNITS)
276638fd1498Szrj return false;
276738fd1498Szrj return op && (assemble_integer_with_op (op, x), true);
276838fd1498Szrj }
276938fd1498Szrj
277038fd1498Szrj /* Assemble the integer constant X into an object of SIZE bytes. ALIGN is
277138fd1498Szrj the alignment of the integer in bits. Return 1 if we were able to output
277238fd1498Szrj the constant, otherwise 0. We must be able to output the constant,
277338fd1498Szrj if FORCE is nonzero. */
277438fd1498Szrj
277538fd1498Szrj bool
assemble_integer(rtx x,unsigned int size,unsigned int align,int force)277638fd1498Szrj assemble_integer (rtx x, unsigned int size, unsigned int align, int force)
277738fd1498Szrj {
277838fd1498Szrj int aligned_p;
277938fd1498Szrj
278038fd1498Szrj aligned_p = (align >= MIN (size * BITS_PER_UNIT, BIGGEST_ALIGNMENT));
278138fd1498Szrj
278238fd1498Szrj /* See if the target hook can handle this kind of object. */
278338fd1498Szrj if (targetm.asm_out.integer (x, size, aligned_p))
278438fd1498Szrj return true;
278538fd1498Szrj
278638fd1498Szrj /* If the object is a multi-byte one, try splitting it up. Split
278738fd1498Szrj it into words it if is multi-word, otherwise split it into bytes. */
278838fd1498Szrj if (size > 1)
278938fd1498Szrj {
279038fd1498Szrj machine_mode omode, imode;
279138fd1498Szrj unsigned int subalign;
279238fd1498Szrj unsigned int subsize, i;
279338fd1498Szrj enum mode_class mclass;
279438fd1498Szrj
279538fd1498Szrj subsize = size > UNITS_PER_WORD? UNITS_PER_WORD : 1;
279638fd1498Szrj subalign = MIN (align, subsize * BITS_PER_UNIT);
279738fd1498Szrj if (GET_CODE (x) == CONST_FIXED)
279838fd1498Szrj mclass = GET_MODE_CLASS (GET_MODE (x));
279938fd1498Szrj else
280038fd1498Szrj mclass = MODE_INT;
280138fd1498Szrj
280238fd1498Szrj omode = mode_for_size (subsize * BITS_PER_UNIT, mclass, 0).require ();
280338fd1498Szrj imode = mode_for_size (size * BITS_PER_UNIT, mclass, 0).require ();
280438fd1498Szrj
280538fd1498Szrj for (i = 0; i < size; i += subsize)
280638fd1498Szrj {
280738fd1498Szrj rtx partial = simplify_subreg (omode, x, imode, i);
280838fd1498Szrj if (!partial || !assemble_integer (partial, subsize, subalign, 0))
280938fd1498Szrj break;
281038fd1498Szrj }
281138fd1498Szrj if (i == size)
281238fd1498Szrj return true;
281338fd1498Szrj
281438fd1498Szrj /* If we've printed some of it, but not all of it, there's no going
281538fd1498Szrj back now. */
281638fd1498Szrj gcc_assert (!i);
281738fd1498Szrj }
281838fd1498Szrj
281938fd1498Szrj gcc_assert (!force);
282038fd1498Szrj
282138fd1498Szrj return false;
282238fd1498Szrj }
282338fd1498Szrj
282438fd1498Szrj /* Assemble the floating-point constant D into an object of size MODE. ALIGN
282538fd1498Szrj is the alignment of the constant in bits. If REVERSE is true, D is output
282638fd1498Szrj in reverse storage order. */
282738fd1498Szrj
282838fd1498Szrj void
assemble_real(REAL_VALUE_TYPE d,scalar_float_mode mode,unsigned int align,bool reverse)282938fd1498Szrj assemble_real (REAL_VALUE_TYPE d, scalar_float_mode mode, unsigned int align,
283038fd1498Szrj bool reverse)
283138fd1498Szrj {
283238fd1498Szrj long data[4] = {0, 0, 0, 0};
283338fd1498Szrj int bitsize, nelts, nunits, units_per;
283438fd1498Szrj rtx elt;
283538fd1498Szrj
283638fd1498Szrj /* This is hairy. We have a quantity of known size. real_to_target
283738fd1498Szrj will put it into an array of *host* longs, 32 bits per element
283838fd1498Szrj (even if long is more than 32 bits). We need to determine the
283938fd1498Szrj number of array elements that are occupied (nelts) and the number
284038fd1498Szrj of *target* min-addressable units that will be occupied in the
284138fd1498Szrj object file (nunits). We cannot assume that 32 divides the
284238fd1498Szrj mode's bitsize (size * BITS_PER_UNIT) evenly.
284338fd1498Szrj
284438fd1498Szrj size * BITS_PER_UNIT is used here to make sure that padding bits
284538fd1498Szrj (which might appear at either end of the value; real_to_target
284638fd1498Szrj will include the padding bits in its output array) are included. */
284738fd1498Szrj
284838fd1498Szrj nunits = GET_MODE_SIZE (mode);
284938fd1498Szrj bitsize = nunits * BITS_PER_UNIT;
285038fd1498Szrj nelts = CEIL (bitsize, 32);
285138fd1498Szrj units_per = 32 / BITS_PER_UNIT;
285238fd1498Szrj
285338fd1498Szrj real_to_target (data, &d, mode);
285438fd1498Szrj
285538fd1498Szrj /* Put out the first word with the specified alignment. */
285638fd1498Szrj if (reverse)
285738fd1498Szrj elt = flip_storage_order (SImode, gen_int_mode (data[nelts - 1], SImode));
285838fd1498Szrj else
285938fd1498Szrj elt = GEN_INT (data[0]);
286038fd1498Szrj assemble_integer (elt, MIN (nunits, units_per), align, 1);
286138fd1498Szrj nunits -= units_per;
286238fd1498Szrj
286338fd1498Szrj /* Subsequent words need only 32-bit alignment. */
286438fd1498Szrj align = min_align (align, 32);
286538fd1498Szrj
286638fd1498Szrj for (int i = 1; i < nelts; i++)
286738fd1498Szrj {
286838fd1498Szrj if (reverse)
286938fd1498Szrj elt = flip_storage_order (SImode,
287038fd1498Szrj gen_int_mode (data[nelts - 1 - i], SImode));
287138fd1498Szrj else
287238fd1498Szrj elt = GEN_INT (data[i]);
287338fd1498Szrj assemble_integer (elt, MIN (nunits, units_per), align, 1);
287438fd1498Szrj nunits -= units_per;
287538fd1498Szrj }
287638fd1498Szrj }
287738fd1498Szrj
287838fd1498Szrj /* Given an expression EXP with a constant value,
287938fd1498Szrj reduce it to the sum of an assembler symbol and an integer.
288038fd1498Szrj Store them both in the structure *VALUE.
288138fd1498Szrj EXP must be reducible. */
288238fd1498Szrj
288338fd1498Szrj struct addr_const {
288438fd1498Szrj rtx base;
288538fd1498Szrj poly_int64 offset;
288638fd1498Szrj };
288738fd1498Szrj
288838fd1498Szrj static void
decode_addr_const(tree exp,struct addr_const * value)288938fd1498Szrj decode_addr_const (tree exp, struct addr_const *value)
289038fd1498Szrj {
289138fd1498Szrj tree target = TREE_OPERAND (exp, 0);
289238fd1498Szrj poly_int64 offset = 0;
289338fd1498Szrj rtx x;
289438fd1498Szrj
289538fd1498Szrj while (1)
289638fd1498Szrj {
289738fd1498Szrj poly_int64 bytepos;
289838fd1498Szrj if (TREE_CODE (target) == COMPONENT_REF
289938fd1498Szrj && poly_int_tree_p (byte_position (TREE_OPERAND (target, 1)),
290038fd1498Szrj &bytepos))
290138fd1498Szrj {
290238fd1498Szrj offset += bytepos;
290338fd1498Szrj target = TREE_OPERAND (target, 0);
290438fd1498Szrj }
290538fd1498Szrj else if (TREE_CODE (target) == ARRAY_REF
290638fd1498Szrj || TREE_CODE (target) == ARRAY_RANGE_REF)
290738fd1498Szrj {
290838fd1498Szrj /* Truncate big offset. */
290938fd1498Szrj offset
291038fd1498Szrj += (TREE_INT_CST_LOW (TYPE_SIZE_UNIT (TREE_TYPE (target)))
291138fd1498Szrj * wi::to_poly_widest (TREE_OPERAND (target, 1)).force_shwi ());
291238fd1498Szrj target = TREE_OPERAND (target, 0);
291338fd1498Szrj }
291438fd1498Szrj else if (TREE_CODE (target) == MEM_REF
291538fd1498Szrj && TREE_CODE (TREE_OPERAND (target, 0)) == ADDR_EXPR)
291638fd1498Szrj {
291738fd1498Szrj offset += mem_ref_offset (target).force_shwi ();
291838fd1498Szrj target = TREE_OPERAND (TREE_OPERAND (target, 0), 0);
291938fd1498Szrj }
292038fd1498Szrj else if (TREE_CODE (target) == INDIRECT_REF
292138fd1498Szrj && TREE_CODE (TREE_OPERAND (target, 0)) == NOP_EXPR
292238fd1498Szrj && TREE_CODE (TREE_OPERAND (TREE_OPERAND (target, 0), 0))
292338fd1498Szrj == ADDR_EXPR)
292438fd1498Szrj target = TREE_OPERAND (TREE_OPERAND (TREE_OPERAND (target, 0), 0), 0);
292538fd1498Szrj else
292638fd1498Szrj break;
292738fd1498Szrj }
292838fd1498Szrj
292938fd1498Szrj switch (TREE_CODE (target))
293038fd1498Szrj {
293138fd1498Szrj case VAR_DECL:
293238fd1498Szrj case FUNCTION_DECL:
293338fd1498Szrj x = DECL_RTL (target);
293438fd1498Szrj break;
293538fd1498Szrj
293638fd1498Szrj case LABEL_DECL:
293738fd1498Szrj x = gen_rtx_MEM (FUNCTION_MODE,
293838fd1498Szrj gen_rtx_LABEL_REF (Pmode, force_label_rtx (target)));
293938fd1498Szrj break;
294038fd1498Szrj
294138fd1498Szrj case REAL_CST:
294238fd1498Szrj case FIXED_CST:
294338fd1498Szrj case STRING_CST:
294438fd1498Szrj case COMPLEX_CST:
294538fd1498Szrj case CONSTRUCTOR:
294638fd1498Szrj case INTEGER_CST:
294738fd1498Szrj x = output_constant_def (target, 1);
294838fd1498Szrj break;
294938fd1498Szrj
295038fd1498Szrj case INDIRECT_REF:
295138fd1498Szrj /* This deals with absolute addresses. */
295238fd1498Szrj offset += tree_to_shwi (TREE_OPERAND (target, 0));
295338fd1498Szrj x = gen_rtx_MEM (QImode,
295438fd1498Szrj gen_rtx_SYMBOL_REF (Pmode, "origin of addresses"));
295538fd1498Szrj break;
295638fd1498Szrj
2957*58e805e6Szrj case COMPOUND_LITERAL_EXPR:
2958*58e805e6Szrj gcc_assert (COMPOUND_LITERAL_EXPR_DECL (target));
2959*58e805e6Szrj x = DECL_RTL (COMPOUND_LITERAL_EXPR_DECL (target));
2960*58e805e6Szrj break;
2961*58e805e6Szrj
296238fd1498Szrj default:
296338fd1498Szrj gcc_unreachable ();
296438fd1498Szrj }
296538fd1498Szrj
296638fd1498Szrj gcc_assert (MEM_P (x));
296738fd1498Szrj x = XEXP (x, 0);
296838fd1498Szrj
296938fd1498Szrj value->base = x;
297038fd1498Szrj value->offset = offset;
297138fd1498Szrj }
297238fd1498Szrj
297338fd1498Szrj static GTY(()) hash_table<tree_descriptor_hasher> *const_desc_htab;
297438fd1498Szrj
297538fd1498Szrj static void maybe_output_constant_def_contents (struct constant_descriptor_tree *, int);
297638fd1498Szrj
297738fd1498Szrj /* Constant pool accessor function. */
297838fd1498Szrj
297938fd1498Szrj hash_table<tree_descriptor_hasher> *
constant_pool_htab(void)298038fd1498Szrj constant_pool_htab (void)
298138fd1498Szrj {
298238fd1498Szrj return const_desc_htab;
298338fd1498Szrj }
298438fd1498Szrj
298538fd1498Szrj /* Compute a hash code for a constant expression. */
298638fd1498Szrj
298738fd1498Szrj hashval_t
hash(constant_descriptor_tree * ptr)298838fd1498Szrj tree_descriptor_hasher::hash (constant_descriptor_tree *ptr)
298938fd1498Szrj {
299038fd1498Szrj return ptr->hash;
299138fd1498Szrj }
299238fd1498Szrj
299338fd1498Szrj static hashval_t
const_hash_1(const tree exp)299438fd1498Szrj const_hash_1 (const tree exp)
299538fd1498Szrj {
299638fd1498Szrj const char *p;
299738fd1498Szrj hashval_t hi;
299838fd1498Szrj int len, i;
299938fd1498Szrj enum tree_code code = TREE_CODE (exp);
300038fd1498Szrj
300138fd1498Szrj /* Either set P and LEN to the address and len of something to hash and
300238fd1498Szrj exit the switch or return a value. */
300338fd1498Szrj
300438fd1498Szrj switch (code)
300538fd1498Szrj {
300638fd1498Szrj case INTEGER_CST:
300738fd1498Szrj p = (char *) &TREE_INT_CST_ELT (exp, 0);
300838fd1498Szrj len = TREE_INT_CST_NUNITS (exp) * sizeof (HOST_WIDE_INT);
300938fd1498Szrj break;
301038fd1498Szrj
301138fd1498Szrj case REAL_CST:
301238fd1498Szrj return real_hash (TREE_REAL_CST_PTR (exp));
301338fd1498Szrj
301438fd1498Szrj case FIXED_CST:
301538fd1498Szrj return fixed_hash (TREE_FIXED_CST_PTR (exp));
301638fd1498Szrj
301738fd1498Szrj case STRING_CST:
301838fd1498Szrj p = TREE_STRING_POINTER (exp);
301938fd1498Szrj len = TREE_STRING_LENGTH (exp);
302038fd1498Szrj break;
302138fd1498Szrj
302238fd1498Szrj case COMPLEX_CST:
302338fd1498Szrj return (const_hash_1 (TREE_REALPART (exp)) * 5
302438fd1498Szrj + const_hash_1 (TREE_IMAGPART (exp)));
302538fd1498Szrj
302638fd1498Szrj case VECTOR_CST:
302738fd1498Szrj {
302838fd1498Szrj hi = 7 + VECTOR_CST_NPATTERNS (exp);
302938fd1498Szrj hi = hi * 563 + VECTOR_CST_NELTS_PER_PATTERN (exp);
303038fd1498Szrj unsigned int count = vector_cst_encoded_nelts (exp);
303138fd1498Szrj for (unsigned int i = 0; i < count; ++i)
303238fd1498Szrj hi = hi * 563 + const_hash_1 (VECTOR_CST_ENCODED_ELT (exp, i));
303338fd1498Szrj return hi;
303438fd1498Szrj }
303538fd1498Szrj
303638fd1498Szrj case CONSTRUCTOR:
303738fd1498Szrj {
303838fd1498Szrj unsigned HOST_WIDE_INT idx;
303938fd1498Szrj tree value;
304038fd1498Szrj
304138fd1498Szrj hi = 5 + int_size_in_bytes (TREE_TYPE (exp));
304238fd1498Szrj
304338fd1498Szrj FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (exp), idx, value)
304438fd1498Szrj if (value)
304538fd1498Szrj hi = hi * 603 + const_hash_1 (value);
304638fd1498Szrj
304738fd1498Szrj return hi;
304838fd1498Szrj }
304938fd1498Szrj
305038fd1498Szrj case ADDR_EXPR:
305138fd1498Szrj case FDESC_EXPR:
305238fd1498Szrj {
305338fd1498Szrj struct addr_const value;
305438fd1498Szrj
305538fd1498Szrj decode_addr_const (exp, &value);
305638fd1498Szrj switch (GET_CODE (value.base))
305738fd1498Szrj {
305838fd1498Szrj case SYMBOL_REF:
305938fd1498Szrj /* Don't hash the address of the SYMBOL_REF;
306038fd1498Szrj only use the offset and the symbol name. */
306138fd1498Szrj hi = value.offset.coeffs[0];
306238fd1498Szrj p = XSTR (value.base, 0);
306338fd1498Szrj for (i = 0; p[i] != 0; i++)
306438fd1498Szrj hi = ((hi * 613) + (unsigned) (p[i]));
306538fd1498Szrj break;
306638fd1498Szrj
306738fd1498Szrj case LABEL_REF:
306838fd1498Szrj hi = (value.offset.coeffs[0]
306938fd1498Szrj + CODE_LABEL_NUMBER (label_ref_label (value.base)) * 13);
307038fd1498Szrj break;
307138fd1498Szrj
307238fd1498Szrj default:
307338fd1498Szrj gcc_unreachable ();
307438fd1498Szrj }
307538fd1498Szrj }
307638fd1498Szrj return hi;
307738fd1498Szrj
307838fd1498Szrj case PLUS_EXPR:
307938fd1498Szrj case POINTER_PLUS_EXPR:
308038fd1498Szrj case MINUS_EXPR:
308138fd1498Szrj return (const_hash_1 (TREE_OPERAND (exp, 0)) * 9
308238fd1498Szrj + const_hash_1 (TREE_OPERAND (exp, 1)));
308338fd1498Szrj
308438fd1498Szrj CASE_CONVERT:
308538fd1498Szrj return const_hash_1 (TREE_OPERAND (exp, 0)) * 7 + 2;
308638fd1498Szrj
308738fd1498Szrj default:
308838fd1498Szrj /* A language specific constant. Just hash the code. */
308938fd1498Szrj return code;
309038fd1498Szrj }
309138fd1498Szrj
309238fd1498Szrj /* Compute hashing function. */
309338fd1498Szrj hi = len;
309438fd1498Szrj for (i = 0; i < len; i++)
309538fd1498Szrj hi = ((hi * 613) + (unsigned) (p[i]));
309638fd1498Szrj
309738fd1498Szrj return hi;
309838fd1498Szrj }
309938fd1498Szrj
310038fd1498Szrj /* Wrapper of compare_constant, for the htab interface. */
310138fd1498Szrj bool
equal(constant_descriptor_tree * c1,constant_descriptor_tree * c2)310238fd1498Szrj tree_descriptor_hasher::equal (constant_descriptor_tree *c1,
310338fd1498Szrj constant_descriptor_tree *c2)
310438fd1498Szrj {
310538fd1498Szrj if (c1->hash != c2->hash)
310638fd1498Szrj return 0;
310738fd1498Szrj return compare_constant (c1->value, c2->value);
310838fd1498Szrj }
310938fd1498Szrj
311038fd1498Szrj /* Compare t1 and t2, and return 1 only if they are known to result in
311138fd1498Szrj the same bit pattern on output. */
311238fd1498Szrj
311338fd1498Szrj static int
compare_constant(const tree t1,const tree t2)311438fd1498Szrj compare_constant (const tree t1, const tree t2)
311538fd1498Szrj {
311638fd1498Szrj enum tree_code typecode;
311738fd1498Szrj
311838fd1498Szrj if (t1 == NULL_TREE)
311938fd1498Szrj return t2 == NULL_TREE;
312038fd1498Szrj if (t2 == NULL_TREE)
312138fd1498Szrj return 0;
312238fd1498Szrj
312338fd1498Szrj if (TREE_CODE (t1) != TREE_CODE (t2))
312438fd1498Szrj return 0;
312538fd1498Szrj
312638fd1498Szrj switch (TREE_CODE (t1))
312738fd1498Szrj {
312838fd1498Szrj case INTEGER_CST:
312938fd1498Szrj /* Integer constants are the same only if the same width of type. */
313038fd1498Szrj if (TYPE_PRECISION (TREE_TYPE (t1)) != TYPE_PRECISION (TREE_TYPE (t2)))
313138fd1498Szrj return 0;
313238fd1498Szrj if (TYPE_MODE (TREE_TYPE (t1)) != TYPE_MODE (TREE_TYPE (t2)))
313338fd1498Szrj return 0;
313438fd1498Szrj return tree_int_cst_equal (t1, t2);
313538fd1498Szrj
313638fd1498Szrj case REAL_CST:
313738fd1498Szrj /* Real constants are the same only if the same width of type. In
313838fd1498Szrj addition to the same width, we need to check whether the modes are the
313938fd1498Szrj same. There might be two floating point modes that are the same size
314038fd1498Szrj but have different representations, such as the PowerPC that has 2
314138fd1498Szrj different 128-bit floating point types (IBM extended double and IEEE
314238fd1498Szrj 128-bit floating point). */
314338fd1498Szrj if (TYPE_PRECISION (TREE_TYPE (t1)) != TYPE_PRECISION (TREE_TYPE (t2)))
314438fd1498Szrj return 0;
314538fd1498Szrj if (TYPE_MODE (TREE_TYPE (t1)) != TYPE_MODE (TREE_TYPE (t2)))
314638fd1498Szrj return 0;
314738fd1498Szrj return real_identical (&TREE_REAL_CST (t1), &TREE_REAL_CST (t2));
314838fd1498Szrj
314938fd1498Szrj case FIXED_CST:
315038fd1498Szrj /* Fixed constants are the same only if the same width of type. */
315138fd1498Szrj if (TYPE_PRECISION (TREE_TYPE (t1)) != TYPE_PRECISION (TREE_TYPE (t2)))
315238fd1498Szrj return 0;
315338fd1498Szrj
315438fd1498Szrj return FIXED_VALUES_IDENTICAL (TREE_FIXED_CST (t1), TREE_FIXED_CST (t2));
315538fd1498Szrj
315638fd1498Szrj case STRING_CST:
315738fd1498Szrj if (TYPE_MODE (TREE_TYPE (t1)) != TYPE_MODE (TREE_TYPE (t2)))
315838fd1498Szrj return 0;
315938fd1498Szrj
316038fd1498Szrj return (TREE_STRING_LENGTH (t1) == TREE_STRING_LENGTH (t2)
316138fd1498Szrj && ! memcmp (TREE_STRING_POINTER (t1), TREE_STRING_POINTER (t2),
316238fd1498Szrj TREE_STRING_LENGTH (t1)));
316338fd1498Szrj
316438fd1498Szrj case COMPLEX_CST:
316538fd1498Szrj return (compare_constant (TREE_REALPART (t1), TREE_REALPART (t2))
316638fd1498Szrj && compare_constant (TREE_IMAGPART (t1), TREE_IMAGPART (t2)));
316738fd1498Szrj
316838fd1498Szrj case VECTOR_CST:
316938fd1498Szrj {
317038fd1498Szrj if (VECTOR_CST_NPATTERNS (t1)
317138fd1498Szrj != VECTOR_CST_NPATTERNS (t2))
317238fd1498Szrj return 0;
317338fd1498Szrj
317438fd1498Szrj if (VECTOR_CST_NELTS_PER_PATTERN (t1)
317538fd1498Szrj != VECTOR_CST_NELTS_PER_PATTERN (t2))
317638fd1498Szrj return 0;
317738fd1498Szrj
317838fd1498Szrj unsigned int count = vector_cst_encoded_nelts (t1);
317938fd1498Szrj for (unsigned int i = 0; i < count; ++i)
318038fd1498Szrj if (!compare_constant (VECTOR_CST_ENCODED_ELT (t1, i),
318138fd1498Szrj VECTOR_CST_ENCODED_ELT (t2, i)))
318238fd1498Szrj return 0;
318338fd1498Szrj
318438fd1498Szrj return 1;
318538fd1498Szrj }
318638fd1498Szrj
318738fd1498Szrj case CONSTRUCTOR:
318838fd1498Szrj {
318938fd1498Szrj vec<constructor_elt, va_gc> *v1, *v2;
319038fd1498Szrj unsigned HOST_WIDE_INT idx;
319138fd1498Szrj
319238fd1498Szrj typecode = TREE_CODE (TREE_TYPE (t1));
319338fd1498Szrj if (typecode != TREE_CODE (TREE_TYPE (t2)))
319438fd1498Szrj return 0;
319538fd1498Szrj
319638fd1498Szrj if (typecode == ARRAY_TYPE)
319738fd1498Szrj {
319838fd1498Szrj HOST_WIDE_INT size_1 = int_size_in_bytes (TREE_TYPE (t1));
319938fd1498Szrj /* For arrays, check that mode, size and storage order match. */
320038fd1498Szrj if (TYPE_MODE (TREE_TYPE (t1)) != TYPE_MODE (TREE_TYPE (t2))
320138fd1498Szrj || size_1 == -1
320238fd1498Szrj || size_1 != int_size_in_bytes (TREE_TYPE (t2))
320338fd1498Szrj || TYPE_REVERSE_STORAGE_ORDER (TREE_TYPE (t1))
320438fd1498Szrj != TYPE_REVERSE_STORAGE_ORDER (TREE_TYPE (t2)))
320538fd1498Szrj return 0;
320638fd1498Szrj }
320738fd1498Szrj else
320838fd1498Szrj {
320938fd1498Szrj /* For record and union constructors, require exact type
321038fd1498Szrj equality. */
321138fd1498Szrj if (TREE_TYPE (t1) != TREE_TYPE (t2))
321238fd1498Szrj return 0;
321338fd1498Szrj }
321438fd1498Szrj
321538fd1498Szrj v1 = CONSTRUCTOR_ELTS (t1);
321638fd1498Szrj v2 = CONSTRUCTOR_ELTS (t2);
321738fd1498Szrj if (vec_safe_length (v1) != vec_safe_length (v2))
321838fd1498Szrj return 0;
321938fd1498Szrj
322038fd1498Szrj for (idx = 0; idx < vec_safe_length (v1); ++idx)
322138fd1498Szrj {
322238fd1498Szrj constructor_elt *c1 = &(*v1)[idx];
322338fd1498Szrj constructor_elt *c2 = &(*v2)[idx];
322438fd1498Szrj
322538fd1498Szrj /* Check that each value is the same... */
322638fd1498Szrj if (!compare_constant (c1->value, c2->value))
322738fd1498Szrj return 0;
322838fd1498Szrj /* ... and that they apply to the same fields! */
322938fd1498Szrj if (typecode == ARRAY_TYPE)
323038fd1498Szrj {
323138fd1498Szrj if (!compare_constant (c1->index, c2->index))
323238fd1498Szrj return 0;
323338fd1498Szrj }
323438fd1498Szrj else
323538fd1498Szrj {
323638fd1498Szrj if (c1->index != c2->index)
323738fd1498Szrj return 0;
323838fd1498Szrj }
323938fd1498Szrj }
324038fd1498Szrj
324138fd1498Szrj return 1;
324238fd1498Szrj }
324338fd1498Szrj
324438fd1498Szrj case ADDR_EXPR:
324538fd1498Szrj case FDESC_EXPR:
324638fd1498Szrj {
324738fd1498Szrj struct addr_const value1, value2;
324838fd1498Szrj enum rtx_code code;
324938fd1498Szrj int ret;
325038fd1498Szrj
325138fd1498Szrj decode_addr_const (t1, &value1);
325238fd1498Szrj decode_addr_const (t2, &value2);
325338fd1498Szrj
325438fd1498Szrj if (maybe_ne (value1.offset, value2.offset))
325538fd1498Szrj return 0;
325638fd1498Szrj
325738fd1498Szrj code = GET_CODE (value1.base);
325838fd1498Szrj if (code != GET_CODE (value2.base))
325938fd1498Szrj return 0;
326038fd1498Szrj
326138fd1498Szrj switch (code)
326238fd1498Szrj {
326338fd1498Szrj case SYMBOL_REF:
326438fd1498Szrj ret = (strcmp (XSTR (value1.base, 0), XSTR (value2.base, 0)) == 0);
326538fd1498Szrj break;
326638fd1498Szrj
326738fd1498Szrj case LABEL_REF:
326838fd1498Szrj ret = (CODE_LABEL_NUMBER (label_ref_label (value1.base))
326938fd1498Szrj == CODE_LABEL_NUMBER (label_ref_label (value2.base)));
327038fd1498Szrj break;
327138fd1498Szrj
327238fd1498Szrj default:
327338fd1498Szrj gcc_unreachable ();
327438fd1498Szrj }
327538fd1498Szrj return ret;
327638fd1498Szrj }
327738fd1498Szrj
327838fd1498Szrj case PLUS_EXPR:
327938fd1498Szrj case POINTER_PLUS_EXPR:
328038fd1498Szrj case MINUS_EXPR:
328138fd1498Szrj case RANGE_EXPR:
328238fd1498Szrj return (compare_constant (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0))
328338fd1498Szrj && compare_constant (TREE_OPERAND (t1, 1), TREE_OPERAND (t2, 1)));
328438fd1498Szrj
328538fd1498Szrj CASE_CONVERT:
328638fd1498Szrj case VIEW_CONVERT_EXPR:
328738fd1498Szrj return compare_constant (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
328838fd1498Szrj
328938fd1498Szrj default:
329038fd1498Szrj return 0;
329138fd1498Szrj }
329238fd1498Szrj
329338fd1498Szrj gcc_unreachable ();
329438fd1498Szrj }
329538fd1498Szrj
329638fd1498Szrj /* Return the section into which constant EXP should be placed. */
329738fd1498Szrj
329838fd1498Szrj static section *
get_constant_section(tree exp,unsigned int align)329938fd1498Szrj get_constant_section (tree exp, unsigned int align)
330038fd1498Szrj {
330138fd1498Szrj return targetm.asm_out.select_section (exp,
330238fd1498Szrj compute_reloc_for_constant (exp),
330338fd1498Szrj align);
330438fd1498Szrj }
330538fd1498Szrj
330638fd1498Szrj /* Return the size of constant EXP in bytes. */
330738fd1498Szrj
330838fd1498Szrj static HOST_WIDE_INT
get_constant_size(tree exp)330938fd1498Szrj get_constant_size (tree exp)
331038fd1498Szrj {
331138fd1498Szrj HOST_WIDE_INT size;
331238fd1498Szrj
331338fd1498Szrj size = int_size_in_bytes (TREE_TYPE (exp));
331438fd1498Szrj if (TREE_CODE (exp) == STRING_CST)
331538fd1498Szrj size = MAX (TREE_STRING_LENGTH (exp), size);
331638fd1498Szrj return size;
331738fd1498Szrj }
331838fd1498Szrj
331938fd1498Szrj /* Subroutine of output_constant_def:
332038fd1498Szrj No constant equal to EXP is known to have been output.
332138fd1498Szrj Make a constant descriptor to enter EXP in the hash table.
332238fd1498Szrj Assign the label number and construct RTL to refer to the
332338fd1498Szrj constant's location in memory.
332438fd1498Szrj Caller is responsible for updating the hash table. */
332538fd1498Szrj
332638fd1498Szrj static struct constant_descriptor_tree *
build_constant_desc(tree exp)332738fd1498Szrj build_constant_desc (tree exp)
332838fd1498Szrj {
332938fd1498Szrj struct constant_descriptor_tree *desc;
333038fd1498Szrj rtx symbol, rtl;
333138fd1498Szrj char label[256];
333238fd1498Szrj int labelno;
333338fd1498Szrj tree decl;
333438fd1498Szrj
333538fd1498Szrj desc = ggc_alloc<constant_descriptor_tree> ();
333638fd1498Szrj desc->value = exp;
333738fd1498Szrj
333838fd1498Szrj /* Create a string containing the label name, in LABEL. */
333938fd1498Szrj labelno = const_labelno++;
334038fd1498Szrj ASM_GENERATE_INTERNAL_LABEL (label, "LC", labelno);
334138fd1498Szrj
334238fd1498Szrj /* Construct the VAR_DECL associated with the constant. */
334338fd1498Szrj decl = build_decl (UNKNOWN_LOCATION, VAR_DECL, get_identifier (label),
334438fd1498Szrj TREE_TYPE (exp));
334538fd1498Szrj DECL_ARTIFICIAL (decl) = 1;
334638fd1498Szrj DECL_IGNORED_P (decl) = 1;
334738fd1498Szrj TREE_READONLY (decl) = 1;
334838fd1498Szrj TREE_STATIC (decl) = 1;
334938fd1498Szrj TREE_ADDRESSABLE (decl) = 1;
335038fd1498Szrj /* We don't set the RTL yet as this would cause varpool to assume that the
335138fd1498Szrj variable is referenced. Moreover, it would just be dropped in LTO mode.
335238fd1498Szrj Instead we set the flag that will be recognized in make_decl_rtl. */
335338fd1498Szrj DECL_IN_CONSTANT_POOL (decl) = 1;
335438fd1498Szrj DECL_INITIAL (decl) = desc->value;
335538fd1498Szrj /* ??? targetm.constant_alignment hasn't been updated for vector types on
335638fd1498Szrj most architectures so use DATA_ALIGNMENT as well, except for strings. */
335738fd1498Szrj if (TREE_CODE (exp) == STRING_CST)
335838fd1498Szrj SET_DECL_ALIGN (decl, targetm.constant_alignment (exp, DECL_ALIGN (decl)));
335938fd1498Szrj else
336038fd1498Szrj align_variable (decl, 0);
336138fd1498Szrj
336238fd1498Szrj /* Now construct the SYMBOL_REF and the MEM. */
336338fd1498Szrj if (use_object_blocks_p ())
336438fd1498Szrj {
336538fd1498Szrj int align = (TREE_CODE (decl) == CONST_DECL
336638fd1498Szrj || (VAR_P (decl) && DECL_IN_CONSTANT_POOL (decl))
336738fd1498Szrj ? DECL_ALIGN (decl)
336838fd1498Szrj : symtab_node::get (decl)->definition_alignment ());
336938fd1498Szrj section *sect = get_constant_section (exp, align);
337038fd1498Szrj symbol = create_block_symbol (ggc_strdup (label),
337138fd1498Szrj get_block_for_section (sect), -1);
337238fd1498Szrj }
337338fd1498Szrj else
337438fd1498Szrj symbol = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (label));
337538fd1498Szrj SYMBOL_REF_FLAGS (symbol) |= SYMBOL_FLAG_LOCAL;
337638fd1498Szrj SET_SYMBOL_REF_DECL (symbol, decl);
337738fd1498Szrj TREE_CONSTANT_POOL_ADDRESS_P (symbol) = 1;
337838fd1498Szrj
337938fd1498Szrj rtl = gen_const_mem (TYPE_MODE (TREE_TYPE (exp)), symbol);
338038fd1498Szrj set_mem_attributes (rtl, exp, 1);
338138fd1498Szrj set_mem_alias_set (rtl, 0);
338238fd1498Szrj
338338fd1498Szrj /* Putting EXP into the literal pool might have imposed a different
338438fd1498Szrj alignment which should be visible in the RTX as well. */
338538fd1498Szrj set_mem_align (rtl, DECL_ALIGN (decl));
338638fd1498Szrj
338738fd1498Szrj /* We cannot share RTX'es in pool entries.
338838fd1498Szrj Mark this piece of RTL as required for unsharing. */
338938fd1498Szrj RTX_FLAG (rtl, used) = 1;
339038fd1498Szrj
339138fd1498Szrj /* Set flags or add text to the name to record information, such as
339238fd1498Szrj that it is a local symbol. If the name is changed, the macro
339338fd1498Szrj ASM_OUTPUT_LABELREF will have to know how to strip this
339438fd1498Szrj information. This call might invalidate our local variable
339538fd1498Szrj SYMBOL; we can't use it afterward. */
339638fd1498Szrj targetm.encode_section_info (exp, rtl, true);
339738fd1498Szrj
339838fd1498Szrj desc->rtl = rtl;
339938fd1498Szrj
340038fd1498Szrj return desc;
340138fd1498Szrj }
340238fd1498Szrj
340338fd1498Szrj /* Return an rtx representing a reference to constant data in memory
340438fd1498Szrj for the constant expression EXP.
340538fd1498Szrj
340638fd1498Szrj If assembler code for such a constant has already been output,
340738fd1498Szrj return an rtx to refer to it.
340838fd1498Szrj Otherwise, output such a constant in memory
340938fd1498Szrj and generate an rtx for it.
341038fd1498Szrj
341138fd1498Szrj If DEFER is nonzero, this constant can be deferred and output only
341238fd1498Szrj if referenced in the function after all optimizations.
341338fd1498Szrj
341438fd1498Szrj `const_desc_table' records which constants already have label strings. */
341538fd1498Szrj
341638fd1498Szrj rtx
output_constant_def(tree exp,int defer)341738fd1498Szrj output_constant_def (tree exp, int defer)
341838fd1498Szrj {
341938fd1498Szrj struct constant_descriptor_tree *desc;
342038fd1498Szrj struct constant_descriptor_tree key;
342138fd1498Szrj
342238fd1498Szrj /* Look up EXP in the table of constant descriptors. If we didn't find
342338fd1498Szrj it, create a new one. */
342438fd1498Szrj key.value = exp;
342538fd1498Szrj key.hash = const_hash_1 (exp);
342638fd1498Szrj constant_descriptor_tree **loc
342738fd1498Szrj = const_desc_htab->find_slot_with_hash (&key, key.hash, INSERT);
342838fd1498Szrj
342938fd1498Szrj desc = *loc;
343038fd1498Szrj if (desc == 0)
343138fd1498Szrj {
343238fd1498Szrj desc = build_constant_desc (exp);
343338fd1498Szrj desc->hash = key.hash;
343438fd1498Szrj *loc = desc;
343538fd1498Szrj }
343638fd1498Szrj
343738fd1498Szrj maybe_output_constant_def_contents (desc, defer);
343838fd1498Szrj return desc->rtl;
343938fd1498Szrj }
344038fd1498Szrj
344138fd1498Szrj /* Subroutine of output_constant_def: Decide whether or not we need to
344238fd1498Szrj output the constant DESC now, and if so, do it. */
344338fd1498Szrj static void
maybe_output_constant_def_contents(struct constant_descriptor_tree * desc,int defer)344438fd1498Szrj maybe_output_constant_def_contents (struct constant_descriptor_tree *desc,
344538fd1498Szrj int defer)
344638fd1498Szrj {
344738fd1498Szrj rtx symbol = XEXP (desc->rtl, 0);
344838fd1498Szrj tree exp = desc->value;
344938fd1498Szrj
345038fd1498Szrj if (flag_syntax_only)
345138fd1498Szrj return;
345238fd1498Szrj
345338fd1498Szrj if (TREE_ASM_WRITTEN (exp))
345438fd1498Szrj /* Already output; don't do it again. */
345538fd1498Szrj return;
345638fd1498Szrj
345738fd1498Szrj /* We can always defer constants as long as the context allows
345838fd1498Szrj doing so. */
345938fd1498Szrj if (defer)
346038fd1498Szrj {
346138fd1498Szrj /* Increment n_deferred_constants if it exists. It needs to be at
346238fd1498Szrj least as large as the number of constants actually referred to
346338fd1498Szrj by the function. If it's too small we'll stop looking too early
346438fd1498Szrj and fail to emit constants; if it's too large we'll only look
346538fd1498Szrj through the entire function when we could have stopped earlier. */
346638fd1498Szrj if (cfun)
346738fd1498Szrj n_deferred_constants++;
346838fd1498Szrj return;
346938fd1498Szrj }
347038fd1498Szrj
347138fd1498Szrj output_constant_def_contents (symbol);
347238fd1498Szrj }
347338fd1498Szrj
347438fd1498Szrj /* Subroutine of output_constant_def_contents. Output the definition
347538fd1498Szrj of constant EXP, which is pointed to by label LABEL. ALIGN is the
347638fd1498Szrj constant's alignment in bits. */
347738fd1498Szrj
347838fd1498Szrj static void
assemble_constant_contents(tree exp,const char * label,unsigned int align)347938fd1498Szrj assemble_constant_contents (tree exp, const char *label, unsigned int align)
348038fd1498Szrj {
348138fd1498Szrj HOST_WIDE_INT size;
348238fd1498Szrj
348338fd1498Szrj size = get_constant_size (exp);
348438fd1498Szrj
348538fd1498Szrj /* Do any machine/system dependent processing of the constant. */
348638fd1498Szrj targetm.asm_out.declare_constant_name (asm_out_file, label, exp, size);
348738fd1498Szrj
348838fd1498Szrj /* Output the value of EXP. */
348938fd1498Szrj output_constant (exp, size, align, false);
349038fd1498Szrj
349138fd1498Szrj targetm.asm_out.decl_end ();
349238fd1498Szrj }
349338fd1498Szrj
349438fd1498Szrj /* We must output the constant data referred to by SYMBOL; do so. */
349538fd1498Szrj
349638fd1498Szrj static void
output_constant_def_contents(rtx symbol)349738fd1498Szrj output_constant_def_contents (rtx symbol)
349838fd1498Szrj {
349938fd1498Szrj tree decl = SYMBOL_REF_DECL (symbol);
350038fd1498Szrj tree exp = DECL_INITIAL (decl);
350138fd1498Szrj bool asan_protected = false;
350238fd1498Szrj
350338fd1498Szrj /* Make sure any other constants whose addresses appear in EXP
350438fd1498Szrj are assigned label numbers. */
350538fd1498Szrj output_addressed_constants (exp);
350638fd1498Szrj
350738fd1498Szrj /* We are no longer deferring this constant. */
350838fd1498Szrj TREE_ASM_WRITTEN (decl) = TREE_ASM_WRITTEN (exp) = 1;
350938fd1498Szrj
351038fd1498Szrj if ((flag_sanitize & SANITIZE_ADDRESS)
351138fd1498Szrj && TREE_CODE (exp) == STRING_CST
351238fd1498Szrj && asan_protect_global (exp))
351338fd1498Szrj {
351438fd1498Szrj asan_protected = true;
351538fd1498Szrj SET_DECL_ALIGN (decl, MAX (DECL_ALIGN (decl),
351638fd1498Szrj ASAN_RED_ZONE_SIZE * BITS_PER_UNIT));
351738fd1498Szrj }
351838fd1498Szrj
351938fd1498Szrj /* If the constant is part of an object block, make sure that the
352038fd1498Szrj decl has been positioned within its block, but do not write out
352138fd1498Szrj its definition yet. output_object_blocks will do that later. */
352238fd1498Szrj if (SYMBOL_REF_HAS_BLOCK_INFO_P (symbol) && SYMBOL_REF_BLOCK (symbol))
352338fd1498Szrj place_block_symbol (symbol);
352438fd1498Szrj else
352538fd1498Szrj {
352638fd1498Szrj int align = (TREE_CODE (decl) == CONST_DECL
352738fd1498Szrj || (VAR_P (decl) && DECL_IN_CONSTANT_POOL (decl))
352838fd1498Szrj ? DECL_ALIGN (decl)
352938fd1498Szrj : symtab_node::get (decl)->definition_alignment ());
353038fd1498Szrj switch_to_section (get_constant_section (exp, align));
353138fd1498Szrj if (align > BITS_PER_UNIT)
353238fd1498Szrj ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (align / BITS_PER_UNIT));
353338fd1498Szrj assemble_constant_contents (exp, XSTR (symbol, 0), align);
353438fd1498Szrj if (asan_protected)
353538fd1498Szrj {
353638fd1498Szrj HOST_WIDE_INT size = get_constant_size (exp);
353738fd1498Szrj assemble_zeros (asan_red_zone_size (size));
353838fd1498Szrj }
353938fd1498Szrj }
354038fd1498Szrj }
354138fd1498Szrj
354238fd1498Szrj /* Look up EXP in the table of constant descriptors. Return the rtl
354338fd1498Szrj if it has been emitted, else null. */
354438fd1498Szrj
354538fd1498Szrj rtx
lookup_constant_def(tree exp)354638fd1498Szrj lookup_constant_def (tree exp)
354738fd1498Szrj {
354838fd1498Szrj struct constant_descriptor_tree key;
354938fd1498Szrj
355038fd1498Szrj key.value = exp;
355138fd1498Szrj key.hash = const_hash_1 (exp);
355238fd1498Szrj constant_descriptor_tree *desc
355338fd1498Szrj = const_desc_htab->find_with_hash (&key, key.hash);
355438fd1498Szrj
355538fd1498Szrj return (desc ? desc->rtl : NULL_RTX);
355638fd1498Szrj }
355738fd1498Szrj
355838fd1498Szrj /* Return a tree representing a reference to constant data in memory
355938fd1498Szrj for the constant expression EXP.
356038fd1498Szrj
356138fd1498Szrj This is the counterpart of output_constant_def at the Tree level. */
356238fd1498Szrj
356338fd1498Szrj tree
tree_output_constant_def(tree exp)356438fd1498Szrj tree_output_constant_def (tree exp)
356538fd1498Szrj {
356638fd1498Szrj struct constant_descriptor_tree *desc, key;
356738fd1498Szrj tree decl;
356838fd1498Szrj
356938fd1498Szrj /* Look up EXP in the table of constant descriptors. If we didn't find
357038fd1498Szrj it, create a new one. */
357138fd1498Szrj key.value = exp;
357238fd1498Szrj key.hash = const_hash_1 (exp);
357338fd1498Szrj constant_descriptor_tree **loc
357438fd1498Szrj = const_desc_htab->find_slot_with_hash (&key, key.hash, INSERT);
357538fd1498Szrj
357638fd1498Szrj desc = *loc;
357738fd1498Szrj if (desc == 0)
357838fd1498Szrj {
357938fd1498Szrj desc = build_constant_desc (exp);
358038fd1498Szrj desc->hash = key.hash;
358138fd1498Szrj *loc = desc;
358238fd1498Szrj }
358338fd1498Szrj
358438fd1498Szrj decl = SYMBOL_REF_DECL (XEXP (desc->rtl, 0));
358538fd1498Szrj varpool_node::finalize_decl (decl);
358638fd1498Szrj return decl;
358738fd1498Szrj }
358838fd1498Szrj
358938fd1498Szrj struct GTY((chain_next ("%h.next"), for_user)) constant_descriptor_rtx {
359038fd1498Szrj struct constant_descriptor_rtx *next;
359138fd1498Szrj rtx mem;
359238fd1498Szrj rtx sym;
359338fd1498Szrj rtx constant;
359438fd1498Szrj HOST_WIDE_INT offset;
359538fd1498Szrj hashval_t hash;
359638fd1498Szrj fixed_size_mode mode;
359738fd1498Szrj unsigned int align;
359838fd1498Szrj int labelno;
359938fd1498Szrj int mark;
360038fd1498Szrj };
360138fd1498Szrj
360238fd1498Szrj struct const_rtx_desc_hasher : ggc_ptr_hash<constant_descriptor_rtx>
360338fd1498Szrj {
360438fd1498Szrj static hashval_t hash (constant_descriptor_rtx *);
360538fd1498Szrj static bool equal (constant_descriptor_rtx *, constant_descriptor_rtx *);
360638fd1498Szrj };
360738fd1498Szrj
360838fd1498Szrj /* Used in the hash tables to avoid outputting the same constant
360938fd1498Szrj twice. Unlike 'struct constant_descriptor_tree', RTX constants
361038fd1498Szrj are output once per function, not once per file. */
361138fd1498Szrj /* ??? Only a few targets need per-function constant pools. Most
361238fd1498Szrj can use one per-file pool. Should add a targetm bit to tell the
361338fd1498Szrj difference. */
361438fd1498Szrj
361538fd1498Szrj struct GTY(()) rtx_constant_pool {
361638fd1498Szrj /* Pointers to first and last constant in pool, as ordered by offset. */
361738fd1498Szrj struct constant_descriptor_rtx *first;
361838fd1498Szrj struct constant_descriptor_rtx *last;
361938fd1498Szrj
362038fd1498Szrj /* Hash facility for making memory-constants from constant rtl-expressions.
362138fd1498Szrj It is used on RISC machines where immediate integer arguments and
362238fd1498Szrj constant addresses are restricted so that such constants must be stored
362338fd1498Szrj in memory. */
362438fd1498Szrj hash_table<const_rtx_desc_hasher> *const_rtx_htab;
362538fd1498Szrj
362638fd1498Szrj /* Current offset in constant pool (does not include any
362738fd1498Szrj machine-specific header). */
362838fd1498Szrj HOST_WIDE_INT offset;
362938fd1498Szrj };
363038fd1498Szrj
363138fd1498Szrj /* Hash and compare functions for const_rtx_htab. */
363238fd1498Szrj
363338fd1498Szrj hashval_t
hash(constant_descriptor_rtx * desc)363438fd1498Szrj const_rtx_desc_hasher::hash (constant_descriptor_rtx *desc)
363538fd1498Szrj {
363638fd1498Szrj return desc->hash;
363738fd1498Szrj }
363838fd1498Szrj
363938fd1498Szrj bool
equal(constant_descriptor_rtx * x,constant_descriptor_rtx * y)364038fd1498Szrj const_rtx_desc_hasher::equal (constant_descriptor_rtx *x,
364138fd1498Szrj constant_descriptor_rtx *y)
364238fd1498Szrj {
364338fd1498Szrj if (x->mode != y->mode)
364438fd1498Szrj return 0;
364538fd1498Szrj return rtx_equal_p (x->constant, y->constant);
364638fd1498Szrj }
364738fd1498Szrj
364838fd1498Szrj /* Hash one component of a constant. */
364938fd1498Szrj
365038fd1498Szrj static hashval_t
const_rtx_hash_1(const_rtx x)365138fd1498Szrj const_rtx_hash_1 (const_rtx x)
365238fd1498Szrj {
365338fd1498Szrj unsigned HOST_WIDE_INT hwi;
365438fd1498Szrj machine_mode mode;
365538fd1498Szrj enum rtx_code code;
365638fd1498Szrj hashval_t h;
365738fd1498Szrj int i;
365838fd1498Szrj
365938fd1498Szrj code = GET_CODE (x);
366038fd1498Szrj mode = GET_MODE (x);
366138fd1498Szrj h = (hashval_t) code * 1048573 + mode;
366238fd1498Szrj
366338fd1498Szrj switch (code)
366438fd1498Szrj {
366538fd1498Szrj case CONST_INT:
366638fd1498Szrj hwi = INTVAL (x);
366738fd1498Szrj
366838fd1498Szrj fold_hwi:
366938fd1498Szrj {
367038fd1498Szrj int shift = sizeof (hashval_t) * CHAR_BIT;
367138fd1498Szrj const int n = sizeof (HOST_WIDE_INT) / sizeof (hashval_t);
367238fd1498Szrj
367338fd1498Szrj h ^= (hashval_t) hwi;
367438fd1498Szrj for (i = 1; i < n; ++i)
367538fd1498Szrj {
367638fd1498Szrj hwi >>= shift;
367738fd1498Szrj h ^= (hashval_t) hwi;
367838fd1498Szrj }
367938fd1498Szrj }
368038fd1498Szrj break;
368138fd1498Szrj
368238fd1498Szrj case CONST_WIDE_INT:
368338fd1498Szrj hwi = 0;
368438fd1498Szrj {
368538fd1498Szrj for (i = 0; i < CONST_WIDE_INT_NUNITS (x); i++)
368638fd1498Szrj hwi ^= CONST_WIDE_INT_ELT (x, i);
368738fd1498Szrj goto fold_hwi;
368838fd1498Szrj }
368938fd1498Szrj
369038fd1498Szrj case CONST_DOUBLE:
369138fd1498Szrj if (TARGET_SUPPORTS_WIDE_INT == 0 && mode == VOIDmode)
369238fd1498Szrj {
369338fd1498Szrj hwi = CONST_DOUBLE_LOW (x) ^ CONST_DOUBLE_HIGH (x);
369438fd1498Szrj goto fold_hwi;
369538fd1498Szrj }
369638fd1498Szrj else
369738fd1498Szrj h ^= real_hash (CONST_DOUBLE_REAL_VALUE (x));
369838fd1498Szrj break;
369938fd1498Szrj
370038fd1498Szrj case CONST_FIXED:
370138fd1498Szrj h ^= fixed_hash (CONST_FIXED_VALUE (x));
370238fd1498Szrj break;
370338fd1498Szrj
370438fd1498Szrj case SYMBOL_REF:
370538fd1498Szrj h ^= htab_hash_string (XSTR (x, 0));
370638fd1498Szrj break;
370738fd1498Szrj
370838fd1498Szrj case LABEL_REF:
370938fd1498Szrj h = h * 251 + CODE_LABEL_NUMBER (label_ref_label (x));
371038fd1498Szrj break;
371138fd1498Szrj
371238fd1498Szrj case UNSPEC:
371338fd1498Szrj case UNSPEC_VOLATILE:
371438fd1498Szrj h = h * 251 + XINT (x, 1);
371538fd1498Szrj break;
371638fd1498Szrj
371738fd1498Szrj default:
371838fd1498Szrj break;
371938fd1498Szrj }
372038fd1498Szrj
372138fd1498Szrj return h;
372238fd1498Szrj }
372338fd1498Szrj
372438fd1498Szrj /* Compute a hash value for X, which should be a constant. */
372538fd1498Szrj
372638fd1498Szrj static hashval_t
const_rtx_hash(rtx x)372738fd1498Szrj const_rtx_hash (rtx x)
372838fd1498Szrj {
372938fd1498Szrj hashval_t h = 0;
373038fd1498Szrj subrtx_iterator::array_type array;
373138fd1498Szrj FOR_EACH_SUBRTX (iter, array, x, ALL)
373238fd1498Szrj h = h * 509 + const_rtx_hash_1 (*iter);
373338fd1498Szrj return h;
373438fd1498Szrj }
373538fd1498Szrj
373638fd1498Szrj
373738fd1498Szrj /* Create and return a new rtx constant pool. */
373838fd1498Szrj
373938fd1498Szrj static struct rtx_constant_pool *
create_constant_pool(void)374038fd1498Szrj create_constant_pool (void)
374138fd1498Szrj {
374238fd1498Szrj struct rtx_constant_pool *pool;
374338fd1498Szrj
374438fd1498Szrj pool = ggc_alloc<rtx_constant_pool> ();
374538fd1498Szrj pool->const_rtx_htab = hash_table<const_rtx_desc_hasher>::create_ggc (31);
374638fd1498Szrj pool->first = NULL;
374738fd1498Szrj pool->last = NULL;
374838fd1498Szrj pool->offset = 0;
374938fd1498Szrj return pool;
375038fd1498Szrj }
375138fd1498Szrj
375238fd1498Szrj /* Initialize constant pool hashing for a new function. */
375338fd1498Szrj
375438fd1498Szrj void
init_varasm_status(void)375538fd1498Szrj init_varasm_status (void)
375638fd1498Szrj {
375738fd1498Szrj crtl->varasm.pool = create_constant_pool ();
375838fd1498Szrj crtl->varasm.deferred_constants = 0;
375938fd1498Szrj }
376038fd1498Szrj
376138fd1498Szrj /* Given a MINUS expression, simplify it if both sides
376238fd1498Szrj include the same symbol. */
376338fd1498Szrj
376438fd1498Szrj rtx
simplify_subtraction(rtx x)376538fd1498Szrj simplify_subtraction (rtx x)
376638fd1498Szrj {
376738fd1498Szrj rtx r = simplify_rtx (x);
376838fd1498Szrj return r ? r : x;
376938fd1498Szrj }
377038fd1498Szrj
377138fd1498Szrj /* Given a constant rtx X, make (or find) a memory constant for its value
377238fd1498Szrj and return a MEM rtx to refer to it in memory. IN_MODE is the mode
377338fd1498Szrj of X. */
377438fd1498Szrj
377538fd1498Szrj rtx
force_const_mem(machine_mode in_mode,rtx x)377638fd1498Szrj force_const_mem (machine_mode in_mode, rtx x)
377738fd1498Szrj {
377838fd1498Szrj struct constant_descriptor_rtx *desc, tmp;
377938fd1498Szrj struct rtx_constant_pool *pool;
378038fd1498Szrj char label[256];
378138fd1498Szrj rtx def, symbol;
378238fd1498Szrj hashval_t hash;
378338fd1498Szrj unsigned int align;
378438fd1498Szrj constant_descriptor_rtx **slot;
378538fd1498Szrj fixed_size_mode mode;
378638fd1498Szrj
378738fd1498Szrj /* We can't force variable-sized objects to memory. */
378838fd1498Szrj if (!is_a <fixed_size_mode> (in_mode, &mode))
378938fd1498Szrj return NULL_RTX;
379038fd1498Szrj
379138fd1498Szrj /* If we're not allowed to drop X into the constant pool, don't. */
379238fd1498Szrj if (targetm.cannot_force_const_mem (mode, x))
379338fd1498Szrj return NULL_RTX;
379438fd1498Szrj
379538fd1498Szrj /* Record that this function has used a constant pool entry. */
379638fd1498Szrj crtl->uses_const_pool = 1;
379738fd1498Szrj
379838fd1498Szrj /* Decide which pool to use. */
379938fd1498Szrj pool = (targetm.use_blocks_for_constant_p (mode, x)
380038fd1498Szrj ? shared_constant_pool
380138fd1498Szrj : crtl->varasm.pool);
380238fd1498Szrj
380338fd1498Szrj /* Lookup the value in the hashtable. */
380438fd1498Szrj tmp.constant = x;
380538fd1498Szrj tmp.mode = mode;
380638fd1498Szrj hash = const_rtx_hash (x);
380738fd1498Szrj slot = pool->const_rtx_htab->find_slot_with_hash (&tmp, hash, INSERT);
380838fd1498Szrj desc = *slot;
380938fd1498Szrj
381038fd1498Szrj /* If the constant was already present, return its memory. */
381138fd1498Szrj if (desc)
381238fd1498Szrj return copy_rtx (desc->mem);
381338fd1498Szrj
381438fd1498Szrj /* Otherwise, create a new descriptor. */
381538fd1498Szrj desc = ggc_alloc<constant_descriptor_rtx> ();
381638fd1498Szrj *slot = desc;
381738fd1498Szrj
381838fd1498Szrj /* Align the location counter as required by EXP's data type. */
381938fd1498Szrj machine_mode align_mode = (mode == VOIDmode ? word_mode : mode);
382038fd1498Szrj align = targetm.static_rtx_alignment (align_mode);
382138fd1498Szrj
382238fd1498Szrj pool->offset += (align / BITS_PER_UNIT) - 1;
382338fd1498Szrj pool->offset &= ~ ((align / BITS_PER_UNIT) - 1);
382438fd1498Szrj
382538fd1498Szrj desc->next = NULL;
382638fd1498Szrj desc->constant = copy_rtx (tmp.constant);
382738fd1498Szrj desc->offset = pool->offset;
382838fd1498Szrj desc->hash = hash;
382938fd1498Szrj desc->mode = mode;
383038fd1498Szrj desc->align = align;
383138fd1498Szrj desc->labelno = const_labelno;
383238fd1498Szrj desc->mark = 0;
383338fd1498Szrj
383438fd1498Szrj pool->offset += GET_MODE_SIZE (mode);
383538fd1498Szrj if (pool->last)
383638fd1498Szrj pool->last->next = desc;
383738fd1498Szrj else
383838fd1498Szrj pool->first = pool->last = desc;
383938fd1498Szrj pool->last = desc;
384038fd1498Szrj
384138fd1498Szrj /* Create a string containing the label name, in LABEL. */
384238fd1498Szrj ASM_GENERATE_INTERNAL_LABEL (label, "LC", const_labelno);
384338fd1498Szrj ++const_labelno;
384438fd1498Szrj
384538fd1498Szrj /* Construct the SYMBOL_REF. Make sure to mark it as belonging to
384638fd1498Szrj the constants pool. */
384738fd1498Szrj if (use_object_blocks_p () && targetm.use_blocks_for_constant_p (mode, x))
384838fd1498Szrj {
384938fd1498Szrj section *sect = targetm.asm_out.select_rtx_section (mode, x, align);
385038fd1498Szrj symbol = create_block_symbol (ggc_strdup (label),
385138fd1498Szrj get_block_for_section (sect), -1);
385238fd1498Szrj }
385338fd1498Szrj else
385438fd1498Szrj symbol = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (label));
385538fd1498Szrj desc->sym = symbol;
385638fd1498Szrj SYMBOL_REF_FLAGS (symbol) |= SYMBOL_FLAG_LOCAL;
385738fd1498Szrj CONSTANT_POOL_ADDRESS_P (symbol) = 1;
385838fd1498Szrj SET_SYMBOL_REF_CONSTANT (symbol, desc);
385938fd1498Szrj
386038fd1498Szrj /* Construct the MEM. */
386138fd1498Szrj desc->mem = def = gen_const_mem (mode, symbol);
386238fd1498Szrj set_mem_align (def, align);
386338fd1498Szrj
386438fd1498Szrj /* If we're dropping a label to the constant pool, make sure we
386538fd1498Szrj don't delete it. */
386638fd1498Szrj if (GET_CODE (x) == LABEL_REF)
386738fd1498Szrj LABEL_PRESERVE_P (XEXP (x, 0)) = 1;
386838fd1498Szrj
386938fd1498Szrj return copy_rtx (def);
387038fd1498Szrj }
387138fd1498Szrj
387238fd1498Szrj /* Given a constant pool SYMBOL_REF, return the corresponding constant. */
387338fd1498Szrj
387438fd1498Szrj rtx
get_pool_constant(const_rtx addr)387538fd1498Szrj get_pool_constant (const_rtx addr)
387638fd1498Szrj {
387738fd1498Szrj return SYMBOL_REF_CONSTANT (addr)->constant;
387838fd1498Szrj }
387938fd1498Szrj
388038fd1498Szrj /* Given a constant pool SYMBOL_REF, return the corresponding constant
388138fd1498Szrj and whether it has been output or not. */
388238fd1498Szrj
388338fd1498Szrj rtx
get_pool_constant_mark(rtx addr,bool * pmarked)388438fd1498Szrj get_pool_constant_mark (rtx addr, bool *pmarked)
388538fd1498Szrj {
388638fd1498Szrj struct constant_descriptor_rtx *desc;
388738fd1498Szrj
388838fd1498Szrj desc = SYMBOL_REF_CONSTANT (addr);
388938fd1498Szrj *pmarked = (desc->mark != 0);
389038fd1498Szrj return desc->constant;
389138fd1498Szrj }
389238fd1498Szrj
389338fd1498Szrj /* Similar, return the mode. */
389438fd1498Szrj
389538fd1498Szrj fixed_size_mode
get_pool_mode(const_rtx addr)389638fd1498Szrj get_pool_mode (const_rtx addr)
389738fd1498Szrj {
389838fd1498Szrj return SYMBOL_REF_CONSTANT (addr)->mode;
389938fd1498Szrj }
390038fd1498Szrj
390138fd1498Szrj /* Return TRUE if and only if the constant pool has no entries. Note
390238fd1498Szrj that even entries we might end up choosing not to emit are counted
390338fd1498Szrj here, so there is the potential for missed optimizations. */
390438fd1498Szrj
390538fd1498Szrj bool
constant_pool_empty_p(void)390638fd1498Szrj constant_pool_empty_p (void)
390738fd1498Szrj {
390838fd1498Szrj return crtl->varasm.pool->first == NULL;
390938fd1498Szrj }
391038fd1498Szrj
391138fd1498Szrj /* Worker function for output_constant_pool_1. Emit assembly for X
391238fd1498Szrj in MODE with known alignment ALIGN. */
391338fd1498Szrj
391438fd1498Szrj static void
output_constant_pool_2(fixed_size_mode mode,rtx x,unsigned int align)391538fd1498Szrj output_constant_pool_2 (fixed_size_mode mode, rtx x, unsigned int align)
391638fd1498Szrj {
391738fd1498Szrj switch (GET_MODE_CLASS (mode))
391838fd1498Szrj {
391938fd1498Szrj case MODE_FLOAT:
392038fd1498Szrj case MODE_DECIMAL_FLOAT:
392138fd1498Szrj {
392238fd1498Szrj gcc_assert (CONST_DOUBLE_AS_FLOAT_P (x));
392338fd1498Szrj assemble_real (*CONST_DOUBLE_REAL_VALUE (x),
392438fd1498Szrj as_a <scalar_float_mode> (mode), align, false);
392538fd1498Szrj break;
392638fd1498Szrj }
392738fd1498Szrj
392838fd1498Szrj case MODE_INT:
392938fd1498Szrj case MODE_PARTIAL_INT:
393038fd1498Szrj case MODE_FRACT:
393138fd1498Szrj case MODE_UFRACT:
393238fd1498Szrj case MODE_ACCUM:
393338fd1498Szrj case MODE_UACCUM:
393438fd1498Szrj case MODE_POINTER_BOUNDS:
393538fd1498Szrj assemble_integer (x, GET_MODE_SIZE (mode), align, 1);
393638fd1498Szrj break;
393738fd1498Szrj
393838fd1498Szrj case MODE_VECTOR_BOOL:
393938fd1498Szrj {
394038fd1498Szrj gcc_assert (GET_CODE (x) == CONST_VECTOR);
394138fd1498Szrj
394238fd1498Szrj /* Pick the smallest integer mode that contains at least one
394338fd1498Szrj whole element. Often this is byte_mode and contains more
394438fd1498Szrj than one element. */
394538fd1498Szrj unsigned int nelts = GET_MODE_NUNITS (mode);
394638fd1498Szrj unsigned int elt_bits = GET_MODE_BITSIZE (mode) / nelts;
394738fd1498Szrj unsigned int int_bits = MAX (elt_bits, BITS_PER_UNIT);
394838fd1498Szrj scalar_int_mode int_mode = int_mode_for_size (int_bits, 0).require ();
394938fd1498Szrj
395038fd1498Szrj /* Build the constant up one integer at a time. */
395138fd1498Szrj unsigned int elts_per_int = int_bits / elt_bits;
395238fd1498Szrj for (unsigned int i = 0; i < nelts; i += elts_per_int)
395338fd1498Szrj {
395438fd1498Szrj unsigned HOST_WIDE_INT value = 0;
395538fd1498Szrj unsigned int limit = MIN (nelts - i, elts_per_int);
395638fd1498Szrj for (unsigned int j = 0; j < limit; ++j)
395738fd1498Szrj if (INTVAL (CONST_VECTOR_ELT (x, i + j)) != 0)
395838fd1498Szrj value |= 1 << (j * elt_bits);
395938fd1498Szrj output_constant_pool_2 (int_mode, gen_int_mode (value, int_mode),
396038fd1498Szrj i != 0 ? MIN (align, int_bits) : align);
396138fd1498Szrj }
396238fd1498Szrj break;
396338fd1498Szrj }
396438fd1498Szrj case MODE_VECTOR_FLOAT:
396538fd1498Szrj case MODE_VECTOR_INT:
396638fd1498Szrj case MODE_VECTOR_FRACT:
396738fd1498Szrj case MODE_VECTOR_UFRACT:
396838fd1498Szrj case MODE_VECTOR_ACCUM:
396938fd1498Szrj case MODE_VECTOR_UACCUM:
397038fd1498Szrj {
397138fd1498Szrj int i, units;
397238fd1498Szrj scalar_mode submode = GET_MODE_INNER (mode);
397338fd1498Szrj unsigned int subalign = MIN (align, GET_MODE_BITSIZE (submode));
397438fd1498Szrj
397538fd1498Szrj gcc_assert (GET_CODE (x) == CONST_VECTOR);
397638fd1498Szrj units = GET_MODE_NUNITS (mode);
397738fd1498Szrj
397838fd1498Szrj for (i = 0; i < units; i++)
397938fd1498Szrj {
398038fd1498Szrj rtx elt = CONST_VECTOR_ELT (x, i);
398138fd1498Szrj output_constant_pool_2 (submode, elt, i ? subalign : align);
398238fd1498Szrj }
398338fd1498Szrj }
398438fd1498Szrj break;
398538fd1498Szrj
398638fd1498Szrj default:
398738fd1498Szrj gcc_unreachable ();
398838fd1498Szrj }
398938fd1498Szrj }
399038fd1498Szrj
399138fd1498Szrj /* Worker function for output_constant_pool. Emit constant DESC,
399238fd1498Szrj giving it ALIGN bits of alignment. */
399338fd1498Szrj
399438fd1498Szrj static void
output_constant_pool_1(struct constant_descriptor_rtx * desc,unsigned int align)399538fd1498Szrj output_constant_pool_1 (struct constant_descriptor_rtx *desc,
399638fd1498Szrj unsigned int align)
399738fd1498Szrj {
399838fd1498Szrj rtx x, tmp;
399938fd1498Szrj
400038fd1498Szrj x = desc->constant;
400138fd1498Szrj
400238fd1498Szrj /* See if X is a LABEL_REF (or a CONST referring to a LABEL_REF)
400338fd1498Szrj whose CODE_LABEL has been deleted. This can occur if a jump table
400438fd1498Szrj is eliminated by optimization. If so, write a constant of zero
400538fd1498Szrj instead. Note that this can also happen by turning the
400638fd1498Szrj CODE_LABEL into a NOTE. */
400738fd1498Szrj /* ??? This seems completely and utterly wrong. Certainly it's
400838fd1498Szrj not true for NOTE_INSN_DELETED_LABEL, but I disbelieve proper
400938fd1498Szrj functioning even with rtx_insn::deleted and friends. */
401038fd1498Szrj
401138fd1498Szrj tmp = x;
401238fd1498Szrj switch (GET_CODE (tmp))
401338fd1498Szrj {
401438fd1498Szrj case CONST:
401538fd1498Szrj if (GET_CODE (XEXP (tmp, 0)) != PLUS
401638fd1498Szrj || GET_CODE (XEXP (XEXP (tmp, 0), 0)) != LABEL_REF)
401738fd1498Szrj break;
401838fd1498Szrj tmp = XEXP (XEXP (tmp, 0), 0);
401938fd1498Szrj /* FALLTHRU */
402038fd1498Szrj
402138fd1498Szrj case LABEL_REF:
402238fd1498Szrj {
402338fd1498Szrj rtx_insn *insn = label_ref_label (tmp);
402438fd1498Szrj gcc_assert (!insn->deleted ());
402538fd1498Szrj gcc_assert (!NOTE_P (insn)
402638fd1498Szrj || NOTE_KIND (insn) != NOTE_INSN_DELETED);
402738fd1498Szrj break;
402838fd1498Szrj }
402938fd1498Szrj
403038fd1498Szrj default:
403138fd1498Szrj break;
403238fd1498Szrj }
403338fd1498Szrj
403438fd1498Szrj #ifdef ASM_OUTPUT_SPECIAL_POOL_ENTRY
403538fd1498Szrj ASM_OUTPUT_SPECIAL_POOL_ENTRY (asm_out_file, x, desc->mode,
403638fd1498Szrj align, desc->labelno, done);
403738fd1498Szrj #endif
403838fd1498Szrj
403938fd1498Szrj assemble_align (align);
404038fd1498Szrj
404138fd1498Szrj /* Output the label. */
404238fd1498Szrj targetm.asm_out.internal_label (asm_out_file, "LC", desc->labelno);
404338fd1498Szrj
404438fd1498Szrj /* Output the data.
404538fd1498Szrj Pass actual alignment value while emitting string constant to asm code
404638fd1498Szrj as function 'output_constant_pool_1' explicitly passes the alignment as 1
404738fd1498Szrj assuming that the data is already aligned which prevents the generation
404838fd1498Szrj of fix-up table entries. */
404938fd1498Szrj output_constant_pool_2 (desc->mode, x, desc->align);
405038fd1498Szrj
405138fd1498Szrj /* Make sure all constants in SECTION_MERGE and not SECTION_STRINGS
405238fd1498Szrj sections have proper size. */
405338fd1498Szrj if (align > GET_MODE_BITSIZE (desc->mode)
405438fd1498Szrj && in_section
405538fd1498Szrj && (in_section->common.flags & SECTION_MERGE))
405638fd1498Szrj assemble_align (align);
405738fd1498Szrj
405838fd1498Szrj #ifdef ASM_OUTPUT_SPECIAL_POOL_ENTRY
405938fd1498Szrj done:
406038fd1498Szrj #endif
406138fd1498Szrj return;
406238fd1498Szrj }
406338fd1498Szrj
406438fd1498Szrj /* Recompute the offsets of entries in POOL, and the overall size of
406538fd1498Szrj POOL. Do this after calling mark_constant_pool to ensure that we
406638fd1498Szrj are computing the offset values for the pool which we will actually
406738fd1498Szrj emit. */
406838fd1498Szrj
406938fd1498Szrj static void
recompute_pool_offsets(struct rtx_constant_pool * pool)407038fd1498Szrj recompute_pool_offsets (struct rtx_constant_pool *pool)
407138fd1498Szrj {
407238fd1498Szrj struct constant_descriptor_rtx *desc;
407338fd1498Szrj pool->offset = 0;
407438fd1498Szrj
407538fd1498Szrj for (desc = pool->first; desc ; desc = desc->next)
407638fd1498Szrj if (desc->mark)
407738fd1498Szrj {
407838fd1498Szrj /* Recalculate offset. */
407938fd1498Szrj unsigned int align = desc->align;
408038fd1498Szrj pool->offset += (align / BITS_PER_UNIT) - 1;
408138fd1498Szrj pool->offset &= ~ ((align / BITS_PER_UNIT) - 1);
408238fd1498Szrj desc->offset = pool->offset;
408338fd1498Szrj pool->offset += GET_MODE_SIZE (desc->mode);
408438fd1498Szrj }
408538fd1498Szrj }
408638fd1498Szrj
408738fd1498Szrj /* Mark all constants that are referenced by SYMBOL_REFs in X.
408838fd1498Szrj Emit referenced deferred strings. */
408938fd1498Szrj
409038fd1498Szrj static void
mark_constants_in_pattern(rtx insn)409138fd1498Szrj mark_constants_in_pattern (rtx insn)
409238fd1498Szrj {
409338fd1498Szrj subrtx_iterator::array_type array;
409438fd1498Szrj FOR_EACH_SUBRTX (iter, array, PATTERN (insn), ALL)
409538fd1498Szrj {
409638fd1498Szrj const_rtx x = *iter;
409738fd1498Szrj if (GET_CODE (x) == SYMBOL_REF)
409838fd1498Szrj {
409938fd1498Szrj if (CONSTANT_POOL_ADDRESS_P (x))
410038fd1498Szrj {
410138fd1498Szrj struct constant_descriptor_rtx *desc = SYMBOL_REF_CONSTANT (x);
410238fd1498Szrj if (desc->mark == 0)
410338fd1498Szrj {
410438fd1498Szrj desc->mark = 1;
410538fd1498Szrj iter.substitute (desc->constant);
410638fd1498Szrj }
410738fd1498Szrj }
410838fd1498Szrj else if (TREE_CONSTANT_POOL_ADDRESS_P (x))
410938fd1498Szrj {
411038fd1498Szrj tree decl = SYMBOL_REF_DECL (x);
411138fd1498Szrj if (!TREE_ASM_WRITTEN (DECL_INITIAL (decl)))
411238fd1498Szrj {
411338fd1498Szrj n_deferred_constants--;
411438fd1498Szrj output_constant_def_contents (CONST_CAST_RTX (x));
411538fd1498Szrj }
411638fd1498Szrj }
411738fd1498Szrj }
411838fd1498Szrj }
411938fd1498Szrj }
412038fd1498Szrj
412138fd1498Szrj /* Look through appropriate parts of INSN, marking all entries in the
412238fd1498Szrj constant pool which are actually being used. Entries that are only
412338fd1498Szrj referenced by other constants are also marked as used. Emit
412438fd1498Szrj deferred strings that are used. */
412538fd1498Szrj
412638fd1498Szrj static void
mark_constants(rtx_insn * insn)412738fd1498Szrj mark_constants (rtx_insn *insn)
412838fd1498Szrj {
412938fd1498Szrj if (!INSN_P (insn))
413038fd1498Szrj return;
413138fd1498Szrj
413238fd1498Szrj /* Insns may appear inside a SEQUENCE. Only check the patterns of
413338fd1498Szrj insns, not any notes that may be attached. We don't want to mark
413438fd1498Szrj a constant just because it happens to appear in a REG_EQUIV note. */
413538fd1498Szrj if (rtx_sequence *seq = dyn_cast <rtx_sequence *> (PATTERN (insn)))
413638fd1498Szrj {
413738fd1498Szrj int i, n = seq->len ();
413838fd1498Szrj for (i = 0; i < n; ++i)
413938fd1498Szrj {
414038fd1498Szrj rtx subinsn = seq->element (i);
414138fd1498Szrj if (INSN_P (subinsn))
414238fd1498Szrj mark_constants_in_pattern (subinsn);
414338fd1498Szrj }
414438fd1498Szrj }
414538fd1498Szrj else
414638fd1498Szrj mark_constants_in_pattern (insn);
414738fd1498Szrj }
414838fd1498Szrj
414938fd1498Szrj /* Look through the instructions for this function, and mark all the
415038fd1498Szrj entries in POOL which are actually being used. Emit deferred constants
415138fd1498Szrj which have indeed been used. */
415238fd1498Szrj
415338fd1498Szrj static void
mark_constant_pool(void)415438fd1498Szrj mark_constant_pool (void)
415538fd1498Szrj {
415638fd1498Szrj rtx_insn *insn;
415738fd1498Szrj
415838fd1498Szrj if (!crtl->uses_const_pool && n_deferred_constants == 0)
415938fd1498Szrj return;
416038fd1498Szrj
416138fd1498Szrj for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
416238fd1498Szrj mark_constants (insn);
416338fd1498Szrj }
416438fd1498Szrj
416538fd1498Szrj /* Write all the constants in POOL. */
416638fd1498Szrj
416738fd1498Szrj static void
output_constant_pool_contents(struct rtx_constant_pool * pool)416838fd1498Szrj output_constant_pool_contents (struct rtx_constant_pool *pool)
416938fd1498Szrj {
417038fd1498Szrj struct constant_descriptor_rtx *desc;
417138fd1498Szrj
417238fd1498Szrj for (desc = pool->first; desc ; desc = desc->next)
417338fd1498Szrj if (desc->mark)
417438fd1498Szrj {
417538fd1498Szrj /* If the constant is part of an object_block, make sure that
417638fd1498Szrj the constant has been positioned within its block, but do not
417738fd1498Szrj write out its definition yet. output_object_blocks will do
417838fd1498Szrj that later. */
417938fd1498Szrj if (SYMBOL_REF_HAS_BLOCK_INFO_P (desc->sym)
418038fd1498Szrj && SYMBOL_REF_BLOCK (desc->sym))
418138fd1498Szrj place_block_symbol (desc->sym);
418238fd1498Szrj else
418338fd1498Szrj {
418438fd1498Szrj switch_to_section (targetm.asm_out.select_rtx_section
418538fd1498Szrj (desc->mode, desc->constant, desc->align));
418638fd1498Szrj output_constant_pool_1 (desc, desc->align);
418738fd1498Szrj }
418838fd1498Szrj }
418938fd1498Szrj }
419038fd1498Szrj
419138fd1498Szrj /* Mark all constants that are used in the current function, then write
419238fd1498Szrj out the function's private constant pool. */
419338fd1498Szrj
419438fd1498Szrj static void
output_constant_pool(const char * fnname ATTRIBUTE_UNUSED,tree fndecl ATTRIBUTE_UNUSED)419538fd1498Szrj output_constant_pool (const char *fnname ATTRIBUTE_UNUSED,
419638fd1498Szrj tree fndecl ATTRIBUTE_UNUSED)
419738fd1498Szrj {
419838fd1498Szrj struct rtx_constant_pool *pool = crtl->varasm.pool;
419938fd1498Szrj
420038fd1498Szrj /* It is possible for gcc to call force_const_mem and then to later
420138fd1498Szrj discard the instructions which refer to the constant. In such a
420238fd1498Szrj case we do not need to output the constant. */
420338fd1498Szrj mark_constant_pool ();
420438fd1498Szrj
420538fd1498Szrj /* Having marked the constant pool entries we'll actually emit, we
420638fd1498Szrj now need to rebuild the offset information, which may have become
420738fd1498Szrj stale. */
420838fd1498Szrj recompute_pool_offsets (pool);
420938fd1498Szrj
421038fd1498Szrj #ifdef ASM_OUTPUT_POOL_PROLOGUE
421138fd1498Szrj ASM_OUTPUT_POOL_PROLOGUE (asm_out_file, fnname, fndecl, pool->offset);
421238fd1498Szrj #endif
421338fd1498Szrj
421438fd1498Szrj output_constant_pool_contents (pool);
421538fd1498Szrj
421638fd1498Szrj #ifdef ASM_OUTPUT_POOL_EPILOGUE
421738fd1498Szrj ASM_OUTPUT_POOL_EPILOGUE (asm_out_file, fnname, fndecl, pool->offset);
421838fd1498Szrj #endif
421938fd1498Szrj }
422038fd1498Szrj
422138fd1498Szrj /* Write the contents of the shared constant pool. */
422238fd1498Szrj
422338fd1498Szrj void
output_shared_constant_pool(void)422438fd1498Szrj output_shared_constant_pool (void)
422538fd1498Szrj {
422638fd1498Szrj output_constant_pool_contents (shared_constant_pool);
422738fd1498Szrj }
422838fd1498Szrj
422938fd1498Szrj /* Determine what kind of relocations EXP may need. */
423038fd1498Szrj
423138fd1498Szrj int
compute_reloc_for_constant(tree exp)423238fd1498Szrj compute_reloc_for_constant (tree exp)
423338fd1498Szrj {
423438fd1498Szrj int reloc = 0, reloc2;
423538fd1498Szrj tree tem;
423638fd1498Szrj
423738fd1498Szrj switch (TREE_CODE (exp))
423838fd1498Szrj {
423938fd1498Szrj case ADDR_EXPR:
424038fd1498Szrj case FDESC_EXPR:
424138fd1498Szrj /* Go inside any operations that get_inner_reference can handle and see
424238fd1498Szrj if what's inside is a constant: no need to do anything here for
424338fd1498Szrj addresses of variables or functions. */
424438fd1498Szrj for (tem = TREE_OPERAND (exp, 0); handled_component_p (tem);
424538fd1498Szrj tem = TREE_OPERAND (tem, 0))
424638fd1498Szrj ;
424738fd1498Szrj
424838fd1498Szrj if (TREE_CODE (tem) == MEM_REF
424938fd1498Szrj && TREE_CODE (TREE_OPERAND (tem, 0)) == ADDR_EXPR)
425038fd1498Szrj {
425138fd1498Szrj reloc = compute_reloc_for_constant (TREE_OPERAND (tem, 0));
425238fd1498Szrj break;
425338fd1498Szrj }
425438fd1498Szrj
425538fd1498Szrj if (!targetm.binds_local_p (tem))
425638fd1498Szrj reloc |= 2;
425738fd1498Szrj else
425838fd1498Szrj reloc |= 1;
425938fd1498Szrj break;
426038fd1498Szrj
426138fd1498Szrj case PLUS_EXPR:
426238fd1498Szrj case POINTER_PLUS_EXPR:
426338fd1498Szrj reloc = compute_reloc_for_constant (TREE_OPERAND (exp, 0));
426438fd1498Szrj reloc |= compute_reloc_for_constant (TREE_OPERAND (exp, 1));
426538fd1498Szrj break;
426638fd1498Szrj
426738fd1498Szrj case MINUS_EXPR:
426838fd1498Szrj reloc = compute_reloc_for_constant (TREE_OPERAND (exp, 0));
426938fd1498Szrj reloc2 = compute_reloc_for_constant (TREE_OPERAND (exp, 1));
427038fd1498Szrj /* The difference of two local labels is computable at link time. */
427138fd1498Szrj if (reloc == 1 && reloc2 == 1)
427238fd1498Szrj reloc = 0;
427338fd1498Szrj else
427438fd1498Szrj reloc |= reloc2;
427538fd1498Szrj break;
427638fd1498Szrj
427738fd1498Szrj CASE_CONVERT:
427838fd1498Szrj case VIEW_CONVERT_EXPR:
427938fd1498Szrj reloc = compute_reloc_for_constant (TREE_OPERAND (exp, 0));
428038fd1498Szrj break;
428138fd1498Szrj
428238fd1498Szrj case CONSTRUCTOR:
428338fd1498Szrj {
428438fd1498Szrj unsigned HOST_WIDE_INT idx;
428538fd1498Szrj FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (exp), idx, tem)
428638fd1498Szrj if (tem != 0)
428738fd1498Szrj reloc |= compute_reloc_for_constant (tem);
428838fd1498Szrj }
428938fd1498Szrj break;
429038fd1498Szrj
429138fd1498Szrj default:
429238fd1498Szrj break;
429338fd1498Szrj }
429438fd1498Szrj return reloc;
429538fd1498Szrj }
429638fd1498Szrj
429738fd1498Szrj /* Find all the constants whose addresses are referenced inside of EXP,
429838fd1498Szrj and make sure assembler code with a label has been output for each one.
429938fd1498Szrj Indicate whether an ADDR_EXPR has been encountered. */
430038fd1498Szrj
430138fd1498Szrj static void
output_addressed_constants(tree exp)430238fd1498Szrj output_addressed_constants (tree exp)
430338fd1498Szrj {
430438fd1498Szrj tree tem;
430538fd1498Szrj
430638fd1498Szrj switch (TREE_CODE (exp))
430738fd1498Szrj {
430838fd1498Szrj case ADDR_EXPR:
430938fd1498Szrj case FDESC_EXPR:
431038fd1498Szrj /* Go inside any operations that get_inner_reference can handle and see
431138fd1498Szrj if what's inside is a constant: no need to do anything here for
431238fd1498Szrj addresses of variables or functions. */
431338fd1498Szrj for (tem = TREE_OPERAND (exp, 0); handled_component_p (tem);
431438fd1498Szrj tem = TREE_OPERAND (tem, 0))
431538fd1498Szrj ;
431638fd1498Szrj
431738fd1498Szrj /* If we have an initialized CONST_DECL, retrieve the initializer. */
431838fd1498Szrj if (TREE_CODE (tem) == CONST_DECL && DECL_INITIAL (tem))
431938fd1498Szrj tem = DECL_INITIAL (tem);
432038fd1498Szrj
432138fd1498Szrj if (CONSTANT_CLASS_P (tem) || TREE_CODE (tem) == CONSTRUCTOR)
432238fd1498Szrj output_constant_def (tem, 0);
432338fd1498Szrj
432438fd1498Szrj if (TREE_CODE (tem) == MEM_REF)
432538fd1498Szrj output_addressed_constants (TREE_OPERAND (tem, 0));
432638fd1498Szrj break;
432738fd1498Szrj
432838fd1498Szrj case PLUS_EXPR:
432938fd1498Szrj case POINTER_PLUS_EXPR:
433038fd1498Szrj case MINUS_EXPR:
433138fd1498Szrj output_addressed_constants (TREE_OPERAND (exp, 1));
433238fd1498Szrj gcc_fallthrough ();
433338fd1498Szrj
433438fd1498Szrj CASE_CONVERT:
433538fd1498Szrj case VIEW_CONVERT_EXPR:
433638fd1498Szrj output_addressed_constants (TREE_OPERAND (exp, 0));
433738fd1498Szrj break;
433838fd1498Szrj
433938fd1498Szrj case CONSTRUCTOR:
434038fd1498Szrj {
434138fd1498Szrj unsigned HOST_WIDE_INT idx;
434238fd1498Szrj FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (exp), idx, tem)
434338fd1498Szrj if (tem != 0)
434438fd1498Szrj output_addressed_constants (tem);
434538fd1498Szrj }
434638fd1498Szrj break;
434738fd1498Szrj
434838fd1498Szrj default:
434938fd1498Szrj break;
435038fd1498Szrj }
435138fd1498Szrj }
435238fd1498Szrj
435338fd1498Szrj /* Whether a constructor CTOR is a valid static constant initializer if all
435438fd1498Szrj its elements are. This used to be internal to initializer_constant_valid_p
435538fd1498Szrj and has been exposed to let other functions like categorize_ctor_elements
435638fd1498Szrj evaluate the property while walking a constructor for other purposes. */
435738fd1498Szrj
435838fd1498Szrj bool
constructor_static_from_elts_p(const_tree ctor)435938fd1498Szrj constructor_static_from_elts_p (const_tree ctor)
436038fd1498Szrj {
436138fd1498Szrj return (TREE_CONSTANT (ctor)
436238fd1498Szrj && (TREE_CODE (TREE_TYPE (ctor)) == UNION_TYPE
436338fd1498Szrj || TREE_CODE (TREE_TYPE (ctor)) == RECORD_TYPE
436438fd1498Szrj || TREE_CODE (TREE_TYPE (ctor)) == ARRAY_TYPE));
436538fd1498Szrj }
436638fd1498Szrj
436738fd1498Szrj static tree initializer_constant_valid_p_1 (tree value, tree endtype,
436838fd1498Szrj tree *cache);
436938fd1498Szrj
437038fd1498Szrj /* A subroutine of initializer_constant_valid_p. VALUE is a MINUS_EXPR,
437138fd1498Szrj PLUS_EXPR or POINTER_PLUS_EXPR. This looks for cases of VALUE
437238fd1498Szrj which are valid when ENDTYPE is an integer of any size; in
437338fd1498Szrj particular, this does not accept a pointer minus a constant. This
437438fd1498Szrj returns null_pointer_node if the VALUE is an absolute constant
437538fd1498Szrj which can be used to initialize a static variable. Otherwise it
437638fd1498Szrj returns NULL. */
437738fd1498Szrj
437838fd1498Szrj static tree
narrowing_initializer_constant_valid_p(tree value,tree endtype,tree * cache)437938fd1498Szrj narrowing_initializer_constant_valid_p (tree value, tree endtype, tree *cache)
438038fd1498Szrj {
438138fd1498Szrj tree op0, op1;
438238fd1498Szrj
438338fd1498Szrj if (!INTEGRAL_TYPE_P (endtype))
438438fd1498Szrj return NULL_TREE;
438538fd1498Szrj
438638fd1498Szrj op0 = TREE_OPERAND (value, 0);
438738fd1498Szrj op1 = TREE_OPERAND (value, 1);
438838fd1498Szrj
438938fd1498Szrj /* Like STRIP_NOPS except allow the operand mode to widen. This
439038fd1498Szrj works around a feature of fold that simplifies (int)(p1 - p2) to
439138fd1498Szrj ((int)p1 - (int)p2) under the theory that the narrower operation
439238fd1498Szrj is cheaper. */
439338fd1498Szrj
439438fd1498Szrj while (CONVERT_EXPR_P (op0)
439538fd1498Szrj || TREE_CODE (op0) == NON_LVALUE_EXPR)
439638fd1498Szrj {
439738fd1498Szrj tree inner = TREE_OPERAND (op0, 0);
439838fd1498Szrj if (inner == error_mark_node
439938fd1498Szrj || ! INTEGRAL_MODE_P (TYPE_MODE (TREE_TYPE (inner)))
440038fd1498Szrj || (GET_MODE_SIZE (SCALAR_INT_TYPE_MODE (TREE_TYPE (op0)))
440138fd1498Szrj > GET_MODE_SIZE (SCALAR_INT_TYPE_MODE (TREE_TYPE (inner)))))
440238fd1498Szrj break;
440338fd1498Szrj op0 = inner;
440438fd1498Szrj }
440538fd1498Szrj
440638fd1498Szrj while (CONVERT_EXPR_P (op1)
440738fd1498Szrj || TREE_CODE (op1) == NON_LVALUE_EXPR)
440838fd1498Szrj {
440938fd1498Szrj tree inner = TREE_OPERAND (op1, 0);
441038fd1498Szrj if (inner == error_mark_node
441138fd1498Szrj || ! INTEGRAL_MODE_P (TYPE_MODE (TREE_TYPE (inner)))
441238fd1498Szrj || (GET_MODE_SIZE (SCALAR_INT_TYPE_MODE (TREE_TYPE (op1)))
441338fd1498Szrj > GET_MODE_SIZE (SCALAR_INT_TYPE_MODE (TREE_TYPE (inner)))))
441438fd1498Szrj break;
441538fd1498Szrj op1 = inner;
441638fd1498Szrj }
441738fd1498Szrj
441838fd1498Szrj op0 = initializer_constant_valid_p_1 (op0, endtype, cache);
441938fd1498Szrj if (!op0)
442038fd1498Szrj return NULL_TREE;
442138fd1498Szrj
442238fd1498Szrj op1 = initializer_constant_valid_p_1 (op1, endtype,
442338fd1498Szrj cache ? cache + 2 : NULL);
442438fd1498Szrj /* Both initializers must be known. */
442538fd1498Szrj if (op1)
442638fd1498Szrj {
442738fd1498Szrj if (op0 == op1
442838fd1498Szrj && (op0 == null_pointer_node
442938fd1498Szrj || TREE_CODE (value) == MINUS_EXPR))
443038fd1498Szrj return null_pointer_node;
443138fd1498Szrj
443238fd1498Szrj /* Support differences between labels. */
443338fd1498Szrj if (TREE_CODE (op0) == LABEL_DECL
443438fd1498Szrj && TREE_CODE (op1) == LABEL_DECL)
443538fd1498Szrj return null_pointer_node;
443638fd1498Szrj
443738fd1498Szrj if (TREE_CODE (op0) == STRING_CST
443838fd1498Szrj && TREE_CODE (op1) == STRING_CST
443938fd1498Szrj && operand_equal_p (op0, op1, 1))
444038fd1498Szrj return null_pointer_node;
444138fd1498Szrj }
444238fd1498Szrj
444338fd1498Szrj return NULL_TREE;
444438fd1498Szrj }
444538fd1498Szrj
444638fd1498Szrj /* Helper function of initializer_constant_valid_p.
444738fd1498Szrj Return nonzero if VALUE is a valid constant-valued expression
444838fd1498Szrj for use in initializing a static variable; one that can be an
444938fd1498Szrj element of a "constant" initializer.
445038fd1498Szrj
445138fd1498Szrj Return null_pointer_node if the value is absolute;
445238fd1498Szrj if it is relocatable, return the variable that determines the relocation.
445338fd1498Szrj We assume that VALUE has been folded as much as possible;
445438fd1498Szrj therefore, we do not need to check for such things as
445538fd1498Szrj arithmetic-combinations of integers.
445638fd1498Szrj
445738fd1498Szrj Use CACHE (pointer to 2 tree values) for caching if non-NULL. */
445838fd1498Szrj
445938fd1498Szrj static tree
initializer_constant_valid_p_1(tree value,tree endtype,tree * cache)446038fd1498Szrj initializer_constant_valid_p_1 (tree value, tree endtype, tree *cache)
446138fd1498Szrj {
446238fd1498Szrj tree ret;
446338fd1498Szrj
446438fd1498Szrj switch (TREE_CODE (value))
446538fd1498Szrj {
446638fd1498Szrj case CONSTRUCTOR:
446738fd1498Szrj if (constructor_static_from_elts_p (value))
446838fd1498Szrj {
446938fd1498Szrj unsigned HOST_WIDE_INT idx;
447038fd1498Szrj tree elt;
447138fd1498Szrj bool absolute = true;
447238fd1498Szrj
447338fd1498Szrj if (cache && cache[0] == value)
447438fd1498Szrj return cache[1];
447538fd1498Szrj FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (value), idx, elt)
447638fd1498Szrj {
447738fd1498Szrj tree reloc;
447838fd1498Szrj reloc = initializer_constant_valid_p_1 (elt, TREE_TYPE (elt),
447938fd1498Szrj NULL);
448038fd1498Szrj if (!reloc
448138fd1498Szrj /* An absolute value is required with reverse SSO. */
448238fd1498Szrj || (reloc != null_pointer_node
448338fd1498Szrj && TYPE_REVERSE_STORAGE_ORDER (TREE_TYPE (value))
448438fd1498Szrj && !AGGREGATE_TYPE_P (TREE_TYPE (elt))))
448538fd1498Szrj {
448638fd1498Szrj if (cache)
448738fd1498Szrj {
448838fd1498Szrj cache[0] = value;
448938fd1498Szrj cache[1] = NULL_TREE;
449038fd1498Szrj }
449138fd1498Szrj return NULL_TREE;
449238fd1498Szrj }
449338fd1498Szrj if (reloc != null_pointer_node)
449438fd1498Szrj absolute = false;
449538fd1498Szrj }
449638fd1498Szrj /* For a non-absolute relocation, there is no single
449738fd1498Szrj variable that can be "the variable that determines the
449838fd1498Szrj relocation." */
449938fd1498Szrj if (cache)
450038fd1498Szrj {
450138fd1498Szrj cache[0] = value;
450238fd1498Szrj cache[1] = absolute ? null_pointer_node : error_mark_node;
450338fd1498Szrj }
450438fd1498Szrj return absolute ? null_pointer_node : error_mark_node;
450538fd1498Szrj }
450638fd1498Szrj
450738fd1498Szrj return TREE_STATIC (value) ? null_pointer_node : NULL_TREE;
450838fd1498Szrj
450938fd1498Szrj case INTEGER_CST:
451038fd1498Szrj case VECTOR_CST:
451138fd1498Szrj case REAL_CST:
451238fd1498Szrj case FIXED_CST:
451338fd1498Szrj case STRING_CST:
451438fd1498Szrj case COMPLEX_CST:
451538fd1498Szrj return null_pointer_node;
451638fd1498Szrj
451738fd1498Szrj case ADDR_EXPR:
451838fd1498Szrj case FDESC_EXPR:
451938fd1498Szrj {
452038fd1498Szrj tree op0 = staticp (TREE_OPERAND (value, 0));
452138fd1498Szrj if (op0)
452238fd1498Szrj {
452338fd1498Szrj /* "&(*a).f" is like unto pointer arithmetic. If "a" turns out
452438fd1498Szrj to be a constant, this is old-skool offsetof-like nonsense. */
452538fd1498Szrj if (TREE_CODE (op0) == INDIRECT_REF
452638fd1498Szrj && TREE_CONSTANT (TREE_OPERAND (op0, 0)))
452738fd1498Szrj return null_pointer_node;
452838fd1498Szrj /* Taking the address of a nested function involves a trampoline,
452938fd1498Szrj unless we don't need or want one. */
453038fd1498Szrj if (TREE_CODE (op0) == FUNCTION_DECL
453138fd1498Szrj && DECL_STATIC_CHAIN (op0)
453238fd1498Szrj && !TREE_NO_TRAMPOLINE (value))
453338fd1498Szrj return NULL_TREE;
453438fd1498Szrj /* "&{...}" requires a temporary to hold the constructed
453538fd1498Szrj object. */
453638fd1498Szrj if (TREE_CODE (op0) == CONSTRUCTOR)
453738fd1498Szrj return NULL_TREE;
453838fd1498Szrj }
453938fd1498Szrj return op0;
454038fd1498Szrj }
454138fd1498Szrj
454238fd1498Szrj case NON_LVALUE_EXPR:
454338fd1498Szrj return initializer_constant_valid_p_1 (TREE_OPERAND (value, 0),
454438fd1498Szrj endtype, cache);
454538fd1498Szrj
454638fd1498Szrj case VIEW_CONVERT_EXPR:
454738fd1498Szrj {
454838fd1498Szrj tree src = TREE_OPERAND (value, 0);
454938fd1498Szrj tree src_type = TREE_TYPE (src);
455038fd1498Szrj tree dest_type = TREE_TYPE (value);
455138fd1498Szrj
455238fd1498Szrj /* Allow view-conversions from aggregate to non-aggregate type only
455338fd1498Szrj if the bit pattern is fully preserved afterwards; otherwise, the
455438fd1498Szrj RTL expander won't be able to apply a subsequent transformation
455538fd1498Szrj to the underlying constructor. */
455638fd1498Szrj if (AGGREGATE_TYPE_P (src_type) && !AGGREGATE_TYPE_P (dest_type))
455738fd1498Szrj {
455838fd1498Szrj if (TYPE_MODE (endtype) == TYPE_MODE (dest_type))
455938fd1498Szrj return initializer_constant_valid_p_1 (src, endtype, cache);
456038fd1498Szrj else
456138fd1498Szrj return NULL_TREE;
456238fd1498Szrj }
456338fd1498Szrj
456438fd1498Szrj /* Allow all other kinds of view-conversion. */
456538fd1498Szrj return initializer_constant_valid_p_1 (src, endtype, cache);
456638fd1498Szrj }
456738fd1498Szrj
456838fd1498Szrj CASE_CONVERT:
456938fd1498Szrj {
457038fd1498Szrj tree src = TREE_OPERAND (value, 0);
457138fd1498Szrj tree src_type = TREE_TYPE (src);
457238fd1498Szrj tree dest_type = TREE_TYPE (value);
457338fd1498Szrj
457438fd1498Szrj /* Allow conversions between pointer types, floating-point
457538fd1498Szrj types, and offset types. */
457638fd1498Szrj if ((POINTER_TYPE_P (dest_type) && POINTER_TYPE_P (src_type))
457738fd1498Szrj || (FLOAT_TYPE_P (dest_type) && FLOAT_TYPE_P (src_type))
457838fd1498Szrj || (TREE_CODE (dest_type) == OFFSET_TYPE
457938fd1498Szrj && TREE_CODE (src_type) == OFFSET_TYPE))
458038fd1498Szrj return initializer_constant_valid_p_1 (src, endtype, cache);
458138fd1498Szrj
458238fd1498Szrj /* Allow length-preserving conversions between integer types. */
458338fd1498Szrj if (INTEGRAL_TYPE_P (dest_type) && INTEGRAL_TYPE_P (src_type)
458438fd1498Szrj && (TYPE_PRECISION (dest_type) == TYPE_PRECISION (src_type)))
458538fd1498Szrj return initializer_constant_valid_p_1 (src, endtype, cache);
458638fd1498Szrj
458738fd1498Szrj /* Allow conversions between other integer types only if
458838fd1498Szrj explicit value. Don't allow sign-extension to a type larger
458938fd1498Szrj than word and pointer, there aren't relocations that would
459038fd1498Szrj allow to sign extend it to a wider type. */
459138fd1498Szrj if (INTEGRAL_TYPE_P (dest_type)
459238fd1498Szrj && INTEGRAL_TYPE_P (src_type)
459338fd1498Szrj && (TYPE_UNSIGNED (src_type)
459438fd1498Szrj || TYPE_PRECISION (dest_type) <= TYPE_PRECISION (src_type)
459538fd1498Szrj || TYPE_PRECISION (dest_type) <= BITS_PER_WORD
459638fd1498Szrj || TYPE_PRECISION (dest_type) <= POINTER_SIZE))
459738fd1498Szrj {
459838fd1498Szrj tree inner = initializer_constant_valid_p_1 (src, endtype, cache);
459938fd1498Szrj if (inner == null_pointer_node)
460038fd1498Szrj return null_pointer_node;
460138fd1498Szrj break;
460238fd1498Szrj }
460338fd1498Szrj
460438fd1498Szrj /* Allow (int) &foo provided int is as wide as a pointer. */
460538fd1498Szrj if (INTEGRAL_TYPE_P (dest_type) && POINTER_TYPE_P (src_type)
460638fd1498Szrj && (TYPE_PRECISION (dest_type) >= TYPE_PRECISION (src_type)))
460738fd1498Szrj return initializer_constant_valid_p_1 (src, endtype, cache);
460838fd1498Szrj
460938fd1498Szrj /* Likewise conversions from int to pointers, but also allow
461038fd1498Szrj conversions from 0. */
461138fd1498Szrj if ((POINTER_TYPE_P (dest_type)
461238fd1498Szrj || TREE_CODE (dest_type) == OFFSET_TYPE)
461338fd1498Szrj && INTEGRAL_TYPE_P (src_type))
461438fd1498Szrj {
461538fd1498Szrj if (TREE_CODE (src) == INTEGER_CST
461638fd1498Szrj && TYPE_PRECISION (dest_type) >= TYPE_PRECISION (src_type))
461738fd1498Szrj return null_pointer_node;
461838fd1498Szrj if (integer_zerop (src))
461938fd1498Szrj return null_pointer_node;
462038fd1498Szrj else if (TYPE_PRECISION (dest_type) <= TYPE_PRECISION (src_type))
462138fd1498Szrj return initializer_constant_valid_p_1 (src, endtype, cache);
462238fd1498Szrj }
462338fd1498Szrj
462438fd1498Szrj /* Allow conversions to struct or union types if the value
462538fd1498Szrj inside is okay. */
462638fd1498Szrj if (TREE_CODE (dest_type) == RECORD_TYPE
462738fd1498Szrj || TREE_CODE (dest_type) == UNION_TYPE)
462838fd1498Szrj return initializer_constant_valid_p_1 (src, endtype, cache);
462938fd1498Szrj }
463038fd1498Szrj break;
463138fd1498Szrj
463238fd1498Szrj case POINTER_PLUS_EXPR:
463338fd1498Szrj case PLUS_EXPR:
463438fd1498Szrj /* Any valid floating-point constants will have been folded by now;
463538fd1498Szrj with -frounding-math we hit this with addition of two constants. */
463638fd1498Szrj if (TREE_CODE (endtype) == REAL_TYPE)
463738fd1498Szrj return NULL_TREE;
463838fd1498Szrj if (cache && cache[0] == value)
463938fd1498Szrj return cache[1];
464038fd1498Szrj if (! INTEGRAL_TYPE_P (endtype)
464138fd1498Szrj || TYPE_PRECISION (endtype) >= TYPE_PRECISION (TREE_TYPE (value)))
464238fd1498Szrj {
464338fd1498Szrj tree ncache[4] = { NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE };
464438fd1498Szrj tree valid0
464538fd1498Szrj = initializer_constant_valid_p_1 (TREE_OPERAND (value, 0),
464638fd1498Szrj endtype, ncache);
464738fd1498Szrj tree valid1
464838fd1498Szrj = initializer_constant_valid_p_1 (TREE_OPERAND (value, 1),
464938fd1498Szrj endtype, ncache + 2);
465038fd1498Szrj /* If either term is absolute, use the other term's relocation. */
465138fd1498Szrj if (valid0 == null_pointer_node)
465238fd1498Szrj ret = valid1;
465338fd1498Szrj else if (valid1 == null_pointer_node)
465438fd1498Szrj ret = valid0;
465538fd1498Szrj /* Support narrowing pointer differences. */
465638fd1498Szrj else
465738fd1498Szrj ret = narrowing_initializer_constant_valid_p (value, endtype,
465838fd1498Szrj ncache);
465938fd1498Szrj }
466038fd1498Szrj else
466138fd1498Szrj /* Support narrowing pointer differences. */
466238fd1498Szrj ret = narrowing_initializer_constant_valid_p (value, endtype, NULL);
466338fd1498Szrj if (cache)
466438fd1498Szrj {
466538fd1498Szrj cache[0] = value;
466638fd1498Szrj cache[1] = ret;
466738fd1498Szrj }
466838fd1498Szrj return ret;
466938fd1498Szrj
467038fd1498Szrj case POINTER_DIFF_EXPR:
467138fd1498Szrj case MINUS_EXPR:
467238fd1498Szrj if (TREE_CODE (endtype) == REAL_TYPE)
467338fd1498Szrj return NULL_TREE;
467438fd1498Szrj if (cache && cache[0] == value)
467538fd1498Szrj return cache[1];
467638fd1498Szrj if (! INTEGRAL_TYPE_P (endtype)
467738fd1498Szrj || TYPE_PRECISION (endtype) >= TYPE_PRECISION (TREE_TYPE (value)))
467838fd1498Szrj {
467938fd1498Szrj tree ncache[4] = { NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE };
468038fd1498Szrj tree valid0
468138fd1498Szrj = initializer_constant_valid_p_1 (TREE_OPERAND (value, 0),
468238fd1498Szrj endtype, ncache);
468338fd1498Szrj tree valid1
468438fd1498Szrj = initializer_constant_valid_p_1 (TREE_OPERAND (value, 1),
468538fd1498Szrj endtype, ncache + 2);
468638fd1498Szrj /* Win if second argument is absolute. */
468738fd1498Szrj if (valid1 == null_pointer_node)
468838fd1498Szrj ret = valid0;
468938fd1498Szrj /* Win if both arguments have the same relocation.
469038fd1498Szrj Then the value is absolute. */
469138fd1498Szrj else if (valid0 == valid1 && valid0 != 0)
469238fd1498Szrj ret = null_pointer_node;
469338fd1498Szrj /* Since GCC guarantees that string constants are unique in the
469438fd1498Szrj generated code, a subtraction between two copies of the same
469538fd1498Szrj constant string is absolute. */
469638fd1498Szrj else if (valid0 && TREE_CODE (valid0) == STRING_CST
469738fd1498Szrj && valid1 && TREE_CODE (valid1) == STRING_CST
469838fd1498Szrj && operand_equal_p (valid0, valid1, 1))
469938fd1498Szrj ret = null_pointer_node;
470038fd1498Szrj /* Support narrowing differences. */
470138fd1498Szrj else
470238fd1498Szrj ret = narrowing_initializer_constant_valid_p (value, endtype,
470338fd1498Szrj ncache);
470438fd1498Szrj }
470538fd1498Szrj else
470638fd1498Szrj /* Support narrowing differences. */
470738fd1498Szrj ret = narrowing_initializer_constant_valid_p (value, endtype, NULL);
470838fd1498Szrj if (cache)
470938fd1498Szrj {
471038fd1498Szrj cache[0] = value;
471138fd1498Szrj cache[1] = ret;
471238fd1498Szrj }
471338fd1498Szrj return ret;
471438fd1498Szrj
471538fd1498Szrj default:
471638fd1498Szrj break;
471738fd1498Szrj }
471838fd1498Szrj
471938fd1498Szrj return NULL_TREE;
472038fd1498Szrj }
472138fd1498Szrj
472238fd1498Szrj /* Return nonzero if VALUE is a valid constant-valued expression
472338fd1498Szrj for use in initializing a static variable; one that can be an
472438fd1498Szrj element of a "constant" initializer.
472538fd1498Szrj
472638fd1498Szrj Return null_pointer_node if the value is absolute;
472738fd1498Szrj if it is relocatable, return the variable that determines the relocation.
472838fd1498Szrj We assume that VALUE has been folded as much as possible;
472938fd1498Szrj therefore, we do not need to check for such things as
473038fd1498Szrj arithmetic-combinations of integers. */
473138fd1498Szrj tree
initializer_constant_valid_p(tree value,tree endtype,bool reverse)473238fd1498Szrj initializer_constant_valid_p (tree value, tree endtype, bool reverse)
473338fd1498Szrj {
473438fd1498Szrj tree reloc = initializer_constant_valid_p_1 (value, endtype, NULL);
473538fd1498Szrj
473638fd1498Szrj /* An absolute value is required with reverse storage order. */
473738fd1498Szrj if (reloc
473838fd1498Szrj && reloc != null_pointer_node
473938fd1498Szrj && reverse
474038fd1498Szrj && !AGGREGATE_TYPE_P (endtype)
474138fd1498Szrj && !VECTOR_TYPE_P (endtype))
474238fd1498Szrj reloc = NULL_TREE;
474338fd1498Szrj
474438fd1498Szrj return reloc;
474538fd1498Szrj }
474638fd1498Szrj
474738fd1498Szrj /* Return true if VALUE is a valid constant-valued expression
474838fd1498Szrj for use in initializing a static bit-field; one that can be
474938fd1498Szrj an element of a "constant" initializer. */
475038fd1498Szrj
475138fd1498Szrj bool
initializer_constant_valid_for_bitfield_p(tree value)475238fd1498Szrj initializer_constant_valid_for_bitfield_p (tree value)
475338fd1498Szrj {
475438fd1498Szrj /* For bitfields we support integer constants or possibly nested aggregates
475538fd1498Szrj of such. */
475638fd1498Szrj switch (TREE_CODE (value))
475738fd1498Szrj {
475838fd1498Szrj case CONSTRUCTOR:
475938fd1498Szrj {
476038fd1498Szrj unsigned HOST_WIDE_INT idx;
476138fd1498Szrj tree elt;
476238fd1498Szrj
476338fd1498Szrj FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (value), idx, elt)
476438fd1498Szrj if (!initializer_constant_valid_for_bitfield_p (elt))
476538fd1498Szrj return false;
476638fd1498Szrj return true;
476738fd1498Szrj }
476838fd1498Szrj
476938fd1498Szrj case INTEGER_CST:
477038fd1498Szrj case REAL_CST:
477138fd1498Szrj return true;
477238fd1498Szrj
477338fd1498Szrj case VIEW_CONVERT_EXPR:
477438fd1498Szrj case NON_LVALUE_EXPR:
477538fd1498Szrj return
477638fd1498Szrj initializer_constant_valid_for_bitfield_p (TREE_OPERAND (value, 0));
477738fd1498Szrj
477838fd1498Szrj default:
477938fd1498Szrj break;
478038fd1498Szrj }
478138fd1498Szrj
478238fd1498Szrj return false;
478338fd1498Szrj }
478438fd1498Szrj
478538fd1498Szrj /* output_constructor outer state of relevance in recursive calls, typically
478638fd1498Szrj for nested aggregate bitfields. */
478738fd1498Szrj
478838fd1498Szrj struct oc_outer_state {
478938fd1498Szrj unsigned int bit_offset; /* current position in ... */
479038fd1498Szrj int byte; /* ... the outer byte buffer. */
479138fd1498Szrj };
479238fd1498Szrj
479338fd1498Szrj static unsigned HOST_WIDE_INT
479438fd1498Szrj output_constructor (tree, unsigned HOST_WIDE_INT, unsigned int, bool,
479538fd1498Szrj oc_outer_state *);
479638fd1498Szrj
479738fd1498Szrj /* Output assembler code for constant EXP, with no label.
479838fd1498Szrj This includes the pseudo-op such as ".int" or ".byte", and a newline.
479938fd1498Szrj Assumes output_addressed_constants has been done on EXP already.
480038fd1498Szrj
480138fd1498Szrj Generate at least SIZE bytes of assembler data, padding at the end
480238fd1498Szrj with zeros if necessary. SIZE must always be specified. The returned
480338fd1498Szrj value is the actual number of bytes of assembler data generated, which
480438fd1498Szrj may be bigger than SIZE if the object contains a variable length field.
480538fd1498Szrj
480638fd1498Szrj SIZE is important for structure constructors,
480738fd1498Szrj since trailing members may have been omitted from the constructor.
480838fd1498Szrj It is also important for initialization of arrays from string constants
480938fd1498Szrj since the full length of the string constant might not be wanted.
481038fd1498Szrj It is also needed for initialization of unions, where the initializer's
481138fd1498Szrj type is just one member, and that may not be as long as the union.
481238fd1498Szrj
481338fd1498Szrj There a case in which we would fail to output exactly SIZE bytes:
481438fd1498Szrj for a structure constructor that wants to produce more than SIZE bytes.
481538fd1498Szrj But such constructors will never be generated for any possible input.
481638fd1498Szrj
481738fd1498Szrj ALIGN is the alignment of the data in bits.
481838fd1498Szrj
481938fd1498Szrj If REVERSE is true, EXP is output in reverse storage order. */
482038fd1498Szrj
482138fd1498Szrj static unsigned HOST_WIDE_INT
output_constant(tree exp,unsigned HOST_WIDE_INT size,unsigned int align,bool reverse)482238fd1498Szrj output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align,
482338fd1498Szrj bool reverse)
482438fd1498Szrj {
482538fd1498Szrj enum tree_code code;
482638fd1498Szrj unsigned HOST_WIDE_INT thissize;
482738fd1498Szrj rtx cst;
482838fd1498Szrj
482938fd1498Szrj if (size == 0 || flag_syntax_only)
483038fd1498Szrj return size;
483138fd1498Szrj
483238fd1498Szrj /* See if we're trying to initialize a pointer in a non-default mode
483338fd1498Szrj to the address of some declaration somewhere. If the target says
483438fd1498Szrj the mode is valid for pointers, assume the target has a way of
483538fd1498Szrj resolving it. */
483638fd1498Szrj if (TREE_CODE (exp) == NOP_EXPR
483738fd1498Szrj && POINTER_TYPE_P (TREE_TYPE (exp))
483838fd1498Szrj && targetm.addr_space.valid_pointer_mode
483938fd1498Szrj (SCALAR_INT_TYPE_MODE (TREE_TYPE (exp)),
484038fd1498Szrj TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (exp)))))
484138fd1498Szrj {
484238fd1498Szrj tree saved_type = TREE_TYPE (exp);
484338fd1498Szrj
484438fd1498Szrj /* Peel off any intermediate conversions-to-pointer for valid
484538fd1498Szrj pointer modes. */
484638fd1498Szrj while (TREE_CODE (exp) == NOP_EXPR
484738fd1498Szrj && POINTER_TYPE_P (TREE_TYPE (exp))
484838fd1498Szrj && targetm.addr_space.valid_pointer_mode
484938fd1498Szrj (SCALAR_INT_TYPE_MODE (TREE_TYPE (exp)),
485038fd1498Szrj TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (exp)))))
485138fd1498Szrj exp = TREE_OPERAND (exp, 0);
485238fd1498Szrj
485338fd1498Szrj /* If what we're left with is the address of something, we can
485438fd1498Szrj convert the address to the final type and output it that
485538fd1498Szrj way. */
485638fd1498Szrj if (TREE_CODE (exp) == ADDR_EXPR)
485738fd1498Szrj exp = build1 (ADDR_EXPR, saved_type, TREE_OPERAND (exp, 0));
485838fd1498Szrj /* Likewise for constant ints. */
485938fd1498Szrj else if (TREE_CODE (exp) == INTEGER_CST)
486038fd1498Szrj exp = fold_convert (saved_type, exp);
486138fd1498Szrj
486238fd1498Szrj }
486338fd1498Szrj
486438fd1498Szrj /* Eliminate any conversions since we'll be outputting the underlying
486538fd1498Szrj constant. */
486638fd1498Szrj while (CONVERT_EXPR_P (exp)
486738fd1498Szrj || TREE_CODE (exp) == NON_LVALUE_EXPR
486838fd1498Szrj || TREE_CODE (exp) == VIEW_CONVERT_EXPR)
486938fd1498Szrj {
487038fd1498Szrj HOST_WIDE_INT type_size = int_size_in_bytes (TREE_TYPE (exp));
487138fd1498Szrj HOST_WIDE_INT op_size = int_size_in_bytes (TREE_TYPE (TREE_OPERAND (exp, 0)));
487238fd1498Szrj
487338fd1498Szrj /* Make sure eliminating the conversion is really a no-op, except with
487438fd1498Szrj VIEW_CONVERT_EXPRs to allow for wild Ada unchecked conversions and
487538fd1498Szrj union types to allow for Ada unchecked unions. */
487638fd1498Szrj if (type_size > op_size
487738fd1498Szrj && TREE_CODE (exp) != VIEW_CONVERT_EXPR
487838fd1498Szrj && TREE_CODE (TREE_TYPE (exp)) != UNION_TYPE)
487938fd1498Szrj /* Keep the conversion. */
488038fd1498Szrj break;
488138fd1498Szrj else
488238fd1498Szrj exp = TREE_OPERAND (exp, 0);
488338fd1498Szrj }
488438fd1498Szrj
488538fd1498Szrj code = TREE_CODE (TREE_TYPE (exp));
488638fd1498Szrj thissize = int_size_in_bytes (TREE_TYPE (exp));
488738fd1498Szrj
488838fd1498Szrj /* Allow a constructor with no elements for any data type.
488938fd1498Szrj This means to fill the space with zeros. */
489038fd1498Szrj if (TREE_CODE (exp) == CONSTRUCTOR
489138fd1498Szrj && vec_safe_is_empty (CONSTRUCTOR_ELTS (exp)))
489238fd1498Szrj {
489338fd1498Szrj assemble_zeros (size);
489438fd1498Szrj return size;
489538fd1498Szrj }
489638fd1498Szrj
489738fd1498Szrj if (TREE_CODE (exp) == FDESC_EXPR)
489838fd1498Szrj {
489938fd1498Szrj #ifdef ASM_OUTPUT_FDESC
490038fd1498Szrj HOST_WIDE_INT part = tree_to_shwi (TREE_OPERAND (exp, 1));
490138fd1498Szrj tree decl = TREE_OPERAND (exp, 0);
490238fd1498Szrj ASM_OUTPUT_FDESC (asm_out_file, decl, part);
490338fd1498Szrj #else
490438fd1498Szrj gcc_unreachable ();
490538fd1498Szrj #endif
490638fd1498Szrj return size;
490738fd1498Szrj }
490838fd1498Szrj
490938fd1498Szrj /* Now output the underlying data. If we've handling the padding, return.
491038fd1498Szrj Otherwise, break and ensure SIZE is the size written. */
491138fd1498Szrj switch (code)
491238fd1498Szrj {
491338fd1498Szrj case BOOLEAN_TYPE:
491438fd1498Szrj case INTEGER_TYPE:
491538fd1498Szrj case ENUMERAL_TYPE:
491638fd1498Szrj case POINTER_TYPE:
491738fd1498Szrj case REFERENCE_TYPE:
491838fd1498Szrj case OFFSET_TYPE:
491938fd1498Szrj case FIXED_POINT_TYPE:
492038fd1498Szrj case POINTER_BOUNDS_TYPE:
492138fd1498Szrj case NULLPTR_TYPE:
492238fd1498Szrj cst = expand_expr (exp, NULL_RTX, VOIDmode, EXPAND_INITIALIZER);
492338fd1498Szrj if (reverse)
492438fd1498Szrj cst = flip_storage_order (TYPE_MODE (TREE_TYPE (exp)), cst);
492538fd1498Szrj if (!assemble_integer (cst, MIN (size, thissize), align, 0))
492638fd1498Szrj error ("initializer for integer/fixed-point value is too complicated");
492738fd1498Szrj break;
492838fd1498Szrj
492938fd1498Szrj case REAL_TYPE:
493038fd1498Szrj if (TREE_CODE (exp) != REAL_CST)
493138fd1498Szrj error ("initializer for floating value is not a floating constant");
493238fd1498Szrj else
493338fd1498Szrj assemble_real (TREE_REAL_CST (exp),
493438fd1498Szrj SCALAR_FLOAT_TYPE_MODE (TREE_TYPE (exp)),
493538fd1498Szrj align, reverse);
493638fd1498Szrj break;
493738fd1498Szrj
493838fd1498Szrj case COMPLEX_TYPE:
493938fd1498Szrj output_constant (TREE_REALPART (exp), thissize / 2, align, reverse);
494038fd1498Szrj output_constant (TREE_IMAGPART (exp), thissize / 2,
494138fd1498Szrj min_align (align, BITS_PER_UNIT * (thissize / 2)),
494238fd1498Szrj reverse);
494338fd1498Szrj break;
494438fd1498Szrj
494538fd1498Szrj case ARRAY_TYPE:
494638fd1498Szrj case VECTOR_TYPE:
494738fd1498Szrj switch (TREE_CODE (exp))
494838fd1498Szrj {
494938fd1498Szrj case CONSTRUCTOR:
495038fd1498Szrj return output_constructor (exp, size, align, reverse, NULL);
495138fd1498Szrj case STRING_CST:
495238fd1498Szrj thissize
495338fd1498Szrj = MIN ((unsigned HOST_WIDE_INT)TREE_STRING_LENGTH (exp), size);
495438fd1498Szrj assemble_string (TREE_STRING_POINTER (exp), thissize);
495538fd1498Szrj break;
495638fd1498Szrj case VECTOR_CST:
495738fd1498Szrj {
495838fd1498Szrj scalar_mode inner = SCALAR_TYPE_MODE (TREE_TYPE (TREE_TYPE (exp)));
495938fd1498Szrj unsigned int nalign = MIN (align, GET_MODE_ALIGNMENT (inner));
496038fd1498Szrj int elt_size = GET_MODE_SIZE (inner);
496138fd1498Szrj output_constant (VECTOR_CST_ELT (exp, 0), elt_size, align,
496238fd1498Szrj reverse);
496338fd1498Szrj thissize = elt_size;
496438fd1498Szrj /* Static constants must have a fixed size. */
496538fd1498Szrj unsigned int nunits = VECTOR_CST_NELTS (exp).to_constant ();
496638fd1498Szrj for (unsigned int i = 1; i < nunits; i++)
496738fd1498Szrj {
496838fd1498Szrj output_constant (VECTOR_CST_ELT (exp, i), elt_size, nalign,
496938fd1498Szrj reverse);
497038fd1498Szrj thissize += elt_size;
497138fd1498Szrj }
497238fd1498Szrj break;
497338fd1498Szrj }
497438fd1498Szrj default:
497538fd1498Szrj gcc_unreachable ();
497638fd1498Szrj }
497738fd1498Szrj break;
497838fd1498Szrj
497938fd1498Szrj case RECORD_TYPE:
498038fd1498Szrj case UNION_TYPE:
498138fd1498Szrj gcc_assert (TREE_CODE (exp) == CONSTRUCTOR);
498238fd1498Szrj return output_constructor (exp, size, align, reverse, NULL);
498338fd1498Szrj
498438fd1498Szrj case ERROR_MARK:
498538fd1498Szrj return 0;
498638fd1498Szrj
498738fd1498Szrj default:
498838fd1498Szrj gcc_unreachable ();
498938fd1498Szrj }
499038fd1498Szrj
499138fd1498Szrj if (size > thissize)
499238fd1498Szrj assemble_zeros (size - thissize);
499338fd1498Szrj
499438fd1498Szrj return size;
499538fd1498Szrj }
499638fd1498Szrj
499738fd1498Szrj /* Subroutine of output_constructor, used for computing the size of
499838fd1498Szrj arrays of unspecified length. VAL must be a CONSTRUCTOR of an array
499938fd1498Szrj type with an unspecified upper bound. */
500038fd1498Szrj
500138fd1498Szrj static unsigned HOST_WIDE_INT
array_size_for_constructor(tree val)500238fd1498Szrj array_size_for_constructor (tree val)
500338fd1498Szrj {
500438fd1498Szrj tree max_index;
500538fd1498Szrj unsigned HOST_WIDE_INT cnt;
500638fd1498Szrj tree index, value, tmp;
500738fd1498Szrj offset_int i;
500838fd1498Szrj
500938fd1498Szrj /* This code used to attempt to handle string constants that are not
501038fd1498Szrj arrays of single-bytes, but nothing else does, so there's no point in
501138fd1498Szrj doing it here. */
501238fd1498Szrj if (TREE_CODE (val) == STRING_CST)
501338fd1498Szrj return TREE_STRING_LENGTH (val);
501438fd1498Szrj
501538fd1498Szrj max_index = NULL_TREE;
501638fd1498Szrj FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (val), cnt, index, value)
501738fd1498Szrj {
501838fd1498Szrj if (TREE_CODE (index) == RANGE_EXPR)
501938fd1498Szrj index = TREE_OPERAND (index, 1);
502038fd1498Szrj if (max_index == NULL_TREE || tree_int_cst_lt (max_index, index))
502138fd1498Szrj max_index = index;
502238fd1498Szrj }
502338fd1498Szrj
502438fd1498Szrj if (max_index == NULL_TREE)
502538fd1498Szrj return 0;
502638fd1498Szrj
502738fd1498Szrj /* Compute the total number of array elements. */
502838fd1498Szrj tmp = TYPE_MIN_VALUE (TYPE_DOMAIN (TREE_TYPE (val)));
502938fd1498Szrj i = wi::to_offset (max_index) - wi::to_offset (tmp) + 1;
503038fd1498Szrj
503138fd1498Szrj /* Multiply by the array element unit size to find number of bytes. */
503238fd1498Szrj i *= wi::to_offset (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (val))));
503338fd1498Szrj
503438fd1498Szrj gcc_assert (wi::fits_uhwi_p (i));
503538fd1498Szrj return i.to_uhwi ();
503638fd1498Szrj }
503738fd1498Szrj
503838fd1498Szrj /* Other datastructures + helpers for output_constructor. */
503938fd1498Szrj
504038fd1498Szrj /* output_constructor local state to support interaction with helpers. */
504138fd1498Szrj
504238fd1498Szrj struct oc_local_state {
504338fd1498Szrj
504438fd1498Szrj /* Received arguments. */
504538fd1498Szrj tree exp; /* Constructor expression. */
504638fd1498Szrj tree type; /* Type of constructor expression. */
504738fd1498Szrj unsigned HOST_WIDE_INT size; /* # bytes to output - pad if necessary. */
504838fd1498Szrj unsigned int align; /* Known initial alignment. */
504938fd1498Szrj tree min_index; /* Lower bound if specified for an array. */
505038fd1498Szrj
505138fd1498Szrj /* Output processing state. */
505238fd1498Szrj HOST_WIDE_INT total_bytes; /* # bytes output so far / current position. */
505338fd1498Szrj int byte; /* Part of a bitfield byte yet to be output. */
505438fd1498Szrj int last_relative_index; /* Implicit or explicit index of the last
505538fd1498Szrj array element output within a bitfield. */
505638fd1498Szrj bool byte_buffer_in_use; /* Whether BYTE is in use. */
505738fd1498Szrj bool reverse; /* Whether reverse storage order is in use. */
505838fd1498Szrj
505938fd1498Szrj /* Current element. */
506038fd1498Szrj tree field; /* Current field decl in a record. */
506138fd1498Szrj tree val; /* Current element value. */
506238fd1498Szrj tree index; /* Current element index. */
506338fd1498Szrj
506438fd1498Szrj };
506538fd1498Szrj
506638fd1498Szrj /* Helper for output_constructor. From the current LOCAL state, output a
506738fd1498Szrj RANGE_EXPR element. */
506838fd1498Szrj
506938fd1498Szrj static void
output_constructor_array_range(oc_local_state * local)507038fd1498Szrj output_constructor_array_range (oc_local_state *local)
507138fd1498Szrj {
507238fd1498Szrj unsigned HOST_WIDE_INT fieldsize
507338fd1498Szrj = int_size_in_bytes (TREE_TYPE (local->type));
507438fd1498Szrj
507538fd1498Szrj HOST_WIDE_INT lo_index
507638fd1498Szrj = tree_to_shwi (TREE_OPERAND (local->index, 0));
507738fd1498Szrj HOST_WIDE_INT hi_index
507838fd1498Szrj = tree_to_shwi (TREE_OPERAND (local->index, 1));
507938fd1498Szrj HOST_WIDE_INT index;
508038fd1498Szrj
508138fd1498Szrj unsigned int align2
508238fd1498Szrj = min_align (local->align, fieldsize * BITS_PER_UNIT);
508338fd1498Szrj
508438fd1498Szrj for (index = lo_index; index <= hi_index; index++)
508538fd1498Szrj {
508638fd1498Szrj /* Output the element's initial value. */
508738fd1498Szrj if (local->val == NULL_TREE)
508838fd1498Szrj assemble_zeros (fieldsize);
508938fd1498Szrj else
509038fd1498Szrj fieldsize
509138fd1498Szrj = output_constant (local->val, fieldsize, align2, local->reverse);
509238fd1498Szrj
509338fd1498Szrj /* Count its size. */
509438fd1498Szrj local->total_bytes += fieldsize;
509538fd1498Szrj }
509638fd1498Szrj }
509738fd1498Szrj
509838fd1498Szrj /* Helper for output_constructor. From the current LOCAL state, output a
509938fd1498Szrj field element that is not true bitfield or part of an outer one. */
510038fd1498Szrj
510138fd1498Szrj static void
output_constructor_regular_field(oc_local_state * local)510238fd1498Szrj output_constructor_regular_field (oc_local_state *local)
510338fd1498Szrj {
510438fd1498Szrj /* Field size and position. Since this structure is static, we know the
510538fd1498Szrj positions are constant. */
510638fd1498Szrj unsigned HOST_WIDE_INT fieldsize;
510738fd1498Szrj HOST_WIDE_INT fieldpos;
510838fd1498Szrj
510938fd1498Szrj unsigned int align2;
511038fd1498Szrj
511138fd1498Szrj /* Output any buffered-up bit-fields preceding this element. */
511238fd1498Szrj if (local->byte_buffer_in_use)
511338fd1498Szrj {
511438fd1498Szrj assemble_integer (GEN_INT (local->byte), 1, BITS_PER_UNIT, 1);
511538fd1498Szrj local->total_bytes++;
511638fd1498Szrj local->byte_buffer_in_use = false;
511738fd1498Szrj }
511838fd1498Szrj
511938fd1498Szrj if (local->index != NULL_TREE)
512038fd1498Szrj {
512138fd1498Szrj /* Perform the index calculation in modulo arithmetic but
512238fd1498Szrj sign-extend the result because Ada has negative DECL_FIELD_OFFSETs
512338fd1498Szrj but we are using an unsigned sizetype. */
512438fd1498Szrj unsigned prec = TYPE_PRECISION (sizetype);
512538fd1498Szrj offset_int idx = wi::sext (wi::to_offset (local->index)
512638fd1498Szrj - wi::to_offset (local->min_index), prec);
512738fd1498Szrj fieldpos = (idx * wi::to_offset (TYPE_SIZE_UNIT (TREE_TYPE (local->val))))
512838fd1498Szrj .to_short_addr ();
512938fd1498Szrj }
513038fd1498Szrj else if (local->field != NULL_TREE)
513138fd1498Szrj fieldpos = int_byte_position (local->field);
513238fd1498Szrj else
513338fd1498Szrj fieldpos = 0;
513438fd1498Szrj
513538fd1498Szrj /* Advance to offset of this element.
513638fd1498Szrj Note no alignment needed in an array, since that is guaranteed
513738fd1498Szrj if each element has the proper size. */
513838fd1498Szrj if (local->field != NULL_TREE || local->index != NULL_TREE)
513938fd1498Szrj {
514038fd1498Szrj if (fieldpos > local->total_bytes)
514138fd1498Szrj {
514238fd1498Szrj assemble_zeros (fieldpos - local->total_bytes);
514338fd1498Szrj local->total_bytes = fieldpos;
514438fd1498Szrj }
514538fd1498Szrj else
514638fd1498Szrj /* Must not go backwards. */
514738fd1498Szrj gcc_assert (fieldpos == local->total_bytes);
514838fd1498Szrj }
514938fd1498Szrj
515038fd1498Szrj /* Find the alignment of this element. */
515138fd1498Szrj align2 = min_align (local->align, BITS_PER_UNIT * fieldpos);
515238fd1498Szrj
515338fd1498Szrj /* Determine size this element should occupy. */
515438fd1498Szrj if (local->field)
515538fd1498Szrj {
515638fd1498Szrj fieldsize = 0;
515738fd1498Szrj
515838fd1498Szrj /* If this is an array with an unspecified upper bound,
515938fd1498Szrj the initializer determines the size. */
516038fd1498Szrj /* ??? This ought to only checked if DECL_SIZE_UNIT is NULL,
516138fd1498Szrj but we cannot do this until the deprecated support for
516238fd1498Szrj initializing zero-length array members is removed. */
516338fd1498Szrj if (TREE_CODE (TREE_TYPE (local->field)) == ARRAY_TYPE
516438fd1498Szrj && (!TYPE_DOMAIN (TREE_TYPE (local->field))
516538fd1498Szrj || !TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (local->field)))))
516638fd1498Szrj {
516738fd1498Szrj fieldsize = array_size_for_constructor (local->val);
516838fd1498Szrj /* Given a non-empty initialization, this field had better
516938fd1498Szrj be last. Given a flexible array member, the next field
517038fd1498Szrj on the chain is a TYPE_DECL of the enclosing struct. */
517138fd1498Szrj const_tree next = DECL_CHAIN (local->field);
517238fd1498Szrj gcc_assert (!fieldsize || !next || TREE_CODE (next) != FIELD_DECL);
517338fd1498Szrj }
517438fd1498Szrj else
517538fd1498Szrj fieldsize = tree_to_uhwi (DECL_SIZE_UNIT (local->field));
517638fd1498Szrj }
517738fd1498Szrj else
517838fd1498Szrj fieldsize = int_size_in_bytes (TREE_TYPE (local->type));
517938fd1498Szrj
518038fd1498Szrj /* Output the element's initial value. */
518138fd1498Szrj if (local->val == NULL_TREE)
518238fd1498Szrj assemble_zeros (fieldsize);
518338fd1498Szrj else
518438fd1498Szrj fieldsize
518538fd1498Szrj = output_constant (local->val, fieldsize, align2, local->reverse);
518638fd1498Szrj
518738fd1498Szrj /* Count its size. */
518838fd1498Szrj local->total_bytes += fieldsize;
518938fd1498Szrj }
519038fd1498Szrj
519138fd1498Szrj /* Helper for output_constructor. From the LOCAL state, output an element
519238fd1498Szrj that is a true bitfield or part of an outer one. BIT_OFFSET is the offset
519338fd1498Szrj from the start of a possibly ongoing outer byte buffer. */
519438fd1498Szrj
519538fd1498Szrj static void
output_constructor_bitfield(oc_local_state * local,unsigned int bit_offset)519638fd1498Szrj output_constructor_bitfield (oc_local_state *local, unsigned int bit_offset)
519738fd1498Szrj {
519838fd1498Szrj /* Bit size of this element. */
519938fd1498Szrj HOST_WIDE_INT ebitsize
520038fd1498Szrj = (local->field
520138fd1498Szrj ? tree_to_uhwi (DECL_SIZE (local->field))
520238fd1498Szrj : tree_to_uhwi (TYPE_SIZE (TREE_TYPE (local->type))));
520338fd1498Szrj
520438fd1498Szrj /* Relative index of this element if this is an array component. */
520538fd1498Szrj HOST_WIDE_INT relative_index
520638fd1498Szrj = (!local->field
520738fd1498Szrj ? (local->index
520838fd1498Szrj ? (tree_to_shwi (local->index)
520938fd1498Szrj - tree_to_shwi (local->min_index))
521038fd1498Szrj : local->last_relative_index + 1)
521138fd1498Szrj : 0);
521238fd1498Szrj
521338fd1498Szrj /* Bit position of this element from the start of the containing
521438fd1498Szrj constructor. */
521538fd1498Szrj HOST_WIDE_INT constructor_relative_ebitpos
521638fd1498Szrj = (local->field
521738fd1498Szrj ? int_bit_position (local->field)
521838fd1498Szrj : ebitsize * relative_index);
521938fd1498Szrj
522038fd1498Szrj /* Bit position of this element from the start of a possibly ongoing
522138fd1498Szrj outer byte buffer. */
522238fd1498Szrj HOST_WIDE_INT byte_relative_ebitpos
522338fd1498Szrj = bit_offset + constructor_relative_ebitpos;
522438fd1498Szrj
522538fd1498Szrj /* From the start of a possibly ongoing outer byte buffer, offsets to
522638fd1498Szrj the first bit of this element and to the first bit past the end of
522738fd1498Szrj this element. */
522838fd1498Szrj HOST_WIDE_INT next_offset = byte_relative_ebitpos;
522938fd1498Szrj HOST_WIDE_INT end_offset = byte_relative_ebitpos + ebitsize;
523038fd1498Szrj
523138fd1498Szrj local->last_relative_index = relative_index;
523238fd1498Szrj
523338fd1498Szrj if (local->val == NULL_TREE)
523438fd1498Szrj local->val = integer_zero_node;
523538fd1498Szrj
523638fd1498Szrj while (TREE_CODE (local->val) == VIEW_CONVERT_EXPR
523738fd1498Szrj || TREE_CODE (local->val) == NON_LVALUE_EXPR)
523838fd1498Szrj local->val = TREE_OPERAND (local->val, 0);
523938fd1498Szrj
524038fd1498Szrj if (TREE_CODE (local->val) != INTEGER_CST
524138fd1498Szrj && TREE_CODE (local->val) != CONSTRUCTOR)
524238fd1498Szrj {
524338fd1498Szrj error ("invalid initial value for member %qE", DECL_NAME (local->field));
524438fd1498Szrj return;
524538fd1498Szrj }
524638fd1498Szrj
524738fd1498Szrj /* If this field does not start in this (or next) byte, skip some bytes. */
524838fd1498Szrj if (next_offset / BITS_PER_UNIT != local->total_bytes)
524938fd1498Szrj {
525038fd1498Szrj /* Output remnant of any bit field in previous bytes. */
525138fd1498Szrj if (local->byte_buffer_in_use)
525238fd1498Szrj {
525338fd1498Szrj assemble_integer (GEN_INT (local->byte), 1, BITS_PER_UNIT, 1);
525438fd1498Szrj local->total_bytes++;
525538fd1498Szrj local->byte_buffer_in_use = false;
525638fd1498Szrj }
525738fd1498Szrj
525838fd1498Szrj /* If still not at proper byte, advance to there. */
525938fd1498Szrj if (next_offset / BITS_PER_UNIT != local->total_bytes)
526038fd1498Szrj {
526138fd1498Szrj gcc_assert (next_offset / BITS_PER_UNIT >= local->total_bytes);
526238fd1498Szrj assemble_zeros (next_offset / BITS_PER_UNIT - local->total_bytes);
526338fd1498Szrj local->total_bytes = next_offset / BITS_PER_UNIT;
526438fd1498Szrj }
526538fd1498Szrj }
526638fd1498Szrj
526738fd1498Szrj /* Set up the buffer if necessary. */
526838fd1498Szrj if (!local->byte_buffer_in_use)
526938fd1498Szrj {
527038fd1498Szrj local->byte = 0;
527138fd1498Szrj if (ebitsize > 0)
527238fd1498Szrj local->byte_buffer_in_use = true;
527338fd1498Szrj }
527438fd1498Szrj
527538fd1498Szrj /* If this is nested constructor, recurse passing the bit offset and the
527638fd1498Szrj pending data, then retrieve the new pending data afterwards. */
527738fd1498Szrj if (TREE_CODE (local->val) == CONSTRUCTOR)
527838fd1498Szrj {
527938fd1498Szrj oc_outer_state temp_state;
528038fd1498Szrj temp_state.bit_offset = next_offset % BITS_PER_UNIT;
528138fd1498Szrj temp_state.byte = local->byte;
528238fd1498Szrj local->total_bytes
528338fd1498Szrj += output_constructor (local->val, 0, 0, local->reverse, &temp_state);
528438fd1498Szrj local->byte = temp_state.byte;
528538fd1498Szrj return;
528638fd1498Szrj }
528738fd1498Szrj
528838fd1498Szrj /* Otherwise, we must split the element into pieces that fall within
528938fd1498Szrj separate bytes, and combine each byte with previous or following
529038fd1498Szrj bit-fields. */
529138fd1498Szrj while (next_offset < end_offset)
529238fd1498Szrj {
529338fd1498Szrj int this_time;
529438fd1498Szrj int shift;
529538fd1498Szrj HOST_WIDE_INT value;
529638fd1498Szrj HOST_WIDE_INT next_byte = next_offset / BITS_PER_UNIT;
529738fd1498Szrj HOST_WIDE_INT next_bit = next_offset % BITS_PER_UNIT;
529838fd1498Szrj
529938fd1498Szrj /* Advance from byte to byte within this element when necessary. */
530038fd1498Szrj while (next_byte != local->total_bytes)
530138fd1498Szrj {
530238fd1498Szrj assemble_integer (GEN_INT (local->byte), 1, BITS_PER_UNIT, 1);
530338fd1498Szrj local->total_bytes++;
530438fd1498Szrj local->byte = 0;
530538fd1498Szrj }
530638fd1498Szrj
530738fd1498Szrj /* Number of bits we can process at once (all part of the same byte). */
530838fd1498Szrj this_time = MIN (end_offset - next_offset, BITS_PER_UNIT - next_bit);
530938fd1498Szrj if (local->reverse ? !BYTES_BIG_ENDIAN : BYTES_BIG_ENDIAN)
531038fd1498Szrj {
531138fd1498Szrj /* For big-endian data, take the most significant bits (of the
531238fd1498Szrj bits that are significant) first and put them into bytes from
531338fd1498Szrj the most significant end. */
531438fd1498Szrj shift = end_offset - next_offset - this_time;
531538fd1498Szrj
531638fd1498Szrj /* Don't try to take a bunch of bits that cross
531738fd1498Szrj the word boundary in the INTEGER_CST. We can
531838fd1498Szrj only select bits from one element. */
531938fd1498Szrj if ((shift / HOST_BITS_PER_WIDE_INT)
532038fd1498Szrj != ((shift + this_time - 1) / HOST_BITS_PER_WIDE_INT))
532138fd1498Szrj {
532238fd1498Szrj const int end = shift + this_time - 1;
532338fd1498Szrj shift = end & -HOST_BITS_PER_WIDE_INT;
532438fd1498Szrj this_time = end - shift + 1;
532538fd1498Szrj }
532638fd1498Szrj
532738fd1498Szrj /* Now get the bits from the appropriate constant word. */
532838fd1498Szrj value = TREE_INT_CST_ELT (local->val, shift / HOST_BITS_PER_WIDE_INT);
532938fd1498Szrj shift = shift & (HOST_BITS_PER_WIDE_INT - 1);
533038fd1498Szrj
533138fd1498Szrj /* Get the result. This works only when:
533238fd1498Szrj 1 <= this_time <= HOST_BITS_PER_WIDE_INT. */
533338fd1498Szrj local->byte |= (((value >> shift)
533438fd1498Szrj & (((HOST_WIDE_INT) 2 << (this_time - 1)) - 1))
533538fd1498Szrj << (BITS_PER_UNIT - this_time - next_bit));
533638fd1498Szrj }
533738fd1498Szrj else
533838fd1498Szrj {
533938fd1498Szrj /* On little-endian machines, take the least significant bits of
534038fd1498Szrj the value first and pack them starting at the least significant
534138fd1498Szrj bits of the bytes. */
534238fd1498Szrj shift = next_offset - byte_relative_ebitpos;
534338fd1498Szrj
534438fd1498Szrj /* Don't try to take a bunch of bits that cross
534538fd1498Szrj the word boundary in the INTEGER_CST. We can
534638fd1498Szrj only select bits from one element. */
534738fd1498Szrj if ((shift / HOST_BITS_PER_WIDE_INT)
534838fd1498Szrj != ((shift + this_time - 1) / HOST_BITS_PER_WIDE_INT))
534938fd1498Szrj this_time
535038fd1498Szrj = HOST_BITS_PER_WIDE_INT - (shift & (HOST_BITS_PER_WIDE_INT - 1));
535138fd1498Szrj
535238fd1498Szrj /* Now get the bits from the appropriate constant word. */
535338fd1498Szrj value = TREE_INT_CST_ELT (local->val, shift / HOST_BITS_PER_WIDE_INT);
535438fd1498Szrj shift = shift & (HOST_BITS_PER_WIDE_INT - 1);
535538fd1498Szrj
535638fd1498Szrj /* Get the result. This works only when:
535738fd1498Szrj 1 <= this_time <= HOST_BITS_PER_WIDE_INT. */
535838fd1498Szrj local->byte |= (((value >> shift)
535938fd1498Szrj & (((HOST_WIDE_INT) 2 << (this_time - 1)) - 1))
536038fd1498Szrj << next_bit);
536138fd1498Szrj }
536238fd1498Szrj
536338fd1498Szrj next_offset += this_time;
536438fd1498Szrj local->byte_buffer_in_use = true;
536538fd1498Szrj }
536638fd1498Szrj }
536738fd1498Szrj
536838fd1498Szrj /* Subroutine of output_constant, used for CONSTRUCTORs (aggregate constants).
536938fd1498Szrj Generate at least SIZE bytes, padding if necessary. OUTER designates the
537038fd1498Szrj caller output state of relevance in recursive invocations. */
537138fd1498Szrj
537238fd1498Szrj static unsigned HOST_WIDE_INT
output_constructor(tree exp,unsigned HOST_WIDE_INT size,unsigned int align,bool reverse,oc_outer_state * outer)537338fd1498Szrj output_constructor (tree exp, unsigned HOST_WIDE_INT size, unsigned int align,
537438fd1498Szrj bool reverse, oc_outer_state *outer)
537538fd1498Szrj {
537638fd1498Szrj unsigned HOST_WIDE_INT cnt;
537738fd1498Szrj constructor_elt *ce;
537838fd1498Szrj oc_local_state local;
537938fd1498Szrj
538038fd1498Szrj /* Setup our local state to communicate with helpers. */
538138fd1498Szrj local.exp = exp;
538238fd1498Szrj local.type = TREE_TYPE (exp);
538338fd1498Szrj local.size = size;
538438fd1498Szrj local.align = align;
538538fd1498Szrj if (TREE_CODE (local.type) == ARRAY_TYPE && TYPE_DOMAIN (local.type))
538638fd1498Szrj local.min_index = TYPE_MIN_VALUE (TYPE_DOMAIN (local.type));
538738fd1498Szrj else
538838fd1498Szrj local.min_index = integer_zero_node;
538938fd1498Szrj
539038fd1498Szrj local.total_bytes = 0;
539138fd1498Szrj local.byte_buffer_in_use = outer != NULL;
539238fd1498Szrj local.byte = outer ? outer->byte : 0;
539338fd1498Szrj local.last_relative_index = -1;
539438fd1498Szrj /* The storage order is specified for every aggregate type. */
539538fd1498Szrj if (AGGREGATE_TYPE_P (local.type))
539638fd1498Szrj local.reverse = TYPE_REVERSE_STORAGE_ORDER (local.type);
539738fd1498Szrj else
539838fd1498Szrj local.reverse = reverse;
539938fd1498Szrj
540038fd1498Szrj gcc_assert (HOST_BITS_PER_WIDE_INT >= BITS_PER_UNIT);
540138fd1498Szrj
540238fd1498Szrj /* As CE goes through the elements of the constant, FIELD goes through the
540338fd1498Szrj structure fields if the constant is a structure. If the constant is a
540438fd1498Szrj union, we override this by getting the field from the TREE_LIST element.
540538fd1498Szrj But the constant could also be an array. Then FIELD is zero.
540638fd1498Szrj
540738fd1498Szrj There is always a maximum of one element in the chain LINK for unions
540838fd1498Szrj (even if the initializer in a source program incorrectly contains
540938fd1498Szrj more one). */
541038fd1498Szrj
541138fd1498Szrj if (TREE_CODE (local.type) == RECORD_TYPE)
541238fd1498Szrj local.field = TYPE_FIELDS (local.type);
541338fd1498Szrj else
541438fd1498Szrj local.field = NULL_TREE;
541538fd1498Szrj
541638fd1498Szrj for (cnt = 0;
541738fd1498Szrj vec_safe_iterate (CONSTRUCTOR_ELTS (exp), cnt, &ce);
541838fd1498Szrj cnt++, local.field = local.field ? DECL_CHAIN (local.field) : 0)
541938fd1498Szrj {
542038fd1498Szrj local.val = ce->value;
542138fd1498Szrj local.index = NULL_TREE;
542238fd1498Szrj
542338fd1498Szrj /* The element in a union constructor specifies the proper field
542438fd1498Szrj or index. */
542538fd1498Szrj if (RECORD_OR_UNION_TYPE_P (local.type) && ce->index != NULL_TREE)
542638fd1498Szrj local.field = ce->index;
542738fd1498Szrj
542838fd1498Szrj else if (TREE_CODE (local.type) == ARRAY_TYPE)
542938fd1498Szrj local.index = ce->index;
543038fd1498Szrj
543138fd1498Szrj if (local.field && flag_verbose_asm)
543238fd1498Szrj fprintf (asm_out_file, "%s %s:\n",
543338fd1498Szrj ASM_COMMENT_START,
543438fd1498Szrj DECL_NAME (local.field)
543538fd1498Szrj ? IDENTIFIER_POINTER (DECL_NAME (local.field))
543638fd1498Szrj : "<anonymous>");
543738fd1498Szrj
543838fd1498Szrj /* Eliminate the marker that makes a cast not be an lvalue. */
543938fd1498Szrj if (local.val != NULL_TREE)
544038fd1498Szrj STRIP_NOPS (local.val);
544138fd1498Szrj
544238fd1498Szrj /* Output the current element, using the appropriate helper ... */
544338fd1498Szrj
544438fd1498Szrj /* For an array slice not part of an outer bitfield. */
544538fd1498Szrj if (!outer
544638fd1498Szrj && local.index != NULL_TREE
544738fd1498Szrj && TREE_CODE (local.index) == RANGE_EXPR)
544838fd1498Szrj output_constructor_array_range (&local);
544938fd1498Szrj
545038fd1498Szrj /* For a field that is neither a true bitfield nor part of an outer one,
545138fd1498Szrj known to be at least byte aligned and multiple-of-bytes long. */
545238fd1498Szrj else if (!outer
545338fd1498Szrj && (local.field == NULL_TREE
545438fd1498Szrj || !CONSTRUCTOR_BITFIELD_P (local.field)))
545538fd1498Szrj output_constructor_regular_field (&local);
545638fd1498Szrj
545738fd1498Szrj /* For a true bitfield or part of an outer one. Only INTEGER_CSTs are
545838fd1498Szrj supported for scalar fields, so we may need to convert first. */
545938fd1498Szrj else
546038fd1498Szrj {
546138fd1498Szrj if (TREE_CODE (local.val) == REAL_CST)
546238fd1498Szrj local.val
546338fd1498Szrj = fold_unary (VIEW_CONVERT_EXPR,
546438fd1498Szrj build_nonstandard_integer_type
546538fd1498Szrj (TYPE_PRECISION (TREE_TYPE (local.val)), 0),
546638fd1498Szrj local.val);
546738fd1498Szrj output_constructor_bitfield (&local, outer ? outer->bit_offset : 0);
546838fd1498Szrj }
546938fd1498Szrj }
547038fd1498Szrj
547138fd1498Szrj /* If we are not at toplevel, save the pending data for our caller.
547238fd1498Szrj Otherwise output the pending data and padding zeros as needed. */
547338fd1498Szrj if (outer)
547438fd1498Szrj outer->byte = local.byte;
547538fd1498Szrj else
547638fd1498Szrj {
547738fd1498Szrj if (local.byte_buffer_in_use)
547838fd1498Szrj {
547938fd1498Szrj assemble_integer (GEN_INT (local.byte), 1, BITS_PER_UNIT, 1);
548038fd1498Szrj local.total_bytes++;
548138fd1498Szrj }
548238fd1498Szrj
548338fd1498Szrj if ((unsigned HOST_WIDE_INT)local.total_bytes < local.size)
548438fd1498Szrj {
548538fd1498Szrj assemble_zeros (local.size - local.total_bytes);
548638fd1498Szrj local.total_bytes = local.size;
548738fd1498Szrj }
548838fd1498Szrj }
548938fd1498Szrj
549038fd1498Szrj return local.total_bytes;
549138fd1498Szrj }
549238fd1498Szrj
549338fd1498Szrj /* Mark DECL as weak. */
549438fd1498Szrj
549538fd1498Szrj static void
mark_weak(tree decl)549638fd1498Szrj mark_weak (tree decl)
549738fd1498Szrj {
549838fd1498Szrj if (DECL_WEAK (decl))
549938fd1498Szrj return;
550038fd1498Szrj
550138fd1498Szrj struct symtab_node *n = symtab_node::get (decl);
550238fd1498Szrj if (n && n->refuse_visibility_changes)
550338fd1498Szrj error ("%+qD declared weak after being used", decl);
550438fd1498Szrj DECL_WEAK (decl) = 1;
550538fd1498Szrj
550638fd1498Szrj if (DECL_RTL_SET_P (decl)
550738fd1498Szrj && MEM_P (DECL_RTL (decl))
550838fd1498Szrj && XEXP (DECL_RTL (decl), 0)
550938fd1498Szrj && GET_CODE (XEXP (DECL_RTL (decl), 0)) == SYMBOL_REF)
551038fd1498Szrj SYMBOL_REF_WEAK (XEXP (DECL_RTL (decl), 0)) = 1;
551138fd1498Szrj }
551238fd1498Szrj
551338fd1498Szrj /* Merge weak status between NEWDECL and OLDDECL. */
551438fd1498Szrj
551538fd1498Szrj void
merge_weak(tree newdecl,tree olddecl)551638fd1498Szrj merge_weak (tree newdecl, tree olddecl)
551738fd1498Szrj {
551838fd1498Szrj if (DECL_WEAK (newdecl) == DECL_WEAK (olddecl))
551938fd1498Szrj {
552038fd1498Szrj if (DECL_WEAK (newdecl) && TARGET_SUPPORTS_WEAK)
552138fd1498Szrj {
552238fd1498Szrj tree *pwd;
552338fd1498Szrj /* We put the NEWDECL on the weak_decls list at some point
552438fd1498Szrj and OLDDECL as well. Keep just OLDDECL on the list. */
552538fd1498Szrj for (pwd = &weak_decls; *pwd; pwd = &TREE_CHAIN (*pwd))
552638fd1498Szrj if (TREE_VALUE (*pwd) == newdecl)
552738fd1498Szrj {
552838fd1498Szrj *pwd = TREE_CHAIN (*pwd);
552938fd1498Szrj break;
553038fd1498Szrj }
553138fd1498Szrj }
553238fd1498Szrj return;
553338fd1498Szrj }
553438fd1498Szrj
553538fd1498Szrj if (DECL_WEAK (newdecl))
553638fd1498Szrj {
553738fd1498Szrj tree wd;
553838fd1498Szrj
553938fd1498Szrj /* NEWDECL is weak, but OLDDECL is not. */
554038fd1498Szrj
554138fd1498Szrj /* If we already output the OLDDECL, we're in trouble; we can't
554238fd1498Szrj go back and make it weak. This should never happen in
554338fd1498Szrj unit-at-a-time compilation. */
554438fd1498Szrj gcc_assert (!TREE_ASM_WRITTEN (olddecl));
554538fd1498Szrj
554638fd1498Szrj /* If we've already generated rtl referencing OLDDECL, we may
554738fd1498Szrj have done so in a way that will not function properly with
554838fd1498Szrj a weak symbol. Again in unit-at-a-time this should be
554938fd1498Szrj impossible. */
555038fd1498Szrj gcc_assert (!TREE_USED (olddecl)
555138fd1498Szrj || !TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (olddecl)));
555238fd1498Szrj
555338fd1498Szrj /* PR 49899: You cannot convert a static function into a weak, public function. */
555438fd1498Szrj if (! TREE_PUBLIC (olddecl) && TREE_PUBLIC (newdecl))
555538fd1498Szrj error ("weak declaration of %q+D being applied to a already "
555638fd1498Szrj "existing, static definition", newdecl);
555738fd1498Szrj
555838fd1498Szrj if (TARGET_SUPPORTS_WEAK)
555938fd1498Szrj {
556038fd1498Szrj /* We put the NEWDECL on the weak_decls list at some point.
556138fd1498Szrj Replace it with the OLDDECL. */
556238fd1498Szrj for (wd = weak_decls; wd; wd = TREE_CHAIN (wd))
556338fd1498Szrj if (TREE_VALUE (wd) == newdecl)
556438fd1498Szrj {
556538fd1498Szrj TREE_VALUE (wd) = olddecl;
556638fd1498Szrj break;
556738fd1498Szrj }
556838fd1498Szrj /* We may not find the entry on the list. If NEWDECL is a
556938fd1498Szrj weak alias, then we will have already called
557038fd1498Szrj globalize_decl to remove the entry; in that case, we do
557138fd1498Szrj not need to do anything. */
557238fd1498Szrj }
557338fd1498Szrj
557438fd1498Szrj /* Make the OLDDECL weak; it's OLDDECL that we'll be keeping. */
557538fd1498Szrj mark_weak (olddecl);
557638fd1498Szrj }
557738fd1498Szrj else
557838fd1498Szrj /* OLDDECL was weak, but NEWDECL was not explicitly marked as
557938fd1498Szrj weak. Just update NEWDECL to indicate that it's weak too. */
558038fd1498Szrj mark_weak (newdecl);
558138fd1498Szrj }
558238fd1498Szrj
558338fd1498Szrj /* Declare DECL to be a weak symbol. */
558438fd1498Szrj
558538fd1498Szrj void
declare_weak(tree decl)558638fd1498Szrj declare_weak (tree decl)
558738fd1498Szrj {
558838fd1498Szrj gcc_assert (TREE_CODE (decl) != FUNCTION_DECL || !TREE_ASM_WRITTEN (decl));
558938fd1498Szrj if (! TREE_PUBLIC (decl))
559038fd1498Szrj {
559138fd1498Szrj error ("weak declaration of %q+D must be public", decl);
559238fd1498Szrj return;
559338fd1498Szrj }
559438fd1498Szrj else if (!TARGET_SUPPORTS_WEAK)
559538fd1498Szrj warning (0, "weak declaration of %q+D not supported", decl);
559638fd1498Szrj
559738fd1498Szrj mark_weak (decl);
559838fd1498Szrj if (!lookup_attribute ("weak", DECL_ATTRIBUTES (decl)))
559938fd1498Szrj DECL_ATTRIBUTES (decl)
560038fd1498Szrj = tree_cons (get_identifier ("weak"), NULL, DECL_ATTRIBUTES (decl));
560138fd1498Szrj }
560238fd1498Szrj
560338fd1498Szrj static void
weak_finish_1(tree decl)560438fd1498Szrj weak_finish_1 (tree decl)
560538fd1498Szrj {
560638fd1498Szrj #if defined (ASM_WEAKEN_DECL) || defined (ASM_WEAKEN_LABEL)
560738fd1498Szrj const char *const name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
560838fd1498Szrj #endif
560938fd1498Szrj
561038fd1498Szrj if (! TREE_USED (decl))
561138fd1498Szrj return;
561238fd1498Szrj
561338fd1498Szrj #ifdef ASM_WEAKEN_DECL
561438fd1498Szrj ASM_WEAKEN_DECL (asm_out_file, decl, name, NULL);
561538fd1498Szrj #else
561638fd1498Szrj #ifdef ASM_WEAKEN_LABEL
561738fd1498Szrj ASM_WEAKEN_LABEL (asm_out_file, name);
561838fd1498Szrj #else
561938fd1498Szrj #ifdef ASM_OUTPUT_WEAK_ALIAS
562038fd1498Szrj {
562138fd1498Szrj static bool warn_once = 0;
562238fd1498Szrj if (! warn_once)
562338fd1498Szrj {
562438fd1498Szrj warning (0, "only weak aliases are supported in this configuration");
562538fd1498Szrj warn_once = 1;
562638fd1498Szrj }
562738fd1498Szrj return;
562838fd1498Szrj }
562938fd1498Szrj #endif
563038fd1498Szrj #endif
563138fd1498Szrj #endif
563238fd1498Szrj }
563338fd1498Szrj
563438fd1498Szrj /* Fiven an assembly name, find the decl it is associated with. */
563538fd1498Szrj static tree
find_decl(tree target)563638fd1498Szrj find_decl (tree target)
563738fd1498Szrj {
563838fd1498Szrj symtab_node *node = symtab_node::get_for_asmname (target);
563938fd1498Szrj if (node)
564038fd1498Szrj return node->decl;
564138fd1498Szrj return NULL_TREE;
564238fd1498Szrj }
564338fd1498Szrj
564438fd1498Szrj /* This TREE_LIST contains weakref targets. */
564538fd1498Szrj
564638fd1498Szrj static GTY(()) tree weakref_targets;
564738fd1498Szrj
564838fd1498Szrj /* Emit any pending weak declarations. */
564938fd1498Szrj
565038fd1498Szrj void
weak_finish(void)565138fd1498Szrj weak_finish (void)
565238fd1498Szrj {
565338fd1498Szrj tree t;
565438fd1498Szrj
565538fd1498Szrj for (t = weakref_targets; t; t = TREE_CHAIN (t))
565638fd1498Szrj {
565738fd1498Szrj tree alias_decl = TREE_PURPOSE (t);
565838fd1498Szrj tree target = ultimate_transparent_alias_target (&TREE_VALUE (t));
565938fd1498Szrj
566038fd1498Szrj if (! TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (alias_decl)))
566138fd1498Szrj /* Remove alias_decl from the weak list, but leave entries for
566238fd1498Szrj the target alone. */
566338fd1498Szrj target = NULL_TREE;
566438fd1498Szrj #ifndef ASM_OUTPUT_WEAKREF
566538fd1498Szrj else if (! TREE_SYMBOL_REFERENCED (target))
566638fd1498Szrj {
566738fd1498Szrj /* Use ASM_WEAKEN_LABEL only if ASM_WEAKEN_DECL is not
566838fd1498Szrj defined, otherwise we and weak_finish_1 would use
566938fd1498Szrj different macros. */
567038fd1498Szrj # if defined ASM_WEAKEN_LABEL && ! defined ASM_WEAKEN_DECL
567138fd1498Szrj ASM_WEAKEN_LABEL (asm_out_file, IDENTIFIER_POINTER (target));
567238fd1498Szrj # else
567338fd1498Szrj tree decl = find_decl (target);
567438fd1498Szrj
567538fd1498Szrj if (! decl)
567638fd1498Szrj {
567738fd1498Szrj decl = build_decl (DECL_SOURCE_LOCATION (alias_decl),
567838fd1498Szrj TREE_CODE (alias_decl), target,
567938fd1498Szrj TREE_TYPE (alias_decl));
568038fd1498Szrj
568138fd1498Szrj DECL_EXTERNAL (decl) = 1;
568238fd1498Szrj TREE_PUBLIC (decl) = 1;
568338fd1498Szrj DECL_ARTIFICIAL (decl) = 1;
568438fd1498Szrj TREE_NOTHROW (decl) = TREE_NOTHROW (alias_decl);
568538fd1498Szrj TREE_USED (decl) = 1;
568638fd1498Szrj }
568738fd1498Szrj
568838fd1498Szrj weak_finish_1 (decl);
568938fd1498Szrj # endif
569038fd1498Szrj }
569138fd1498Szrj #endif
569238fd1498Szrj
569338fd1498Szrj {
569438fd1498Szrj tree *p;
569538fd1498Szrj tree t2;
569638fd1498Szrj
569738fd1498Szrj /* Remove the alias and the target from the pending weak list
569838fd1498Szrj so that we do not emit any .weak directives for the former,
569938fd1498Szrj nor multiple .weak directives for the latter. */
570038fd1498Szrj for (p = &weak_decls; (t2 = *p) ; )
570138fd1498Szrj {
570238fd1498Szrj if (TREE_VALUE (t2) == alias_decl
570338fd1498Szrj || target == DECL_ASSEMBLER_NAME (TREE_VALUE (t2)))
570438fd1498Szrj *p = TREE_CHAIN (t2);
570538fd1498Szrj else
570638fd1498Szrj p = &TREE_CHAIN (t2);
570738fd1498Szrj }
570838fd1498Szrj
570938fd1498Szrj /* Remove other weakrefs to the same target, to speed things up. */
571038fd1498Szrj for (p = &TREE_CHAIN (t); (t2 = *p) ; )
571138fd1498Szrj {
571238fd1498Szrj if (target == ultimate_transparent_alias_target (&TREE_VALUE (t2)))
571338fd1498Szrj *p = TREE_CHAIN (t2);
571438fd1498Szrj else
571538fd1498Szrj p = &TREE_CHAIN (t2);
571638fd1498Szrj }
571738fd1498Szrj }
571838fd1498Szrj }
571938fd1498Szrj
572038fd1498Szrj for (t = weak_decls; t; t = TREE_CHAIN (t))
572138fd1498Szrj {
572238fd1498Szrj tree decl = TREE_VALUE (t);
572338fd1498Szrj
572438fd1498Szrj weak_finish_1 (decl);
572538fd1498Szrj }
572638fd1498Szrj }
572738fd1498Szrj
572838fd1498Szrj /* Emit the assembly bits to indicate that DECL is globally visible. */
572938fd1498Szrj
573038fd1498Szrj static void
globalize_decl(tree decl)573138fd1498Szrj globalize_decl (tree decl)
573238fd1498Szrj {
573338fd1498Szrj
573438fd1498Szrj #if defined (ASM_WEAKEN_LABEL) || defined (ASM_WEAKEN_DECL)
573538fd1498Szrj if (DECL_WEAK (decl))
573638fd1498Szrj {
573738fd1498Szrj const char *name = XSTR (XEXP (DECL_RTL (decl), 0), 0);
573838fd1498Szrj tree *p, t;
573938fd1498Szrj
574038fd1498Szrj #ifdef ASM_WEAKEN_DECL
574138fd1498Szrj ASM_WEAKEN_DECL (asm_out_file, decl, name, 0);
574238fd1498Szrj #else
574338fd1498Szrj ASM_WEAKEN_LABEL (asm_out_file, name);
574438fd1498Szrj #endif
574538fd1498Szrj
574638fd1498Szrj /* Remove this function from the pending weak list so that
574738fd1498Szrj we do not emit multiple .weak directives for it. */
574838fd1498Szrj for (p = &weak_decls; (t = *p) ; )
574938fd1498Szrj {
575038fd1498Szrj if (DECL_ASSEMBLER_NAME (decl) == DECL_ASSEMBLER_NAME (TREE_VALUE (t)))
575138fd1498Szrj *p = TREE_CHAIN (t);
575238fd1498Szrj else
575338fd1498Szrj p = &TREE_CHAIN (t);
575438fd1498Szrj }
575538fd1498Szrj
575638fd1498Szrj /* Remove weakrefs to the same target from the pending weakref
575738fd1498Szrj list, for the same reason. */
575838fd1498Szrj for (p = &weakref_targets; (t = *p) ; )
575938fd1498Szrj {
576038fd1498Szrj if (DECL_ASSEMBLER_NAME (decl)
576138fd1498Szrj == ultimate_transparent_alias_target (&TREE_VALUE (t)))
576238fd1498Szrj *p = TREE_CHAIN (t);
576338fd1498Szrj else
576438fd1498Szrj p = &TREE_CHAIN (t);
576538fd1498Szrj }
576638fd1498Szrj
576738fd1498Szrj return;
576838fd1498Szrj }
576938fd1498Szrj #endif
577038fd1498Szrj
577138fd1498Szrj targetm.asm_out.globalize_decl_name (asm_out_file, decl);
577238fd1498Szrj }
577338fd1498Szrj
577438fd1498Szrj vec<alias_pair, va_gc> *alias_pairs;
577538fd1498Szrj
577638fd1498Szrj /* Output the assembler code for a define (equate) using ASM_OUTPUT_DEF
577738fd1498Szrj or ASM_OUTPUT_DEF_FROM_DECLS. The function defines the symbol whose
577838fd1498Szrj tree node is DECL to have the value of the tree node TARGET. */
577938fd1498Szrj
578038fd1498Szrj void
do_assemble_alias(tree decl,tree target)578138fd1498Szrj do_assemble_alias (tree decl, tree target)
578238fd1498Szrj {
578338fd1498Szrj tree id;
578438fd1498Szrj
578538fd1498Szrj /* Emulated TLS had better not get this var. */
578638fd1498Szrj gcc_assert (!(!targetm.have_tls
578738fd1498Szrj && VAR_P (decl)
578838fd1498Szrj && DECL_THREAD_LOCAL_P (decl)));
578938fd1498Szrj
579038fd1498Szrj if (TREE_ASM_WRITTEN (decl))
579138fd1498Szrj return;
579238fd1498Szrj
579338fd1498Szrj id = DECL_ASSEMBLER_NAME (decl);
579438fd1498Szrj ultimate_transparent_alias_target (&id);
579538fd1498Szrj ultimate_transparent_alias_target (&target);
579638fd1498Szrj
579738fd1498Szrj /* We must force creation of DECL_RTL for debug info generation, even though
579838fd1498Szrj we don't use it here. */
579938fd1498Szrj make_decl_rtl (decl);
580038fd1498Szrj
580138fd1498Szrj TREE_ASM_WRITTEN (decl) = 1;
580238fd1498Szrj TREE_ASM_WRITTEN (DECL_ASSEMBLER_NAME (decl)) = 1;
580338fd1498Szrj TREE_ASM_WRITTEN (id) = 1;
580438fd1498Szrj
580538fd1498Szrj if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl)))
580638fd1498Szrj {
580738fd1498Szrj if (!TREE_SYMBOL_REFERENCED (target))
580838fd1498Szrj weakref_targets = tree_cons (decl, target, weakref_targets);
580938fd1498Szrj
581038fd1498Szrj #ifdef ASM_OUTPUT_WEAKREF
581138fd1498Szrj ASM_OUTPUT_WEAKREF (asm_out_file, decl,
581238fd1498Szrj IDENTIFIER_POINTER (id),
581338fd1498Szrj IDENTIFIER_POINTER (target));
581438fd1498Szrj #else
581538fd1498Szrj if (!TARGET_SUPPORTS_WEAK)
581638fd1498Szrj {
581738fd1498Szrj error_at (DECL_SOURCE_LOCATION (decl),
581838fd1498Szrj "weakref is not supported in this configuration");
581938fd1498Szrj return;
582038fd1498Szrj }
582138fd1498Szrj #endif
582238fd1498Szrj return;
582338fd1498Szrj }
582438fd1498Szrj
582538fd1498Szrj #ifdef ASM_OUTPUT_DEF
582638fd1498Szrj tree orig_decl = decl;
582738fd1498Szrj
582838fd1498Szrj if (TREE_CODE (decl) == FUNCTION_DECL
582938fd1498Szrj && cgraph_node::get (decl)->instrumentation_clone
583038fd1498Szrj && cgraph_node::get (decl)->instrumented_version)
583138fd1498Szrj orig_decl = cgraph_node::get (decl)->instrumented_version->decl;
583238fd1498Szrj
583338fd1498Szrj /* Make name accessible from other files, if appropriate. */
583438fd1498Szrj
583538fd1498Szrj if (TREE_PUBLIC (decl) || TREE_PUBLIC (orig_decl))
583638fd1498Szrj {
583738fd1498Szrj globalize_decl (decl);
583838fd1498Szrj maybe_assemble_visibility (decl);
583938fd1498Szrj }
5840*58e805e6Szrj if (TREE_CODE (decl) == FUNCTION_DECL
5841*58e805e6Szrj && cgraph_node::get (decl)->ifunc_resolver)
584238fd1498Szrj {
584338fd1498Szrj #if defined (ASM_OUTPUT_TYPE_DIRECTIVE)
584438fd1498Szrj if (targetm.has_ifunc_p ())
584538fd1498Szrj ASM_OUTPUT_TYPE_DIRECTIVE
584638fd1498Szrj (asm_out_file, IDENTIFIER_POINTER (id),
584738fd1498Szrj IFUNC_ASM_TYPE);
584838fd1498Szrj else
584938fd1498Szrj #endif
585038fd1498Szrj error_at (DECL_SOURCE_LOCATION (decl),
585138fd1498Szrj "ifunc is not supported on this target");
585238fd1498Szrj }
585338fd1498Szrj
585438fd1498Szrj # ifdef ASM_OUTPUT_DEF_FROM_DECLS
585538fd1498Szrj ASM_OUTPUT_DEF_FROM_DECLS (asm_out_file, decl, target);
585638fd1498Szrj # else
585738fd1498Szrj ASM_OUTPUT_DEF (asm_out_file,
585838fd1498Szrj IDENTIFIER_POINTER (id),
585938fd1498Szrj IDENTIFIER_POINTER (target));
586038fd1498Szrj # endif
586138fd1498Szrj #elif defined (ASM_OUTPUT_WEAK_ALIAS) || defined (ASM_WEAKEN_DECL)
586238fd1498Szrj {
586338fd1498Szrj const char *name;
586438fd1498Szrj tree *p, t;
586538fd1498Szrj
586638fd1498Szrj name = IDENTIFIER_POINTER (id);
586738fd1498Szrj # ifdef ASM_WEAKEN_DECL
586838fd1498Szrj ASM_WEAKEN_DECL (asm_out_file, decl, name, IDENTIFIER_POINTER (target));
586938fd1498Szrj # else
587038fd1498Szrj ASM_OUTPUT_WEAK_ALIAS (asm_out_file, name, IDENTIFIER_POINTER (target));
587138fd1498Szrj # endif
587238fd1498Szrj /* Remove this function from the pending weak list so that
587338fd1498Szrj we do not emit multiple .weak directives for it. */
587438fd1498Szrj for (p = &weak_decls; (t = *p) ; )
587538fd1498Szrj if (DECL_ASSEMBLER_NAME (decl) == DECL_ASSEMBLER_NAME (TREE_VALUE (t))
587638fd1498Szrj || id == DECL_ASSEMBLER_NAME (TREE_VALUE (t)))
587738fd1498Szrj *p = TREE_CHAIN (t);
587838fd1498Szrj else
587938fd1498Szrj p = &TREE_CHAIN (t);
588038fd1498Szrj
588138fd1498Szrj /* Remove weakrefs to the same target from the pending weakref
588238fd1498Szrj list, for the same reason. */
588338fd1498Szrj for (p = &weakref_targets; (t = *p) ; )
588438fd1498Szrj {
588538fd1498Szrj if (id == ultimate_transparent_alias_target (&TREE_VALUE (t)))
588638fd1498Szrj *p = TREE_CHAIN (t);
588738fd1498Szrj else
588838fd1498Szrj p = &TREE_CHAIN (t);
588938fd1498Szrj }
589038fd1498Szrj }
589138fd1498Szrj #endif
589238fd1498Szrj }
589338fd1498Szrj
589438fd1498Szrj /* Emit an assembler directive to make the symbol for DECL an alias to
589538fd1498Szrj the symbol for TARGET. */
589638fd1498Szrj
589738fd1498Szrj void
assemble_alias(tree decl,tree target)589838fd1498Szrj assemble_alias (tree decl, tree target)
589938fd1498Szrj {
590038fd1498Szrj tree target_decl;
590138fd1498Szrj
590238fd1498Szrj if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl)))
590338fd1498Szrj {
590438fd1498Szrj tree alias = DECL_ASSEMBLER_NAME (decl);
590538fd1498Szrj
590638fd1498Szrj ultimate_transparent_alias_target (&target);
590738fd1498Szrj
590838fd1498Szrj if (alias == target)
590938fd1498Szrj error ("weakref %q+D ultimately targets itself", decl);
591038fd1498Szrj if (TREE_PUBLIC (decl))
591138fd1498Szrj error ("weakref %q+D must have static linkage", decl);
591238fd1498Szrj }
591338fd1498Szrj else
591438fd1498Szrj {
591538fd1498Szrj #if !defined (ASM_OUTPUT_DEF)
591638fd1498Szrj # if !defined(ASM_OUTPUT_WEAK_ALIAS) && !defined (ASM_WEAKEN_DECL)
591738fd1498Szrj error_at (DECL_SOURCE_LOCATION (decl),
591838fd1498Szrj "alias definitions not supported in this configuration");
591938fd1498Szrj TREE_ASM_WRITTEN (decl) = 1;
592038fd1498Szrj return;
592138fd1498Szrj # else
592238fd1498Szrj if (!DECL_WEAK (decl))
592338fd1498Szrj {
5924*58e805e6Szrj /* NB: ifunc_resolver isn't set when an error is detected. */
5925*58e805e6Szrj if (TREE_CODE (decl) == FUNCTION_DECL
5926*58e805e6Szrj && lookup_attribute ("ifunc", DECL_ATTRIBUTES (decl)))
592738fd1498Szrj error_at (DECL_SOURCE_LOCATION (decl),
592838fd1498Szrj "ifunc is not supported in this configuration");
592938fd1498Szrj else
593038fd1498Szrj error_at (DECL_SOURCE_LOCATION (decl),
593138fd1498Szrj "only weak aliases are supported in this configuration");
593238fd1498Szrj TREE_ASM_WRITTEN (decl) = 1;
593338fd1498Szrj return;
593438fd1498Szrj }
593538fd1498Szrj # endif
593638fd1498Szrj #endif
593738fd1498Szrj }
593838fd1498Szrj TREE_USED (decl) = 1;
593938fd1498Szrj
594038fd1498Szrj /* Allow aliases to aliases. */
594138fd1498Szrj if (TREE_CODE (decl) == FUNCTION_DECL)
594238fd1498Szrj cgraph_node::get_create (decl)->alias = true;
594338fd1498Szrj else
594438fd1498Szrj varpool_node::get_create (decl)->alias = true;
594538fd1498Szrj
594638fd1498Szrj /* If the target has already been emitted, we don't have to queue the
594738fd1498Szrj alias. This saves a tad of memory. */
594838fd1498Szrj if (symtab->global_info_ready)
594938fd1498Szrj target_decl = find_decl (target);
595038fd1498Szrj else
595138fd1498Szrj target_decl= NULL;
595238fd1498Szrj if ((target_decl && TREE_ASM_WRITTEN (target_decl))
595338fd1498Szrj || symtab->state >= EXPANSION)
595438fd1498Szrj do_assemble_alias (decl, target);
595538fd1498Szrj else
595638fd1498Szrj {
595738fd1498Szrj alias_pair p = {decl, target};
595838fd1498Szrj vec_safe_push (alias_pairs, p);
595938fd1498Szrj }
596038fd1498Szrj }
596138fd1498Szrj
596238fd1498Szrj /* Record and output a table of translations from original function
596338fd1498Szrj to its transaction aware clone. Note that tm_pure functions are
596438fd1498Szrj considered to be their own clone. */
596538fd1498Szrj
596638fd1498Szrj struct tm_clone_hasher : ggc_cache_ptr_hash<tree_map>
596738fd1498Szrj {
hashtm_clone_hasher596838fd1498Szrj static hashval_t hash (tree_map *m) { return tree_map_hash (m); }
equaltm_clone_hasher596938fd1498Szrj static bool equal (tree_map *a, tree_map *b) { return tree_map_eq (a, b); }
597038fd1498Szrj
597138fd1498Szrj static int
keep_cache_entrytm_clone_hasher597238fd1498Szrj keep_cache_entry (tree_map *&e)
597338fd1498Szrj {
597438fd1498Szrj return ggc_marked_p (e->base.from);
597538fd1498Szrj }
597638fd1498Szrj };
597738fd1498Szrj
597838fd1498Szrj static GTY((cache)) hash_table<tm_clone_hasher> *tm_clone_hash;
597938fd1498Szrj
598038fd1498Szrj void
record_tm_clone_pair(tree o,tree n)598138fd1498Szrj record_tm_clone_pair (tree o, tree n)
598238fd1498Szrj {
598338fd1498Szrj struct tree_map **slot, *h;
598438fd1498Szrj
598538fd1498Szrj if (tm_clone_hash == NULL)
598638fd1498Szrj tm_clone_hash = hash_table<tm_clone_hasher>::create_ggc (32);
598738fd1498Szrj
598838fd1498Szrj h = ggc_alloc<tree_map> ();
598938fd1498Szrj h->hash = htab_hash_pointer (o);
599038fd1498Szrj h->base.from = o;
599138fd1498Szrj h->to = n;
599238fd1498Szrj
599338fd1498Szrj slot = tm_clone_hash->find_slot_with_hash (h, h->hash, INSERT);
599438fd1498Szrj *slot = h;
599538fd1498Szrj }
599638fd1498Szrj
599738fd1498Szrj tree
get_tm_clone_pair(tree o)599838fd1498Szrj get_tm_clone_pair (tree o)
599938fd1498Szrj {
600038fd1498Szrj if (tm_clone_hash)
600138fd1498Szrj {
600238fd1498Szrj struct tree_map *h, in;
600338fd1498Szrj
600438fd1498Szrj in.base.from = o;
600538fd1498Szrj in.hash = htab_hash_pointer (o);
600638fd1498Szrj h = tm_clone_hash->find_with_hash (&in, in.hash);
600738fd1498Szrj if (h)
600838fd1498Szrj return h->to;
600938fd1498Szrj }
601038fd1498Szrj return NULL_TREE;
601138fd1498Szrj }
601238fd1498Szrj
601338fd1498Szrj struct tm_alias_pair
601438fd1498Szrj {
601538fd1498Szrj unsigned int uid;
601638fd1498Szrj tree from;
601738fd1498Szrj tree to;
601838fd1498Szrj };
601938fd1498Szrj
602038fd1498Szrj
602138fd1498Szrj /* Dump the actual pairs to the .tm_clone_table section. */
602238fd1498Szrj
602338fd1498Szrj static void
dump_tm_clone_pairs(vec<tm_alias_pair> tm_alias_pairs)602438fd1498Szrj dump_tm_clone_pairs (vec<tm_alias_pair> tm_alias_pairs)
602538fd1498Szrj {
602638fd1498Szrj unsigned i;
602738fd1498Szrj tm_alias_pair *p;
602838fd1498Szrj bool switched = false;
602938fd1498Szrj
603038fd1498Szrj FOR_EACH_VEC_ELT (tm_alias_pairs, i, p)
603138fd1498Szrj {
603238fd1498Szrj tree src = p->from;
603338fd1498Szrj tree dst = p->to;
603438fd1498Szrj struct cgraph_node *src_n = cgraph_node::get (src);
603538fd1498Szrj struct cgraph_node *dst_n = cgraph_node::get (dst);
603638fd1498Szrj
603738fd1498Szrj /* The function ipa_tm_create_version() marks the clone as needed if
603838fd1498Szrj the original function was needed. But we also mark the clone as
603938fd1498Szrj needed if we ever called the clone indirectly through
604038fd1498Szrj TM_GETTMCLONE. If neither of these are true, we didn't generate
604138fd1498Szrj a clone, and we didn't call it indirectly... no sense keeping it
604238fd1498Szrj in the clone table. */
604338fd1498Szrj if (!dst_n || !dst_n->definition)
604438fd1498Szrj continue;
604538fd1498Szrj
604638fd1498Szrj /* This covers the case where we have optimized the original
604738fd1498Szrj function away, and only access the transactional clone. */
604838fd1498Szrj if (!src_n || !src_n->definition)
604938fd1498Szrj continue;
605038fd1498Szrj
605138fd1498Szrj if (!switched)
605238fd1498Szrj {
605338fd1498Szrj switch_to_section (targetm.asm_out.tm_clone_table_section ());
605438fd1498Szrj assemble_align (POINTER_SIZE);
605538fd1498Szrj switched = true;
605638fd1498Szrj }
605738fd1498Szrj
605838fd1498Szrj assemble_integer (XEXP (DECL_RTL (src), 0),
605938fd1498Szrj POINTER_SIZE_UNITS, POINTER_SIZE, 1);
606038fd1498Szrj assemble_integer (XEXP (DECL_RTL (dst), 0),
606138fd1498Szrj POINTER_SIZE_UNITS, POINTER_SIZE, 1);
606238fd1498Szrj }
606338fd1498Szrj }
606438fd1498Szrj
606538fd1498Szrj /* Provide a default for the tm_clone_table section. */
606638fd1498Szrj
606738fd1498Szrj section *
default_clone_table_section(void)606838fd1498Szrj default_clone_table_section (void)
606938fd1498Szrj {
607038fd1498Szrj return get_named_section (NULL, ".tm_clone_table", 3);
607138fd1498Szrj }
607238fd1498Szrj
607338fd1498Szrj /* Helper comparison function for qsorting by the DECL_UID stored in
607438fd1498Szrj alias_pair->emitted_diags. */
607538fd1498Szrj
607638fd1498Szrj static int
tm_alias_pair_cmp(const void * x,const void * y)607738fd1498Szrj tm_alias_pair_cmp (const void *x, const void *y)
607838fd1498Szrj {
607938fd1498Szrj const tm_alias_pair *p1 = (const tm_alias_pair *) x;
608038fd1498Szrj const tm_alias_pair *p2 = (const tm_alias_pair *) y;
608138fd1498Szrj if (p1->uid < p2->uid)
608238fd1498Szrj return -1;
608338fd1498Szrj if (p1->uid > p2->uid)
608438fd1498Szrj return 1;
608538fd1498Szrj return 0;
608638fd1498Szrj }
608738fd1498Szrj
608838fd1498Szrj void
finish_tm_clone_pairs(void)608938fd1498Szrj finish_tm_clone_pairs (void)
609038fd1498Szrj {
609138fd1498Szrj vec<tm_alias_pair> tm_alias_pairs = vNULL;
609238fd1498Szrj
609338fd1498Szrj if (tm_clone_hash == NULL)
609438fd1498Szrj return;
609538fd1498Szrj
609638fd1498Szrj /* We need a determenistic order for the .tm_clone_table, otherwise
609738fd1498Szrj we will get bootstrap comparison failures, so dump the hash table
609838fd1498Szrj to a vector, sort it, and dump the vector. */
609938fd1498Szrj
610038fd1498Szrj /* Dump the hashtable to a vector. */
610138fd1498Szrj tree_map *map;
610238fd1498Szrj hash_table<tm_clone_hasher>::iterator iter;
610338fd1498Szrj FOR_EACH_HASH_TABLE_ELEMENT (*tm_clone_hash, map, tree_map *, iter)
610438fd1498Szrj {
610538fd1498Szrj tm_alias_pair p = {DECL_UID (map->base.from), map->base.from, map->to};
610638fd1498Szrj tm_alias_pairs.safe_push (p);
610738fd1498Szrj }
610838fd1498Szrj /* Sort it. */
610938fd1498Szrj tm_alias_pairs.qsort (tm_alias_pair_cmp);
611038fd1498Szrj
611138fd1498Szrj /* Dump it. */
611238fd1498Szrj dump_tm_clone_pairs (tm_alias_pairs);
611338fd1498Szrj
611438fd1498Szrj tm_clone_hash->empty ();
611538fd1498Szrj tm_clone_hash = NULL;
611638fd1498Szrj tm_alias_pairs.release ();
611738fd1498Szrj }
611838fd1498Szrj
611938fd1498Szrj
612038fd1498Szrj /* Emit an assembler directive to set symbol for DECL visibility to
612138fd1498Szrj the visibility type VIS, which must not be VISIBILITY_DEFAULT. */
612238fd1498Szrj
612338fd1498Szrj void
default_assemble_visibility(tree decl ATTRIBUTE_UNUSED,int vis ATTRIBUTE_UNUSED)612438fd1498Szrj default_assemble_visibility (tree decl ATTRIBUTE_UNUSED,
612538fd1498Szrj int vis ATTRIBUTE_UNUSED)
612638fd1498Szrj {
612738fd1498Szrj #ifdef HAVE_GAS_HIDDEN
612838fd1498Szrj static const char * const visibility_types[] = {
612938fd1498Szrj NULL, "protected", "hidden", "internal"
613038fd1498Szrj };
613138fd1498Szrj
613238fd1498Szrj const char *name, *type;
613338fd1498Szrj tree id;
613438fd1498Szrj
613538fd1498Szrj id = DECL_ASSEMBLER_NAME (decl);
613638fd1498Szrj ultimate_transparent_alias_target (&id);
613738fd1498Szrj name = IDENTIFIER_POINTER (id);
613838fd1498Szrj
613938fd1498Szrj type = visibility_types[vis];
614038fd1498Szrj
614138fd1498Szrj fprintf (asm_out_file, "\t.%s\t", type);
614238fd1498Szrj assemble_name (asm_out_file, name);
614338fd1498Szrj fprintf (asm_out_file, "\n");
614438fd1498Szrj #else
614538fd1498Szrj if (!DECL_ARTIFICIAL (decl))
614638fd1498Szrj warning (OPT_Wattributes, "visibility attribute not supported "
614738fd1498Szrj "in this configuration; ignored");
614838fd1498Szrj #endif
614938fd1498Szrj }
615038fd1498Szrj
615138fd1498Szrj /* A helper function to call assemble_visibility when needed for a decl. */
615238fd1498Szrj
615338fd1498Szrj int
maybe_assemble_visibility(tree decl)615438fd1498Szrj maybe_assemble_visibility (tree decl)
615538fd1498Szrj {
615638fd1498Szrj enum symbol_visibility vis = DECL_VISIBILITY (decl);
615738fd1498Szrj
615838fd1498Szrj if (TREE_CODE (decl) == FUNCTION_DECL
615938fd1498Szrj && cgraph_node::get (decl)
616038fd1498Szrj && cgraph_node::get (decl)->instrumentation_clone
616138fd1498Szrj && cgraph_node::get (decl)->instrumented_version)
616238fd1498Szrj vis = DECL_VISIBILITY (cgraph_node::get (decl)->instrumented_version->decl);
616338fd1498Szrj
616438fd1498Szrj if (vis != VISIBILITY_DEFAULT)
616538fd1498Szrj {
616638fd1498Szrj targetm.asm_out.assemble_visibility (decl, vis);
616738fd1498Szrj return 1;
616838fd1498Szrj }
616938fd1498Szrj else
617038fd1498Szrj return 0;
617138fd1498Szrj }
617238fd1498Szrj
617338fd1498Szrj /* Returns 1 if the target configuration supports defining public symbols
617438fd1498Szrj so that one of them will be chosen at link time instead of generating a
617538fd1498Szrj multiply-defined symbol error, whether through the use of weak symbols or
617638fd1498Szrj a target-specific mechanism for having duplicates discarded. */
617738fd1498Szrj
617838fd1498Szrj int
supports_one_only(void)617938fd1498Szrj supports_one_only (void)
618038fd1498Szrj {
618138fd1498Szrj if (SUPPORTS_ONE_ONLY)
618238fd1498Szrj return 1;
618338fd1498Szrj return TARGET_SUPPORTS_WEAK;
618438fd1498Szrj }
618538fd1498Szrj
618638fd1498Szrj /* Set up DECL as a public symbol that can be defined in multiple
618738fd1498Szrj translation units without generating a linker error. */
618838fd1498Szrj
618938fd1498Szrj void
make_decl_one_only(tree decl,tree comdat_group)619038fd1498Szrj make_decl_one_only (tree decl, tree comdat_group)
619138fd1498Szrj {
619238fd1498Szrj struct symtab_node *symbol;
619338fd1498Szrj gcc_assert (VAR_OR_FUNCTION_DECL_P (decl));
619438fd1498Szrj
619538fd1498Szrj TREE_PUBLIC (decl) = 1;
619638fd1498Szrj
619738fd1498Szrj if (VAR_P (decl))
619838fd1498Szrj symbol = varpool_node::get_create (decl);
619938fd1498Szrj else
620038fd1498Szrj symbol = cgraph_node::get_create (decl);
620138fd1498Szrj
620238fd1498Szrj if (SUPPORTS_ONE_ONLY)
620338fd1498Szrj {
620438fd1498Szrj #ifdef MAKE_DECL_ONE_ONLY
620538fd1498Szrj MAKE_DECL_ONE_ONLY (decl);
620638fd1498Szrj #endif
620738fd1498Szrj symbol->set_comdat_group (comdat_group);
620838fd1498Szrj }
620938fd1498Szrj else if (VAR_P (decl)
621038fd1498Szrj && (DECL_INITIAL (decl) == 0
621138fd1498Szrj || (!in_lto_p && DECL_INITIAL (decl) == error_mark_node)))
621238fd1498Szrj DECL_COMMON (decl) = 1;
621338fd1498Szrj else
621438fd1498Szrj {
621538fd1498Szrj gcc_assert (TARGET_SUPPORTS_WEAK);
621638fd1498Szrj DECL_WEAK (decl) = 1;
621738fd1498Szrj }
621838fd1498Szrj }
621938fd1498Szrj
622038fd1498Szrj void
init_varasm_once(void)622138fd1498Szrj init_varasm_once (void)
622238fd1498Szrj {
622338fd1498Szrj section_htab = hash_table<section_hasher>::create_ggc (31);
622438fd1498Szrj object_block_htab = hash_table<object_block_hasher>::create_ggc (31);
622538fd1498Szrj const_desc_htab = hash_table<tree_descriptor_hasher>::create_ggc (1009);
622638fd1498Szrj
622738fd1498Szrj shared_constant_pool = create_constant_pool ();
622838fd1498Szrj
622938fd1498Szrj #ifdef TEXT_SECTION_ASM_OP
623038fd1498Szrj text_section = get_unnamed_section (SECTION_CODE, output_section_asm_op,
623138fd1498Szrj TEXT_SECTION_ASM_OP);
623238fd1498Szrj #endif
623338fd1498Szrj
623438fd1498Szrj #ifdef DATA_SECTION_ASM_OP
623538fd1498Szrj data_section = get_unnamed_section (SECTION_WRITE, output_section_asm_op,
623638fd1498Szrj DATA_SECTION_ASM_OP);
623738fd1498Szrj #endif
623838fd1498Szrj
623938fd1498Szrj #ifdef SDATA_SECTION_ASM_OP
624038fd1498Szrj sdata_section = get_unnamed_section (SECTION_WRITE, output_section_asm_op,
624138fd1498Szrj SDATA_SECTION_ASM_OP);
624238fd1498Szrj #endif
624338fd1498Szrj
624438fd1498Szrj #ifdef READONLY_DATA_SECTION_ASM_OP
624538fd1498Szrj readonly_data_section = get_unnamed_section (0, output_section_asm_op,
624638fd1498Szrj READONLY_DATA_SECTION_ASM_OP);
624738fd1498Szrj #endif
624838fd1498Szrj
624938fd1498Szrj #ifdef CTORS_SECTION_ASM_OP
625038fd1498Szrj ctors_section = get_unnamed_section (0, output_section_asm_op,
625138fd1498Szrj CTORS_SECTION_ASM_OP);
625238fd1498Szrj #endif
625338fd1498Szrj
625438fd1498Szrj #ifdef DTORS_SECTION_ASM_OP
625538fd1498Szrj dtors_section = get_unnamed_section (0, output_section_asm_op,
625638fd1498Szrj DTORS_SECTION_ASM_OP);
625738fd1498Szrj #endif
625838fd1498Szrj
625938fd1498Szrj #ifdef BSS_SECTION_ASM_OP
626038fd1498Szrj bss_section = get_unnamed_section (SECTION_WRITE | SECTION_BSS,
626138fd1498Szrj output_section_asm_op,
626238fd1498Szrj BSS_SECTION_ASM_OP);
626338fd1498Szrj #endif
626438fd1498Szrj
626538fd1498Szrj #ifdef SBSS_SECTION_ASM_OP
626638fd1498Szrj sbss_section = get_unnamed_section (SECTION_WRITE | SECTION_BSS,
626738fd1498Szrj output_section_asm_op,
626838fd1498Szrj SBSS_SECTION_ASM_OP);
626938fd1498Szrj #endif
627038fd1498Szrj
627138fd1498Szrj tls_comm_section = get_noswitch_section (SECTION_WRITE | SECTION_BSS
627238fd1498Szrj | SECTION_COMMON, emit_tls_common);
627338fd1498Szrj lcomm_section = get_noswitch_section (SECTION_WRITE | SECTION_BSS
627438fd1498Szrj | SECTION_COMMON, emit_local);
627538fd1498Szrj comm_section = get_noswitch_section (SECTION_WRITE | SECTION_BSS
627638fd1498Szrj | SECTION_COMMON, emit_common);
627738fd1498Szrj
627838fd1498Szrj #if defined ASM_OUTPUT_ALIGNED_BSS
627938fd1498Szrj bss_noswitch_section = get_noswitch_section (SECTION_WRITE | SECTION_BSS,
628038fd1498Szrj emit_bss);
628138fd1498Szrj #endif
628238fd1498Szrj
628338fd1498Szrj targetm.asm_out.init_sections ();
628438fd1498Szrj
628538fd1498Szrj if (readonly_data_section == NULL)
628638fd1498Szrj readonly_data_section = text_section;
628738fd1498Szrj
628838fd1498Szrj #ifdef ASM_OUTPUT_EXTERNAL
628938fd1498Szrj pending_assemble_externals_set = new hash_set<tree>;
629038fd1498Szrj #endif
629138fd1498Szrj }
629238fd1498Szrj
629338fd1498Szrj enum tls_model
decl_default_tls_model(const_tree decl)629438fd1498Szrj decl_default_tls_model (const_tree decl)
629538fd1498Szrj {
629638fd1498Szrj enum tls_model kind;
629738fd1498Szrj bool is_local;
629838fd1498Szrj
629938fd1498Szrj is_local = targetm.binds_local_p (decl);
630038fd1498Szrj if (!flag_shlib)
630138fd1498Szrj {
630238fd1498Szrj if (is_local)
630338fd1498Szrj kind = TLS_MODEL_LOCAL_EXEC;
630438fd1498Szrj else
630538fd1498Szrj kind = TLS_MODEL_INITIAL_EXEC;
630638fd1498Szrj }
630738fd1498Szrj
630838fd1498Szrj /* Local dynamic is inefficient when we're not combining the
630938fd1498Szrj parts of the address. */
631038fd1498Szrj else if (optimize && is_local)
631138fd1498Szrj kind = TLS_MODEL_LOCAL_DYNAMIC;
631238fd1498Szrj else
631338fd1498Szrj kind = TLS_MODEL_GLOBAL_DYNAMIC;
631438fd1498Szrj if (kind < flag_tls_default)
631538fd1498Szrj kind = flag_tls_default;
631638fd1498Szrj
631738fd1498Szrj return kind;
631838fd1498Szrj }
631938fd1498Szrj
632038fd1498Szrj /* Select a set of attributes for section NAME based on the properties
632138fd1498Szrj of DECL and whether or not RELOC indicates that DECL's initializer
632238fd1498Szrj might contain runtime relocations.
632338fd1498Szrj
632438fd1498Szrj We make the section read-only and executable for a function decl,
632538fd1498Szrj read-only for a const data decl, and writable for a non-const data decl. */
632638fd1498Szrj
632738fd1498Szrj unsigned int
default_section_type_flags(tree decl,const char * name,int reloc)632838fd1498Szrj default_section_type_flags (tree decl, const char *name, int reloc)
632938fd1498Szrj {
633038fd1498Szrj unsigned int flags;
633138fd1498Szrj
633238fd1498Szrj if (decl && TREE_CODE (decl) == FUNCTION_DECL)
633338fd1498Szrj flags = SECTION_CODE;
633438fd1498Szrj else if (decl)
633538fd1498Szrj {
633638fd1498Szrj enum section_category category
633738fd1498Szrj = categorize_decl_for_section (decl, reloc);
633838fd1498Szrj if (decl_readonly_section_1 (category))
633938fd1498Szrj flags = 0;
634038fd1498Szrj else if (category == SECCAT_DATA_REL_RO
634138fd1498Szrj || category == SECCAT_DATA_REL_RO_LOCAL)
634238fd1498Szrj flags = SECTION_WRITE | SECTION_RELRO;
634338fd1498Szrj else
634438fd1498Szrj flags = SECTION_WRITE;
634538fd1498Szrj }
634638fd1498Szrj else
634738fd1498Szrj {
634838fd1498Szrj flags = SECTION_WRITE;
634938fd1498Szrj if (strcmp (name, ".data.rel.ro") == 0
635038fd1498Szrj || strcmp (name, ".data.rel.ro.local") == 0)
635138fd1498Szrj flags |= SECTION_RELRO;
635238fd1498Szrj }
635338fd1498Szrj
635438fd1498Szrj if (decl && DECL_P (decl) && DECL_COMDAT_GROUP (decl))
635538fd1498Szrj flags |= SECTION_LINKONCE;
635638fd1498Szrj
635738fd1498Szrj if (strcmp (name, ".vtable_map_vars") == 0)
635838fd1498Szrj flags |= SECTION_LINKONCE;
635938fd1498Szrj
636038fd1498Szrj if (decl && VAR_P (decl) && DECL_THREAD_LOCAL_P (decl))
636138fd1498Szrj flags |= SECTION_TLS | SECTION_WRITE;
636238fd1498Szrj
636338fd1498Szrj if (strcmp (name, ".bss") == 0
636438fd1498Szrj || strncmp (name, ".bss.", 5) == 0
636538fd1498Szrj || strncmp (name, ".gnu.linkonce.b.", 16) == 0
636638fd1498Szrj || strcmp (name, ".persistent.bss") == 0
636738fd1498Szrj || strcmp (name, ".sbss") == 0
636838fd1498Szrj || strncmp (name, ".sbss.", 6) == 0
636938fd1498Szrj || strncmp (name, ".gnu.linkonce.sb.", 17) == 0)
637038fd1498Szrj flags |= SECTION_BSS;
637138fd1498Szrj
637238fd1498Szrj if (strcmp (name, ".tdata") == 0
637338fd1498Szrj || strncmp (name, ".tdata.", 7) == 0
637438fd1498Szrj || strncmp (name, ".gnu.linkonce.td.", 17) == 0)
637538fd1498Szrj flags |= SECTION_TLS;
637638fd1498Szrj
637738fd1498Szrj if (strcmp (name, ".tbss") == 0
637838fd1498Szrj || strncmp (name, ".tbss.", 6) == 0
637938fd1498Szrj || strncmp (name, ".gnu.linkonce.tb.", 17) == 0)
638038fd1498Szrj flags |= SECTION_TLS | SECTION_BSS;
638138fd1498Szrj
6382*58e805e6Szrj /* Various sections have special ELF types that the assembler will
6383*58e805e6Szrj assign by default based on the name. They are neither SHT_PROGBITS
6384*58e805e6Szrj nor SHT_NOBITS, so when changing sections we don't want to print a
6385*58e805e6Szrj section type (@progbits or @nobits). Rather than duplicating the
6386*58e805e6Szrj assembler's knowledge of what those special name patterns are, just
6387*58e805e6Szrj let the assembler choose the type if we don't know a specific
6388*58e805e6Szrj reason to set it to something other than the default. SHT_PROGBITS
6389*58e805e6Szrj is the default for sections whose name is not specially known to
6390*58e805e6Szrj the assembler, so it does no harm to leave the choice to the
6391*58e805e6Szrj assembler when @progbits is the best thing we know to use. If
6392*58e805e6Szrj someone is silly enough to emit code or TLS variables to one of
6393*58e805e6Szrj these sections, then don't handle them specially.
6394*58e805e6Szrj
6395*58e805e6Szrj default_elf_asm_named_section (below) handles the BSS, TLS, ENTSIZE, and
6396*58e805e6Szrj LINKONCE cases when NOTYPE is not set, so leave those to its logic. */
6397*58e805e6Szrj if (!(flags & (SECTION_CODE | SECTION_BSS | SECTION_TLS | SECTION_ENTSIZE))
6398*58e805e6Szrj && !(HAVE_COMDAT_GROUP && (flags & SECTION_LINKONCE)))
639938fd1498Szrj flags |= SECTION_NOTYPE;
640038fd1498Szrj
640138fd1498Szrj return flags;
640238fd1498Szrj }
640338fd1498Szrj
640438fd1498Szrj /* Return true if the target supports some form of global BSS,
640538fd1498Szrj either through bss_noswitch_section, or by selecting a BSS
640638fd1498Szrj section in TARGET_ASM_SELECT_SECTION. */
640738fd1498Szrj
640838fd1498Szrj bool
have_global_bss_p(void)640938fd1498Szrj have_global_bss_p (void)
641038fd1498Szrj {
641138fd1498Szrj return bss_noswitch_section || targetm.have_switchable_bss_sections;
641238fd1498Szrj }
641338fd1498Szrj
641438fd1498Szrj /* Output assembly to switch to section NAME with attribute FLAGS.
641538fd1498Szrj Four variants for common object file formats. */
641638fd1498Szrj
641738fd1498Szrj void
default_no_named_section(const char * name ATTRIBUTE_UNUSED,unsigned int flags ATTRIBUTE_UNUSED,tree decl ATTRIBUTE_UNUSED)641838fd1498Szrj default_no_named_section (const char *name ATTRIBUTE_UNUSED,
641938fd1498Szrj unsigned int flags ATTRIBUTE_UNUSED,
642038fd1498Szrj tree decl ATTRIBUTE_UNUSED)
642138fd1498Szrj {
642238fd1498Szrj /* Some object formats don't support named sections at all. The
642338fd1498Szrj front-end should already have flagged this as an error. */
642438fd1498Szrj gcc_unreachable ();
642538fd1498Szrj }
642638fd1498Szrj
642738fd1498Szrj #ifndef TLS_SECTION_ASM_FLAG
642838fd1498Szrj #define TLS_SECTION_ASM_FLAG 'T'
642938fd1498Szrj #endif
643038fd1498Szrj
643138fd1498Szrj void
default_elf_asm_named_section(const char * name,unsigned int flags,tree decl)643238fd1498Szrj default_elf_asm_named_section (const char *name, unsigned int flags,
643338fd1498Szrj tree decl)
643438fd1498Szrj {
643538fd1498Szrj char flagchars[11], *f = flagchars;
643638fd1498Szrj unsigned int numeric_value = 0;
643738fd1498Szrj
643838fd1498Szrj /* If we have already declared this section, we can use an
643938fd1498Szrj abbreviated form to switch back to it -- unless this section is
644038fd1498Szrj part of a COMDAT groups, in which case GAS requires the full
644138fd1498Szrj declaration every time. */
644238fd1498Szrj if (!(HAVE_COMDAT_GROUP && (flags & SECTION_LINKONCE))
644338fd1498Szrj && (flags & SECTION_DECLARED))
644438fd1498Szrj {
644538fd1498Szrj fprintf (asm_out_file, "\t.section\t%s\n", name);
644638fd1498Szrj return;
644738fd1498Szrj }
644838fd1498Szrj
644938fd1498Szrj /* If we have a machine specific flag, then use the numeric value to pass
645038fd1498Szrj this on to GAS. */
645138fd1498Szrj if (targetm.asm_out.elf_flags_numeric (flags, &numeric_value))
645238fd1498Szrj snprintf (f, sizeof (flagchars), "0x%08x", numeric_value);
645338fd1498Szrj else
645438fd1498Szrj {
645538fd1498Szrj if (!(flags & SECTION_DEBUG))
645638fd1498Szrj *f++ = 'a';
645738fd1498Szrj #if defined (HAVE_GAS_SECTION_EXCLUDE) && HAVE_GAS_SECTION_EXCLUDE == 1
645838fd1498Szrj if (flags & SECTION_EXCLUDE)
645938fd1498Szrj *f++ = 'e';
646038fd1498Szrj #endif
646138fd1498Szrj if (flags & SECTION_WRITE)
646238fd1498Szrj *f++ = 'w';
646338fd1498Szrj if (flags & SECTION_CODE)
646438fd1498Szrj *f++ = 'x';
646538fd1498Szrj if (flags & SECTION_SMALL)
646638fd1498Szrj *f++ = 's';
646738fd1498Szrj if (flags & SECTION_MERGE)
646838fd1498Szrj *f++ = 'M';
646938fd1498Szrj if (flags & SECTION_STRINGS)
647038fd1498Szrj *f++ = 'S';
647138fd1498Szrj if (flags & SECTION_TLS)
647238fd1498Szrj *f++ = TLS_SECTION_ASM_FLAG;
647338fd1498Szrj if (HAVE_COMDAT_GROUP && (flags & SECTION_LINKONCE))
647438fd1498Szrj *f++ = 'G';
647538fd1498Szrj #ifdef MACH_DEP_SECTION_ASM_FLAG
647638fd1498Szrj if (flags & SECTION_MACH_DEP)
647738fd1498Szrj *f++ = MACH_DEP_SECTION_ASM_FLAG;
647838fd1498Szrj #endif
647938fd1498Szrj *f = '\0';
648038fd1498Szrj }
648138fd1498Szrj
648238fd1498Szrj fprintf (asm_out_file, "\t.section\t%s,\"%s\"", name, flagchars);
648338fd1498Szrj
6484*58e805e6Szrj /* default_section_type_flags (above) knows which flags need special
6485*58e805e6Szrj handling here, and sets NOTYPE when none of these apply so that the
6486*58e805e6Szrj assembler's logic for default types can apply to user-chosen
6487*58e805e6Szrj section names. */
648838fd1498Szrj if (!(flags & SECTION_NOTYPE))
648938fd1498Szrj {
649038fd1498Szrj const char *type;
649138fd1498Szrj const char *format;
649238fd1498Szrj
649338fd1498Szrj if (flags & SECTION_BSS)
649438fd1498Szrj type = "nobits";
649538fd1498Szrj else
649638fd1498Szrj type = "progbits";
649738fd1498Szrj
649838fd1498Szrj format = ",@%s";
649938fd1498Szrj /* On platforms that use "@" as the assembly comment character,
650038fd1498Szrj use "%" instead. */
650138fd1498Szrj if (strcmp (ASM_COMMENT_START, "@") == 0)
650238fd1498Szrj format = ",%%%s";
650338fd1498Szrj fprintf (asm_out_file, format, type);
650438fd1498Szrj
650538fd1498Szrj if (flags & SECTION_ENTSIZE)
650638fd1498Szrj fprintf (asm_out_file, ",%d", flags & SECTION_ENTSIZE);
650738fd1498Szrj if (HAVE_COMDAT_GROUP && (flags & SECTION_LINKONCE))
650838fd1498Szrj {
650938fd1498Szrj if (TREE_CODE (decl) == IDENTIFIER_NODE)
651038fd1498Szrj fprintf (asm_out_file, ",%s,comdat", IDENTIFIER_POINTER (decl));
651138fd1498Szrj else
651238fd1498Szrj fprintf (asm_out_file, ",%s,comdat",
651338fd1498Szrj IDENTIFIER_POINTER (DECL_COMDAT_GROUP (decl)));
651438fd1498Szrj }
651538fd1498Szrj }
651638fd1498Szrj
651738fd1498Szrj putc ('\n', asm_out_file);
651838fd1498Szrj }
651938fd1498Szrj
652038fd1498Szrj void
default_coff_asm_named_section(const char * name,unsigned int flags,tree decl ATTRIBUTE_UNUSED)652138fd1498Szrj default_coff_asm_named_section (const char *name, unsigned int flags,
652238fd1498Szrj tree decl ATTRIBUTE_UNUSED)
652338fd1498Szrj {
652438fd1498Szrj char flagchars[8], *f = flagchars;
652538fd1498Szrj
652638fd1498Szrj if (flags & SECTION_WRITE)
652738fd1498Szrj *f++ = 'w';
652838fd1498Szrj if (flags & SECTION_CODE)
652938fd1498Szrj *f++ = 'x';
653038fd1498Szrj *f = '\0';
653138fd1498Szrj
653238fd1498Szrj fprintf (asm_out_file, "\t.section\t%s,\"%s\"\n", name, flagchars);
653338fd1498Szrj }
653438fd1498Szrj
653538fd1498Szrj void
default_pe_asm_named_section(const char * name,unsigned int flags,tree decl)653638fd1498Szrj default_pe_asm_named_section (const char *name, unsigned int flags,
653738fd1498Szrj tree decl)
653838fd1498Szrj {
653938fd1498Szrj default_coff_asm_named_section (name, flags, decl);
654038fd1498Szrj
654138fd1498Szrj if (flags & SECTION_LINKONCE)
654238fd1498Szrj {
654338fd1498Szrj /* Functions may have been compiled at various levels of
654438fd1498Szrj optimization so we can't use `same_size' here.
654538fd1498Szrj Instead, have the linker pick one. */
654638fd1498Szrj fprintf (asm_out_file, "\t.linkonce %s\n",
654738fd1498Szrj (flags & SECTION_CODE ? "discard" : "same_size"));
654838fd1498Szrj }
654938fd1498Szrj }
655038fd1498Szrj
655138fd1498Szrj /* The lame default section selector. */
655238fd1498Szrj
655338fd1498Szrj section *
default_select_section(tree decl,int reloc,unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)655438fd1498Szrj default_select_section (tree decl, int reloc,
655538fd1498Szrj unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
655638fd1498Szrj {
655738fd1498Szrj if (DECL_P (decl))
655838fd1498Szrj {
655938fd1498Szrj if (decl_readonly_section (decl, reloc))
656038fd1498Szrj return readonly_data_section;
656138fd1498Szrj }
656238fd1498Szrj else if (TREE_CODE (decl) == CONSTRUCTOR)
656338fd1498Szrj {
656438fd1498Szrj if (! ((flag_pic && reloc)
656538fd1498Szrj || !TREE_READONLY (decl)
656638fd1498Szrj || TREE_SIDE_EFFECTS (decl)
656738fd1498Szrj || !TREE_CONSTANT (decl)))
656838fd1498Szrj return readonly_data_section;
656938fd1498Szrj }
657038fd1498Szrj else if (TREE_CODE (decl) == STRING_CST)
657138fd1498Szrj return readonly_data_section;
657238fd1498Szrj else if (! (flag_pic && reloc))
657338fd1498Szrj return readonly_data_section;
657438fd1498Szrj
657538fd1498Szrj return data_section;
657638fd1498Szrj }
657738fd1498Szrj
657838fd1498Szrj enum section_category
categorize_decl_for_section(const_tree decl,int reloc)657938fd1498Szrj categorize_decl_for_section (const_tree decl, int reloc)
658038fd1498Szrj {
658138fd1498Szrj enum section_category ret;
658238fd1498Szrj
658338fd1498Szrj if (TREE_CODE (decl) == FUNCTION_DECL)
658438fd1498Szrj return SECCAT_TEXT;
658538fd1498Szrj else if (TREE_CODE (decl) == STRING_CST)
658638fd1498Szrj {
658738fd1498Szrj if ((flag_sanitize & SANITIZE_ADDRESS)
658838fd1498Szrj && asan_protect_global (CONST_CAST_TREE (decl)))
658938fd1498Szrj /* or !flag_merge_constants */
659038fd1498Szrj return SECCAT_RODATA;
659138fd1498Szrj else
659238fd1498Szrj return SECCAT_RODATA_MERGE_STR;
659338fd1498Szrj }
659438fd1498Szrj else if (VAR_P (decl))
659538fd1498Szrj {
659638fd1498Szrj tree d = CONST_CAST_TREE (decl);
659738fd1498Szrj if (bss_initializer_p (decl))
659838fd1498Szrj ret = SECCAT_BSS;
659938fd1498Szrj else if (! TREE_READONLY (decl)
660038fd1498Szrj || TREE_SIDE_EFFECTS (decl)
660138fd1498Szrj || (DECL_INITIAL (decl)
660238fd1498Szrj && ! TREE_CONSTANT (DECL_INITIAL (decl))))
660338fd1498Szrj {
660438fd1498Szrj /* Here the reloc_rw_mask is not testing whether the section should
660538fd1498Szrj be read-only or not, but whether the dynamic link will have to
660638fd1498Szrj do something. If so, we wish to segregate the data in order to
660738fd1498Szrj minimize cache misses inside the dynamic linker. */
660838fd1498Szrj if (reloc & targetm.asm_out.reloc_rw_mask ())
660938fd1498Szrj ret = reloc == 1 ? SECCAT_DATA_REL_LOCAL : SECCAT_DATA_REL;
661038fd1498Szrj else
661138fd1498Szrj ret = SECCAT_DATA;
661238fd1498Szrj }
661338fd1498Szrj else if (reloc & targetm.asm_out.reloc_rw_mask ())
661438fd1498Szrj ret = reloc == 1 ? SECCAT_DATA_REL_RO_LOCAL : SECCAT_DATA_REL_RO;
661538fd1498Szrj else if (reloc || flag_merge_constants < 2
661638fd1498Szrj || ((flag_sanitize & SANITIZE_ADDRESS)
661738fd1498Szrj /* PR 81697: for architectures that use section anchors we
661838fd1498Szrj need to ignore DECL_RTL_SET_P (decl) for string constants
661938fd1498Szrj inside this asan_protect_global call because otherwise
662038fd1498Szrj we'll wrongly put them into SECCAT_RODATA_MERGE_CONST
662138fd1498Szrj section, set DECL_RTL (decl) later on and add DECL to
662238fd1498Szrj protected globals via successive asan_protect_global
662338fd1498Szrj calls. In this scenario we'll end up with wrong
662438fd1498Szrj alignment of these strings at runtime and possible ASan
662538fd1498Szrj false positives. */
662638fd1498Szrj && asan_protect_global (d, use_object_blocks_p ()
662738fd1498Szrj && use_blocks_for_decl_p (d))))
662838fd1498Szrj /* C and C++ don't allow different variables to share the same
662938fd1498Szrj location. -fmerge-all-constants allows even that (at the
663038fd1498Szrj expense of not conforming). */
663138fd1498Szrj ret = SECCAT_RODATA;
663238fd1498Szrj else if (DECL_INITIAL (decl)
663338fd1498Szrj && TREE_CODE (DECL_INITIAL (decl)) == STRING_CST)
663438fd1498Szrj ret = SECCAT_RODATA_MERGE_STR_INIT;
663538fd1498Szrj else
663638fd1498Szrj ret = SECCAT_RODATA_MERGE_CONST;
663738fd1498Szrj }
663838fd1498Szrj else if (TREE_CODE (decl) == CONSTRUCTOR)
663938fd1498Szrj {
664038fd1498Szrj if ((reloc & targetm.asm_out.reloc_rw_mask ())
664138fd1498Szrj || TREE_SIDE_EFFECTS (decl)
664238fd1498Szrj || ! TREE_CONSTANT (decl))
664338fd1498Szrj ret = SECCAT_DATA;
664438fd1498Szrj else
664538fd1498Szrj ret = SECCAT_RODATA;
664638fd1498Szrj }
664738fd1498Szrj else
664838fd1498Szrj ret = SECCAT_RODATA;
664938fd1498Szrj
665038fd1498Szrj /* There are no read-only thread-local sections. */
665138fd1498Szrj if (VAR_P (decl) && DECL_THREAD_LOCAL_P (decl))
665238fd1498Szrj {
665338fd1498Szrj /* Note that this would be *just* SECCAT_BSS, except that there's
665438fd1498Szrj no concept of a read-only thread-local-data section. */
665538fd1498Szrj if (ret == SECCAT_BSS
665638fd1498Szrj || DECL_INITIAL (decl) == NULL
665738fd1498Szrj || (flag_zero_initialized_in_bss
665838fd1498Szrj && initializer_zerop (DECL_INITIAL (decl))))
665938fd1498Szrj ret = SECCAT_TBSS;
666038fd1498Szrj else
666138fd1498Szrj ret = SECCAT_TDATA;
666238fd1498Szrj }
666338fd1498Szrj
666438fd1498Szrj /* If the target uses small data sections, select it. */
666538fd1498Szrj else if (targetm.in_small_data_p (decl))
666638fd1498Szrj {
666738fd1498Szrj if (ret == SECCAT_BSS)
666838fd1498Szrj ret = SECCAT_SBSS;
666938fd1498Szrj else if (targetm.have_srodata_section && ret == SECCAT_RODATA)
667038fd1498Szrj ret = SECCAT_SRODATA;
667138fd1498Szrj else
667238fd1498Szrj ret = SECCAT_SDATA;
667338fd1498Szrj }
667438fd1498Szrj
667538fd1498Szrj return ret;
667638fd1498Szrj }
667738fd1498Szrj
667838fd1498Szrj static bool
decl_readonly_section_1(enum section_category category)667938fd1498Szrj decl_readonly_section_1 (enum section_category category)
668038fd1498Szrj {
668138fd1498Szrj switch (category)
668238fd1498Szrj {
668338fd1498Szrj case SECCAT_RODATA:
668438fd1498Szrj case SECCAT_RODATA_MERGE_STR:
668538fd1498Szrj case SECCAT_RODATA_MERGE_STR_INIT:
668638fd1498Szrj case SECCAT_RODATA_MERGE_CONST:
668738fd1498Szrj case SECCAT_SRODATA:
668838fd1498Szrj return true;
668938fd1498Szrj default:
669038fd1498Szrj return false;
669138fd1498Szrj }
669238fd1498Szrj }
669338fd1498Szrj
669438fd1498Szrj bool
decl_readonly_section(const_tree decl,int reloc)669538fd1498Szrj decl_readonly_section (const_tree decl, int reloc)
669638fd1498Szrj {
669738fd1498Szrj return decl_readonly_section_1 (categorize_decl_for_section (decl, reloc));
669838fd1498Szrj }
669938fd1498Szrj
670038fd1498Szrj /* Select a section based on the above categorization. */
670138fd1498Szrj
670238fd1498Szrj section *
default_elf_select_section(tree decl,int reloc,unsigned HOST_WIDE_INT align)670338fd1498Szrj default_elf_select_section (tree decl, int reloc,
670438fd1498Szrj unsigned HOST_WIDE_INT align)
670538fd1498Szrj {
670638fd1498Szrj const char *sname;
670738fd1498Szrj switch (categorize_decl_for_section (decl, reloc))
670838fd1498Szrj {
670938fd1498Szrj case SECCAT_TEXT:
671038fd1498Szrj /* We're not supposed to be called on FUNCTION_DECLs. */
671138fd1498Szrj gcc_unreachable ();
671238fd1498Szrj case SECCAT_RODATA:
671338fd1498Szrj return readonly_data_section;
671438fd1498Szrj case SECCAT_RODATA_MERGE_STR:
671538fd1498Szrj return mergeable_string_section (decl, align, 0);
671638fd1498Szrj case SECCAT_RODATA_MERGE_STR_INIT:
671738fd1498Szrj return mergeable_string_section (DECL_INITIAL (decl), align, 0);
671838fd1498Szrj case SECCAT_RODATA_MERGE_CONST:
671938fd1498Szrj return mergeable_constant_section (DECL_MODE (decl), align, 0);
672038fd1498Szrj case SECCAT_SRODATA:
672138fd1498Szrj sname = ".sdata2";
672238fd1498Szrj break;
672338fd1498Szrj case SECCAT_DATA:
672438fd1498Szrj return data_section;
672538fd1498Szrj case SECCAT_DATA_REL:
672638fd1498Szrj sname = ".data.rel";
672738fd1498Szrj break;
672838fd1498Szrj case SECCAT_DATA_REL_LOCAL:
672938fd1498Szrj sname = ".data.rel.local";
673038fd1498Szrj break;
673138fd1498Szrj case SECCAT_DATA_REL_RO:
673238fd1498Szrj sname = ".data.rel.ro";
673338fd1498Szrj break;
673438fd1498Szrj case SECCAT_DATA_REL_RO_LOCAL:
673538fd1498Szrj sname = ".data.rel.ro.local";
673638fd1498Szrj break;
673738fd1498Szrj case SECCAT_SDATA:
673838fd1498Szrj sname = ".sdata";
673938fd1498Szrj break;
674038fd1498Szrj case SECCAT_TDATA:
674138fd1498Szrj sname = ".tdata";
674238fd1498Szrj break;
674338fd1498Szrj case SECCAT_BSS:
674438fd1498Szrj if (bss_section)
674538fd1498Szrj return bss_section;
674638fd1498Szrj sname = ".bss";
674738fd1498Szrj break;
674838fd1498Szrj case SECCAT_SBSS:
674938fd1498Szrj sname = ".sbss";
675038fd1498Szrj break;
675138fd1498Szrj case SECCAT_TBSS:
675238fd1498Szrj sname = ".tbss";
675338fd1498Szrj break;
675438fd1498Szrj default:
675538fd1498Szrj gcc_unreachable ();
675638fd1498Szrj }
675738fd1498Szrj
675838fd1498Szrj return get_named_section (decl, sname, reloc);
675938fd1498Szrj }
676038fd1498Szrj
676138fd1498Szrj /* Construct a unique section name based on the decl name and the
676238fd1498Szrj categorization performed above. */
676338fd1498Szrj
676438fd1498Szrj void
default_unique_section(tree decl,int reloc)676538fd1498Szrj default_unique_section (tree decl, int reloc)
676638fd1498Szrj {
676738fd1498Szrj /* We only need to use .gnu.linkonce if we don't have COMDAT groups. */
676838fd1498Szrj bool one_only = DECL_ONE_ONLY (decl) && !HAVE_COMDAT_GROUP;
676938fd1498Szrj const char *prefix, *name, *linkonce;
677038fd1498Szrj char *string;
677138fd1498Szrj tree id;
677238fd1498Szrj
677338fd1498Szrj switch (categorize_decl_for_section (decl, reloc))
677438fd1498Szrj {
677538fd1498Szrj case SECCAT_TEXT:
677638fd1498Szrj prefix = one_only ? ".t" : ".text";
677738fd1498Szrj break;
677838fd1498Szrj case SECCAT_RODATA:
677938fd1498Szrj case SECCAT_RODATA_MERGE_STR:
678038fd1498Szrj case SECCAT_RODATA_MERGE_STR_INIT:
678138fd1498Szrj case SECCAT_RODATA_MERGE_CONST:
678238fd1498Szrj prefix = one_only ? ".r" : ".rodata";
678338fd1498Szrj break;
678438fd1498Szrj case SECCAT_SRODATA:
678538fd1498Szrj prefix = one_only ? ".s2" : ".sdata2";
678638fd1498Szrj break;
678738fd1498Szrj case SECCAT_DATA:
678838fd1498Szrj prefix = one_only ? ".d" : ".data";
678938fd1498Szrj break;
679038fd1498Szrj case SECCAT_DATA_REL:
679138fd1498Szrj prefix = one_only ? ".d.rel" : ".data.rel";
679238fd1498Szrj break;
679338fd1498Szrj case SECCAT_DATA_REL_LOCAL:
679438fd1498Szrj prefix = one_only ? ".d.rel.local" : ".data.rel.local";
679538fd1498Szrj break;
679638fd1498Szrj case SECCAT_DATA_REL_RO:
679738fd1498Szrj prefix = one_only ? ".d.rel.ro" : ".data.rel.ro";
679838fd1498Szrj break;
679938fd1498Szrj case SECCAT_DATA_REL_RO_LOCAL:
680038fd1498Szrj prefix = one_only ? ".d.rel.ro.local" : ".data.rel.ro.local";
680138fd1498Szrj break;
680238fd1498Szrj case SECCAT_SDATA:
680338fd1498Szrj prefix = one_only ? ".s" : ".sdata";
680438fd1498Szrj break;
680538fd1498Szrj case SECCAT_BSS:
680638fd1498Szrj prefix = one_only ? ".b" : ".bss";
680738fd1498Szrj break;
680838fd1498Szrj case SECCAT_SBSS:
680938fd1498Szrj prefix = one_only ? ".sb" : ".sbss";
681038fd1498Szrj break;
681138fd1498Szrj case SECCAT_TDATA:
681238fd1498Szrj prefix = one_only ? ".td" : ".tdata";
681338fd1498Szrj break;
681438fd1498Szrj case SECCAT_TBSS:
681538fd1498Szrj prefix = one_only ? ".tb" : ".tbss";
681638fd1498Szrj break;
681738fd1498Szrj default:
681838fd1498Szrj gcc_unreachable ();
681938fd1498Szrj }
682038fd1498Szrj
682138fd1498Szrj id = DECL_ASSEMBLER_NAME (decl);
682238fd1498Szrj ultimate_transparent_alias_target (&id);
682338fd1498Szrj name = IDENTIFIER_POINTER (id);
682438fd1498Szrj name = targetm.strip_name_encoding (name);
682538fd1498Szrj
682638fd1498Szrj /* If we're using one_only, then there needs to be a .gnu.linkonce
682738fd1498Szrj prefix to the section name. */
682838fd1498Szrj linkonce = one_only ? ".gnu.linkonce" : "";
682938fd1498Szrj
683038fd1498Szrj string = ACONCAT ((linkonce, prefix, ".", name, NULL));
683138fd1498Szrj
683238fd1498Szrj set_decl_section_name (decl, string);
683338fd1498Szrj }
683438fd1498Szrj
683538fd1498Szrj /* Subroutine of compute_reloc_for_rtx for leaf rtxes. */
683638fd1498Szrj
683738fd1498Szrj static int
compute_reloc_for_rtx_1(const_rtx x)683838fd1498Szrj compute_reloc_for_rtx_1 (const_rtx x)
683938fd1498Szrj {
684038fd1498Szrj switch (GET_CODE (x))
684138fd1498Szrj {
684238fd1498Szrj case SYMBOL_REF:
684338fd1498Szrj return SYMBOL_REF_LOCAL_P (x) ? 1 : 2;
684438fd1498Szrj case LABEL_REF:
684538fd1498Szrj return 1;
684638fd1498Szrj default:
684738fd1498Szrj return 0;
684838fd1498Szrj }
684938fd1498Szrj }
685038fd1498Szrj
685138fd1498Szrj /* Like compute_reloc_for_constant, except for an RTX. The return value
685238fd1498Szrj is a mask for which bit 1 indicates a global relocation, and bit 0
685338fd1498Szrj indicates a local relocation. */
685438fd1498Szrj
685538fd1498Szrj static int
compute_reloc_for_rtx(const_rtx x)685638fd1498Szrj compute_reloc_for_rtx (const_rtx x)
685738fd1498Szrj {
685838fd1498Szrj switch (GET_CODE (x))
685938fd1498Szrj {
686038fd1498Szrj case SYMBOL_REF:
686138fd1498Szrj case LABEL_REF:
686238fd1498Szrj return compute_reloc_for_rtx_1 (x);
686338fd1498Szrj
686438fd1498Szrj case CONST:
686538fd1498Szrj {
686638fd1498Szrj int reloc = 0;
686738fd1498Szrj subrtx_iterator::array_type array;
686838fd1498Szrj FOR_EACH_SUBRTX (iter, array, x, ALL)
686938fd1498Szrj reloc |= compute_reloc_for_rtx_1 (*iter);
687038fd1498Szrj return reloc;
687138fd1498Szrj }
687238fd1498Szrj
687338fd1498Szrj default:
687438fd1498Szrj return 0;
687538fd1498Szrj }
687638fd1498Szrj }
687738fd1498Szrj
687838fd1498Szrj section *
default_select_rtx_section(machine_mode mode ATTRIBUTE_UNUSED,rtx x,unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)687938fd1498Szrj default_select_rtx_section (machine_mode mode ATTRIBUTE_UNUSED,
688038fd1498Szrj rtx x,
688138fd1498Szrj unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
688238fd1498Szrj {
688338fd1498Szrj if (compute_reloc_for_rtx (x) & targetm.asm_out.reloc_rw_mask ())
688438fd1498Szrj return data_section;
688538fd1498Szrj else
688638fd1498Szrj return readonly_data_section;
688738fd1498Szrj }
688838fd1498Szrj
688938fd1498Szrj section *
default_elf_select_rtx_section(machine_mode mode,rtx x,unsigned HOST_WIDE_INT align)689038fd1498Szrj default_elf_select_rtx_section (machine_mode mode, rtx x,
689138fd1498Szrj unsigned HOST_WIDE_INT align)
689238fd1498Szrj {
689338fd1498Szrj int reloc = compute_reloc_for_rtx (x);
689438fd1498Szrj
689538fd1498Szrj /* ??? Handle small data here somehow. */
689638fd1498Szrj
689738fd1498Szrj if (reloc & targetm.asm_out.reloc_rw_mask ())
689838fd1498Szrj {
689938fd1498Szrj if (reloc == 1)
690038fd1498Szrj return get_named_section (NULL, ".data.rel.ro.local", 1);
690138fd1498Szrj else
690238fd1498Szrj return get_named_section (NULL, ".data.rel.ro", 3);
690338fd1498Szrj }
690438fd1498Szrj
690538fd1498Szrj return mergeable_constant_section (mode, align, 0);
690638fd1498Szrj }
690738fd1498Szrj
690838fd1498Szrj /* Set the generally applicable flags on the SYMBOL_REF for EXP. */
690938fd1498Szrj
691038fd1498Szrj void
default_encode_section_info(tree decl,rtx rtl,int first ATTRIBUTE_UNUSED)691138fd1498Szrj default_encode_section_info (tree decl, rtx rtl, int first ATTRIBUTE_UNUSED)
691238fd1498Szrj {
691338fd1498Szrj rtx symbol;
691438fd1498Szrj int flags;
691538fd1498Szrj
691638fd1498Szrj /* Careful not to prod global register variables. */
691738fd1498Szrj if (!MEM_P (rtl))
691838fd1498Szrj return;
691938fd1498Szrj symbol = XEXP (rtl, 0);
692038fd1498Szrj if (GET_CODE (symbol) != SYMBOL_REF)
692138fd1498Szrj return;
692238fd1498Szrj
692338fd1498Szrj flags = SYMBOL_REF_FLAGS (symbol) & SYMBOL_FLAG_HAS_BLOCK_INFO;
692438fd1498Szrj if (TREE_CODE (decl) == FUNCTION_DECL)
692538fd1498Szrj flags |= SYMBOL_FLAG_FUNCTION;
692638fd1498Szrj if (targetm.binds_local_p (decl))
692738fd1498Szrj flags |= SYMBOL_FLAG_LOCAL;
692838fd1498Szrj if (VAR_P (decl) && DECL_THREAD_LOCAL_P (decl))
692938fd1498Szrj flags |= DECL_TLS_MODEL (decl) << SYMBOL_FLAG_TLS_SHIFT;
693038fd1498Szrj else if (targetm.in_small_data_p (decl))
693138fd1498Szrj flags |= SYMBOL_FLAG_SMALL;
693238fd1498Szrj /* ??? Why is DECL_EXTERNAL ever set for non-PUBLIC names? Without
693338fd1498Szrj being PUBLIC, the thing *must* be defined in this translation unit.
693438fd1498Szrj Prevent this buglet from being propagated into rtl code as well. */
693538fd1498Szrj if (DECL_P (decl) && DECL_EXTERNAL (decl) && TREE_PUBLIC (decl))
693638fd1498Szrj flags |= SYMBOL_FLAG_EXTERNAL;
693738fd1498Szrj
693838fd1498Szrj SYMBOL_REF_FLAGS (symbol) = flags;
693938fd1498Szrj }
694038fd1498Szrj
694138fd1498Szrj /* By default, we do nothing for encode_section_info, so we need not
694238fd1498Szrj do anything but discard the '*' marker. */
694338fd1498Szrj
694438fd1498Szrj const char *
default_strip_name_encoding(const char * str)694538fd1498Szrj default_strip_name_encoding (const char *str)
694638fd1498Szrj {
694738fd1498Szrj return str + (*str == '*');
694838fd1498Szrj }
694938fd1498Szrj
695038fd1498Szrj #ifdef ASM_OUTPUT_DEF
695138fd1498Szrj /* The default implementation of TARGET_ASM_OUTPUT_ANCHOR. Define the
695238fd1498Szrj anchor relative to ".", the current section position. */
695338fd1498Szrj
695438fd1498Szrj void
default_asm_output_anchor(rtx symbol)695538fd1498Szrj default_asm_output_anchor (rtx symbol)
695638fd1498Szrj {
695738fd1498Szrj char buffer[100];
695838fd1498Szrj
695938fd1498Szrj sprintf (buffer, "*. + " HOST_WIDE_INT_PRINT_DEC,
696038fd1498Szrj SYMBOL_REF_BLOCK_OFFSET (symbol));
696138fd1498Szrj ASM_OUTPUT_DEF (asm_out_file, XSTR (symbol, 0), buffer);
696238fd1498Szrj }
696338fd1498Szrj #endif
696438fd1498Szrj
696538fd1498Szrj /* The default implementation of TARGET_USE_ANCHORS_FOR_SYMBOL_P. */
696638fd1498Szrj
696738fd1498Szrj bool
default_use_anchors_for_symbol_p(const_rtx symbol)696838fd1498Szrj default_use_anchors_for_symbol_p (const_rtx symbol)
696938fd1498Szrj {
697038fd1498Szrj section *sect;
697138fd1498Szrj tree decl;
697238fd1498Szrj
697338fd1498Szrj /* Don't use anchors for mergeable sections. The linker might move
697438fd1498Szrj the objects around. */
697538fd1498Szrj sect = SYMBOL_REF_BLOCK (symbol)->sect;
697638fd1498Szrj if (sect->common.flags & SECTION_MERGE)
697738fd1498Szrj return false;
697838fd1498Szrj
697938fd1498Szrj /* Don't use anchors for small data sections. The small data register
698038fd1498Szrj acts as an anchor for such sections. */
698138fd1498Szrj if (sect->common.flags & SECTION_SMALL)
698238fd1498Szrj return false;
698338fd1498Szrj
698438fd1498Szrj decl = SYMBOL_REF_DECL (symbol);
698538fd1498Szrj if (decl && DECL_P (decl))
698638fd1498Szrj {
698738fd1498Szrj /* Don't use section anchors for decls that might be defined or
698838fd1498Szrj usurped by other modules. */
698938fd1498Szrj if (TREE_PUBLIC (decl) && !decl_binds_to_current_def_p (decl))
699038fd1498Szrj return false;
699138fd1498Szrj
699238fd1498Szrj /* Don't use section anchors for decls that will be placed in a
699338fd1498Szrj small data section. */
699438fd1498Szrj /* ??? Ideally, this check would be redundant with the SECTION_SMALL
699538fd1498Szrj one above. The problem is that we only use SECTION_SMALL for
699638fd1498Szrj sections that should be marked as small in the section directive. */
699738fd1498Szrj if (targetm.in_small_data_p (decl))
699838fd1498Szrj return false;
699938fd1498Szrj
700038fd1498Szrj /* Don't use section anchors for decls that won't fit inside a single
700138fd1498Szrj anchor range to reduce the amount of instructions required to refer
700238fd1498Szrj to the entire declaration. */
700338fd1498Szrj if (DECL_SIZE_UNIT (decl) == NULL_TREE
700438fd1498Szrj || !tree_fits_uhwi_p (DECL_SIZE_UNIT (decl))
700538fd1498Szrj || (tree_to_uhwi (DECL_SIZE_UNIT (decl))
700638fd1498Szrj >= (unsigned HOST_WIDE_INT) targetm.max_anchor_offset))
700738fd1498Szrj return false;
700838fd1498Szrj
700938fd1498Szrj }
701038fd1498Szrj return true;
701138fd1498Szrj }
701238fd1498Szrj
701338fd1498Szrj /* Return true when RESOLUTION indicate that symbol will be bound to the
701438fd1498Szrj definition provided by current .o file. */
701538fd1498Szrj
701638fd1498Szrj static bool
resolution_to_local_definition_p(enum ld_plugin_symbol_resolution resolution)701738fd1498Szrj resolution_to_local_definition_p (enum ld_plugin_symbol_resolution resolution)
701838fd1498Szrj {
701938fd1498Szrj return (resolution == LDPR_PREVAILING_DEF
702038fd1498Szrj || resolution == LDPR_PREVAILING_DEF_IRONLY_EXP
702138fd1498Szrj || resolution == LDPR_PREVAILING_DEF_IRONLY);
702238fd1498Szrj }
702338fd1498Szrj
702438fd1498Szrj /* Return true when RESOLUTION indicate that symbol will be bound locally
702538fd1498Szrj within current executable or DSO. */
702638fd1498Szrj
702738fd1498Szrj static bool
resolution_local_p(enum ld_plugin_symbol_resolution resolution)702838fd1498Szrj resolution_local_p (enum ld_plugin_symbol_resolution resolution)
702938fd1498Szrj {
703038fd1498Szrj return (resolution == LDPR_PREVAILING_DEF
703138fd1498Szrj || resolution == LDPR_PREVAILING_DEF_IRONLY
703238fd1498Szrj || resolution == LDPR_PREVAILING_DEF_IRONLY_EXP
703338fd1498Szrj || resolution == LDPR_PREEMPTED_REG
703438fd1498Szrj || resolution == LDPR_PREEMPTED_IR
703538fd1498Szrj || resolution == LDPR_RESOLVED_IR
703638fd1498Szrj || resolution == LDPR_RESOLVED_EXEC);
703738fd1498Szrj }
703838fd1498Szrj
703938fd1498Szrj /* COMMON_LOCAL_P is true means that the linker can guarantee that an
704038fd1498Szrj uninitialized common symbol in the executable will still be defined
704138fd1498Szrj (through COPY relocation) in the executable. */
704238fd1498Szrj
704338fd1498Szrj bool
default_binds_local_p_3(const_tree exp,bool shlib,bool weak_dominate,bool extern_protected_data,bool common_local_p)704438fd1498Szrj default_binds_local_p_3 (const_tree exp, bool shlib, bool weak_dominate,
704538fd1498Szrj bool extern_protected_data, bool common_local_p)
704638fd1498Szrj {
704738fd1498Szrj /* A non-decl is an entry in the constant pool. */
704838fd1498Szrj if (!DECL_P (exp))
704938fd1498Szrj return true;
705038fd1498Szrj
705138fd1498Szrj /* Weakrefs may not bind locally, even though the weakref itself is always
705238fd1498Szrj static and therefore local. Similarly, the resolver for ifunc functions
705338fd1498Szrj might resolve to a non-local function.
705438fd1498Szrj FIXME: We can resolve the weakref case more curefuly by looking at the
705538fd1498Szrj weakref alias. */
705638fd1498Szrj if (lookup_attribute ("weakref", DECL_ATTRIBUTES (exp))
705738fd1498Szrj || (TREE_CODE (exp) == FUNCTION_DECL
7058*58e805e6Szrj && cgraph_node::get (exp)
7059*58e805e6Szrj && cgraph_node::get (exp)->ifunc_resolver))
706038fd1498Szrj return false;
706138fd1498Szrj
706238fd1498Szrj /* Static variables are always local. */
706338fd1498Szrj if (! TREE_PUBLIC (exp))
706438fd1498Szrj return true;
706538fd1498Szrj
706638fd1498Szrj /* With resolution file in hand, take look into resolutions.
706738fd1498Szrj We can't just return true for resolved_locally symbols,
706838fd1498Szrj because dynamic linking might overwrite symbols
706938fd1498Szrj in shared libraries. */
707038fd1498Szrj bool resolved_locally = false;
707138fd1498Szrj
707238fd1498Szrj bool uninited_common = (DECL_COMMON (exp)
707338fd1498Szrj && (DECL_INITIAL (exp) == NULL
707438fd1498Szrj || (!in_lto_p
707538fd1498Szrj && DECL_INITIAL (exp) == error_mark_node)));
707638fd1498Szrj
707738fd1498Szrj /* A non-external variable is defined locally only if it isn't
707838fd1498Szrj uninitialized COMMON variable or common_local_p is true. */
707938fd1498Szrj bool defined_locally = (!DECL_EXTERNAL (exp)
708038fd1498Szrj && (!uninited_common || common_local_p));
708138fd1498Szrj if (symtab_node *node = symtab_node::get (exp))
708238fd1498Szrj {
708338fd1498Szrj if (node->in_other_partition)
708438fd1498Szrj defined_locally = true;
708538fd1498Szrj if (node->can_be_discarded_p ())
708638fd1498Szrj ;
708738fd1498Szrj else if (resolution_to_local_definition_p (node->resolution))
708838fd1498Szrj defined_locally = resolved_locally = true;
708938fd1498Szrj else if (resolution_local_p (node->resolution))
709038fd1498Szrj resolved_locally = true;
709138fd1498Szrj }
709238fd1498Szrj if (defined_locally && weak_dominate && !shlib)
709338fd1498Szrj resolved_locally = true;
709438fd1498Szrj
709538fd1498Szrj /* Undefined weak symbols are never defined locally. */
709638fd1498Szrj if (DECL_WEAK (exp) && !defined_locally)
709738fd1498Szrj return false;
709838fd1498Szrj
709938fd1498Szrj /* A symbol is local if the user has said explicitly that it will be,
710038fd1498Szrj or if we have a definition for the symbol. We cannot infer visibility
710138fd1498Szrj for undefined symbols. */
710238fd1498Szrj if (DECL_VISIBILITY (exp) != VISIBILITY_DEFAULT
710338fd1498Szrj && (TREE_CODE (exp) == FUNCTION_DECL
710438fd1498Szrj || !extern_protected_data
710538fd1498Szrj || DECL_VISIBILITY (exp) != VISIBILITY_PROTECTED)
710638fd1498Szrj && (DECL_VISIBILITY_SPECIFIED (exp) || defined_locally))
710738fd1498Szrj return true;
710838fd1498Szrj
710938fd1498Szrj /* If PIC, then assume that any global name can be overridden by
711038fd1498Szrj symbols resolved from other modules. */
711138fd1498Szrj if (shlib)
711238fd1498Szrj return false;
711338fd1498Szrj
711438fd1498Szrj /* Variables defined outside this object might not be local. */
711538fd1498Szrj if (DECL_EXTERNAL (exp) && !resolved_locally)
711638fd1498Szrj return false;
711738fd1498Szrj
711838fd1498Szrj /* Non-dominant weak symbols are not defined locally. */
711938fd1498Szrj if (DECL_WEAK (exp) && !resolved_locally)
712038fd1498Szrj return false;
712138fd1498Szrj
712238fd1498Szrj /* Uninitialized COMMON variable may be unified with symbols
712338fd1498Szrj resolved from other modules. */
712438fd1498Szrj if (uninited_common && !resolved_locally)
712538fd1498Szrj return false;
712638fd1498Szrj
712738fd1498Szrj /* Otherwise we're left with initialized (or non-common) global data
712838fd1498Szrj which is of necessity defined locally. */
712938fd1498Szrj return true;
713038fd1498Szrj }
713138fd1498Szrj
713238fd1498Szrj /* Assume ELF-ish defaults, since that's pretty much the most liberal
713338fd1498Szrj wrt cross-module name binding. */
713438fd1498Szrj
713538fd1498Szrj bool
default_binds_local_p(const_tree exp)713638fd1498Szrj default_binds_local_p (const_tree exp)
713738fd1498Szrj {
713838fd1498Szrj return default_binds_local_p_3 (exp, flag_shlib != 0, true, false, false);
713938fd1498Szrj }
714038fd1498Szrj
714138fd1498Szrj /* Similar to default_binds_local_p, but common symbol may be local and
714238fd1498Szrj extern protected data is non-local. */
714338fd1498Szrj
714438fd1498Szrj bool
default_binds_local_p_2(const_tree exp)714538fd1498Szrj default_binds_local_p_2 (const_tree exp)
714638fd1498Szrj {
714738fd1498Szrj return default_binds_local_p_3 (exp, flag_shlib != 0, true, true,
714838fd1498Szrj !flag_pic);
714938fd1498Szrj }
715038fd1498Szrj
715138fd1498Szrj bool
default_binds_local_p_1(const_tree exp,int shlib)715238fd1498Szrj default_binds_local_p_1 (const_tree exp, int shlib)
715338fd1498Szrj {
715438fd1498Szrj return default_binds_local_p_3 (exp, shlib != 0, false, false, false);
715538fd1498Szrj }
715638fd1498Szrj
715738fd1498Szrj /* Return true when references to DECL must bind to current definition in
715838fd1498Szrj final executable.
715938fd1498Szrj
716038fd1498Szrj The condition is usually equivalent to whether the function binds to the
716138fd1498Szrj current module (shared library or executable), that is to binds_local_p.
716238fd1498Szrj We use this fact to avoid need for another target hook and implement
716338fd1498Szrj the logic using binds_local_p and just special cases where
716438fd1498Szrj decl_binds_to_current_def_p is stronger than binds_local_p. In particular
716538fd1498Szrj the weak definitions (that can be overwritten at linktime by other
716638fd1498Szrj definition from different object file) and when resolution info is available
716738fd1498Szrj we simply use the knowledge passed to us by linker plugin. */
716838fd1498Szrj bool
decl_binds_to_current_def_p(const_tree decl)716938fd1498Szrj decl_binds_to_current_def_p (const_tree decl)
717038fd1498Szrj {
717138fd1498Szrj gcc_assert (DECL_P (decl));
717238fd1498Szrj if (!targetm.binds_local_p (decl))
717338fd1498Szrj return false;
717438fd1498Szrj if (!TREE_PUBLIC (decl))
717538fd1498Szrj return true;
717638fd1498Szrj
717738fd1498Szrj /* When resolution is available, just use it. */
717838fd1498Szrj if (symtab_node *node = symtab_node::get (decl))
717938fd1498Szrj {
718038fd1498Szrj if (node->resolution != LDPR_UNKNOWN
718138fd1498Szrj && !node->can_be_discarded_p ())
718238fd1498Szrj return resolution_to_local_definition_p (node->resolution);
718338fd1498Szrj }
718438fd1498Szrj
718538fd1498Szrj /* Otherwise we have to assume the worst for DECL_WEAK (hidden weaks
718638fd1498Szrj binds locally but still can be overwritten), DECL_COMMON (can be merged
718738fd1498Szrj with a non-common definition somewhere in the same module) or
718838fd1498Szrj DECL_EXTERNAL.
718938fd1498Szrj This rely on fact that binds_local_p behave as decl_replaceable_p
719038fd1498Szrj for all other declaration types. */
719138fd1498Szrj if (DECL_WEAK (decl))
719238fd1498Szrj return false;
719338fd1498Szrj if (DECL_COMMON (decl)
719438fd1498Szrj && (DECL_INITIAL (decl) == NULL
719538fd1498Szrj || (!in_lto_p && DECL_INITIAL (decl) == error_mark_node)))
719638fd1498Szrj return false;
719738fd1498Szrj if (DECL_EXTERNAL (decl))
719838fd1498Szrj return false;
719938fd1498Szrj return true;
720038fd1498Szrj }
720138fd1498Szrj
720238fd1498Szrj /* A replaceable function or variable is one which may be replaced
720338fd1498Szrj at link-time with an entirely different definition, provided that the
720438fd1498Szrj replacement has the same type. For example, functions declared
720538fd1498Szrj with __attribute__((weak)) on most systems are replaceable.
720638fd1498Szrj
720738fd1498Szrj COMDAT functions are not replaceable, since all definitions of the
720838fd1498Szrj function must be equivalent. It is important that COMDAT functions
720938fd1498Szrj not be treated as replaceable so that use of C++ template
721038fd1498Szrj instantiations is not penalized. */
721138fd1498Szrj
721238fd1498Szrj bool
decl_replaceable_p(tree decl)721338fd1498Szrj decl_replaceable_p (tree decl)
721438fd1498Szrj {
721538fd1498Szrj gcc_assert (DECL_P (decl));
721638fd1498Szrj if (!TREE_PUBLIC (decl) || DECL_COMDAT (decl))
721738fd1498Szrj return false;
721838fd1498Szrj if (!flag_semantic_interposition
721938fd1498Szrj && !DECL_WEAK (decl))
722038fd1498Szrj return false;
722138fd1498Szrj return !decl_binds_to_current_def_p (decl);
722238fd1498Szrj }
722338fd1498Szrj
722438fd1498Szrj /* Default function to output code that will globalize a label. A
722538fd1498Szrj target must define GLOBAL_ASM_OP or provide its own function to
722638fd1498Szrj globalize a label. */
722738fd1498Szrj #ifdef GLOBAL_ASM_OP
722838fd1498Szrj void
default_globalize_label(FILE * stream,const char * name)722938fd1498Szrj default_globalize_label (FILE * stream, const char *name)
723038fd1498Szrj {
723138fd1498Szrj fputs (GLOBAL_ASM_OP, stream);
723238fd1498Szrj assemble_name (stream, name);
723338fd1498Szrj putc ('\n', stream);
723438fd1498Szrj }
723538fd1498Szrj #endif /* GLOBAL_ASM_OP */
723638fd1498Szrj
723738fd1498Szrj /* Default function to output code that will globalize a declaration. */
723838fd1498Szrj void
default_globalize_decl_name(FILE * stream,tree decl)723938fd1498Szrj default_globalize_decl_name (FILE * stream, tree decl)
724038fd1498Szrj {
724138fd1498Szrj const char *name = XSTR (XEXP (DECL_RTL (decl), 0), 0);
724238fd1498Szrj targetm.asm_out.globalize_label (stream, name);
724338fd1498Szrj }
724438fd1498Szrj
724538fd1498Szrj /* Default function to output a label for unwind information. The
724638fd1498Szrj default is to do nothing. A target that needs nonlocal labels for
724738fd1498Szrj unwind information must provide its own function to do this. */
724838fd1498Szrj void
default_emit_unwind_label(FILE * stream ATTRIBUTE_UNUSED,tree decl ATTRIBUTE_UNUSED,int for_eh ATTRIBUTE_UNUSED,int empty ATTRIBUTE_UNUSED)724938fd1498Szrj default_emit_unwind_label (FILE * stream ATTRIBUTE_UNUSED,
725038fd1498Szrj tree decl ATTRIBUTE_UNUSED,
725138fd1498Szrj int for_eh ATTRIBUTE_UNUSED,
725238fd1498Szrj int empty ATTRIBUTE_UNUSED)
725338fd1498Szrj {
725438fd1498Szrj }
725538fd1498Szrj
725638fd1498Szrj /* Default function to output a label to divide up the exception table.
725738fd1498Szrj The default is to do nothing. A target that needs/wants to divide
725838fd1498Szrj up the table must provide it's own function to do this. */
725938fd1498Szrj void
default_emit_except_table_label(FILE * stream ATTRIBUTE_UNUSED)726038fd1498Szrj default_emit_except_table_label (FILE * stream ATTRIBUTE_UNUSED)
726138fd1498Szrj {
726238fd1498Szrj }
726338fd1498Szrj
726438fd1498Szrj /* This is how to output an internal numbered label where PREFIX is
726538fd1498Szrj the class of label and LABELNO is the number within the class. */
726638fd1498Szrj
726738fd1498Szrj void
default_generate_internal_label(char * buf,const char * prefix,unsigned long labelno)726838fd1498Szrj default_generate_internal_label (char *buf, const char *prefix,
726938fd1498Szrj unsigned long labelno)
727038fd1498Szrj {
727138fd1498Szrj ASM_GENERATE_INTERNAL_LABEL (buf, prefix, labelno);
727238fd1498Szrj }
727338fd1498Szrj
727438fd1498Szrj /* This is how to output an internal numbered label where PREFIX is
727538fd1498Szrj the class of label and LABELNO is the number within the class. */
727638fd1498Szrj
727738fd1498Szrj void
default_internal_label(FILE * stream,const char * prefix,unsigned long labelno)727838fd1498Szrj default_internal_label (FILE *stream, const char *prefix,
727938fd1498Szrj unsigned long labelno)
728038fd1498Szrj {
728138fd1498Szrj char *const buf = (char *) alloca (40 + strlen (prefix));
728238fd1498Szrj ASM_GENERATE_INTERNAL_LABEL (buf, prefix, labelno);
728338fd1498Szrj ASM_OUTPUT_INTERNAL_LABEL (stream, buf);
728438fd1498Szrj }
728538fd1498Szrj
728638fd1498Szrj
728738fd1498Szrj /* The default implementation of ASM_DECLARE_CONSTANT_NAME. */
728838fd1498Szrj
728938fd1498Szrj void
default_asm_declare_constant_name(FILE * file,const char * name,const_tree exp ATTRIBUTE_UNUSED,HOST_WIDE_INT size ATTRIBUTE_UNUSED)729038fd1498Szrj default_asm_declare_constant_name (FILE *file, const char *name,
729138fd1498Szrj const_tree exp ATTRIBUTE_UNUSED,
729238fd1498Szrj HOST_WIDE_INT size ATTRIBUTE_UNUSED)
729338fd1498Szrj {
729438fd1498Szrj assemble_label (file, name);
729538fd1498Szrj }
729638fd1498Szrj
729738fd1498Szrj /* This is the default behavior at the beginning of a file. It's
729838fd1498Szrj controlled by two other target-hook toggles. */
729938fd1498Szrj void
default_file_start(void)730038fd1498Szrj default_file_start (void)
730138fd1498Szrj {
730238fd1498Szrj if (targetm.asm_file_start_app_off
730338fd1498Szrj && !(flag_verbose_asm || flag_debug_asm || flag_dump_rtl_in_asm))
730438fd1498Szrj fputs (ASM_APP_OFF, asm_out_file);
730538fd1498Szrj
730638fd1498Szrj if (targetm.asm_file_start_file_directive)
730738fd1498Szrj {
730838fd1498Szrj /* LTO produced units have no meaningful main_input_filename. */
730938fd1498Szrj if (in_lto_p)
731038fd1498Szrj output_file_directive (asm_out_file, "<artificial>");
731138fd1498Szrj else
731238fd1498Szrj output_file_directive (asm_out_file, main_input_filename);
731338fd1498Szrj }
731438fd1498Szrj }
731538fd1498Szrj
731638fd1498Szrj /* This is a generic routine suitable for use as TARGET_ASM_FILE_END
731738fd1498Szrj which emits a special section directive used to indicate whether or
731838fd1498Szrj not this object file needs an executable stack. This is primarily
731938fd1498Szrj a GNU extension to ELF but could be used on other targets. */
732038fd1498Szrj
732138fd1498Szrj int trampolines_created;
732238fd1498Szrj
732338fd1498Szrj void
file_end_indicate_exec_stack(void)732438fd1498Szrj file_end_indicate_exec_stack (void)
732538fd1498Szrj {
732638fd1498Szrj unsigned int flags = SECTION_DEBUG;
732738fd1498Szrj if (trampolines_created)
732838fd1498Szrj flags |= SECTION_CODE;
732938fd1498Szrj
733038fd1498Szrj switch_to_section (get_section (".note.GNU-stack", flags, NULL));
733138fd1498Szrj }
733238fd1498Szrj
733338fd1498Szrj /* Emit a special section directive to indicate that this object file
733438fd1498Szrj was compiled with -fsplit-stack. This is used to let the linker
733538fd1498Szrj detect calls between split-stack code and non-split-stack code, so
733638fd1498Szrj that it can modify the split-stack code to allocate a sufficiently
733738fd1498Szrj large stack. We emit another special section if there are any
733838fd1498Szrj functions in this file which have the no_split_stack attribute, to
733938fd1498Szrj prevent the linker from warning about being unable to convert the
734038fd1498Szrj functions if they call non-split-stack code. */
734138fd1498Szrj
734238fd1498Szrj void
file_end_indicate_split_stack(void)734338fd1498Szrj file_end_indicate_split_stack (void)
734438fd1498Szrj {
734538fd1498Szrj if (flag_split_stack)
734638fd1498Szrj {
734738fd1498Szrj switch_to_section (get_section (".note.GNU-split-stack", SECTION_DEBUG,
734838fd1498Szrj NULL));
734938fd1498Szrj if (saw_no_split_stack)
735038fd1498Szrj switch_to_section (get_section (".note.GNU-no-split-stack",
735138fd1498Szrj SECTION_DEBUG, NULL));
735238fd1498Szrj }
735338fd1498Szrj }
735438fd1498Szrj
735538fd1498Szrj /* Output DIRECTIVE (a C string) followed by a newline. This is used as
735638fd1498Szrj a get_unnamed_section callback. */
735738fd1498Szrj
735838fd1498Szrj void
output_section_asm_op(const void * directive)735938fd1498Szrj output_section_asm_op (const void *directive)
736038fd1498Szrj {
736138fd1498Szrj fprintf (asm_out_file, "%s\n", (const char *) directive);
736238fd1498Szrj }
736338fd1498Szrj
736438fd1498Szrj /* Emit assembly code to switch to section NEW_SECTION. Do nothing if
736538fd1498Szrj the current section is NEW_SECTION. */
736638fd1498Szrj
736738fd1498Szrj void
switch_to_section(section * new_section)736838fd1498Szrj switch_to_section (section *new_section)
736938fd1498Szrj {
737038fd1498Szrj if (in_section == new_section)
737138fd1498Szrj return;
737238fd1498Szrj
737338fd1498Szrj if (new_section->common.flags & SECTION_FORGET)
737438fd1498Szrj in_section = NULL;
737538fd1498Szrj else
737638fd1498Szrj in_section = new_section;
737738fd1498Szrj
737838fd1498Szrj switch (SECTION_STYLE (new_section))
737938fd1498Szrj {
738038fd1498Szrj case SECTION_NAMED:
738138fd1498Szrj targetm.asm_out.named_section (new_section->named.name,
738238fd1498Szrj new_section->named.common.flags,
738338fd1498Szrj new_section->named.decl);
738438fd1498Szrj break;
738538fd1498Szrj
738638fd1498Szrj case SECTION_UNNAMED:
738738fd1498Szrj new_section->unnamed.callback (new_section->unnamed.data);
738838fd1498Szrj break;
738938fd1498Szrj
739038fd1498Szrj case SECTION_NOSWITCH:
739138fd1498Szrj gcc_unreachable ();
739238fd1498Szrj break;
739338fd1498Szrj }
739438fd1498Szrj
739538fd1498Szrj new_section->common.flags |= SECTION_DECLARED;
739638fd1498Szrj }
739738fd1498Szrj
739838fd1498Szrj /* If block symbol SYMBOL has not yet been assigned an offset, place
739938fd1498Szrj it at the end of its block. */
740038fd1498Szrj
740138fd1498Szrj void
place_block_symbol(rtx symbol)740238fd1498Szrj place_block_symbol (rtx symbol)
740338fd1498Szrj {
740438fd1498Szrj unsigned HOST_WIDE_INT size, mask, offset;
740538fd1498Szrj struct constant_descriptor_rtx *desc;
740638fd1498Szrj unsigned int alignment;
740738fd1498Szrj struct object_block *block;
740838fd1498Szrj tree decl;
740938fd1498Szrj
741038fd1498Szrj gcc_assert (SYMBOL_REF_BLOCK (symbol));
741138fd1498Szrj if (SYMBOL_REF_BLOCK_OFFSET (symbol) >= 0)
741238fd1498Szrj return;
741338fd1498Szrj
741438fd1498Szrj /* Work out the symbol's size and alignment. */
741538fd1498Szrj if (CONSTANT_POOL_ADDRESS_P (symbol))
741638fd1498Szrj {
741738fd1498Szrj desc = SYMBOL_REF_CONSTANT (symbol);
741838fd1498Szrj alignment = desc->align;
741938fd1498Szrj size = GET_MODE_SIZE (desc->mode);
742038fd1498Szrj }
742138fd1498Szrj else if (TREE_CONSTANT_POOL_ADDRESS_P (symbol))
742238fd1498Szrj {
742338fd1498Szrj decl = SYMBOL_REF_DECL (symbol);
742438fd1498Szrj gcc_checking_assert (DECL_IN_CONSTANT_POOL (decl));
742538fd1498Szrj alignment = DECL_ALIGN (decl);
742638fd1498Szrj size = get_constant_size (DECL_INITIAL (decl));
742738fd1498Szrj if ((flag_sanitize & SANITIZE_ADDRESS)
742838fd1498Szrj && TREE_CODE (DECL_INITIAL (decl)) == STRING_CST
742938fd1498Szrj && asan_protect_global (DECL_INITIAL (decl)))
743038fd1498Szrj {
743138fd1498Szrj size += asan_red_zone_size (size);
743238fd1498Szrj alignment = MAX (alignment,
743338fd1498Szrj ASAN_RED_ZONE_SIZE * BITS_PER_UNIT);
743438fd1498Szrj }
743538fd1498Szrj }
743638fd1498Szrj else
743738fd1498Szrj {
743838fd1498Szrj struct symtab_node *snode;
743938fd1498Szrj decl = SYMBOL_REF_DECL (symbol);
744038fd1498Szrj
744138fd1498Szrj snode = symtab_node::get (decl);
744238fd1498Szrj if (snode->alias)
744338fd1498Szrj {
744438fd1498Szrj rtx target = DECL_RTL (snode->ultimate_alias_target ()->decl);
744538fd1498Szrj
744638fd1498Szrj gcc_assert (MEM_P (target)
744738fd1498Szrj && GET_CODE (XEXP (target, 0)) == SYMBOL_REF
744838fd1498Szrj && SYMBOL_REF_HAS_BLOCK_INFO_P (XEXP (target, 0)));
744938fd1498Szrj target = XEXP (target, 0);
745038fd1498Szrj place_block_symbol (target);
745138fd1498Szrj SYMBOL_REF_BLOCK_OFFSET (symbol) = SYMBOL_REF_BLOCK_OFFSET (target);
745238fd1498Szrj return;
745338fd1498Szrj }
745438fd1498Szrj alignment = get_variable_align (decl);
745538fd1498Szrj size = tree_to_uhwi (DECL_SIZE_UNIT (decl));
745638fd1498Szrj if ((flag_sanitize & SANITIZE_ADDRESS)
745738fd1498Szrj && asan_protect_global (decl))
745838fd1498Szrj {
745938fd1498Szrj size += asan_red_zone_size (size);
746038fd1498Szrj alignment = MAX (alignment,
746138fd1498Szrj ASAN_RED_ZONE_SIZE * BITS_PER_UNIT);
746238fd1498Szrj }
746338fd1498Szrj }
746438fd1498Szrj
746538fd1498Szrj /* Calculate the object's offset from the start of the block. */
746638fd1498Szrj block = SYMBOL_REF_BLOCK (symbol);
746738fd1498Szrj mask = alignment / BITS_PER_UNIT - 1;
746838fd1498Szrj offset = (block->size + mask) & ~mask;
746938fd1498Szrj SYMBOL_REF_BLOCK_OFFSET (symbol) = offset;
747038fd1498Szrj
747138fd1498Szrj /* Record the block's new alignment and size. */
747238fd1498Szrj block->alignment = MAX (block->alignment, alignment);
747338fd1498Szrj block->size = offset + size;
747438fd1498Szrj
747538fd1498Szrj vec_safe_push (block->objects, symbol);
747638fd1498Szrj }
747738fd1498Szrj
747838fd1498Szrj /* Return the anchor that should be used to address byte offset OFFSET
747938fd1498Szrj from the first object in BLOCK. MODEL is the TLS model used
748038fd1498Szrj to access it. */
748138fd1498Szrj
748238fd1498Szrj rtx
get_section_anchor(struct object_block * block,HOST_WIDE_INT offset,enum tls_model model)748338fd1498Szrj get_section_anchor (struct object_block *block, HOST_WIDE_INT offset,
748438fd1498Szrj enum tls_model model)
748538fd1498Szrj {
748638fd1498Szrj char label[100];
748738fd1498Szrj unsigned int begin, middle, end;
748838fd1498Szrj unsigned HOST_WIDE_INT min_offset, max_offset, range, bias, delta;
748938fd1498Szrj rtx anchor;
749038fd1498Szrj
749138fd1498Szrj /* Work out the anchor's offset. Use an offset of 0 for the first
749238fd1498Szrj anchor so that we don't pessimize the case where we take the address
749338fd1498Szrj of a variable at the beginning of the block. This is particularly
749438fd1498Szrj useful when a block has only one variable assigned to it.
749538fd1498Szrj
749638fd1498Szrj We try to place anchors RANGE bytes apart, so there can then be
749738fd1498Szrj anchors at +/-RANGE, +/-2 * RANGE, and so on, up to the limits of
749838fd1498Szrj a ptr_mode offset. With some target settings, the lowest such
749938fd1498Szrj anchor might be out of range for the lowest ptr_mode offset;
750038fd1498Szrj likewise the highest anchor for the highest offset. Use anchors
750138fd1498Szrj at the extreme ends of the ptr_mode range in such cases.
750238fd1498Szrj
750338fd1498Szrj All arithmetic uses unsigned integers in order to avoid
750438fd1498Szrj signed overflow. */
750538fd1498Szrj max_offset = (unsigned HOST_WIDE_INT) targetm.max_anchor_offset;
750638fd1498Szrj min_offset = (unsigned HOST_WIDE_INT) targetm.min_anchor_offset;
750738fd1498Szrj range = max_offset - min_offset + 1;
750838fd1498Szrj if (range == 0)
750938fd1498Szrj offset = 0;
751038fd1498Szrj else
751138fd1498Szrj {
751238fd1498Szrj bias = HOST_WIDE_INT_1U << (GET_MODE_BITSIZE (ptr_mode) - 1);
751338fd1498Szrj if (offset < 0)
751438fd1498Szrj {
751538fd1498Szrj delta = -(unsigned HOST_WIDE_INT) offset + max_offset;
751638fd1498Szrj delta -= delta % range;
751738fd1498Szrj if (delta > bias)
751838fd1498Szrj delta = bias;
751938fd1498Szrj offset = (HOST_WIDE_INT) (-delta);
752038fd1498Szrj }
752138fd1498Szrj else
752238fd1498Szrj {
752338fd1498Szrj delta = (unsigned HOST_WIDE_INT) offset - min_offset;
752438fd1498Szrj delta -= delta % range;
752538fd1498Szrj if (delta > bias - 1)
752638fd1498Szrj delta = bias - 1;
752738fd1498Szrj offset = (HOST_WIDE_INT) delta;
752838fd1498Szrj }
752938fd1498Szrj }
753038fd1498Szrj
753138fd1498Szrj /* Do a binary search to see if there's already an anchor we can use.
753238fd1498Szrj Set BEGIN to the new anchor's index if not. */
753338fd1498Szrj begin = 0;
753438fd1498Szrj end = vec_safe_length (block->anchors);
753538fd1498Szrj while (begin != end)
753638fd1498Szrj {
753738fd1498Szrj middle = (end + begin) / 2;
753838fd1498Szrj anchor = (*block->anchors)[middle];
753938fd1498Szrj if (SYMBOL_REF_BLOCK_OFFSET (anchor) > offset)
754038fd1498Szrj end = middle;
754138fd1498Szrj else if (SYMBOL_REF_BLOCK_OFFSET (anchor) < offset)
754238fd1498Szrj begin = middle + 1;
754338fd1498Szrj else if (SYMBOL_REF_TLS_MODEL (anchor) > model)
754438fd1498Szrj end = middle;
754538fd1498Szrj else if (SYMBOL_REF_TLS_MODEL (anchor) < model)
754638fd1498Szrj begin = middle + 1;
754738fd1498Szrj else
754838fd1498Szrj return anchor;
754938fd1498Szrj }
755038fd1498Szrj
755138fd1498Szrj /* Create a new anchor with a unique label. */
755238fd1498Szrj ASM_GENERATE_INTERNAL_LABEL (label, "LANCHOR", anchor_labelno++);
755338fd1498Szrj anchor = create_block_symbol (ggc_strdup (label), block, offset);
755438fd1498Szrj SYMBOL_REF_FLAGS (anchor) |= SYMBOL_FLAG_LOCAL | SYMBOL_FLAG_ANCHOR;
755538fd1498Szrj SYMBOL_REF_FLAGS (anchor) |= model << SYMBOL_FLAG_TLS_SHIFT;
755638fd1498Szrj
755738fd1498Szrj /* Insert it at index BEGIN. */
755838fd1498Szrj vec_safe_insert (block->anchors, begin, anchor);
755938fd1498Szrj return anchor;
756038fd1498Szrj }
756138fd1498Szrj
756238fd1498Szrj /* Output the objects in BLOCK. */
756338fd1498Szrj
756438fd1498Szrj static void
output_object_block(struct object_block * block)756538fd1498Szrj output_object_block (struct object_block *block)
756638fd1498Szrj {
756738fd1498Szrj struct constant_descriptor_rtx *desc;
756838fd1498Szrj unsigned int i;
756938fd1498Szrj HOST_WIDE_INT offset;
757038fd1498Szrj tree decl;
757138fd1498Szrj rtx symbol;
757238fd1498Szrj
757338fd1498Szrj if (!block->objects)
757438fd1498Szrj return;
757538fd1498Szrj
757638fd1498Szrj /* Switch to the section and make sure that the first byte is
757738fd1498Szrj suitably aligned. */
757838fd1498Szrj /* Special case VTV comdat sections similar to assemble_variable. */
757938fd1498Szrj if (SECTION_STYLE (block->sect) == SECTION_NAMED
758038fd1498Szrj && block->sect->named.name
758138fd1498Szrj && (strcmp (block->sect->named.name, ".vtable_map_vars") == 0))
758238fd1498Szrj handle_vtv_comdat_section (block->sect, block->sect->named.decl);
758338fd1498Szrj else
758438fd1498Szrj switch_to_section (block->sect);
758538fd1498Szrj
758638fd1498Szrj assemble_align (block->alignment);
758738fd1498Szrj
758838fd1498Szrj /* Define the values of all anchors relative to the current section
758938fd1498Szrj position. */
759038fd1498Szrj FOR_EACH_VEC_SAFE_ELT (block->anchors, i, symbol)
759138fd1498Szrj targetm.asm_out.output_anchor (symbol);
759238fd1498Szrj
759338fd1498Szrj /* Output the objects themselves. */
759438fd1498Szrj offset = 0;
759538fd1498Szrj FOR_EACH_VEC_ELT (*block->objects, i, symbol)
759638fd1498Szrj {
759738fd1498Szrj /* Move to the object's offset, padding with zeros if necessary. */
759838fd1498Szrj assemble_zeros (SYMBOL_REF_BLOCK_OFFSET (symbol) - offset);
759938fd1498Szrj offset = SYMBOL_REF_BLOCK_OFFSET (symbol);
760038fd1498Szrj if (CONSTANT_POOL_ADDRESS_P (symbol))
760138fd1498Szrj {
760238fd1498Szrj desc = SYMBOL_REF_CONSTANT (symbol);
760338fd1498Szrj /* Pass 1 for align as we have already laid out everything in the block.
760438fd1498Szrj So aligning shouldn't be necessary. */
760538fd1498Szrj output_constant_pool_1 (desc, 1);
760638fd1498Szrj offset += GET_MODE_SIZE (desc->mode);
760738fd1498Szrj }
760838fd1498Szrj else if (TREE_CONSTANT_POOL_ADDRESS_P (symbol))
760938fd1498Szrj {
761038fd1498Szrj HOST_WIDE_INT size;
761138fd1498Szrj decl = SYMBOL_REF_DECL (symbol);
761238fd1498Szrj assemble_constant_contents
761338fd1498Szrj (DECL_INITIAL (decl), XSTR (symbol, 0), DECL_ALIGN (decl));
761438fd1498Szrj
761538fd1498Szrj size = get_constant_size (DECL_INITIAL (decl));
761638fd1498Szrj offset += size;
761738fd1498Szrj if ((flag_sanitize & SANITIZE_ADDRESS)
761838fd1498Szrj && TREE_CODE (DECL_INITIAL (decl)) == STRING_CST
761938fd1498Szrj && asan_protect_global (DECL_INITIAL (decl)))
762038fd1498Szrj {
762138fd1498Szrj size = asan_red_zone_size (size);
762238fd1498Szrj assemble_zeros (size);
762338fd1498Szrj offset += size;
762438fd1498Szrj }
762538fd1498Szrj }
762638fd1498Szrj else
762738fd1498Szrj {
762838fd1498Szrj HOST_WIDE_INT size;
762938fd1498Szrj decl = SYMBOL_REF_DECL (symbol);
763038fd1498Szrj assemble_variable_contents (decl, XSTR (symbol, 0), false);
763138fd1498Szrj size = tree_to_uhwi (DECL_SIZE_UNIT (decl));
763238fd1498Szrj offset += size;
763338fd1498Szrj if ((flag_sanitize & SANITIZE_ADDRESS)
763438fd1498Szrj && asan_protect_global (decl))
763538fd1498Szrj {
763638fd1498Szrj size = asan_red_zone_size (size);
763738fd1498Szrj assemble_zeros (size);
763838fd1498Szrj offset += size;
763938fd1498Szrj }
764038fd1498Szrj }
764138fd1498Szrj }
764238fd1498Szrj }
764338fd1498Szrj
764438fd1498Szrj /* A callback for qsort to compare object_blocks. */
764538fd1498Szrj
764638fd1498Szrj static int
output_object_block_compare(const void * x,const void * y)764738fd1498Szrj output_object_block_compare (const void *x, const void *y)
764838fd1498Szrj {
764938fd1498Szrj object_block *p1 = *(object_block * const*)x;
765038fd1498Szrj object_block *p2 = *(object_block * const*)y;
765138fd1498Szrj
765238fd1498Szrj if (p1->sect->common.flags & SECTION_NAMED
765338fd1498Szrj && !(p2->sect->common.flags & SECTION_NAMED))
765438fd1498Szrj return 1;
765538fd1498Szrj
765638fd1498Szrj if (!(p1->sect->common.flags & SECTION_NAMED)
765738fd1498Szrj && p2->sect->common.flags & SECTION_NAMED)
765838fd1498Szrj return -1;
765938fd1498Szrj
766038fd1498Szrj if (p1->sect->common.flags & SECTION_NAMED
766138fd1498Szrj && p2->sect->common.flags & SECTION_NAMED)
766238fd1498Szrj return strcmp (p1->sect->named.name, p2->sect->named.name);
766338fd1498Szrj
766438fd1498Szrj unsigned f1 = p1->sect->common.flags;
766538fd1498Szrj unsigned f2 = p2->sect->common.flags;
766638fd1498Szrj if (f1 == f2)
766738fd1498Szrj return 0;
766838fd1498Szrj return f1 < f2 ? -1 : 1;
766938fd1498Szrj }
767038fd1498Szrj
767138fd1498Szrj /* Output the definitions of all object_blocks. */
767238fd1498Szrj
767338fd1498Szrj void
output_object_blocks(void)767438fd1498Szrj output_object_blocks (void)
767538fd1498Szrj {
767638fd1498Szrj vec<object_block *, va_heap> v;
767738fd1498Szrj v.create (object_block_htab->elements ());
767838fd1498Szrj object_block *obj;
767938fd1498Szrj hash_table<object_block_hasher>::iterator hi;
768038fd1498Szrj
768138fd1498Szrj FOR_EACH_HASH_TABLE_ELEMENT (*object_block_htab, obj, object_block *, hi)
768238fd1498Szrj v.quick_push (obj);
768338fd1498Szrj
768438fd1498Szrj /* Sort them in order to output them in a deterministic manner,
768538fd1498Szrj otherwise we may get .rodata sections in different orders with
768638fd1498Szrj and without -g. */
768738fd1498Szrj v.qsort (output_object_block_compare);
768838fd1498Szrj unsigned i;
768938fd1498Szrj FOR_EACH_VEC_ELT (v, i, obj)
769038fd1498Szrj output_object_block (obj);
769138fd1498Szrj
769238fd1498Szrj v.release ();
769338fd1498Szrj }
769438fd1498Szrj
769538fd1498Szrj /* This function provides a possible implementation of the
769638fd1498Szrj TARGET_ASM_RECORD_GCC_SWITCHES target hook for ELF targets. When triggered
769738fd1498Szrj by -frecord-gcc-switches it creates a new mergeable, string section in the
769838fd1498Szrj assembler output file called TARGET_ASM_RECORD_GCC_SWITCHES_SECTION which
769938fd1498Szrj contains the switches in ASCII format.
770038fd1498Szrj
770138fd1498Szrj FIXME: This code does not correctly handle double quote characters
770238fd1498Szrj that appear inside strings, (it strips them rather than preserving them).
770338fd1498Szrj FIXME: ASM_OUTPUT_ASCII, as defined in config/elfos.h will not emit NUL
770438fd1498Szrj characters - instead it treats them as sub-string separators. Since
770538fd1498Szrj we want to emit NUL strings terminators into the object file we have to use
770638fd1498Szrj ASM_OUTPUT_SKIP. */
770738fd1498Szrj
770838fd1498Szrj int
elf_record_gcc_switches(print_switch_type type,const char * name)770938fd1498Szrj elf_record_gcc_switches (print_switch_type type, const char * name)
771038fd1498Szrj {
771138fd1498Szrj switch (type)
771238fd1498Szrj {
771338fd1498Szrj case SWITCH_TYPE_PASSED:
771438fd1498Szrj ASM_OUTPUT_ASCII (asm_out_file, name, strlen (name));
771538fd1498Szrj ASM_OUTPUT_SKIP (asm_out_file, HOST_WIDE_INT_1U);
771638fd1498Szrj break;
771738fd1498Szrj
771838fd1498Szrj case SWITCH_TYPE_DESCRIPTIVE:
771938fd1498Szrj if (name == NULL)
772038fd1498Szrj {
772138fd1498Szrj /* Distinguish between invocations where name is NULL. */
772238fd1498Szrj static bool started = false;
772338fd1498Szrj
772438fd1498Szrj if (!started)
772538fd1498Szrj {
772638fd1498Szrj section * sec;
772738fd1498Szrj
772838fd1498Szrj sec = get_section (targetm.asm_out.record_gcc_switches_section,
772938fd1498Szrj SECTION_DEBUG
773038fd1498Szrj | SECTION_MERGE
773138fd1498Szrj | SECTION_STRINGS
773238fd1498Szrj | (SECTION_ENTSIZE & 1),
773338fd1498Szrj NULL);
773438fd1498Szrj switch_to_section (sec);
773538fd1498Szrj started = true;
773638fd1498Szrj }
773738fd1498Szrj }
773838fd1498Szrj
773938fd1498Szrj default:
774038fd1498Szrj break;
774138fd1498Szrj }
774238fd1498Szrj
774338fd1498Szrj /* The return value is currently ignored by the caller, but must be 0.
774438fd1498Szrj For -fverbose-asm the return value would be the number of characters
774538fd1498Szrj emitted into the assembler file. */
774638fd1498Szrj return 0;
774738fd1498Szrj }
774838fd1498Szrj
774938fd1498Szrj /* Emit text to declare externally defined symbols. It is needed to
775038fd1498Szrj properly support non-default visibility. */
775138fd1498Szrj void
default_elf_asm_output_external(FILE * file ATTRIBUTE_UNUSED,tree decl,const char * name ATTRIBUTE_UNUSED)775238fd1498Szrj default_elf_asm_output_external (FILE *file ATTRIBUTE_UNUSED,
775338fd1498Szrj tree decl,
775438fd1498Szrj const char *name ATTRIBUTE_UNUSED)
775538fd1498Szrj {
775638fd1498Szrj /* We output the name if and only if TREE_SYMBOL_REFERENCED is
775738fd1498Szrj set in order to avoid putting out names that are never really
775838fd1498Szrj used. Always output visibility specified in the source. */
775938fd1498Szrj if (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))
776038fd1498Szrj && (DECL_VISIBILITY_SPECIFIED (decl)
776138fd1498Szrj || targetm.binds_local_p (decl)))
776238fd1498Szrj maybe_assemble_visibility (decl);
776338fd1498Szrj }
776438fd1498Szrj
776538fd1498Szrj /* The default hook for TARGET_ASM_OUTPUT_SOURCE_FILENAME. */
776638fd1498Szrj
776738fd1498Szrj void
default_asm_output_source_filename(FILE * file,const char * name)776838fd1498Szrj default_asm_output_source_filename (FILE *file, const char *name)
776938fd1498Szrj {
777038fd1498Szrj #ifdef ASM_OUTPUT_SOURCE_FILENAME
777138fd1498Szrj ASM_OUTPUT_SOURCE_FILENAME (file, name);
777238fd1498Szrj #else
777338fd1498Szrj fprintf (file, "\t.file\t");
777438fd1498Szrj output_quoted_string (file, name);
777538fd1498Szrj putc ('\n', file);
777638fd1498Szrj #endif
777738fd1498Szrj }
777838fd1498Szrj
777938fd1498Szrj /* Output a file name in the form wanted by System V. */
778038fd1498Szrj
778138fd1498Szrj void
output_file_directive(FILE * asm_file,const char * input_name)778238fd1498Szrj output_file_directive (FILE *asm_file, const char *input_name)
778338fd1498Szrj {
778438fd1498Szrj int len;
778538fd1498Szrj const char *na;
778638fd1498Szrj
778738fd1498Szrj if (input_name == NULL)
778838fd1498Szrj input_name = "<stdin>";
778938fd1498Szrj else
779038fd1498Szrj input_name = remap_debug_filename (input_name);
779138fd1498Szrj
779238fd1498Szrj len = strlen (input_name);
779338fd1498Szrj na = input_name + len;
779438fd1498Szrj
779538fd1498Szrj /* NA gets INPUT_NAME sans directory names. */
779638fd1498Szrj while (na > input_name)
779738fd1498Szrj {
779838fd1498Szrj if (IS_DIR_SEPARATOR (na[-1]))
779938fd1498Szrj break;
780038fd1498Szrj na--;
780138fd1498Szrj }
780238fd1498Szrj
780338fd1498Szrj targetm.asm_out.output_source_filename (asm_file, na);
780438fd1498Szrj }
780538fd1498Szrj
780638fd1498Szrj /* Create a DEBUG_EXPR_DECL / DEBUG_EXPR pair from RTL expression
780738fd1498Szrj EXP. */
780838fd1498Szrj rtx
make_debug_expr_from_rtl(const_rtx exp)780938fd1498Szrj make_debug_expr_from_rtl (const_rtx exp)
781038fd1498Szrj {
781138fd1498Szrj tree ddecl = make_node (DEBUG_EXPR_DECL), type;
781238fd1498Szrj machine_mode mode = GET_MODE (exp);
781338fd1498Szrj rtx dval;
781438fd1498Szrj
781538fd1498Szrj DECL_ARTIFICIAL (ddecl) = 1;
781638fd1498Szrj if (REG_P (exp) && REG_EXPR (exp))
781738fd1498Szrj type = TREE_TYPE (REG_EXPR (exp));
781838fd1498Szrj else if (MEM_P (exp) && MEM_EXPR (exp))
781938fd1498Szrj type = TREE_TYPE (MEM_EXPR (exp));
782038fd1498Szrj else
782138fd1498Szrj type = NULL_TREE;
782238fd1498Szrj if (type && TYPE_MODE (type) == mode)
782338fd1498Szrj TREE_TYPE (ddecl) = type;
782438fd1498Szrj else
782538fd1498Szrj TREE_TYPE (ddecl) = lang_hooks.types.type_for_mode (mode, 1);
782638fd1498Szrj SET_DECL_MODE (ddecl, mode);
782738fd1498Szrj dval = gen_rtx_DEBUG_EXPR (mode);
782838fd1498Szrj DEBUG_EXPR_TREE_DECL (dval) = ddecl;
782938fd1498Szrj SET_DECL_RTL (ddecl, dval);
783038fd1498Szrj return dval;
783138fd1498Szrj }
783238fd1498Szrj
783338fd1498Szrj #ifdef ELF_ASCII_ESCAPES
783438fd1498Szrj /* Default ASM_OUTPUT_LIMITED_STRING for ELF targets. */
783538fd1498Szrj
783638fd1498Szrj void
default_elf_asm_output_limited_string(FILE * f,const char * s)783738fd1498Szrj default_elf_asm_output_limited_string (FILE *f, const char *s)
783838fd1498Szrj {
783938fd1498Szrj int escape;
784038fd1498Szrj unsigned char c;
784138fd1498Szrj
784238fd1498Szrj fputs (STRING_ASM_OP, f);
784338fd1498Szrj putc ('"', f);
784438fd1498Szrj while (*s != '\0')
784538fd1498Szrj {
784638fd1498Szrj c = *s;
784738fd1498Szrj escape = ELF_ASCII_ESCAPES[c];
784838fd1498Szrj switch (escape)
784938fd1498Szrj {
785038fd1498Szrj case 0:
785138fd1498Szrj putc (c, f);
785238fd1498Szrj break;
785338fd1498Szrj case 1:
785438fd1498Szrj putc ('\\', f);
785538fd1498Szrj putc ('0'+((c>>6)&7), f);
785638fd1498Szrj putc ('0'+((c>>3)&7), f);
785738fd1498Szrj putc ('0'+(c&7), f);
785838fd1498Szrj break;
785938fd1498Szrj default:
786038fd1498Szrj putc ('\\', f);
786138fd1498Szrj putc (escape, f);
786238fd1498Szrj break;
786338fd1498Szrj }
786438fd1498Szrj s++;
786538fd1498Szrj }
786638fd1498Szrj putc ('\"', f);
786738fd1498Szrj putc ('\n', f);
786838fd1498Szrj }
786938fd1498Szrj
787038fd1498Szrj /* Default ASM_OUTPUT_ASCII for ELF targets. */
787138fd1498Szrj
787238fd1498Szrj void
default_elf_asm_output_ascii(FILE * f,const char * s,unsigned int len)787338fd1498Szrj default_elf_asm_output_ascii (FILE *f, const char *s, unsigned int len)
787438fd1498Szrj {
787538fd1498Szrj const char *limit = s + len;
787638fd1498Szrj const char *last_null = NULL;
787738fd1498Szrj unsigned bytes_in_chunk = 0;
787838fd1498Szrj unsigned char c;
787938fd1498Szrj int escape;
788038fd1498Szrj
788138fd1498Szrj for (; s < limit; s++)
788238fd1498Szrj {
788338fd1498Szrj const char *p;
788438fd1498Szrj
788538fd1498Szrj if (bytes_in_chunk >= 60)
788638fd1498Szrj {
788738fd1498Szrj putc ('\"', f);
788838fd1498Szrj putc ('\n', f);
788938fd1498Szrj bytes_in_chunk = 0;
789038fd1498Szrj }
789138fd1498Szrj
789238fd1498Szrj if (s > last_null)
789338fd1498Szrj {
789438fd1498Szrj for (p = s; p < limit && *p != '\0'; p++)
789538fd1498Szrj continue;
789638fd1498Szrj last_null = p;
789738fd1498Szrj }
789838fd1498Szrj else
789938fd1498Szrj p = last_null;
790038fd1498Szrj
790138fd1498Szrj if (p < limit && (p - s) <= (long) ELF_STRING_LIMIT)
790238fd1498Szrj {
790338fd1498Szrj if (bytes_in_chunk > 0)
790438fd1498Szrj {
790538fd1498Szrj putc ('\"', f);
790638fd1498Szrj putc ('\n', f);
790738fd1498Szrj bytes_in_chunk = 0;
790838fd1498Szrj }
790938fd1498Szrj
791038fd1498Szrj default_elf_asm_output_limited_string (f, s);
791138fd1498Szrj s = p;
791238fd1498Szrj }
791338fd1498Szrj else
791438fd1498Szrj {
791538fd1498Szrj if (bytes_in_chunk == 0)
791638fd1498Szrj fputs (ASCII_DATA_ASM_OP "\"", f);
791738fd1498Szrj
791838fd1498Szrj c = *s;
791938fd1498Szrj escape = ELF_ASCII_ESCAPES[c];
792038fd1498Szrj switch (escape)
792138fd1498Szrj {
792238fd1498Szrj case 0:
792338fd1498Szrj putc (c, f);
792438fd1498Szrj bytes_in_chunk++;
792538fd1498Szrj break;
792638fd1498Szrj case 1:
792738fd1498Szrj putc ('\\', f);
792838fd1498Szrj putc ('0'+((c>>6)&7), f);
792938fd1498Szrj putc ('0'+((c>>3)&7), f);
793038fd1498Szrj putc ('0'+(c&7), f);
793138fd1498Szrj bytes_in_chunk += 4;
793238fd1498Szrj break;
793338fd1498Szrj default:
793438fd1498Szrj putc ('\\', f);
793538fd1498Szrj putc (escape, f);
793638fd1498Szrj bytes_in_chunk += 2;
793738fd1498Szrj break;
793838fd1498Szrj }
793938fd1498Szrj
794038fd1498Szrj }
794138fd1498Szrj }
794238fd1498Szrj
794338fd1498Szrj if (bytes_in_chunk > 0)
794438fd1498Szrj {
794538fd1498Szrj putc ('\"', f);
794638fd1498Szrj putc ('\n', f);
794738fd1498Szrj }
794838fd1498Szrj }
794938fd1498Szrj #endif
795038fd1498Szrj
795138fd1498Szrj static GTY(()) section *elf_init_array_section;
795238fd1498Szrj static GTY(()) section *elf_fini_array_section;
795338fd1498Szrj
795438fd1498Szrj static section *
get_elf_initfini_array_priority_section(int priority,bool constructor_p)795538fd1498Szrj get_elf_initfini_array_priority_section (int priority,
795638fd1498Szrj bool constructor_p)
795738fd1498Szrj {
795838fd1498Szrj section *sec;
795938fd1498Szrj if (priority != DEFAULT_INIT_PRIORITY)
796038fd1498Szrj {
796138fd1498Szrj char buf[18];
796238fd1498Szrj sprintf (buf, "%s.%.5u",
796338fd1498Szrj constructor_p ? ".init_array" : ".fini_array",
796438fd1498Szrj priority);
796538fd1498Szrj sec = get_section (buf, SECTION_WRITE | SECTION_NOTYPE, NULL_TREE);
796638fd1498Szrj }
796738fd1498Szrj else
796838fd1498Szrj {
796938fd1498Szrj if (constructor_p)
797038fd1498Szrj {
797138fd1498Szrj if (elf_init_array_section == NULL)
797238fd1498Szrj elf_init_array_section
797338fd1498Szrj = get_section (".init_array",
797438fd1498Szrj SECTION_WRITE | SECTION_NOTYPE, NULL_TREE);
797538fd1498Szrj sec = elf_init_array_section;
797638fd1498Szrj }
797738fd1498Szrj else
797838fd1498Szrj {
797938fd1498Szrj if (elf_fini_array_section == NULL)
798038fd1498Szrj elf_fini_array_section
798138fd1498Szrj = get_section (".fini_array",
798238fd1498Szrj SECTION_WRITE | SECTION_NOTYPE, NULL_TREE);
798338fd1498Szrj sec = elf_fini_array_section;
798438fd1498Szrj }
798538fd1498Szrj }
798638fd1498Szrj return sec;
798738fd1498Szrj }
798838fd1498Szrj
798938fd1498Szrj /* Use .init_array section for constructors. */
799038fd1498Szrj
799138fd1498Szrj void
default_elf_init_array_asm_out_constructor(rtx symbol,int priority)799238fd1498Szrj default_elf_init_array_asm_out_constructor (rtx symbol, int priority)
799338fd1498Szrj {
799438fd1498Szrj section *sec = get_elf_initfini_array_priority_section (priority,
799538fd1498Szrj true);
799638fd1498Szrj assemble_addr_to_section (symbol, sec);
799738fd1498Szrj }
799838fd1498Szrj
799938fd1498Szrj /* Use .fini_array section for destructors. */
800038fd1498Szrj
800138fd1498Szrj void
default_elf_fini_array_asm_out_destructor(rtx symbol,int priority)800238fd1498Szrj default_elf_fini_array_asm_out_destructor (rtx symbol, int priority)
800338fd1498Szrj {
800438fd1498Szrj section *sec = get_elf_initfini_array_priority_section (priority,
800538fd1498Szrj false);
800638fd1498Szrj assemble_addr_to_section (symbol, sec);
800738fd1498Szrj }
800838fd1498Szrj
800938fd1498Szrj /* Default TARGET_ASM_OUTPUT_IDENT hook.
801038fd1498Szrj
801138fd1498Szrj This is a bit of a cheat. The real default is a no-op, but this
801238fd1498Szrj hook is the default for all targets with a .ident directive. */
801338fd1498Szrj
801438fd1498Szrj void
default_asm_output_ident_directive(const char * ident_str)801538fd1498Szrj default_asm_output_ident_directive (const char *ident_str)
801638fd1498Szrj {
801738fd1498Szrj const char *ident_asm_op = "\t.ident\t";
801838fd1498Szrj
801938fd1498Szrj /* If we are still in the front end, do not write out the string
802038fd1498Szrj to asm_out_file. Instead, add a fake top-level asm statement.
802138fd1498Szrj This allows the front ends to use this hook without actually
802238fd1498Szrj writing to asm_out_file, to handle #ident or Pragma Ident. */
802338fd1498Szrj if (symtab->state == PARSING)
802438fd1498Szrj {
802538fd1498Szrj char *buf = ACONCAT ((ident_asm_op, "\"", ident_str, "\"\n", NULL));
802638fd1498Szrj symtab->finalize_toplevel_asm (build_string (strlen (buf), buf));
802738fd1498Szrj }
802838fd1498Szrj else
802938fd1498Szrj fprintf (asm_out_file, "%s\"%s\"\n", ident_asm_op, ident_str);
803038fd1498Szrj }
803138fd1498Szrj
803238fd1498Szrj
803338fd1498Szrj /* This function ensures that vtable_map variables are not only
803438fd1498Szrj in the comdat section, but that each variable has its own unique
803538fd1498Szrj comdat name. Without this the variables end up in the same section
803638fd1498Szrj with a single comdat name.
803738fd1498Szrj
803838fd1498Szrj FIXME: resolve_unique_section needs to deal better with
803938fd1498Szrj decls with both DECL_SECTION_NAME and DECL_ONE_ONLY. Once
804038fd1498Szrj that is fixed, this if-else statement can be replaced with
804138fd1498Szrj a single call to "switch_to_section (sect)". */
804238fd1498Szrj
804338fd1498Szrj static void
handle_vtv_comdat_section(section * sect,const_tree decl ATTRIBUTE_UNUSED)804438fd1498Szrj handle_vtv_comdat_section (section *sect, const_tree decl ATTRIBUTE_UNUSED)
804538fd1498Szrj {
804638fd1498Szrj #if defined (OBJECT_FORMAT_ELF)
804738fd1498Szrj targetm.asm_out.named_section (sect->named.name,
804838fd1498Szrj sect->named.common.flags
804938fd1498Szrj | SECTION_LINKONCE,
805038fd1498Szrj DECL_NAME (decl));
805138fd1498Szrj in_section = sect;
805238fd1498Szrj #else
805338fd1498Szrj /* Neither OBJECT_FORMAT_PE, nor OBJECT_FORMAT_COFF is set here.
805438fd1498Szrj Therefore the following check is used.
805538fd1498Szrj In case a the target is PE or COFF a comdat group section
805638fd1498Szrj is created, e.g. .vtable_map_vars$foo. The linker places
805738fd1498Szrj everything in .vtable_map_vars at the end.
805838fd1498Szrj
805938fd1498Szrj A fix could be made in
806038fd1498Szrj gcc/config/i386/winnt.c: i386_pe_unique_section. */
806138fd1498Szrj if (TARGET_PECOFF)
806238fd1498Szrj {
806338fd1498Szrj char *name;
806438fd1498Szrj
806538fd1498Szrj if (TREE_CODE (DECL_NAME (decl)) == IDENTIFIER_NODE)
806638fd1498Szrj name = ACONCAT ((sect->named.name, "$",
806738fd1498Szrj IDENTIFIER_POINTER (DECL_NAME (decl)), NULL));
806838fd1498Szrj else
806938fd1498Szrj name = ACONCAT ((sect->named.name, "$",
807038fd1498Szrj IDENTIFIER_POINTER (DECL_COMDAT_GROUP (DECL_NAME (decl))),
807138fd1498Szrj NULL));
807238fd1498Szrj
807338fd1498Szrj targetm.asm_out.named_section (name,
807438fd1498Szrj sect->named.common.flags
807538fd1498Szrj | SECTION_LINKONCE,
807638fd1498Szrj DECL_NAME (decl));
807738fd1498Szrj in_section = sect;
807838fd1498Szrj }
807938fd1498Szrj else
808038fd1498Szrj switch_to_section (sect);
808138fd1498Szrj #endif
808238fd1498Szrj }
808338fd1498Szrj
808438fd1498Szrj #include "gt-varasm.h"
8085