varasm.c revision 132718
118334Speter/* Output variables, constants and external declarations, for GNU compiler.
290075Sobrien   Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997,
3132718Skan   1998, 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
418334Speter
590075SobrienThis file is part of GCC.
618334Speter
790075SobrienGCC is free software; you can redistribute it and/or modify it under
890075Sobrienthe terms of the GNU General Public License as published by the Free
990075SobrienSoftware Foundation; either version 2, or (at your option) any later
1090075Sobrienversion.
1118334Speter
1290075SobrienGCC is distributed in the hope that it will be useful, but WITHOUT ANY
1390075SobrienWARRANTY; without even the implied warranty of MERCHANTABILITY or
1490075SobrienFITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1590075Sobrienfor more details.
1618334Speter
1718334SpeterYou should have received a copy of the GNU General Public License
1890075Sobrienalong with GCC; see the file COPYING.  If not, write to the Free
1990075SobrienSoftware Foundation, 59 Temple Place - Suite 330, Boston, MA
2090075Sobrien02111-1307, USA.  */
2118334Speter
2218334Speter
2318334Speter/* This file handles generation of all the assembler code
2418334Speter   *except* the instructions of a function.
2518334Speter   This includes declarations of variables and their initial values.
2618334Speter
2718334Speter   We also output the assembler code for constants stored in memory
2818334Speter   and are responsible for combining constants with the same value.  */
2918334Speter
3050397Sobrien#include "config.h"
3150397Sobrien#include "system.h"
32132718Skan#include "coretypes.h"
33132718Skan#include "tm.h"
3418334Speter#include "rtl.h"
3518334Speter#include "tree.h"
3618334Speter#include "flags.h"
3718334Speter#include "function.h"
3818334Speter#include "expr.h"
3918334Speter#include "hard-reg-set.h"
4018334Speter#include "regs.h"
41117395Skan#include "real.h"
4290075Sobrien#include "output.h"
4350397Sobrien#include "toplev.h"
4490075Sobrien#include "hashtab.h"
4518334Speter#include "c-pragma.h"
4690075Sobrien#include "ggc.h"
4790075Sobrien#include "langhooks.h"
4890075Sobrien#include "tm_p.h"
4990075Sobrien#include "debug.h"
5090075Sobrien#include "target.h"
51132718Skan#include "cgraph.h"
5218334Speter
5318334Speter#ifdef XCOFF_DEBUGGING_INFO
5490075Sobrien#include "xcoffout.h"		/* Needed for external data
5590075Sobrien				   declarations for e.g. AIX 4.x.  */
5618334Speter#endif
5718334Speter
5850397Sobrien#ifndef TRAMPOLINE_ALIGNMENT
5950397Sobrien#define TRAMPOLINE_ALIGNMENT FUNCTION_BOUNDARY
6050397Sobrien#endif
6118334Speter
6218334Speter#ifndef ASM_STABS_OP
6390075Sobrien#define ASM_STABS_OP "\t.stabs\t"
6418334Speter#endif
6518334Speter
6618334Speter/* The (assembler) name of the first globally-visible object output.  */
6790075Sobrienconst char *first_global_object_name;
6890075Sobrienconst char *weak_global_object_name;
6918334Speter
7090075Sobrienstruct addr_const;
71117395Skanstruct constant_descriptor_rtx;
7290075Sobrienstruct rtx_const;
7390075Sobrienstruct pool_constant;
7490075Sobrien
7590075Sobrien#define MAX_RTX_HASH_TABLE 61
7690075Sobrien
77117395Skanstruct varasm_status GTY(())
7890075Sobrien{
7990075Sobrien  /* Hash facility for making memory-constants
8090075Sobrien     from constant rtl-expressions.  It is used on RISC machines
8190075Sobrien     where immediate integer arguments and constant addresses are restricted
8290075Sobrien     so that such constants must be stored in memory.
8390075Sobrien
8490075Sobrien     This pool of constants is reinitialized for each function
8590075Sobrien     so each function gets its own constants-pool that comes right before
8690075Sobrien     it.  */
87117395Skan  struct constant_descriptor_rtx ** GTY ((length ("MAX_RTX_HASH_TABLE")))
88117395Skan    x_const_rtx_hash_table;
89117395Skan  struct pool_constant ** GTY ((length ("MAX_RTX_HASH_TABLE")))
90117395Skan    x_const_rtx_sym_hash_table;
9190075Sobrien
9290075Sobrien  /* Pointers to first and last constant in pool.  */
93117395Skan  struct pool_constant *x_first_pool;
94117395Skan  struct pool_constant *x_last_pool;
9590075Sobrien
9690075Sobrien  /* Current offset in constant pool (does not include any machine-specific
9790075Sobrien     header).  */
9890075Sobrien  HOST_WIDE_INT x_pool_offset;
99132718Skan
100132718Skan  /* Number of tree-constants deferred during the expansion of this
101132718Skan     function.  */
102132718Skan  unsigned int deferred_constants;
10390075Sobrien};
10490075Sobrien
10590075Sobrien#define const_rtx_hash_table (cfun->varasm->x_const_rtx_hash_table)
10690075Sobrien#define const_rtx_sym_hash_table (cfun->varasm->x_const_rtx_sym_hash_table)
10790075Sobrien#define first_pool (cfun->varasm->x_first_pool)
10890075Sobrien#define last_pool (cfun->varasm->x_last_pool)
10990075Sobrien#define pool_offset (cfun->varasm->x_pool_offset)
110132718Skan#define n_deferred_constants (cfun->varasm->deferred_constants)
11190075Sobrien
11218334Speter/* Number for making the label on the next
11318334Speter   constant that is stored in memory.  */
11418334Speter
115132718Skanstatic GTY(()) int const_labelno;
11618334Speter
11718334Speter/* Carry information from ASM_DECLARE_OBJECT_NAME
11818334Speter   to ASM_FINISH_DECLARE_OBJECT.  */
11918334Speter
12018334Speterint size_directive_output;
12118334Speter
12218334Speter/* The last decl for which assemble_variable was called,
12318334Speter   if it did ASM_DECLARE_OBJECT_NAME.
12418334Speter   If the last call to assemble_variable didn't do that,
12518334Speter   this holds 0.  */
12618334Speter
12718334Spetertree last_assemble_variable_decl;
12818334Speter
12990075Sobrien/* RTX_UNCHANGING_P in a MEM can mean it is stored into, for initialization.
13090075Sobrien   So giving constant the alias set for the type will allow such
13190075Sobrien   initializations to appear to conflict with the load of the constant.  We
13290075Sobrien   avoid this by giving all constants an alias set for just constants.
13390075Sobrien   Since there will be no stores to that alias set, nothing will ever
13490075Sobrien   conflict with them.  */
13518334Speter
13690075Sobrienstatic HOST_WIDE_INT const_alias_set;
13718334Speter
138132718Skanstatic const char *strip_reg_name (const char *);
139132718Skanstatic int contains_pointers_p (tree);
140132718Skan#ifdef ASM_OUTPUT_EXTERNAL
141132718Skanstatic bool incorporeal_function_p (tree);
142132718Skan#endif
143132718Skanstatic void decode_addr_const (tree, struct addr_const *);
144132718Skanstatic hashval_t const_desc_hash (const void *);
145132718Skanstatic int const_desc_eq (const void *, const void *);
146132718Skanstatic hashval_t const_hash_1 (const tree);
147132718Skanstatic int compare_constant (const tree, const tree);
148132718Skanstatic tree copy_constant (tree);
149132718Skanstatic void output_constant_def_contents (rtx);
150132718Skanstatic void decode_rtx_const (enum machine_mode, rtx, struct rtx_const *);
151132718Skanstatic unsigned int const_hash_rtx (enum machine_mode, rtx);
152132718Skanstatic int compare_constant_rtx (enum machine_mode, rtx,
153132718Skan				 struct constant_descriptor_rtx *);
154117395Skanstatic struct constant_descriptor_rtx * record_constant_rtx
155132718Skan  (enum machine_mode, rtx);
156132718Skanstatic struct pool_constant *find_pool_constant (struct function *, rtx);
157132718Skanstatic void mark_constant_pool (void);
158132718Skanstatic void mark_constants (rtx);
159132718Skanstatic int mark_constant (rtx *current_rtx, void *data);
160132718Skanstatic void output_addressed_constants (tree);
161132718Skanstatic unsigned HOST_WIDE_INT array_size_for_constructor (tree);
162132718Skanstatic unsigned min_align (unsigned, unsigned);
163132718Skanstatic void output_constructor (tree, unsigned HOST_WIDE_INT, unsigned int);
164132718Skanstatic void globalize_decl (tree);
165132718Skanstatic void maybe_assemble_visibility (tree);
166132718Skanstatic int in_named_entry_eq (const void *, const void *);
167132718Skanstatic hashval_t in_named_entry_hash (const void *);
16850397Sobrien#ifdef ASM_OUTPUT_BSS
169132718Skanstatic void asm_output_bss (FILE *, tree, const char *,
170132718Skan			    unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT);
17150397Sobrien#endif
17250397Sobrien#ifdef BSS_SECTION_ASM_OP
17350397Sobrien#ifdef ASM_OUTPUT_ALIGNED_BSS
174132718Skanstatic void asm_output_aligned_bss (FILE *, tree, const char *,
175132718Skan				    unsigned HOST_WIDE_INT, int)
176132718Skan     ATTRIBUTE_UNUSED;
17750397Sobrien#endif
17850397Sobrien#endif /* BSS_SECTION_ASM_OP */
179132718Skanstatic bool asm_emit_uninitialised (tree, const char*,
180132718Skan				    unsigned HOST_WIDE_INT,
181132718Skan				    unsigned HOST_WIDE_INT);
182132718Skanstatic void mark_weak (tree);
18318334Speter
184132718Skanenum in_section { no_section, in_text, in_data, in_named
18550397Sobrien#ifdef BSS_SECTION_ASM_OP
18650397Sobrien  , in_bss
18750397Sobrien#endif
18890075Sobrien#ifdef CTORS_SECTION_ASM_OP
18990075Sobrien  , in_ctors
19050397Sobrien#endif
19190075Sobrien#ifdef DTORS_SECTION_ASM_OP
19290075Sobrien  , in_dtors
19390075Sobrien#endif
194117395Skan#ifdef READONLY_DATA_SECTION_ASM_OP
195117395Skan  , in_readonly_data
196117395Skan#endif
19718334Speter#ifdef EXTRA_SECTIONS
19850397Sobrien  , EXTRA_SECTIONS
19918334Speter#endif
200132718Skan};
201132718Skanstatic GTY(()) enum in_section in_section = no_section;
20218334Speter
203117395Skan/* Return a nonzero value if DECL has a section attribute.  */
20490075Sobrien#ifndef IN_NAMED_SECTION
20518334Speter#define IN_NAMED_SECTION(DECL) \
20618334Speter  ((TREE_CODE (DECL) == FUNCTION_DECL || TREE_CODE (DECL) == VAR_DECL) \
20718334Speter   && DECL_SECTION_NAME (DECL) != NULL_TREE)
20890075Sobrien#endif
20918334Speter
21018334Speter/* Text of section name when in_section == in_named.  */
211132718Skanstatic GTY(()) const char *in_named_name;
21218334Speter
21390075Sobrien/* Hash table of flags that have been used for a particular named section.  */
21490075Sobrien
215132718Skanstruct in_named_entry GTY(())
21690075Sobrien{
21790075Sobrien  const char *name;
21890075Sobrien  unsigned int flags;
21990075Sobrien  bool declared;
22090075Sobrien};
22190075Sobrien
222132718Skanstatic GTY((param_is (struct in_named_entry))) htab_t in_named_htab;
22390075Sobrien
22418334Speter/* Define functions like text_section for any extra sections.  */
22518334Speter#ifdef EXTRA_SECTION_FUNCTIONS
22618334SpeterEXTRA_SECTION_FUNCTIONS
22718334Speter#endif
22818334Speter
22918334Speter/* Tell assembler to switch to text section.  */
23018334Speter
23118334Spetervoid
232132718Skantext_section (void)
23318334Speter{
23418334Speter  if (in_section != in_text)
23518334Speter    {
236117395Skan      in_section = in_text;
23750397Sobrien      fprintf (asm_out_file, "%s\n", TEXT_SECTION_ASM_OP);
23818334Speter    }
23918334Speter}
24018334Speter
24118334Speter/* Tell assembler to switch to data section.  */
24218334Speter
24318334Spetervoid
244132718Skandata_section (void)
24518334Speter{
24618334Speter  if (in_section != in_data)
24718334Speter    {
248117395Skan      in_section = in_data;
24950397Sobrien      if (flag_shared_data)
25018334Speter	{
25118334Speter#ifdef SHARED_SECTION_ASM_OP
25250397Sobrien	  fprintf (asm_out_file, "%s\n", SHARED_SECTION_ASM_OP);
25318334Speter#else
25450397Sobrien	  fprintf (asm_out_file, "%s\n", DATA_SECTION_ASM_OP);
25518334Speter#endif
25618334Speter	}
25750397Sobrien      else
25850397Sobrien	fprintf (asm_out_file, "%s\n", DATA_SECTION_ASM_OP);
25918334Speter    }
26018334Speter}
261117395Skan
26218334Speter/* Tell assembler to switch to read-only data section.  This is normally
26318334Speter   the text section.  */
26418334Speter
26518334Spetervoid
266132718Skanreadonly_data_section (void)
26718334Speter{
26818334Speter#ifdef READONLY_DATA_SECTION
26918334Speter  READONLY_DATA_SECTION ();  /* Note this can call data_section.  */
27018334Speter#else
271117395Skan#ifdef READONLY_DATA_SECTION_ASM_OP
272117395Skan  if (in_section != in_readonly_data)
273117395Skan    {
274117395Skan      in_section = in_readonly_data;
275117395Skan      fputs (READONLY_DATA_SECTION_ASM_OP, asm_out_file);
276117395Skan      fputc ('\n', asm_out_file);
277117395Skan    }
278117395Skan#else
27918334Speter  text_section ();
28018334Speter#endif
281117395Skan#endif
28218334Speter}
28318334Speter
28450397Sobrien/* Determine if we're in the text section.  */
28518334Speter
28618334Speterint
287132718Skanin_text_section (void)
28818334Speter{
28918334Speter  return in_section == in_text;
29018334Speter}
29118334Speter
29250397Sobrien/* Determine if we're in the data section.  */
29350397Sobrien
29450397Sobrienint
295132718Skanin_data_section (void)
29650397Sobrien{
29750397Sobrien  return in_section == in_data;
29850397Sobrien}
29950397Sobrien
30090075Sobrien/* Helper routines for maintaining in_named_htab.  */
30190075Sobrien
30290075Sobrienstatic int
303132718Skanin_named_entry_eq (const void *p1, const void *p2)
30490075Sobrien{
30590075Sobrien  const struct in_named_entry *old = p1;
30690075Sobrien  const char *new = p2;
30790075Sobrien
30890075Sobrien  return strcmp (old->name, new) == 0;
30990075Sobrien}
31090075Sobrien
31190075Sobrienstatic hashval_t
312132718Skanin_named_entry_hash (const void *p)
31390075Sobrien{
31490075Sobrien  const struct in_named_entry *old = p;
31590075Sobrien  return htab_hash_string (old->name);
31690075Sobrien}
31790075Sobrien
31890075Sobrien/* If SECTION has been seen before as a named section, return the flags
31990075Sobrien   that were used.  Otherwise, return 0.  Note, that 0 is a perfectly valid
32090075Sobrien   set of flags for a section to have, so 0 does not mean that the section
32190075Sobrien   has not been seen.  */
32290075Sobrien
32390075Sobrienunsigned int
324132718Skanget_named_section_flags (const char *section)
32590075Sobrien{
32690075Sobrien  struct in_named_entry **slot;
32790075Sobrien
328117395Skan  slot = (struct in_named_entry **)
32990075Sobrien    htab_find_slot_with_hash (in_named_htab, section,
33090075Sobrien			      htab_hash_string (section), NO_INSERT);
33190075Sobrien
33290075Sobrien  return slot ? (*slot)->flags : 0;
33390075Sobrien}
33490075Sobrien
33590075Sobrien/* Returns true if the section has been declared before.   Sets internal
336117395Skan   flag on this section in in_named_hash so subsequent calls on this
33790075Sobrien   section will return false.  */
33890075Sobrien
33990075Sobrienbool
340132718Skannamed_section_first_declaration (const char *name)
34190075Sobrien{
34290075Sobrien  struct in_named_entry **slot;
34390075Sobrien
344117395Skan  slot = (struct in_named_entry **)
345117395Skan    htab_find_slot_with_hash (in_named_htab, name,
34690075Sobrien			      htab_hash_string (name), NO_INSERT);
34790075Sobrien  if (! (*slot)->declared)
34890075Sobrien    {
34990075Sobrien      (*slot)->declared = true;
35090075Sobrien      return true;
35190075Sobrien    }
352117395Skan  else
35390075Sobrien    {
35490075Sobrien      return false;
35590075Sobrien    }
35690075Sobrien}
35790075Sobrien
35890075Sobrien
35990075Sobrien/* Record FLAGS for SECTION.  If SECTION was previously recorded with a
36090075Sobrien   different set of flags, return false.  */
36190075Sobrien
36290075Sobrienbool
363132718Skanset_named_section_flags (const char *section, unsigned int flags)
36490075Sobrien{
36590075Sobrien  struct in_named_entry **slot, *entry;
36690075Sobrien
367117395Skan  slot = (struct in_named_entry **)
36890075Sobrien    htab_find_slot_with_hash (in_named_htab, section,
36990075Sobrien			      htab_hash_string (section), INSERT);
37090075Sobrien  entry = *slot;
37190075Sobrien
37290075Sobrien  if (!entry)
37390075Sobrien    {
374132718Skan      entry = ggc_alloc (sizeof (*entry));
37590075Sobrien      *slot = entry;
37690075Sobrien      entry->name = ggc_strdup (section);
37790075Sobrien      entry->flags = flags;
37890075Sobrien      entry->declared = false;
37990075Sobrien    }
38090075Sobrien  else if (entry->flags != flags)
38190075Sobrien    return false;
38290075Sobrien
38390075Sobrien  return true;
38490075Sobrien}
38590075Sobrien
38690075Sobrien/* Tell assembler to change to section NAME with attributes FLAGS.  */
38790075Sobrien
38890075Sobrienvoid
389132718Skannamed_section_flags (const char *name, unsigned int flags)
39090075Sobrien{
39190075Sobrien  if (in_section != in_named || strcmp (name, in_named_name) != 0)
39290075Sobrien    {
39390075Sobrien      if (! set_named_section_flags (name, flags))
39490075Sobrien	abort ();
39590075Sobrien
396117395Skan      (*targetm.asm_out.named_section) (name, flags);
39790075Sobrien
39890075Sobrien      if (flags & SECTION_FORGET)
39990075Sobrien	in_section = no_section;
40090075Sobrien      else
40190075Sobrien	{
40290075Sobrien	  in_named_name = ggc_strdup (name);
40390075Sobrien	  in_section = in_named;
40490075Sobrien	}
40590075Sobrien    }
40690075Sobrien}
40790075Sobrien
40818334Speter/* Tell assembler to change to section NAME for DECL.
40918334Speter   If DECL is NULL, just switch to section NAME.
41050397Sobrien   If NAME is NULL, get the name from DECL.
41150397Sobrien   If RELOC is 1, the initializer for DECL contains relocs.  */
41218334Speter
41318334Spetervoid
414132718Skannamed_section (tree decl, const char *name, int reloc)
41518334Speter{
41690075Sobrien  unsigned int flags;
41790075Sobrien
41890075Sobrien  if (decl != NULL_TREE && !DECL_P (decl))
41918334Speter    abort ();
42018334Speter  if (name == NULL)
42118334Speter    name = TREE_STRING_POINTER (DECL_SECTION_NAME (decl));
42218334Speter
42390075Sobrien  flags = (* targetm.section_type_flags) (decl, name, reloc);
42490075Sobrien
42590075Sobrien  /* Sanity check user variables for flag changes.  Non-user
42696263Sobrien     section flag changes will abort in named_section_flags.
42796263Sobrien     However, don't complain if SECTION_OVERRIDE is set.
42896263Sobrien     We trust that the setter knows that it is safe to ignore
42996263Sobrien     the default flags for this decl.  */
43090075Sobrien  if (decl && ! set_named_section_flags (name, flags))
43118334Speter    {
43290075Sobrien      flags = get_named_section_flags (name);
43396263Sobrien      if ((flags & SECTION_OVERRIDE) == 0)
434132718Skan	error ("%J%D causes a section type conflict", decl, decl);
43590075Sobrien    }
43650397Sobrien
43790075Sobrien  named_section_flags (name, flags);
43818334Speter}
43918334Speter
44090075Sobrien/* If required, set DECL_SECTION_NAME to a unique name.  */
44150397Sobrien
442132718Skanvoid
443132718Skanresolve_unique_section (tree decl, int reloc ATTRIBUTE_UNUSED,
444132718Skan			int flag_function_or_data_sections)
44590075Sobrien{
44690075Sobrien  if (DECL_SECTION_NAME (decl) == NULL_TREE
447117395Skan      && targetm.have_named_sections
448102780Skan      && (flag_function_or_data_sections
449117395Skan	  || DECL_ONE_ONLY (decl)))
450117395Skan    (*targetm.asm_out.unique_section) (decl, reloc);
45190075Sobrien}
45290075Sobrien
45350397Sobrien#ifdef BSS_SECTION_ASM_OP
45450397Sobrien
45550397Sobrien/* Tell the assembler to switch to the bss section.  */
45650397Sobrien
45750397Sobrienvoid
458132718Skanbss_section (void)
45950397Sobrien{
46050397Sobrien  if (in_section != in_bss)
46150397Sobrien    {
462132718Skan      fprintf (asm_out_file, "%s\n", BSS_SECTION_ASM_OP);
46350397Sobrien      in_section = in_bss;
46450397Sobrien    }
46550397Sobrien}
46650397Sobrien
46750397Sobrien#ifdef ASM_OUTPUT_BSS
46850397Sobrien
46950397Sobrien/* Utility function for ASM_OUTPUT_BSS for targets to use if
47050397Sobrien   they don't support alignments in .bss.
47150397Sobrien   ??? It is believed that this function will work in most cases so such
47250397Sobrien   support is localized here.  */
47350397Sobrien
47450397Sobrienstatic void
475132718Skanasm_output_bss (FILE *file, tree decl ATTRIBUTE_UNUSED,
476132718Skan		const char *name,
477132718Skan		unsigned HOST_WIDE_INT size ATTRIBUTE_UNUSED,
478132718Skan		unsigned HOST_WIDE_INT rounded)
47950397Sobrien{
480117395Skan  (*targetm.asm_out.globalize_label) (file, name);
48150397Sobrien  bss_section ();
48250397Sobrien#ifdef ASM_DECLARE_OBJECT_NAME
48350397Sobrien  last_assemble_variable_decl = decl;
48450397Sobrien  ASM_DECLARE_OBJECT_NAME (file, name, decl);
48550397Sobrien#else
48650397Sobrien  /* Standard thing is just output label for the object.  */
48750397Sobrien  ASM_OUTPUT_LABEL (file, name);
48850397Sobrien#endif /* ASM_DECLARE_OBJECT_NAME */
489102780Skan  ASM_OUTPUT_SKIP (file, rounded ? rounded : 1);
49050397Sobrien}
49150397Sobrien
49250397Sobrien#endif
49350397Sobrien
49450397Sobrien#ifdef ASM_OUTPUT_ALIGNED_BSS
49550397Sobrien
49650397Sobrien/* Utility function for targets to use in implementing
49750397Sobrien   ASM_OUTPUT_ALIGNED_BSS.
49850397Sobrien   ??? It is believed that this function will work in most cases so such
49950397Sobrien   support is localized here.  */
50050397Sobrien
50150397Sobrienstatic void
502132718Skanasm_output_aligned_bss (FILE *file, tree decl ATTRIBUTE_UNUSED,
503132718Skan			const char *name, unsigned HOST_WIDE_INT size,
504132718Skan			int align)
50550397Sobrien{
50650397Sobrien  bss_section ();
50750397Sobrien  ASM_OUTPUT_ALIGN (file, floor_log2 (align / BITS_PER_UNIT));
50850397Sobrien#ifdef ASM_DECLARE_OBJECT_NAME
50950397Sobrien  last_assemble_variable_decl = decl;
51050397Sobrien  ASM_DECLARE_OBJECT_NAME (file, name, decl);
51150397Sobrien#else
51250397Sobrien  /* Standard thing is just output label for the object.  */
51350397Sobrien  ASM_OUTPUT_LABEL (file, name);
51450397Sobrien#endif /* ASM_DECLARE_OBJECT_NAME */
51550397Sobrien  ASM_OUTPUT_SKIP (file, size ? size : 1);
51650397Sobrien}
51750397Sobrien
51850397Sobrien#endif
51950397Sobrien
52050397Sobrien#endif /* BSS_SECTION_ASM_OP */
52150397Sobrien
52218334Speter/* Switch to the section for function DECL.
52318334Speter
52418334Speter   If DECL is NULL_TREE, switch to the text section.
52518334Speter   ??? It's not clear that we will ever be passed NULL_TREE, but it's
52618334Speter   safer to handle it.  */
52718334Speter
52818334Spetervoid
529132718Skanfunction_section (tree decl)
53018334Speter{
53118334Speter  if (decl != NULL_TREE
53218334Speter      && DECL_SECTION_NAME (decl) != NULL_TREE)
53350397Sobrien    named_section (decl, (char *) 0, 0);
53450397Sobrien  else
53550397Sobrien    text_section ();
53618334Speter}
53750397Sobrien
538117395Skan/* Switch to section for variable DECL.  RELOC is the same as the
539117395Skan   argument to SELECT_SECTION.  */
54050397Sobrien
54150397Sobrienvoid
542132718Skanvariable_section (tree decl, int reloc)
54350397Sobrien{
54450397Sobrien  if (IN_NAMED_SECTION (decl))
54550397Sobrien    named_section (decl, NULL, reloc);
54650397Sobrien  else
547117395Skan    (*targetm.asm_out.select_section) (decl, reloc, DECL_ALIGN (decl));
54850397Sobrien}
54950397Sobrien
55090075Sobrien/* Tell assembler to switch to the section for string merging.  */
55190075Sobrien
55218334Spetervoid
553132718Skanmergeable_string_section (tree decl ATTRIBUTE_UNUSED,
554132718Skan			  unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED,
555132718Skan			  unsigned int flags ATTRIBUTE_UNUSED)
55618334Speter{
557132718Skan  if (HAVE_GAS_SHF_MERGE && flag_merge_constants
55890075Sobrien      && TREE_CODE (decl) == STRING_CST
55990075Sobrien      && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
56090075Sobrien      && align <= 256
56190075Sobrien      && TREE_STRING_LENGTH (decl) >= int_size_in_bytes (TREE_TYPE (decl)))
56218334Speter    {
56390075Sobrien      enum machine_mode mode;
56490075Sobrien      unsigned int modesize;
56590075Sobrien      const char *str;
56690075Sobrien      int i, j, len, unit;
56790075Sobrien      char name[30];
56818334Speter
56990075Sobrien      mode = TYPE_MODE (TREE_TYPE (TREE_TYPE (decl)));
57090075Sobrien      modesize = GET_MODE_BITSIZE (mode);
57190075Sobrien      if (modesize >= 8 && modesize <= 256
57290075Sobrien	  && (modesize & (modesize - 1)) == 0)
57390075Sobrien	{
57490075Sobrien	  if (align < modesize)
57590075Sobrien	    align = modesize;
57618334Speter
57790075Sobrien	  str = TREE_STRING_POINTER (decl);
57890075Sobrien	  len = TREE_STRING_LENGTH (decl);
57990075Sobrien	  unit = GET_MODE_SIZE (mode);
58018334Speter
58190075Sobrien	  /* Check for embedded NUL characters.  */
58290075Sobrien	  for (i = 0; i < len; i += unit)
58390075Sobrien	    {
58490075Sobrien	      for (j = 0; j < unit; j++)
585117395Skan		if (str[i + j] != '\0')
58690075Sobrien		  break;
58790075Sobrien	      if (j == unit)
58890075Sobrien		break;
58990075Sobrien	    }
59090075Sobrien	  if (i == len - unit)
59190075Sobrien	    {
59290075Sobrien	      sprintf (name, ".rodata.str%d.%d", modesize / 8,
59390075Sobrien		       (int) (align / 8));
59490075Sobrien	      flags |= (modesize / 8) | SECTION_MERGE | SECTION_STRINGS;
59590075Sobrien	      if (!i && modesize < align)
59690075Sobrien		{
59790075Sobrien		  /* A "" string with requested alignment greater than
59890075Sobrien		     character size might cause a problem:
59990075Sobrien		     if some other string required even bigger
60090075Sobrien		     alignment than "", then linker might think the
60190075Sobrien		     "" is just part of padding after some other string
60290075Sobrien		     and not put it into the hash table initially.
60390075Sobrien		     But this means "" could have smaller alignment
60490075Sobrien		     than requested.  */
60590075Sobrien#ifdef ASM_OUTPUT_SECTION_START
60690075Sobrien		  named_section_flags (name, flags);
60790075Sobrien		  ASM_OUTPUT_SECTION_START (asm_out_file);
60890075Sobrien#else
60990075Sobrien		  readonly_data_section ();
61018334Speter#endif
61190075Sobrien		  return;
61290075Sobrien		}
61390075Sobrien
61490075Sobrien	      named_section_flags (name, flags);
61590075Sobrien	      return;
61690075Sobrien	    }
61790075Sobrien	}
61818334Speter    }
619132718Skan
62090075Sobrien  readonly_data_section ();
621117395Skan}
62290075Sobrien
62390075Sobrien/* Tell assembler to switch to the section for constant merging.  */
62490075Sobrien
62590075Sobrienvoid
626132718Skanmergeable_constant_section (enum machine_mode mode ATTRIBUTE_UNUSED,
627132718Skan			    unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED,
628132718Skan			    unsigned int flags ATTRIBUTE_UNUSED)
62990075Sobrien{
63090075Sobrien  unsigned int modesize = GET_MODE_BITSIZE (mode);
63190075Sobrien
632132718Skan  if (HAVE_GAS_SHF_MERGE && flag_merge_constants
63390075Sobrien      && mode != VOIDmode
63490075Sobrien      && mode != BLKmode
63590075Sobrien      && modesize <= align
63690075Sobrien      && align >= 8
63790075Sobrien      && align <= 256
63890075Sobrien      && (align & (align - 1)) == 0)
63950397Sobrien    {
64090075Sobrien      char name[24];
64190075Sobrien
64290075Sobrien      sprintf (name, ".rodata.cst%d", (int) (align / 8));
64390075Sobrien      flags |= (align / 8) | SECTION_MERGE;
64490075Sobrien      named_section_flags (name, flags);
64590075Sobrien      return;
646117395Skan    }
647132718Skan
64890075Sobrien  readonly_data_section ();
64918334Speter}
65090075Sobrien
65118334Speter/* Given NAME, a putative register name, discard any customary prefixes.  */
65218334Speter
65352284Sobrienstatic const char *
654132718Skanstrip_reg_name (const char *name)
65518334Speter{
65618334Speter#ifdef REGISTER_PREFIX
65718334Speter  if (!strncmp (name, REGISTER_PREFIX, strlen (REGISTER_PREFIX)))
65818334Speter    name += strlen (REGISTER_PREFIX);
65918334Speter#endif
66018334Speter  if (name[0] == '%' || name[0] == '#')
66118334Speter    name++;
66218334Speter  return name;
66318334Speter}
66418334Speter
66518334Speter/* Decode an `asm' spec for a declaration as a register name.
66618334Speter   Return the register number, or -1 if nothing specified,
66718334Speter   or -2 if the ASMSPEC is not `cc' or `memory' and is not recognized,
66818334Speter   or -3 if ASMSPEC is `cc' and is not recognized,
66918334Speter   or -4 if ASMSPEC is `memory' and is not recognized.
67018334Speter   Accept an exact spelling or a decimal number.
67118334Speter   Prefixes such as % are optional.  */
67218334Speter
67318334Speterint
674132718Skandecode_reg_name (const char *asmspec)
67518334Speter{
67618334Speter  if (asmspec != 0)
67718334Speter    {
67818334Speter      int i;
67918334Speter
68018334Speter      /* Get rid of confusing prefixes.  */
68118334Speter      asmspec = strip_reg_name (asmspec);
68290075Sobrien
68318334Speter      /* Allow a decimal number as a "register name".  */
68418334Speter      for (i = strlen (asmspec) - 1; i >= 0; i--)
68590075Sobrien	if (! ISDIGIT (asmspec[i]))
68618334Speter	  break;
68718334Speter      if (asmspec[0] != 0 && i < 0)
68818334Speter	{
68918334Speter	  i = atoi (asmspec);
69018334Speter	  if (i < FIRST_PSEUDO_REGISTER && i >= 0)
69118334Speter	    return i;
69218334Speter	  else
69318334Speter	    return -2;
69418334Speter	}
69518334Speter
69618334Speter      for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
69718334Speter	if (reg_names[i][0]
69818334Speter	    && ! strcmp (asmspec, strip_reg_name (reg_names[i])))
69918334Speter	  return i;
70018334Speter
70118334Speter#ifdef ADDITIONAL_REGISTER_NAMES
70218334Speter      {
70390075Sobrien	static const struct { const char *const name; const int number; } table[]
70418334Speter	  = ADDITIONAL_REGISTER_NAMES;
70518334Speter
70690075Sobrien	for (i = 0; i < (int) ARRAY_SIZE (table); i++)
70718334Speter	  if (! strcmp (asmspec, table[i].name))
70818334Speter	    return table[i].number;
70918334Speter      }
71018334Speter#endif /* ADDITIONAL_REGISTER_NAMES */
71118334Speter
71218334Speter      if (!strcmp (asmspec, "memory"))
71318334Speter	return -4;
71418334Speter
71518334Speter      if (!strcmp (asmspec, "cc"))
71618334Speter	return -3;
71718334Speter
71818334Speter      return -2;
71918334Speter    }
72018334Speter
72118334Speter  return -1;
72218334Speter}
72318334Speter
72490075Sobrien/* Create the DECL_RTL for a VAR_DECL or FUNCTION_DECL.  DECL should
72590075Sobrien   have static storage duration.  In other words, it should not be an
72690075Sobrien   automatic variable, including PARM_DECLs.
72718334Speter
72890075Sobrien   There is, however, one exception: this function handles variables
72990075Sobrien   explicitly placed in a particular register by the user.
73090075Sobrien
73190075Sobrien   ASMSPEC, if not 0, is the string which the user specified as the
73290075Sobrien   assembler symbol name.
73390075Sobrien
73418334Speter   This is never called for PARM_DECL nodes.  */
73518334Speter
73618334Spetervoid
737132718Skanmake_decl_rtl (tree decl, const char *asmspec)
73818334Speter{
73990075Sobrien  const char *name = 0;
74018334Speter  int reg_number;
74190075Sobrien  rtx x;
74218334Speter
74390075Sobrien  /* Check that we are not being given an automatic variable.  */
74490075Sobrien  /* A weak alias has TREE_PUBLIC set but not the other bits.  */
74590075Sobrien  if (TREE_CODE (decl) == PARM_DECL
74690075Sobrien      || TREE_CODE (decl) == RESULT_DECL
74790075Sobrien      || (TREE_CODE (decl) == VAR_DECL
74890075Sobrien	  && !TREE_STATIC (decl)
74990075Sobrien	  && !TREE_PUBLIC (decl)
75090075Sobrien	  && !DECL_EXTERNAL (decl)
75190075Sobrien	  && !DECL_REGISTER (decl)))
75290075Sobrien    abort ();
75390075Sobrien  /* And that we were not given a type or a label.  */
75490075Sobrien  else if (TREE_CODE (decl) == TYPE_DECL
75590075Sobrien	   || TREE_CODE (decl) == LABEL_DECL)
75690075Sobrien    abort ();
75718334Speter
75890075Sobrien  /* For a duplicate declaration, we can be called twice on the
75990075Sobrien     same DECL node.  Don't discard the RTL already made.  */
76090075Sobrien  if (DECL_RTL_SET_P (decl))
76190075Sobrien    {
76290075Sobrien      /* If the old RTL had the wrong mode, fix the mode.  */
76390075Sobrien      if (GET_MODE (DECL_RTL (decl)) != DECL_MODE (decl))
76490075Sobrien	SET_DECL_RTL (decl, adjust_address_nv (DECL_RTL (decl),
76590075Sobrien					       DECL_MODE (decl), 0));
76618334Speter
767117395Skan      /* ??? Another way to do this would be to maintain a hashed
768117395Skan	 table of such critters.  Instead of adding stuff to a DECL
769117395Skan	 to give certain attributes to it, we could use an external
770117395Skan	 hash map from DECL to set of attributes.  */
771117395Skan
77290075Sobrien      /* Let the target reassign the RTL if it wants.
77390075Sobrien	 This is necessary, for example, when one machine specific
77490075Sobrien	 decl attribute overrides another.  */
775132718Skan      (* targetm.encode_section_info) (decl, DECL_RTL (decl), false);
77690075Sobrien      return;
77790075Sobrien    }
77890075Sobrien
77990075Sobrien  reg_number = decode_reg_name (asmspec);
78018334Speter  if (reg_number == -2)
78118334Speter    {
78290075Sobrien      /* ASMSPEC is given, and not the name of a register.  Mark the
78390075Sobrien	 name with a star so assemble_name won't munge it.  */
78490075Sobrien      char *starred = alloca (strlen (asmspec) + 2);
78590075Sobrien      starred[0] = '*';
78690075Sobrien      strcpy (starred + 1, asmspec);
787132718Skan      change_decl_assembler_name (decl, get_identifier (starred));
78818334Speter    }
78918334Speter
790132718Skan  name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
791132718Skan
79290075Sobrien  if (TREE_CODE (decl) != FUNCTION_DECL && DECL_REGISTER (decl))
79318334Speter    {
79418334Speter      /* First detect errors in declaring global registers.  */
79590075Sobrien      if (reg_number == -1)
796132718Skan	error ("%Jregister name not specified for '%D'", decl, decl);
79790075Sobrien      else if (reg_number < 0)
798132718Skan	error ("%Jinvalid register name for '%D'", decl, decl);
79990075Sobrien      else if (TYPE_MODE (TREE_TYPE (decl)) == BLKmode)
800132718Skan	error ("%Jdata type of '%D' isn't suitable for a register",
801132718Skan	       decl, decl);
80290075Sobrien      else if (! HARD_REGNO_MODE_OK (reg_number, TYPE_MODE (TREE_TYPE (decl))))
803132718Skan	error ("%Jregister specified for '%D' isn't suitable for data type",
804132718Skan               decl, decl);
80518334Speter      /* Now handle properly declared static register variables.  */
80690075Sobrien      else
80718334Speter	{
80818334Speter	  int nregs;
80950397Sobrien
81090075Sobrien	  if (DECL_INITIAL (decl) != 0 && TREE_STATIC (decl))
81118334Speter	    {
81218334Speter	      DECL_INITIAL (decl) = 0;
81318334Speter	      error ("global register variable has initial value");
81418334Speter	    }
81518334Speter	  if (TREE_THIS_VOLATILE (decl))
81618334Speter	    warning ("volatile register variables don't work as you might wish");
81718334Speter
81818334Speter	  /* If the user specified one of the eliminables registers here,
81918334Speter	     e.g., FRAME_POINTER_REGNUM, we don't want to get this variable
82090075Sobrien	     confused with that register and be eliminated.  This usage is
82190075Sobrien	     somewhat suspect...  */
82218334Speter
82390075Sobrien	  SET_DECL_RTL (decl, gen_rtx_raw_REG (DECL_MODE (decl), reg_number));
82490075Sobrien	  ORIGINAL_REGNO (DECL_RTL (decl)) = reg_number;
82518334Speter	  REG_USERVAR_P (DECL_RTL (decl)) = 1;
82618334Speter
82790075Sobrien	  if (TREE_STATIC (decl))
82818334Speter	    {
82918334Speter	      /* Make this register global, so not usable for anything
83018334Speter		 else.  */
83190075Sobrien#ifdef ASM_DECLARE_REGISTER_GLOBAL
83290075Sobrien	      ASM_DECLARE_REGISTER_GLOBAL (asm_out_file, decl, reg_number, name);
83390075Sobrien#endif
83418334Speter	      nregs = HARD_REGNO_NREGS (reg_number, DECL_MODE (decl));
83518334Speter	      while (nregs > 0)
83618334Speter		globalize_reg (reg_number + --nregs);
83718334Speter	    }
83890075Sobrien
83990075Sobrien	  /* As a register variable, it has no section.  */
84090075Sobrien	  return;
84118334Speter	}
84290075Sobrien    }
84318334Speter
84490075Sobrien  /* Now handle ordinary static variables and functions (in memory).
84590075Sobrien     Also handle vars declared register invalidly.  */
84618334Speter
84790075Sobrien  if (reg_number >= 0 || reg_number == -3)
848132718Skan    error ("%Jregister name given for non-register variable '%D'", decl, decl);
84918334Speter
85090075Sobrien  /* Specifying a section attribute on a variable forces it into a
85190075Sobrien     non-.bss section, and thus it cannot be common.  */
85290075Sobrien  if (TREE_CODE (decl) == VAR_DECL
85390075Sobrien      && DECL_SECTION_NAME (decl) != NULL_TREE
85490075Sobrien      && DECL_INITIAL (decl) == NULL_TREE
85590075Sobrien      && DECL_COMMON (decl))
85690075Sobrien    DECL_COMMON (decl) = 0;
85718334Speter
858117395Skan  /* Variables can't be both common and weak.  */
859117395Skan  if (TREE_CODE (decl) == VAR_DECL && DECL_WEAK (decl))
860117395Skan    DECL_COMMON (decl) = 0;
861117395Skan
862132718Skan  x = gen_rtx_SYMBOL_REF (Pmode, name);
863132718Skan  SYMBOL_REF_WEAK (x) = DECL_WEAK (decl);
864132718Skan  SYMBOL_REF_DECL (x) = decl;
86518334Speter
866132718Skan  x = gen_rtx_MEM (DECL_MODE (decl), x);
86790075Sobrien  if (TREE_CODE (decl) != FUNCTION_DECL)
86890075Sobrien    set_mem_attributes (x, decl, 1);
86990075Sobrien  SET_DECL_RTL (decl, x);
87090075Sobrien
87190075Sobrien  /* Optionally set flags or add text to the name to record information
87290075Sobrien     such as that it is a function name.
87390075Sobrien     If the name is changed, the macro ASM_OUTPUT_LABELREF
87490075Sobrien     will have to know how to strip this information.  */
875132718Skan  (* targetm.encode_section_info) (decl, DECL_RTL (decl), true);
87618334Speter}
87718334Speter
87818334Speter/* Make the rtl for variable VAR be volatile.
87918334Speter   Use this only for static variables.  */
88018334Speter
88118334Spetervoid
882132718Skanmake_var_volatile (tree var)
88318334Speter{
88418334Speter  if (GET_CODE (DECL_RTL (var)) != MEM)
88518334Speter    abort ();
88618334Speter
88718334Speter  MEM_VOLATILE_P (DECL_RTL (var)) = 1;
88818334Speter}
88918334Speter
89018334Speter/* Output a string of literal assembler code
89118334Speter   for an `asm' keyword used between functions.  */
89218334Speter
89318334Spetervoid
894132718Skanassemble_asm (tree string)
89518334Speter{
89618334Speter  app_enable ();
89718334Speter
89818334Speter  if (TREE_CODE (string) == ADDR_EXPR)
89918334Speter    string = TREE_OPERAND (string, 0);
90018334Speter
90118334Speter  fprintf (asm_out_file, "\t%s\n", TREE_STRING_POINTER (string));
90218334Speter}
90318334Speter
90490075Sobrien/* Record an element in the table of global destructors.  SYMBOL is
90590075Sobrien   a SYMBOL_REF of the function to be called; PRIORITY is a number
90690075Sobrien   between 0 and MAX_INIT_PRIORITY.  */
90718334Speter
90890075Sobrienvoid
909132718Skandefault_stabs_asm_out_destructor (rtx symbol, int priority ATTRIBUTE_UNUSED)
91090075Sobrien{
91190075Sobrien  /* Tell GNU LD that this is part of the static destructor set.
91290075Sobrien     This will work for any system that uses stabs, most usefully
91390075Sobrien     aout systems.  */
91490075Sobrien  fprintf (asm_out_file, "%s\"___DTOR_LIST__\",22,0,0,", ASM_STABS_OP);
91590075Sobrien  assemble_name (asm_out_file, XSTR (symbol, 0));
91690075Sobrien  fputc ('\n', asm_out_file);
91790075Sobrien}
91818334Speter
91990075Sobrienvoid
920132718Skandefault_named_section_asm_out_destructor (rtx symbol, int priority)
92190075Sobrien{
92290075Sobrien  const char *section = ".dtors";
92390075Sobrien  char buf[16];
92418334Speter
92590075Sobrien  /* ??? This only works reliably with the GNU linker.  */
92690075Sobrien  if (priority != DEFAULT_INIT_PRIORITY)
92790075Sobrien    {
92890075Sobrien      sprintf (buf, ".dtors.%.5u",
92990075Sobrien	       /* Invert the numbering so the linker puts us in the proper
93090075Sobrien		  order; constructors are run from right to left, and the
93190075Sobrien		  linker sorts in increasing order.  */
93290075Sobrien	       MAX_INIT_PRIORITY - priority);
93390075Sobrien      section = buf;
93490075Sobrien    }
93590075Sobrien
93690075Sobrien  named_section_flags (section, SECTION_WRITE);
93790075Sobrien  assemble_align (POINTER_SIZE);
93890075Sobrien  assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
93990075Sobrien}
94090075Sobrien
94190075Sobrien#ifdef DTORS_SECTION_ASM_OP
94218334Spetervoid
943132718Skandtors_section (void)
94418334Speter{
94590075Sobrien  if (in_section != in_dtors)
94618334Speter    {
94790075Sobrien      in_section = in_dtors;
94890075Sobrien      fputs (DTORS_SECTION_ASM_OP, asm_out_file);
94918334Speter      fputc ('\n', asm_out_file);
95018334Speter    }
95118334Speter}
95218334Speter
95390075Sobrienvoid
954132718Skandefault_dtor_section_asm_out_destructor (rtx symbol,
955132718Skan					 int priority ATTRIBUTE_UNUSED)
95690075Sobrien{
95790075Sobrien  dtors_section ();
95890075Sobrien  assemble_align (POINTER_SIZE);
95990075Sobrien  assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
96090075Sobrien}
96190075Sobrien#endif
96290075Sobrien
96318334Speter/* Likewise for global constructors.  */
96418334Speter
96518334Spetervoid
966132718Skandefault_stabs_asm_out_constructor (rtx symbol, int priority ATTRIBUTE_UNUSED)
96718334Speter{
96890075Sobrien  /* Tell GNU LD that this is part of the static destructor set.
96990075Sobrien     This will work for any system that uses stabs, most usefully
97090075Sobrien     aout systems.  */
97190075Sobrien  fprintf (asm_out_file, "%s\"___CTOR_LIST__\",22,0,0,", ASM_STABS_OP);
97290075Sobrien  assemble_name (asm_out_file, XSTR (symbol, 0));
97390075Sobrien  fputc ('\n', asm_out_file);
97490075Sobrien}
97590075Sobrien
97690075Sobrienvoid
977132718Skandefault_named_section_asm_out_constructor (rtx symbol, int priority)
97890075Sobrien{
97990075Sobrien  const char *section = ".ctors";
98090075Sobrien  char buf[16];
98190075Sobrien
98290075Sobrien  /* ??? This only works reliably with the GNU linker.  */
98390075Sobrien  if (priority != DEFAULT_INIT_PRIORITY)
98418334Speter    {
98590075Sobrien      sprintf (buf, ".ctors.%.5u",
98690075Sobrien	       /* Invert the numbering so the linker puts us in the proper
98790075Sobrien		  order; constructors are run from right to left, and the
98890075Sobrien		  linker sorts in increasing order.  */
98990075Sobrien	       MAX_INIT_PRIORITY - priority);
99090075Sobrien      section = buf;
99118334Speter    }
99290075Sobrien
99390075Sobrien  named_section_flags (section, SECTION_WRITE);
99490075Sobrien  assemble_align (POINTER_SIZE);
99590075Sobrien  assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
99618334Speter}
99718334Speter
99890075Sobrien#ifdef CTORS_SECTION_ASM_OP
99918334Spetervoid
1000132718Skanctors_section (void)
100118334Speter{
100290075Sobrien  if (in_section != in_ctors)
100318334Speter    {
100490075Sobrien      in_section = in_ctors;
100590075Sobrien      fputs (CTORS_SECTION_ASM_OP, asm_out_file);
100618334Speter      fputc ('\n', asm_out_file);
100718334Speter    }
100890075Sobrien}
100990075Sobrien
101090075Sobrienvoid
1011132718Skandefault_ctor_section_asm_out_constructor (rtx symbol,
1012132718Skan					  int priority ATTRIBUTE_UNUSED)
101390075Sobrien{
101490075Sobrien  ctors_section ();
101590075Sobrien  assemble_align (POINTER_SIZE);
101690075Sobrien  assemble_integer (symbol, POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
101790075Sobrien}
101818334Speter#endif
101918334Speter
102050397Sobrien/* CONSTANT_POOL_BEFORE_FUNCTION may be defined as an expression with
1021117395Skan   a nonzero value if the constant pool should be output before the
102250397Sobrien   start of the function, or a zero value if the pool should output
102350397Sobrien   after the end of the function.  The default is to put it before the
102450397Sobrien   start.  */
102550397Sobrien
102650397Sobrien#ifndef CONSTANT_POOL_BEFORE_FUNCTION
102750397Sobrien#define CONSTANT_POOL_BEFORE_FUNCTION 1
102850397Sobrien#endif
102950397Sobrien
1030132718Skan/* DECL is an object (either VAR_DECL or FUNCTION_DECL) which is going
1031132718Skan   to be output to assembler.
1032132718Skan   Set first_global_object_name and weak_global_object_name as appropriate.  */
1033132718Skan
1034132718Skanvoid
1035132718Skannotice_global_symbol (tree decl)
1036132718Skan{
1037132718Skan  const char **type = &first_global_object_name;
1038132718Skan
1039132718Skan  if (first_global_object_name
1040132718Skan      || !TREE_PUBLIC (decl) || DECL_EXTERNAL (decl)
1041132718Skan      || !DECL_NAME (decl)
1042132718Skan      || (TREE_CODE (decl) != FUNCTION_DECL
1043132718Skan	  && (TREE_CODE (decl) != VAR_DECL
1044132718Skan	      || (DECL_COMMON (decl)
1045132718Skan		  && (DECL_INITIAL (decl) == 0
1046132718Skan		      || DECL_INITIAL (decl) == error_mark_node))))
1047132718Skan      || GET_CODE (DECL_RTL (decl)) != MEM)
1048132718Skan    return;
1049132718Skan
1050132718Skan  /* We win when global object is found, but it is usefull to know about weak
1051132718Skan     symbol as well so we can produce nicer unique names.  */
1052132718Skan  if (DECL_WEAK (decl) || DECL_ONE_ONLY (decl))
1053132718Skan    type = &weak_global_object_name;
1054132718Skan
1055132718Skan  if (!*type)
1056132718Skan    {
1057132718Skan      const char *p;
1058132718Skan      char *name;
1059132718Skan      rtx decl_rtl = DECL_RTL (decl);
1060132718Skan
1061132718Skan      p = (* targetm.strip_name_encoding) (XSTR (XEXP (decl_rtl, 0), 0));
1062132718Skan      name = xstrdup (p);
1063132718Skan
1064132718Skan      *type = name;
1065132718Skan    }
1066132718Skan}
1067132718Skan
106818334Speter/* Output assembler code for the constant pool of a function and associated
106918334Speter   with defining the name of the function.  DECL describes the function.
107018334Speter   NAME is the function's name.  For the constant pool, we use the current
107118334Speter   constant pool data.  */
107218334Speter
107318334Spetervoid
1074132718Skanassemble_start_function (tree decl, const char *fnname)
107518334Speter{
107618334Speter  int align;
107718334Speter
107818334Speter  /* The following code does not need preprocessing in the assembler.  */
107918334Speter
108018334Speter  app_disable ();
108118334Speter
108250397Sobrien  if (CONSTANT_POOL_BEFORE_FUNCTION)
108350397Sobrien    output_constant_pool (fnname, decl);
108418334Speter
1085102780Skan  resolve_unique_section (decl, 0, flag_function_sections);
108618334Speter  function_section (decl);
108718334Speter
108818334Speter  /* Tell assembler to move to target machine's alignment for functions.  */
108918334Speter  align = floor_log2 (FUNCTION_BOUNDARY / BITS_PER_UNIT);
1090104752Skan  if (align < force_align_functions_log)
1091104752Skan    align = force_align_functions_log;
109218334Speter  if (align > 0)
109390075Sobrien    {
109490075Sobrien      ASM_OUTPUT_ALIGN (asm_out_file, align);
109590075Sobrien    }
109618334Speter
109790075Sobrien  /* Handle a user-specified function alignment.
109890075Sobrien     Note that we still need to align to FUNCTION_BOUNDARY, as above,
109990075Sobrien     because ASM_OUTPUT_MAX_SKIP_ALIGN might not do any alignment at all.  */
1100117395Skan  if (align_functions_log > align
1101117395Skan      && cfun->function_frequency != FUNCTION_FREQUENCY_UNLIKELY_EXECUTED)
110290075Sobrien    {
110390075Sobrien#ifdef ASM_OUTPUT_MAX_SKIP_ALIGN
110490075Sobrien      ASM_OUTPUT_MAX_SKIP_ALIGN (asm_out_file,
1105117395Skan				 align_functions_log, align_functions - 1);
110690075Sobrien#else
110790075Sobrien      ASM_OUTPUT_ALIGN (asm_out_file, align_functions_log);
110890075Sobrien#endif
110990075Sobrien    }
111090075Sobrien
111118334Speter#ifdef ASM_OUTPUT_FUNCTION_PREFIX
111218334Speter  ASM_OUTPUT_FUNCTION_PREFIX (asm_out_file, fnname);
111318334Speter#endif
111418334Speter
111590075Sobrien  (*debug_hooks->begin_function) (decl);
111618334Speter
111718334Speter  /* Make function name accessible from other files, if appropriate.  */
111818334Speter
111918334Speter  if (TREE_PUBLIC (decl))
112018334Speter    {
1121132718Skan      notice_global_symbol (decl);
112218334Speter
112396263Sobrien      globalize_decl (decl);
1124117395Skan
1125117395Skan      maybe_assemble_visibility (decl);
112618334Speter    }
112718334Speter
1128132718Skan  /* Do any machine/system dependent processing of the function name.  */
112918334Speter#ifdef ASM_DECLARE_FUNCTION_NAME
113018334Speter  ASM_DECLARE_FUNCTION_NAME (asm_out_file, fnname, current_function_decl);
113118334Speter#else
113218334Speter  /* Standard thing is just output label for the function.  */
113350397Sobrien  ASM_OUTPUT_LABEL (asm_out_file, fnname);
113418334Speter#endif /* ASM_DECLARE_FUNCTION_NAME */
113518334Speter}
113618334Speter
113718334Speter/* Output assembler code associated with defining the size of the
113818334Speter   function.  DECL describes the function.  NAME is the function's name.  */
113918334Speter
114018334Spetervoid
1141132718Skanassemble_end_function (tree decl, const char *fnname)
114218334Speter{
114318334Speter#ifdef ASM_DECLARE_FUNCTION_SIZE
114418334Speter  ASM_DECLARE_FUNCTION_SIZE (asm_out_file, fnname, decl);
114518334Speter#endif
114650397Sobrien  if (! CONSTANT_POOL_BEFORE_FUNCTION)
114750397Sobrien    {
114850397Sobrien      output_constant_pool (fnname, decl);
114950397Sobrien      function_section (decl);	/* need to switch back */
115050397Sobrien    }
115118334Speter}
115218334Speter
115318334Speter/* Assemble code to leave SIZE bytes of zeros.  */
115418334Speter
115518334Spetervoid
1156132718Skanassemble_zeros (unsigned HOST_WIDE_INT size)
115718334Speter{
115852284Sobrien  /* Do no output if -fsyntax-only.  */
115952284Sobrien  if (flag_syntax_only)
116052284Sobrien    return;
116152284Sobrien
116218334Speter#ifdef ASM_NO_SKIP_IN_TEXT
116318334Speter  /* The `space' pseudo in the text section outputs nop insns rather than 0s,
116418334Speter     so we must output 0s explicitly in the text section.  */
116518334Speter  if (ASM_NO_SKIP_IN_TEXT && in_text_section ())
116618334Speter    {
1167132718Skan      unsigned HOST_WIDE_INT i;
116890075Sobrien      for (i = 0; i < size; i++)
116990075Sobrien	assemble_integer (const0_rtx, 1, BITS_PER_UNIT, 1);
117018334Speter    }
117118334Speter  else
117218334Speter#endif
117318334Speter    if (size > 0)
117450397Sobrien      ASM_OUTPUT_SKIP (asm_out_file, size);
117518334Speter}
117618334Speter
117718334Speter/* Assemble an alignment pseudo op for an ALIGN-bit boundary.  */
117818334Speter
117918334Spetervoid
1180132718Skanassemble_align (int align)
118118334Speter{
118218334Speter  if (align > BITS_PER_UNIT)
118390075Sobrien    {
118490075Sobrien      ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (align / BITS_PER_UNIT));
118590075Sobrien    }
118618334Speter}
118718334Speter
118818334Speter/* Assemble a string constant with the specified C string as contents.  */
118918334Speter
119018334Spetervoid
1191132718Skanassemble_string (const char *p, int size)
119218334Speter{
119318334Speter  int pos = 0;
119418334Speter  int maximum = 2000;
119518334Speter
119618334Speter  /* If the string is very long, split it up.  */
119718334Speter
119818334Speter  while (pos < size)
119918334Speter    {
120018334Speter      int thissize = size - pos;
120118334Speter      if (thissize > maximum)
120218334Speter	thissize = maximum;
120318334Speter
120450397Sobrien      ASM_OUTPUT_ASCII (asm_out_file, p, thissize);
120518334Speter
120618334Speter      pos += thissize;
120718334Speter      p += thissize;
120818334Speter    }
120918334Speter}
121018334Speter
121118334Speter
121290075Sobrien#if defined  ASM_OUTPUT_ALIGNED_DECL_LOCAL
121390075Sobrien#define ASM_EMIT_LOCAL(decl, name, size, rounded) \
121490075Sobrien  ASM_OUTPUT_ALIGNED_DECL_LOCAL (asm_out_file, decl, name, size, DECL_ALIGN (decl))
121590075Sobrien#else
121690075Sobrien#if defined  ASM_OUTPUT_ALIGNED_LOCAL
121790075Sobrien#define ASM_EMIT_LOCAL(decl, name, size, rounded) \
121890075Sobrien  ASM_OUTPUT_ALIGNED_LOCAL (asm_out_file, name, size, DECL_ALIGN (decl))
121990075Sobrien#else
122090075Sobrien#define ASM_EMIT_LOCAL(decl, name, size, rounded) \
122190075Sobrien  ASM_OUTPUT_LOCAL (asm_out_file, name, size, rounded)
122290075Sobrien#endif
122390075Sobrien#endif
122490075Sobrien
122590075Sobrien#if defined ASM_OUTPUT_ALIGNED_BSS
122690075Sobrien#define ASM_EMIT_BSS(decl, name, size, rounded) \
122790075Sobrien  ASM_OUTPUT_ALIGNED_BSS (asm_out_file, decl, name, size, DECL_ALIGN (decl))
122890075Sobrien#else
122990075Sobrien#if defined ASM_OUTPUT_BSS
123090075Sobrien#define ASM_EMIT_BSS(decl, name, size, rounded) \
123190075Sobrien  ASM_OUTPUT_BSS (asm_out_file, decl, name, size, rounded)
123290075Sobrien#else
123390075Sobrien#undef  ASM_EMIT_BSS
123490075Sobrien#endif
123590075Sobrien#endif
123690075Sobrien
123790075Sobrien#if defined ASM_OUTPUT_ALIGNED_DECL_COMMON
123890075Sobrien#define ASM_EMIT_COMMON(decl, name, size, rounded) \
123990075Sobrien  ASM_OUTPUT_ALIGNED_DECL_COMMON (asm_out_file, decl, name, size, DECL_ALIGN (decl))
124090075Sobrien#else
124190075Sobrien#if defined ASM_OUTPUT_ALIGNED_COMMON
124290075Sobrien#define ASM_EMIT_COMMON(decl, name, size, rounded) \
124390075Sobrien  ASM_OUTPUT_ALIGNED_COMMON (asm_out_file, name, size, DECL_ALIGN (decl))
124490075Sobrien#else
124590075Sobrien#define ASM_EMIT_COMMON(decl, name, size, rounded) \
124690075Sobrien  ASM_OUTPUT_COMMON (asm_out_file, name, size, rounded)
124790075Sobrien#endif
124890075Sobrien#endif
124990075Sobrien
1250117395Skanstatic bool
1251132718Skanasm_emit_uninitialised (tree decl, const char *name,
1252132718Skan			unsigned HOST_WIDE_INT size ATTRIBUTE_UNUSED,
1253132718Skan			unsigned HOST_WIDE_INT rounded ATTRIBUTE_UNUSED)
125490075Sobrien{
125590075Sobrien  enum
125690075Sobrien  {
125790075Sobrien    asm_dest_common,
125890075Sobrien    asm_dest_bss,
125990075Sobrien    asm_dest_local
126090075Sobrien  }
126190075Sobrien  destination = asm_dest_local;
126290075Sobrien
1263117395Skan  /* ??? We should handle .bss via select_section mechanisms rather than
1264117395Skan     via special target hooks.  That would eliminate this special case.  */
126590075Sobrien  if (TREE_PUBLIC (decl))
126690075Sobrien    {
1267117395Skan      if (!DECL_COMMON (decl))
1268117395Skan#ifdef ASM_EMIT_BSS
126990075Sobrien	destination = asm_dest_bss;
1270117395Skan#else
1271117395Skan	return false;
1272117395Skan#endif
127390075Sobrien      else
127490075Sobrien	destination = asm_dest_common;
127590075Sobrien    }
127690075Sobrien
127796263Sobrien  if (destination == asm_dest_bss)
127896263Sobrien    globalize_decl (decl);
1279102780Skan  resolve_unique_section (decl, 0, flag_data_sections);
128096263Sobrien
128190075Sobrien  if (flag_shared_data)
128290075Sobrien    {
128390075Sobrien      switch (destination)
128490075Sobrien	{
128590075Sobrien#ifdef ASM_OUTPUT_SHARED_BSS
128690075Sobrien	case asm_dest_bss:
128790075Sobrien	  ASM_OUTPUT_SHARED_BSS (asm_out_file, decl, name, size, rounded);
128890075Sobrien	  return;
128990075Sobrien#endif
129090075Sobrien#ifdef ASM_OUTPUT_SHARED_COMMON
129190075Sobrien	case asm_dest_common:
129290075Sobrien	  ASM_OUTPUT_SHARED_COMMON (asm_out_file, name, size, rounded);
129390075Sobrien	  return;
129490075Sobrien#endif
129590075Sobrien#ifdef ASM_OUTPUT_SHARED_LOCAL
129690075Sobrien	case asm_dest_local:
129790075Sobrien	  ASM_OUTPUT_SHARED_LOCAL (asm_out_file, name, size, rounded);
129890075Sobrien	  return;
129990075Sobrien#endif
130090075Sobrien	default:
130190075Sobrien	  break;
130290075Sobrien	}
130390075Sobrien    }
130490075Sobrien
130590075Sobrien  switch (destination)
130690075Sobrien    {
130790075Sobrien#ifdef ASM_EMIT_BSS
130890075Sobrien    case asm_dest_bss:
130990075Sobrien      ASM_EMIT_BSS (decl, name, size, rounded);
131090075Sobrien      break;
131190075Sobrien#endif
131290075Sobrien    case asm_dest_common:
131390075Sobrien      ASM_EMIT_COMMON (decl, name, size, rounded);
131490075Sobrien      break;
131590075Sobrien    case asm_dest_local:
131690075Sobrien      ASM_EMIT_LOCAL (decl, name, size, rounded);
131790075Sobrien      break;
131890075Sobrien    default:
131990075Sobrien      abort ();
132090075Sobrien    }
132190075Sobrien
1322117395Skan  return true;
132390075Sobrien}
132490075Sobrien
132518334Speter/* Assemble everything that is needed for a variable or function declaration.
132618334Speter   Not used for automatic variables, and not used for function definitions.
132718334Speter   Should not be called for variables of incomplete structure type.
132818334Speter
132918334Speter   TOP_LEVEL is nonzero if this variable has file scope.
133018334Speter   AT_END is nonzero if this is the special handling, at end of compilation,
133118334Speter   to define things that have had only tentative definitions.
133218334Speter   DONT_OUTPUT_DATA if nonzero means don't actually output the
133318334Speter   initial value (that will be done by the caller).  */
133418334Speter
133518334Spetervoid
1336132718Skanassemble_variable (tree decl, int top_level ATTRIBUTE_UNUSED,
1337132718Skan		   int at_end ATTRIBUTE_UNUSED, int dont_output_data)
133818334Speter{
133990075Sobrien  const char *name;
134050397Sobrien  unsigned int align;
134118334Speter  int reloc = 0;
134290075Sobrien  rtx decl_rtl;
134318334Speter
1344132718Skan  if (lang_hooks.decls.prepare_assemble_variable)
1345132718Skan    (*lang_hooks.decls.prepare_assemble_variable) (decl);
1346132718Skan
134718334Speter  last_assemble_variable_decl = 0;
134818334Speter
134918334Speter  /* Normally no need to say anything here for external references,
135018334Speter     since assemble_external is called by the language-specific code
135118334Speter     when a declaration is first seen.  */
135218334Speter
135318334Speter  if (DECL_EXTERNAL (decl))
135418334Speter    return;
135518334Speter
135618334Speter  /* Output no assembler code for a function declaration.
135718334Speter     Only definitions of functions output anything.  */
135818334Speter
135918334Speter  if (TREE_CODE (decl) == FUNCTION_DECL)
136018334Speter    return;
136118334Speter
136290075Sobrien  /* Do nothing for global register variables.  */
136390075Sobrien  if (DECL_RTL_SET_P (decl) && GET_CODE (DECL_RTL (decl)) == REG)
136490075Sobrien    {
136590075Sobrien      TREE_ASM_WRITTEN (decl) = 1;
136690075Sobrien      return;
136790075Sobrien    }
136890075Sobrien
136918334Speter  /* If type was incomplete when the variable was declared,
137018334Speter     see if it is complete now.  */
137118334Speter
137218334Speter  if (DECL_SIZE (decl) == 0)
137318334Speter    layout_decl (decl, 0);
137418334Speter
137518334Speter  /* Still incomplete => don't allocate it; treat the tentative defn
137618334Speter     (which is what it must have been) as an `extern' reference.  */
137718334Speter
137818334Speter  if (!dont_output_data && DECL_SIZE (decl) == 0)
137918334Speter    {
1380132718Skan      error ("%Jstorage size of `%D' isn't known", decl, decl);
138118334Speter      TREE_ASM_WRITTEN (decl) = 1;
138218334Speter      return;
138318334Speter    }
138418334Speter
138518334Speter  /* The first declaration of a variable that comes through this function
138618334Speter     decides whether it is global (in C, has external linkage)
138718334Speter     or local (in C, has internal linkage).  So do nothing more
138818334Speter     if this function has already run.  */
138918334Speter
139018334Speter  if (TREE_ASM_WRITTEN (decl))
139118334Speter    return;
139218334Speter
1393117395Skan  /* Make sure targetm.encode_section_info is invoked before we set
1394117395Skan     ASM_WRITTEN.  */
139590075Sobrien  decl_rtl = DECL_RTL (decl);
139690075Sobrien
139718334Speter  TREE_ASM_WRITTEN (decl) = 1;
139818334Speter
139952284Sobrien  /* Do no output if -fsyntax-only.  */
140052284Sobrien  if (flag_syntax_only)
140152284Sobrien    return;
140252284Sobrien
140318334Speter  app_disable ();
140418334Speter
140590075Sobrien  if (! dont_output_data
140690075Sobrien      && ! host_integerp (DECL_SIZE_UNIT (decl), 1))
140718334Speter    {
1408132718Skan      error ("%Jsize of variable '%D' is too large", decl, decl);
140990075Sobrien      return;
141018334Speter    }
141118334Speter
141290075Sobrien  name = XSTR (XEXP (decl_rtl, 0), 0);
1413132718Skan  if (TREE_PUBLIC (decl) && DECL_NAME (decl))
1414132718Skan    notice_global_symbol (decl);
141550397Sobrien
141650397Sobrien  /* Compute the alignment of this data.  */
141750397Sobrien
141850397Sobrien  align = DECL_ALIGN (decl);
141950397Sobrien
142050397Sobrien  /* In the case for initialing an array whose length isn't specified,
142150397Sobrien     where we have not yet been able to do the layout,
142250397Sobrien     figure out the proper alignment now.  */
142350397Sobrien  if (dont_output_data && DECL_SIZE (decl) == 0
142450397Sobrien      && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
142550397Sobrien    align = MAX (align, TYPE_ALIGN (TREE_TYPE (TREE_TYPE (decl))));
142650397Sobrien
142750397Sobrien  /* Some object file formats have a maximum alignment which they support.
142850397Sobrien     In particular, a.out format supports a maximum alignment of 4.  */
142950397Sobrien#ifndef MAX_OFILE_ALIGNMENT
143050397Sobrien#define MAX_OFILE_ALIGNMENT BIGGEST_ALIGNMENT
143150397Sobrien#endif
143250397Sobrien  if (align > MAX_OFILE_ALIGNMENT)
143350397Sobrien    {
1434132718Skan      warning ("%Jalignment of '%D' is greater than maximum object "
1435132718Skan               "file alignment.  Using %d", decl, decl,
1436132718Skan	       MAX_OFILE_ALIGNMENT/BITS_PER_UNIT);
143750397Sobrien      align = MAX_OFILE_ALIGNMENT;
143850397Sobrien    }
143950397Sobrien
144050397Sobrien  /* On some machines, it is good to increase alignment sometimes.  */
144190075Sobrien  if (! DECL_USER_ALIGN (decl))
144290075Sobrien    {
144350397Sobrien#ifdef DATA_ALIGNMENT
144490075Sobrien      align = DATA_ALIGNMENT (TREE_TYPE (decl), align);
144550397Sobrien#endif
144650397Sobrien#ifdef CONSTANT_ALIGNMENT
144790075Sobrien      if (DECL_INITIAL (decl) != 0 && DECL_INITIAL (decl) != error_mark_node)
1448117395Skan	align = CONSTANT_ALIGNMENT (DECL_INITIAL (decl), align);
144950397Sobrien#endif
145090075Sobrien    }
145150397Sobrien
145250397Sobrien  /* Reset the alignment in case we have made it tighter, so we can benefit
145350397Sobrien     from it in get_pointer_alignment.  */
145450397Sobrien  DECL_ALIGN (decl) = align;
145590075Sobrien  set_mem_align (decl_rtl, align);
145650397Sobrien
1457117395Skan  if (TREE_PUBLIC (decl))
1458117395Skan    maybe_assemble_visibility (decl);
1459117395Skan
1460117395Skan  /* Output any data that we will need to use the address of.  */
1461117395Skan  if (DECL_INITIAL (decl) == error_mark_node)
1462117395Skan    reloc = contains_pointers_p (TREE_TYPE (decl)) ? 3 : 0;
1463117395Skan  else if (DECL_INITIAL (decl))
1464132718Skan    {
1465132718Skan      reloc = compute_reloc_for_constant (DECL_INITIAL (decl));
1466132718Skan      output_addressed_constants (DECL_INITIAL (decl));
1467132718Skan    }
1468117395Skan  resolve_unique_section (decl, reloc, flag_data_sections);
1469117395Skan
147018334Speter  /* Handle uninitialized definitions.  */
147118334Speter
1472117395Skan  /* If the decl has been given an explicit section name, then it
1473117395Skan     isn't common, and shouldn't be handled as such.  */
1474117395Skan  if (DECL_SECTION_NAME (decl) || dont_output_data)
1475117395Skan    ;
1476117395Skan  /* We don't implement common thread-local data at present.  */
1477117395Skan  else if (DECL_THREAD_LOCAL (decl))
147818334Speter    {
1479117395Skan      if (DECL_COMMON (decl))
1480117395Skan	sorry ("thread-local COMMON data not implemented");
1481117395Skan    }
1482117395Skan  else if (DECL_INITIAL (decl) == 0
1483117395Skan	   || DECL_INITIAL (decl) == error_mark_node
1484117395Skan	   || (flag_zero_initialized_in_bss
1485117395Skan	       /* Leave constant zeroes in .rodata so they can be shared.  */
1486117395Skan	       && !TREE_READONLY (decl)
1487117395Skan	       && initializer_zerop (DECL_INITIAL (decl))))
1488117395Skan    {
148990075Sobrien      unsigned HOST_WIDE_INT size = tree_low_cst (DECL_SIZE_UNIT (decl), 1);
149090075Sobrien      unsigned HOST_WIDE_INT rounded = size;
149118334Speter
149218334Speter      /* Don't allocate zero bytes of common,
149318334Speter	 since that means "undefined external" in the linker.  */
149490075Sobrien      if (size == 0)
149590075Sobrien	rounded = 1;
149690075Sobrien
149718334Speter      /* Round size up to multiple of BIGGEST_ALIGNMENT bits
149818334Speter	 so that each uninitialized object starts on such a boundary.  */
149918334Speter      rounded += (BIGGEST_ALIGNMENT / BITS_PER_UNIT) - 1;
150018334Speter      rounded = (rounded / (BIGGEST_ALIGNMENT / BITS_PER_UNIT)
150118334Speter		 * (BIGGEST_ALIGNMENT / BITS_PER_UNIT));
150290075Sobrien
150390075Sobrien#if !defined(ASM_OUTPUT_ALIGNED_COMMON) && !defined(ASM_OUTPUT_ALIGNED_DECL_COMMON) && !defined(ASM_OUTPUT_ALIGNED_BSS)
150490075Sobrien      if ((unsigned HOST_WIDE_INT) DECL_ALIGN (decl) / BITS_PER_UNIT > rounded)
1505132718Skan	warning ("%Jrequested alignment for '%D' is greater than "
1506132718Skan                 "implemented alignment of %d", decl, decl, rounded);
150750397Sobrien#endif
150818334Speter
1509117395Skan      /* If the target cannot output uninitialized but not common global data
1510117395Skan	 in .bss, then we have to use .data, so fall through.  */
1511117395Skan      if (asm_emit_uninitialised (decl, name, size, rounded))
1512117395Skan	return;
151318334Speter    }
151418334Speter
151550397Sobrien  /* Handle initialized definitions.
151650397Sobrien     Also handle uninitialized global definitions if -fno-common and the
151750397Sobrien     target doesn't support ASM_OUTPUT_BSS.  */
151818334Speter
151918334Speter  /* First make the assembler name(s) global if appropriate.  */
152018334Speter  if (TREE_PUBLIC (decl) && DECL_NAME (decl))
152196263Sobrien    globalize_decl (decl);
152218334Speter
152350397Sobrien  /* Switch to the appropriate section.  */
152450397Sobrien  variable_section (decl, reloc);
152550397Sobrien
152618334Speter  /* dbxout.c needs to know this.  */
152718334Speter  if (in_text_section ())
152818334Speter    DECL_IN_TEXT_SECTION (decl) = 1;
152918334Speter
153050397Sobrien  /* Output the alignment of this data.  */
153118334Speter  if (align > BITS_PER_UNIT)
153290075Sobrien    {
153390075Sobrien      ASM_OUTPUT_ALIGN (asm_out_file,
153490075Sobrien			floor_log2 (DECL_ALIGN (decl) / BITS_PER_UNIT));
153590075Sobrien    }
153618334Speter
153718334Speter  /* Do any machine/system dependent processing of the object.  */
153818334Speter#ifdef ASM_DECLARE_OBJECT_NAME
153918334Speter  last_assemble_variable_decl = decl;
154018334Speter  ASM_DECLARE_OBJECT_NAME (asm_out_file, name, decl);
154118334Speter#else
154218334Speter  /* Standard thing is just output label for the object.  */
154350397Sobrien  ASM_OUTPUT_LABEL (asm_out_file, name);
154418334Speter#endif /* ASM_DECLARE_OBJECT_NAME */
154518334Speter
154618334Speter  if (!dont_output_data)
154718334Speter    {
154896263Sobrien      if (DECL_INITIAL (decl) && DECL_INITIAL (decl) != error_mark_node)
154918334Speter	/* Output the actual data.  */
155090075Sobrien	output_constant (DECL_INITIAL (decl),
155190075Sobrien			 tree_low_cst (DECL_SIZE_UNIT (decl), 1),
155290075Sobrien			 align);
155318334Speter      else
155418334Speter	/* Leave space for it.  */
155590075Sobrien	assemble_zeros (tree_low_cst (DECL_SIZE_UNIT (decl), 1));
155618334Speter    }
155718334Speter}
155818334Speter
155918334Speter/* Return 1 if type TYPE contains any pointers.  */
156018334Speter
156118334Speterstatic int
1562132718Skancontains_pointers_p (tree type)
156318334Speter{
156418334Speter  switch (TREE_CODE (type))
156518334Speter    {
156618334Speter    case POINTER_TYPE:
156718334Speter    case REFERENCE_TYPE:
156818334Speter      /* I'm not sure whether OFFSET_TYPE needs this treatment,
156918334Speter	 so I'll play safe and return 1.  */
157018334Speter    case OFFSET_TYPE:
157118334Speter      return 1;
157218334Speter
157318334Speter    case RECORD_TYPE:
157418334Speter    case UNION_TYPE:
157518334Speter    case QUAL_UNION_TYPE:
157618334Speter      {
157718334Speter	tree fields;
157818334Speter	/* For a type that has fields, see if the fields have pointers.  */
157918334Speter	for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields))
158018334Speter	  if (TREE_CODE (fields) == FIELD_DECL
158118334Speter	      && contains_pointers_p (TREE_TYPE (fields)))
158218334Speter	    return 1;
158318334Speter	return 0;
158418334Speter      }
158518334Speter
158618334Speter    case ARRAY_TYPE:
158718334Speter      /* An array type contains pointers if its element type does.  */
158818334Speter      return contains_pointers_p (TREE_TYPE (type));
158918334Speter
159018334Speter    default:
159118334Speter      return 0;
159218334Speter    }
159318334Speter}
159418334Speter
1595132718Skan#ifdef ASM_OUTPUT_EXTERNAL
1596132718Skan/* True if DECL is a function decl for which no out-of-line copy exists.
1597132718Skan   It is assumed that DECL's assembler name has been set.  */
1598132718Skan
1599132718Skanstatic bool
1600132718Skanincorporeal_function_p (tree decl)
1601132718Skan{
1602132718Skan  if (TREE_CODE (decl) == FUNCTION_DECL && DECL_BUILT_IN (decl))
1603132718Skan    {
1604132718Skan      const char *name;
1605132718Skan
1606132718Skan      if (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL
1607132718Skan	  && DECL_FUNCTION_CODE (decl) == BUILT_IN_ALLOCA)
1608132718Skan	return true;
1609132718Skan
1610132718Skan      name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
1611132718Skan      if (strncmp (name, "__builtin_", strlen ("__builtin_")) == 0)
1612132718Skan	return true;
1613132718Skan    }
1614132718Skan  return false;
1615132718Skan}
1616132718Skan#endif
1617132718Skan
161818334Speter/* Output something to declare an external symbol to the assembler.
161918334Speter   (Most assemblers don't need this, so we normally output nothing.)
162018334Speter   Do nothing if DECL is not external.  */
162118334Speter
162218334Spetervoid
1623132718Skanassemble_external (tree decl ATTRIBUTE_UNUSED)
162418334Speter{
162590075Sobrien  /* Because most platforms do not define ASM_OUTPUT_EXTERNAL, the
162690075Sobrien     main body of this code is only rarely exercised.  To provide some
162790075Sobrien     testing, on all platforms, we make sure that the ASM_OUT_FILE is
162890075Sobrien     open.  If it's not, we should not be calling this function.  */
162990075Sobrien  if (!asm_out_file)
163090075Sobrien    abort ();
163190075Sobrien
163218334Speter#ifdef ASM_OUTPUT_EXTERNAL
163390075Sobrien  if (DECL_P (decl) && DECL_EXTERNAL (decl) && TREE_PUBLIC (decl))
163418334Speter    {
163518334Speter      rtx rtl = DECL_RTL (decl);
163618334Speter
163718334Speter      if (GET_CODE (rtl) == MEM && GET_CODE (XEXP (rtl, 0)) == SYMBOL_REF
1638132718Skan	  && !SYMBOL_REF_USED (XEXP (rtl, 0))
1639132718Skan	  && !incorporeal_function_p (decl))
164018334Speter	{
164118334Speter	  /* Some systems do require some output.  */
164218334Speter	  SYMBOL_REF_USED (XEXP (rtl, 0)) = 1;
164318334Speter	  ASM_OUTPUT_EXTERNAL (asm_out_file, decl, XSTR (XEXP (rtl, 0), 0));
164418334Speter	}
164518334Speter    }
164618334Speter#endif
164718334Speter}
164818334Speter
164918334Speter/* Similar, for calling a library function FUN.  */
165018334Speter
165118334Spetervoid
1652132718Skanassemble_external_libcall (rtx fun)
165318334Speter{
165450397Sobrien  /* Declare library function name external when first used, if nec.  */
165550397Sobrien  if (! SYMBOL_REF_USED (fun))
165618334Speter    {
165750397Sobrien      SYMBOL_REF_USED (fun) = 1;
1658132718Skan      (*targetm.asm_out.external_libcall) (fun);
165918334Speter    }
166018334Speter}
166118334Speter
166218334Speter/* Assemble a label named NAME.  */
166318334Speter
166418334Spetervoid
1665132718Skanassemble_label (const char *name)
166618334Speter{
166750397Sobrien  ASM_OUTPUT_LABEL (asm_out_file, name);
166818334Speter}
166918334Speter
1670132718Skan/* Set the symbol_referenced flag for ID and notify callgraph code.  */
1671132718Skanvoid
1672132718Skanmark_referenced (tree id)
1673132718Skan{
1674132718Skan  if (!TREE_SYMBOL_REFERENCED (id))
1675132718Skan    {
1676132718Skan      struct cgraph_node *node;
1677132718Skan      struct cgraph_varpool_node *vnode;
1678132718Skan
1679132718Skan      if (!cgraph_global_info_ready)
1680132718Skan	{
1681132718Skan	  node = cgraph_node_for_identifier (id);
1682132718Skan	  if (node)
1683132718Skan	    cgraph_mark_needed_node (node);
1684132718Skan	}
1685132718Skan
1686132718Skan      vnode = cgraph_varpool_node_for_identifier (id);
1687132718Skan      if (vnode)
1688132718Skan	cgraph_varpool_mark_needed_node (vnode);
1689132718Skan    }
1690132718Skan  TREE_SYMBOL_REFERENCED (id) = 1;
1691132718Skan}
1692132718Skan
169318334Speter/* Output to FILE a reference to the assembler name of a C-level name NAME.
169418334Speter   If NAME starts with a *, the rest of NAME is output verbatim.
169518334Speter   Otherwise NAME is transformed in an implementation-defined way
169618334Speter   (usually by the addition of an underscore).
169718334Speter   Many macros in the tm file are defined to call this function.  */
169818334Speter
169918334Spetervoid
1700132718Skanassemble_name (FILE *file, const char *name)
170118334Speter{
170290075Sobrien  const char *real_name;
170350397Sobrien  tree id;
170418334Speter
1705117395Skan  real_name = (* targetm.strip_name_encoding) (name);
170618334Speter
170750397Sobrien  id = maybe_get_identifier (real_name);
170850397Sobrien  if (id)
1709132718Skan    mark_referenced (id);
171018334Speter
171118334Speter  if (name[0] == '*')
171250397Sobrien    fputs (&name[1], file);
171318334Speter  else
171450397Sobrien    ASM_OUTPUT_LABELREF (file, name);
171518334Speter}
171618334Speter
171718334Speter/* Allocate SIZE bytes writable static space with a gensym name
171818334Speter   and return an RTX to refer to its address.  */
171918334Speter
172018334Speterrtx
1721132718Skanassemble_static_space (unsigned HOST_WIDE_INT size)
172218334Speter{
172318334Speter  char name[12];
172490075Sobrien  const char *namestring;
172518334Speter  rtx x;
172618334Speter
172718334Speter#if 0
172818334Speter  if (flag_shared_data)
172918334Speter    data_section ();
173018334Speter#endif
173118334Speter
173218334Speter  ASM_GENERATE_INTERNAL_LABEL (name, "LF", const_labelno);
173318334Speter  ++const_labelno;
173490075Sobrien  namestring = ggc_strdup (name);
173518334Speter
173650397Sobrien  x = gen_rtx_SYMBOL_REF (Pmode, namestring);
1737132718Skan  SYMBOL_REF_FLAGS (x) = SYMBOL_FLAG_LOCAL;
173818334Speter
173950397Sobrien#ifdef ASM_OUTPUT_ALIGNED_DECL_LOCAL
174050397Sobrien  ASM_OUTPUT_ALIGNED_DECL_LOCAL (asm_out_file, NULL_TREE, name, size,
174150397Sobrien				 BIGGEST_ALIGNMENT);
174250397Sobrien#else
174318334Speter#ifdef ASM_OUTPUT_ALIGNED_LOCAL
174450397Sobrien  ASM_OUTPUT_ALIGNED_LOCAL (asm_out_file, name, size, BIGGEST_ALIGNMENT);
174518334Speter#else
174650397Sobrien  {
174750397Sobrien    /* Round size up to multiple of BIGGEST_ALIGNMENT bits
174850397Sobrien       so that each uninitialized object starts on such a boundary.  */
174990075Sobrien    /* Variable `rounded' might or might not be used in ASM_OUTPUT_LOCAL.  */
1750132718Skan    unsigned HOST_WIDE_INT rounded ATTRIBUTE_UNUSED
175152284Sobrien      = ((size + (BIGGEST_ALIGNMENT / BITS_PER_UNIT) - 1)
175252284Sobrien	 / (BIGGEST_ALIGNMENT / BITS_PER_UNIT)
175352284Sobrien	 * (BIGGEST_ALIGNMENT / BITS_PER_UNIT));
175450397Sobrien    ASM_OUTPUT_LOCAL (asm_out_file, name, size, rounded);
175550397Sobrien  }
175618334Speter#endif
175750397Sobrien#endif
175818334Speter  return x;
175918334Speter}
176018334Speter
176118334Speter/* Assemble the static constant template for function entry trampolines.
176218334Speter   This is done at most once per compilation.
176318334Speter   Returns an RTX for the address of the template.  */
176418334Speter
176548743Sobrien#ifdef TRAMPOLINE_TEMPLATE
176618334Speterrtx
1767132718Skanassemble_trampoline_template (void)
176818334Speter{
176918334Speter  char label[256];
177090075Sobrien  const char *name;
177118334Speter  int align;
1772132718Skan  rtx symbol;
177318334Speter
177418334Speter  /* By default, put trampoline templates in read-only data section.  */
177518334Speter
177618334Speter#ifdef TRAMPOLINE_SECTION
177718334Speter  TRAMPOLINE_SECTION ();
177818334Speter#else
177918334Speter  readonly_data_section ();
178018334Speter#endif
178118334Speter
178218334Speter  /* Write the assembler code to define one.  */
178350397Sobrien  align = floor_log2 (TRAMPOLINE_ALIGNMENT / BITS_PER_UNIT);
178418334Speter  if (align > 0)
178590075Sobrien    {
178690075Sobrien      ASM_OUTPUT_ALIGN (asm_out_file, align);
178790075Sobrien    }
178818334Speter
1789132718Skan  (*targetm.asm_out.internal_label) (asm_out_file, "LTRAMP", 0);
179018334Speter  TRAMPOLINE_TEMPLATE (asm_out_file);
179118334Speter
179218334Speter  /* Record the rtl to refer to it.  */
179318334Speter  ASM_GENERATE_INTERNAL_LABEL (label, "LTRAMP", 0);
179490075Sobrien  name = ggc_strdup (label);
1795132718Skan  symbol = gen_rtx_SYMBOL_REF (Pmode, name);
1796132718Skan  SYMBOL_REF_FLAGS (symbol) = SYMBOL_FLAG_LOCAL;
1797132718Skan
1798132718Skan  return symbol;
179918334Speter}
180048743Sobrien#endif
180118334Speter
180290075Sobrien/* A and B are either alignments or offsets.  Return the minimum alignment
180390075Sobrien   that may be assumed after adding the two together.  */
180418334Speter
180590075Sobrienstatic inline unsigned
1806132718Skanmin_align (unsigned int a, unsigned int b)
180790075Sobrien{
180890075Sobrien  return (a | b) & -(a | b);
180990075Sobrien}
181018334Speter
181190075Sobrien/* Return the assembler directive for creating a given kind of integer
181290075Sobrien   object.  SIZE is the number of bytes in the object and ALIGNED_P
181390075Sobrien   indicates whether it is known to be aligned.  Return NULL if the
181490075Sobrien   assembly dialect has no such directive.
181590075Sobrien
181690075Sobrien   The returned string should be printed at the start of a new line and
181790075Sobrien   be followed immediately by the object's initial value.  */
181890075Sobrien
181990075Sobrienconst char *
1820132718Skaninteger_asm_op (int size, int aligned_p)
182118334Speter{
182290075Sobrien  struct asm_int_op *ops;
182318334Speter
182490075Sobrien  if (aligned_p)
182590075Sobrien    ops = &targetm.asm_out.aligned_op;
182690075Sobrien  else
182790075Sobrien    ops = &targetm.asm_out.unaligned_op;
182890075Sobrien
182918334Speter  switch (size)
183018334Speter    {
183118334Speter    case 1:
183290075Sobrien      return targetm.asm_out.byte_op;
183318334Speter    case 2:
183490075Sobrien      return ops->hi;
183518334Speter    case 4:
183690075Sobrien      return ops->si;
183718334Speter    case 8:
183890075Sobrien      return ops->di;
183918334Speter    case 16:
184090075Sobrien      return ops->ti;
184190075Sobrien    default:
184290075Sobrien      return NULL;
184318334Speter    }
184490075Sobrien}
184518334Speter
184690075Sobrien/* Use directive OP to assemble an integer object X.  Print OP at the
184790075Sobrien   start of the line, followed immediately by the value of X.  */
184818334Speter
184990075Sobrienvoid
1850132718Skanassemble_integer_with_op (const char *op, rtx x)
185190075Sobrien{
185290075Sobrien  fputs (op, asm_out_file);
185390075Sobrien  output_addr_const (asm_out_file, x);
185490075Sobrien  fputc ('\n', asm_out_file);
185590075Sobrien}
185618334Speter
185790075Sobrien/* The default implementation of the asm_out.integer target hook.  */
185818334Speter
185990075Sobrienbool
1860132718Skandefault_assemble_integer (rtx x ATTRIBUTE_UNUSED,
1861132718Skan			  unsigned int size ATTRIBUTE_UNUSED,
1862132718Skan			  int aligned_p ATTRIBUTE_UNUSED)
186390075Sobrien{
186490075Sobrien  const char *op = integer_asm_op (size, aligned_p);
186590075Sobrien  return op && (assemble_integer_with_op (op, x), true);
186690075Sobrien}
186790075Sobrien
186890075Sobrien/* Assemble the integer constant X into an object of SIZE bytes.  ALIGN is
186990075Sobrien   the alignment of the integer in bits.  Return 1 if we were able to output
1870117395Skan   the constant, otherwise 0.  If FORCE is nonzero, abort if we can't output
187190075Sobrien   the constant.  */
187290075Sobrien
187390075Sobrienbool
1874132718Skanassemble_integer (rtx x, unsigned int size, unsigned int align, int force)
187590075Sobrien{
187690075Sobrien  int aligned_p;
187790075Sobrien
187890075Sobrien  aligned_p = (align >= MIN (size * BITS_PER_UNIT, BIGGEST_ALIGNMENT));
187990075Sobrien
188090075Sobrien  /* See if the target hook can handle this kind of object.  */
188190075Sobrien  if ((*targetm.asm_out.integer) (x, size, aligned_p))
188290075Sobrien    return true;
188390075Sobrien
188490075Sobrien  /* If the object is a multi-byte one, try splitting it up.  Split
188590075Sobrien     it into words it if is multi-word, otherwise split it into bytes.  */
188690075Sobrien  if (size > 1)
188718334Speter    {
188890075Sobrien      enum machine_mode omode, imode;
188990075Sobrien      unsigned int subalign;
189090075Sobrien      unsigned int subsize, i;
189118334Speter
189290075Sobrien      subsize = size > UNITS_PER_WORD? UNITS_PER_WORD : 1;
189390075Sobrien      subalign = MIN (align, subsize * BITS_PER_UNIT);
189490075Sobrien      omode = mode_for_size (subsize * BITS_PER_UNIT, MODE_INT, 0);
189590075Sobrien      imode = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 0);
189690075Sobrien
189790075Sobrien      for (i = 0; i < size; i += subsize)
189818334Speter	{
189990075Sobrien	  rtx partial = simplify_subreg (omode, x, imode, i);
190090075Sobrien	  if (!partial || !assemble_integer (partial, subsize, subalign, 0))
190118334Speter	    break;
190218334Speter	}
190390075Sobrien      if (i == size)
190490075Sobrien	return true;
190518334Speter
190690075Sobrien      /* If we've printed some of it, but not all of it, there's no going
190790075Sobrien	 back now.  */
190818334Speter      if (i > 0)
190918334Speter	abort ();
191018334Speter    }
191118334Speter
191218334Speter  if (force)
191318334Speter    abort ();
191418334Speter
191590075Sobrien  return false;
191618334Speter}
191718334Speter
191818334Spetervoid
1919132718Skanassemble_real (REAL_VALUE_TYPE d, enum machine_mode mode, unsigned int align)
192018334Speter{
192190075Sobrien  long data[4];
1922132718Skan  int i;
1923132718Skan  int bitsize, nelts, nunits, units_per;
192418334Speter
1925132718Skan  /* This is hairy.  We have a quantity of known size.  real_to_target
1926132718Skan     will put it into an array of *host* longs, 32 bits per element
1927132718Skan     (even if long is more than 32 bits).  We need to determine the
1928132718Skan     number of array elements that are occupied (nelts) and the number
1929132718Skan     of *target* min-addressable units that will be occupied in the
1930132718Skan     object file (nunits).  We cannot assume that 32 divides the
1931132718Skan     mode's bitsize (size * BITS_PER_UNIT) evenly.
193218334Speter
1933132718Skan     size * BITS_PER_UNIT is used here to make sure that padding bits
1934132718Skan     (which might appear at either end of the value; real_to_target
1935132718Skan     will include the padding bits in its output array) are included.  */
193618334Speter
1937132718Skan  nunits = GET_MODE_SIZE (mode);
1938132718Skan  bitsize = nunits * BITS_PER_UNIT;
1939132718Skan  nelts = CEIL (bitsize, 32);
1940132718Skan  units_per = 32 / BITS_PER_UNIT;
194118334Speter
1942132718Skan  real_to_target (data, &d, mode);
1943132718Skan
1944132718Skan  /* Put out the first word with the specified alignment.  */
1945132718Skan  assemble_integer (GEN_INT (data[0]), MIN (nunits, units_per), align, 1);
1946132718Skan  nunits -= units_per;
1947132718Skan
1948132718Skan  /* Subsequent words need only 32-bit alignment.  */
1949132718Skan  align = min_align (align, 32);
1950132718Skan
1951132718Skan  for (i = 1; i < nelts; i++)
1952132718Skan    {
1953132718Skan      assemble_integer (GEN_INT (data[i]), MIN (nunits, units_per), align, 1);
1954132718Skan      nunits -= units_per;
195518334Speter    }
195618334Speter}
195718334Speter
195818334Speter/* Given an expression EXP with a constant value,
195918334Speter   reduce it to the sum of an assembler symbol and an integer.
196018334Speter   Store them both in the structure *VALUE.
196118334Speter   Abort if EXP does not reduce.  */
196218334Speter
1963117395Skanstruct addr_const GTY(())
196418334Speter{
196518334Speter  rtx base;
196618334Speter  HOST_WIDE_INT offset;
196718334Speter};
196818334Speter
196918334Speterstatic void
1970132718Skandecode_addr_const (tree exp, struct addr_const *value)
197118334Speter{
197290075Sobrien  tree target = TREE_OPERAND (exp, 0);
197390075Sobrien  int offset = 0;
197490075Sobrien  rtx x;
197518334Speter
197618334Speter  while (1)
197718334Speter    {
197818334Speter      if (TREE_CODE (target) == COMPONENT_REF
197990075Sobrien	  && host_integerp (byte_position (TREE_OPERAND (target, 1)), 0))
198090075Sobrien
198118334Speter	{
198290075Sobrien	  offset += int_byte_position (TREE_OPERAND (target, 1));
198318334Speter	  target = TREE_OPERAND (target, 0);
198418334Speter	}
198590075Sobrien      else if (TREE_CODE (target) == ARRAY_REF
198690075Sobrien	       || TREE_CODE (target) == ARRAY_RANGE_REF)
198718334Speter	{
198890075Sobrien	  offset += (tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (target)), 1)
198990075Sobrien		     * tree_low_cst (TREE_OPERAND (target, 1), 0));
199018334Speter	  target = TREE_OPERAND (target, 0);
199118334Speter	}
199218334Speter      else
199318334Speter	break;
199418334Speter    }
199518334Speter
199618334Speter  switch (TREE_CODE (target))
199718334Speter    {
199818334Speter    case VAR_DECL:
199918334Speter    case FUNCTION_DECL:
200018334Speter      x = DECL_RTL (target);
200118334Speter      break;
200218334Speter
200318334Speter    case LABEL_DECL:
200450397Sobrien      x = gen_rtx_MEM (FUNCTION_MODE,
2005132718Skan		       gen_rtx_LABEL_REF (VOIDmode, force_label_rtx (target)));
200618334Speter      break;
200718334Speter
200818334Speter    case REAL_CST:
200918334Speter    case STRING_CST:
201018334Speter    case COMPLEX_CST:
201118334Speter    case CONSTRUCTOR:
201250397Sobrien    case INTEGER_CST:
201390075Sobrien      x = output_constant_def (target, 1);
201418334Speter      break;
201518334Speter
201618334Speter    default:
201718334Speter      abort ();
201818334Speter    }
201918334Speter
202050397Sobrien  if (GET_CODE (x) != MEM)
202150397Sobrien    abort ();
202250397Sobrien  x = XEXP (x, 0);
202318334Speter
202418334Speter  value->base = x;
202518334Speter  value->offset = offset;
202618334Speter}
202718334Speter
202896263Sobrien/* We do RTX_UNSPEC + XINT (blah), so nothing can go after RTX_UNSPEC.  */
2029117395Skanenum kind { RTX_UNKNOWN, RTX_DOUBLE, RTX_VECTOR, RTX_INT, RTX_UNSPEC };
2030117395Skanstruct rtx_const GTY(())
203190075Sobrien{
203290075Sobrien  ENUM_BITFIELD(kind) kind : 16;
203390075Sobrien  ENUM_BITFIELD(machine_mode) mode : 16;
2034117395Skan  union rtx_const_un {
2035132718Skan    REAL_VALUE_TYPE GTY ((tag ("4"))) du;
2036117395Skan    struct rtx_const_u_addr {
2037117395Skan      rtx base;
2038117395Skan      const char *symbol;
2039117395Skan      HOST_WIDE_INT offset;
2040117395Skan    } GTY ((tag ("1"))) addr;
2041117395Skan    struct rtx_const_u_di {
2042117395Skan      HOST_WIDE_INT high;
2043117395Skan      HOST_WIDE_INT low;
2044117395Skan    } GTY ((tag ("0"))) di;
204596263Sobrien
2046117395Skan    /* The max vector size we have is 16 wide; two variants for
2047117395Skan       integral and floating point vectors.  */
2048117395Skan    struct rtx_const_int_vec {
2049117395Skan      HOST_WIDE_INT high;
2050117395Skan      HOST_WIDE_INT low;
2051117395Skan    } GTY ((tag ("2"))) int_vec[16];
2052117395Skan
2053117395Skan    REAL_VALUE_TYPE GTY ((tag ("3"))) fp_vec[8];
2054117395Skan
2055117395Skan  } GTY ((desc ("%1.kind >= RTX_INT"), descbits ("1"))) un;
205690075Sobrien};
205790075Sobrien
205818334Speter/* Uniquize all constants that appear in memory.
205918334Speter   Each constant in memory thus far output is recorded
2060132718Skan   in `const_desc_table'.  */
206118334Speter
2062117395Skanstruct constant_descriptor_tree GTY(())
2063117395Skan{
2064117395Skan  /* A MEM for the constant.  */
206590075Sobrien  rtx rtl;
2066117395Skan
2067117395Skan  /* The value of the constant.  */
2068117395Skan  tree value;
206918334Speter};
207018334Speter
2071132718Skanstatic GTY((param_is (struct constant_descriptor_tree)))
2072132718Skan     htab_t const_desc_htab;
207318334Speter
2074132718Skanstatic struct constant_descriptor_tree * build_constant_desc (tree);
2075132718Skanstatic void maybe_output_constant_def_contents (struct constant_descriptor_tree *, int);
207690075Sobrien
2077132718Skan/* Compute a hash code for a constant expression.  */
207890075Sobrien
207990075Sobrienstatic hashval_t
2080132718Skanconst_desc_hash (const void *ptr)
208190075Sobrien{
2082132718Skan  return const_hash_1 (((struct constant_descriptor_tree *)ptr)->value);
208390075Sobrien}
208490075Sobrien
2085132718Skanstatic hashval_t
2086132718Skanconst_hash_1 (const tree exp)
208790075Sobrien{
208890075Sobrien  const char *p;
2089132718Skan  hashval_t hi;
2090117395Skan  int len, i;
209190075Sobrien  enum tree_code code = TREE_CODE (exp);
209218334Speter
209350397Sobrien  /* Either set P and LEN to the address and len of something to hash and
209450397Sobrien     exit the switch or return a value.  */
209550397Sobrien
209650397Sobrien  switch (code)
209718334Speter    {
209850397Sobrien    case INTEGER_CST:
209990075Sobrien      p = (char *) &TREE_INT_CST (exp);
210090075Sobrien      len = sizeof TREE_INT_CST (exp);
210150397Sobrien      break;
210250397Sobrien
210350397Sobrien    case REAL_CST:
2104117395Skan      return real_hash (TREE_REAL_CST_PTR (exp));
210518334Speter
210650397Sobrien    case STRING_CST:
2107132718Skan      if (flag_writable_strings)
2108132718Skan	{
2109132718Skan	  p = (char *) &exp;
2110132718Skan	  len = sizeof exp;
2111132718Skan	}
2112132718Skan      else
2113132718Skan	{
2114132718Skan	  p = TREE_STRING_POINTER (exp);
2115132718Skan	  len = TREE_STRING_LENGTH (exp);
2116132718Skan	}
211750397Sobrien      break;
211818334Speter
211950397Sobrien    case COMPLEX_CST:
2120117395Skan      return (const_hash_1 (TREE_REALPART (exp)) * 5
2121117395Skan	      + const_hash_1 (TREE_IMAGPART (exp)));
212218334Speter
212350397Sobrien    case CONSTRUCTOR:
212450397Sobrien      if (TREE_CODE (TREE_TYPE (exp)) == SET_TYPE)
212518334Speter	{
212690075Sobrien	  char *tmp;
212790075Sobrien
212850397Sobrien	  len = int_size_in_bytes (TREE_TYPE (exp));
2129132718Skan	  tmp = alloca (len);
213090075Sobrien	  get_set_constructor_bytes (exp, (unsigned char *) tmp, len);
213190075Sobrien	  p = tmp;
213250397Sobrien	  break;
213318334Speter	}
213450397Sobrien      else
213550397Sobrien	{
213690075Sobrien	  tree link;
213718334Speter
2138117395Skan	  hi = 5 + int_size_in_bytes (TREE_TYPE (exp));
213950397Sobrien
214050397Sobrien	  for (link = CONSTRUCTOR_ELTS (exp); link; link = TREE_CHAIN (link))
214150397Sobrien	    if (TREE_VALUE (link))
2142117395Skan	      hi = hi * 603 + const_hash_1 (TREE_VALUE (link));
214350397Sobrien
214450397Sobrien	  return hi;
214550397Sobrien	}
214650397Sobrien
214750397Sobrien    case ADDR_EXPR:
2148102780Skan    case FDESC_EXPR:
214950397Sobrien      {
215050397Sobrien	struct addr_const value;
215150397Sobrien
215250397Sobrien	decode_addr_const (exp, &value);
215350397Sobrien	if (GET_CODE (value.base) == SYMBOL_REF)
215450397Sobrien	  {
215550397Sobrien	    /* Don't hash the address of the SYMBOL_REF;
215650397Sobrien	       only use the offset and the symbol name.  */
215750397Sobrien	    hi = value.offset;
215850397Sobrien	    p = XSTR (value.base, 0);
215950397Sobrien	    for (i = 0; p[i] != 0; i++)
216050397Sobrien	      hi = ((hi * 613) + (unsigned) (p[i]));
216150397Sobrien	  }
216250397Sobrien	else if (GET_CODE (value.base) == LABEL_REF)
216350397Sobrien	  hi = value.offset + CODE_LABEL_NUMBER (XEXP (value.base, 0)) * 13;
216490075Sobrien	else
216590075Sobrien	  abort ();
216650397Sobrien      }
216718334Speter      return hi;
216850397Sobrien
216950397Sobrien    case PLUS_EXPR:
217050397Sobrien    case MINUS_EXPR:
2171117395Skan      return (const_hash_1 (TREE_OPERAND (exp, 0)) * 9
2172117395Skan	      + const_hash_1 (TREE_OPERAND (exp, 1)));
217350397Sobrien
217450397Sobrien    case NOP_EXPR:
217550397Sobrien    case CONVERT_EXPR:
217650397Sobrien    case NON_LVALUE_EXPR:
2177117395Skan      return const_hash_1 (TREE_OPERAND (exp, 0)) * 7 + 2;
217890075Sobrien
217950397Sobrien    default:
218090075Sobrien      /* A language specific constant. Just hash the code.  */
2181117395Skan      return code;
218218334Speter    }
218318334Speter
2184132718Skan  /* Compute hashing function.  */
218518334Speter  hi = len;
218618334Speter  for (i = 0; i < len; i++)
218750397Sobrien    hi = ((hi * 613) + (unsigned) (p[i]));
218818334Speter
218918334Speter  return hi;
219018334Speter}
219118334Speter
2192132718Skan/* Wrapper of compare_constant, for the htab interface.  */
2193132718Skanstatic int
2194132718Skanconst_desc_eq (const void *p1, const void *p2)
2195132718Skan{
2196132718Skan  return compare_constant (((struct constant_descriptor_tree *)p1)->value,
2197132718Skan			   ((struct constant_descriptor_tree *)p2)->value);
2198132718Skan}
2199132718Skan
2200117395Skan/* Compare t1 and t2, and return 1 only if they are known to result in
2201117395Skan   the same bit pattern on output.  */
2202117395Skan
220318334Speterstatic int
2204132718Skancompare_constant (const tree t1, const tree t2)
220518334Speter{
2206117395Skan  enum tree_code typecode;
220718334Speter
2208117395Skan  if (t1 == NULL_TREE)
2209117395Skan    return t2 == NULL_TREE;
2210117395Skan  if (t2 == NULL_TREE)
2211117395Skan    return 0;
221218334Speter
2213117395Skan  if (TREE_CODE (t1) != TREE_CODE (t2))
221418334Speter    return 0;
221518334Speter
2216117395Skan  switch (TREE_CODE (t1))
221718334Speter    {
221850397Sobrien    case INTEGER_CST:
221918334Speter      /* Integer constants are the same only if the same width of type.  */
2220117395Skan      if (TYPE_PRECISION (TREE_TYPE (t1)) != TYPE_PRECISION (TREE_TYPE (t2)))
222118334Speter	return 0;
2222117395Skan      return tree_int_cst_equal (t1, t2);
222350397Sobrien
222450397Sobrien    case REAL_CST:
222518334Speter      /* Real constants are the same only if the same width of type.  */
2226117395Skan      if (TYPE_PRECISION (TREE_TYPE (t1)) != TYPE_PRECISION (TREE_TYPE (t2)))
222718334Speter	return 0;
222850397Sobrien
2229117395Skan      return REAL_VALUES_IDENTICAL (TREE_REAL_CST (t1), TREE_REAL_CST (t2));
223050397Sobrien
223150397Sobrien    case STRING_CST:
223218334Speter      if (flag_writable_strings)
2233132718Skan	return t1 == t2;
223450397Sobrien
2235117395Skan      if (TYPE_MODE (TREE_TYPE (t1)) != TYPE_MODE (TREE_TYPE (t2)))
223650397Sobrien	return 0;
223750397Sobrien
2238117395Skan      return (TREE_STRING_LENGTH (t1) == TREE_STRING_LENGTH (t2)
2239117395Skan	      && ! memcmp (TREE_STRING_POINTER (t1), TREE_STRING_POINTER (t2),
2240117395Skan			 TREE_STRING_LENGTH (t1)));
224150397Sobrien
2242117395Skan    case COMPLEX_CST:
2243117395Skan      return (compare_constant (TREE_REALPART (t1), TREE_REALPART (t2))
2244117395Skan	      && compare_constant (TREE_IMAGPART (t1), TREE_IMAGPART (t2)));
224550397Sobrien
2246117395Skan    case CONSTRUCTOR:
2247117395Skan      typecode = TREE_CODE (TREE_TYPE (t1));
2248117395Skan      if (typecode != TREE_CODE (TREE_TYPE (t2)))
224918334Speter	return 0;
225018334Speter
2251117395Skan      if (typecode == SET_TYPE)
225218334Speter	{
2253117395Skan	  int len = int_size_in_bytes (TREE_TYPE (t2));
2254117395Skan	  unsigned char *tmp1, *tmp2;
225550397Sobrien
2256117395Skan	  if (int_size_in_bytes (TREE_TYPE (t1)) != len)
225718334Speter	    return 0;
225850397Sobrien
2259132718Skan	  tmp1 = alloca (len);
2260132718Skan	  tmp2 = alloca (len);
2261117395Skan
2262117395Skan	  if (get_set_constructor_bytes (t1, tmp1, len) != NULL_TREE)
2263117395Skan	    return 0;
2264117395Skan	  if (get_set_constructor_bytes (t2, tmp2, len) != NULL_TREE)
2265117395Skan	    return 0;
2266117395Skan
2267122180Skan	  return memcmp (tmp1, tmp2, len) == 0;
226818334Speter	}
226950397Sobrien      else
227050397Sobrien	{
2271117395Skan	  tree l1, l2;
227218334Speter
2273117395Skan	  if (typecode == ARRAY_TYPE)
227490075Sobrien	    {
2275117395Skan	      HOST_WIDE_INT size_1 = int_size_in_bytes (TREE_TYPE (t1));
2276117395Skan	      /* For arrays, check that the sizes all match.  */
2277117395Skan	      if (TYPE_MODE (TREE_TYPE (t1)) != TYPE_MODE (TREE_TYPE (t2))
2278117395Skan		  || size_1 == -1
2279117395Skan		  || size_1 != int_size_in_bytes (TREE_TYPE (t2)))
228090075Sobrien		return 0;
228190075Sobrien	    }
2282117395Skan	  else
228318334Speter	    {
2284117395Skan	      /* For record and union constructors, require exact type
2285117395Skan                 equality.  */
2286117395Skan	      if (TREE_TYPE (t1) != TREE_TYPE (t2))
228718334Speter		return 0;
228818334Speter	    }
228950397Sobrien
2290117395Skan	  for (l1 = CONSTRUCTOR_ELTS (t1), l2 = CONSTRUCTOR_ELTS (t2);
2291117395Skan	       l1 && l2;
2292117395Skan	       l1 = TREE_CHAIN (l1), l2 = TREE_CHAIN (l2))
229318334Speter	    {
2294117395Skan	      /* Check that each value is the same...  */
2295117395Skan	      if (! compare_constant (TREE_VALUE (l1), TREE_VALUE (l2)))
2296117395Skan		return 0;
2297117395Skan	      /* ... and that they apply to the same fields!  */
2298117395Skan	      if (typecode == ARRAY_TYPE)
229950397Sobrien		{
2300117395Skan		  if (! compare_constant (TREE_PURPOSE (l1),
2301117395Skan					  TREE_PURPOSE (l2)))
230250397Sobrien		    return 0;
230350397Sobrien		}
230450397Sobrien	      else
230550397Sobrien		{
2306117395Skan		  if (TREE_PURPOSE (l1) != TREE_PURPOSE (l2))
230750397Sobrien		    return 0;
230850397Sobrien		}
230918334Speter	    }
231050397Sobrien
2311117395Skan	  return l1 == NULL_TREE && l2 == NULL_TREE;
231218334Speter	}
231318334Speter
231450397Sobrien    case ADDR_EXPR:
2315102780Skan    case FDESC_EXPR:
231650397Sobrien      {
2317117395Skan	struct addr_const value1, value2;
231850397Sobrien
2319117395Skan	decode_addr_const (t1, &value1);
2320117395Skan	decode_addr_const (t2, &value2);
2321117395Skan	return (value1.offset == value2.offset
2322117395Skan		&& strcmp (XSTR (value1.base, 0), XSTR (value2.base, 0)) == 0);
232350397Sobrien      }
232450397Sobrien
232550397Sobrien    case PLUS_EXPR:
232650397Sobrien    case MINUS_EXPR:
232752284Sobrien    case RANGE_EXPR:
2328117395Skan      return (compare_constant (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0))
2329117395Skan	      && compare_constant(TREE_OPERAND (t1, 1), TREE_OPERAND (t2, 1)));
233050397Sobrien
233150397Sobrien    case NOP_EXPR:
233250397Sobrien    case CONVERT_EXPR:
233350397Sobrien    case NON_LVALUE_EXPR:
2334117395Skan      return compare_constant (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
233550397Sobrien
233650397Sobrien    default:
233790075Sobrien      {
2338117395Skan	tree nt1, nt2;
2339117395Skan	nt1 = (*lang_hooks.expand_constant) (t1);
2340117395Skan	nt2 = (*lang_hooks.expand_constant) (t2);
2341117395Skan	if (nt1 != t1 || nt2 != t2)
2342117395Skan	  return compare_constant (nt1, nt2);
234390075Sobrien	else
234490075Sobrien	  return 0;
234590075Sobrien      }
234618334Speter    }
234718334Speter
2348117395Skan  /* Should not get here.  */
2349117395Skan  abort ();
235018334Speter}
235118334Speter
2352117395Skan/* Make a copy of the whole tree structure for a constant.  This
2353117395Skan   handles the same types of nodes that compare_constant handles.  */
235418334Speter
235518334Speterstatic tree
2356132718Skancopy_constant (tree exp)
235718334Speter{
235818334Speter  switch (TREE_CODE (exp))
235918334Speter    {
236018334Speter    case ADDR_EXPR:
236118334Speter      /* For ADDR_EXPR, we do not want to copy the decl whose address
236218334Speter	 is requested.  We do want to copy constants though.  */
236318334Speter      if (TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 0))) == 'c')
236418334Speter	return build1 (TREE_CODE (exp), TREE_TYPE (exp),
236518334Speter		       copy_constant (TREE_OPERAND (exp, 0)));
236618334Speter      else
236718334Speter	return copy_node (exp);
236818334Speter
236918334Speter    case INTEGER_CST:
237018334Speter    case REAL_CST:
237118334Speter    case STRING_CST:
237218334Speter      return copy_node (exp);
237318334Speter
237418334Speter    case COMPLEX_CST:
237550397Sobrien      return build_complex (TREE_TYPE (exp),
237650397Sobrien			    copy_constant (TREE_REALPART (exp)),
237718334Speter			    copy_constant (TREE_IMAGPART (exp)));
237818334Speter
237918334Speter    case PLUS_EXPR:
238018334Speter    case MINUS_EXPR:
238118334Speter      return build (TREE_CODE (exp), TREE_TYPE (exp),
238218334Speter		    copy_constant (TREE_OPERAND (exp, 0)),
238318334Speter		    copy_constant (TREE_OPERAND (exp, 1)));
238418334Speter
238518334Speter    case NOP_EXPR:
238618334Speter    case CONVERT_EXPR:
238750397Sobrien    case NON_LVALUE_EXPR:
2388132718Skan    case VIEW_CONVERT_EXPR:
238918334Speter      return build1 (TREE_CODE (exp), TREE_TYPE (exp),
239018334Speter		     copy_constant (TREE_OPERAND (exp, 0)));
239118334Speter
239218334Speter    case CONSTRUCTOR:
239318334Speter      {
239418334Speter	tree copy = copy_node (exp);
239518334Speter	tree list = copy_list (CONSTRUCTOR_ELTS (exp));
239618334Speter	tree tail;
239718334Speter
239818334Speter	CONSTRUCTOR_ELTS (copy) = list;
239918334Speter	for (tail = list; tail; tail = TREE_CHAIN (tail))
240018334Speter	  TREE_VALUE (tail) = copy_constant (TREE_VALUE (tail));
240118334Speter	if (TREE_CODE (TREE_TYPE (exp)) == SET_TYPE)
240218334Speter	  for (tail = list; tail; tail = TREE_CHAIN (tail))
240318334Speter	    TREE_PURPOSE (tail) = copy_constant (TREE_PURPOSE (tail));
240418334Speter
240518334Speter	return copy;
240618334Speter      }
240718334Speter
240818334Speter    default:
2409117395Skan      {
2410117395Skan	tree t;
2411117395Skan	t = (*lang_hooks.expand_constant) (exp);
2412117395Skan	if (t != exp)
2413117395Skan	  return copy_constant (t);
2414117395Skan	else
2415117395Skan	  abort ();
2416117395Skan      }
241718334Speter    }
241818334Speter}
241918334Speter
2420132718Skan/* Subroutine of output_constant_def:
2421132718Skan   No constant equal to EXP is known to have been output.
2422132718Skan   Make a constant descriptor to enter EXP in the hash table.
2423132718Skan   Assign the label number and construct RTL to refer to the
2424132718Skan   constant's location in memory.
2425132718Skan   Caller is responsible for updating the hash table.  */
242618334Speter
2427132718Skanstatic struct constant_descriptor_tree *
2428132718Skanbuild_constant_desc (tree exp)
242918334Speter{
2430132718Skan  rtx symbol;
2431132718Skan  rtx rtl;
2432132718Skan  char label[256];
2433132718Skan  int labelno;
2434117395Skan  struct constant_descriptor_tree *desc;
243518334Speter
2436132718Skan  desc = ggc_alloc (sizeof (*desc));
2437132718Skan  if (flag_writable_strings && TREE_CODE (exp) == STRING_CST)
2438132718Skan    desc->value = exp;
2439132718Skan  else
2440132718Skan    desc->value = copy_constant (exp);
2441122180Skan
2442132718Skan  /* Create a string containing the label name, in LABEL.  */
2443132718Skan  labelno = const_labelno++;
2444132718Skan  ASM_GENERATE_INTERNAL_LABEL (label, "LC", labelno);
244518334Speter
2446132718Skan  /* We have a symbol name; construct the SYMBOL_REF and the MEM.  */
2447132718Skan  symbol = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (label));
2448132718Skan  SYMBOL_REF_FLAGS (symbol) = SYMBOL_FLAG_LOCAL;
2449132718Skan  SYMBOL_REF_DECL (symbol) = desc->value;
2450132718Skan  TREE_CONSTANT_POOL_ADDRESS_P (symbol) = 1;
245118334Speter
2452132718Skan  rtl = gen_rtx_MEM (TYPE_MODE (TREE_TYPE (exp)), symbol);
2453132718Skan  set_mem_attributes (rtl, exp, 1);
2454132718Skan  set_mem_alias_set (rtl, 0);
2455132718Skan  set_mem_alias_set (rtl, const_alias_set);
245618334Speter
2457132718Skan  /* Set flags or add text to the name to record information, such as
2458132718Skan     that it is a local symbol.  If the name is changed, the macro
2459132718Skan     ASM_OUTPUT_LABELREF will have to know how to strip this
2460132718Skan     information.  This call might invalidate our local variable
2461132718Skan     SYMBOL; we can't use it afterward.  */
246218334Speter
2463132718Skan  (*targetm.encode_section_info) (exp, rtl, true);
246490075Sobrien
2465132718Skan  desc->rtl = rtl;
246690075Sobrien
2467132718Skan  return desc;
2468132718Skan}
246990075Sobrien
2470132718Skan/* Return an rtx representing a reference to constant data in memory
2471132718Skan   for the constant expression EXP.
247218334Speter
2473132718Skan   If assembler code for such a constant has already been output,
2474132718Skan   return an rtx to refer to it.
2475132718Skan   Otherwise, output such a constant in memory
2476132718Skan   and generate an rtx for it.
247790075Sobrien
2478132718Skan   If DEFER is nonzero, this constant can be deferred and output only
2479132718Skan   if referenced in the function after all optimizations.
248090075Sobrien
2481132718Skan   `const_desc_table' records which constants already have label strings.  */
248290075Sobrien
2483132718Skanrtx
2484132718Skanoutput_constant_def (tree exp, int defer)
2485132718Skan{
2486132718Skan  struct constant_descriptor_tree *desc;
2487132718Skan  struct constant_descriptor_tree key;
2488132718Skan  void **loc;
248918334Speter
2490132718Skan  /* Look up EXP in the table of constant descriptors.  If we didn't find
2491132718Skan     it, create a new one.  */
2492132718Skan  key.value = exp;
2493132718Skan  loc = htab_find_slot (const_desc_htab, &key, INSERT);
249418334Speter
2495132718Skan  desc = *loc;
2496132718Skan  if (desc == 0)
249790075Sobrien    {
2498132718Skan      desc = build_constant_desc (exp);
2499132718Skan      *loc = desc;
250090075Sobrien    }
250118334Speter
2502132718Skan  maybe_output_constant_def_contents (desc, defer);
2503132718Skan  return desc->rtl;
2504132718Skan}
250590075Sobrien
2506132718Skan/* Subroutine of output_constant_def: Decide whether or not we need to
2507132718Skan   output the constant DESC now, and if so, do it.  */
2508132718Skanstatic void
2509132718Skanmaybe_output_constant_def_contents (struct constant_descriptor_tree *desc,
2510132718Skan				    int defer)
2511132718Skan{
2512132718Skan  rtx symbol = XEXP (desc->rtl, 0);
2513132718Skan  tree exp = desc->value;
251490075Sobrien
2515132718Skan  if (flag_syntax_only)
2516132718Skan    return;
251718334Speter
2518132718Skan  if (TREE_ASM_WRITTEN (exp))
2519132718Skan    /* Already output; don't do it again.  */
2520132718Skan    return;
252190075Sobrien
2522132718Skan  /* The only constants that cannot safely be deferred, assuming the
2523132718Skan     context allows it, are strings under flag_writable_strings.  */
2524132718Skan  if (defer && (TREE_CODE (exp) != STRING_CST || !flag_writable_strings))
2525132718Skan    {
2526132718Skan      /* Increment n_deferred_constants if it exists.  It needs to be at
2527132718Skan	 least as large as the number of constants actually referred to
2528132718Skan	 by the function.  If it's too small we'll stop looking too early
2529132718Skan	 and fail to emit constants; if it's too large we'll only look
2530132718Skan	 through the entire function when we could have stopped earlier.  */
2531132718Skan      if (cfun)
2532132718Skan	n_deferred_constants++;
2533132718Skan      return;
253418334Speter    }
253518334Speter
2536132718Skan  output_constant_def_contents (symbol);
253718334Speter}
253818334Speter
2539132718Skan/* We must output the constant data referred to by SYMBOL; do so.  */
254018334Speter
254118334Speterstatic void
2542132718Skanoutput_constant_def_contents (rtx symbol)
254318334Speter{
2544132718Skan  tree exp = SYMBOL_REF_DECL (symbol);
2545132718Skan  const char *label = XSTR (symbol, 0);
2546122180Skan  HOST_WIDE_INT size;
254718334Speter
2548132718Skan  /* Make sure any other constants whose addresses appear in EXP
2549132718Skan     are assigned label numbers.  */
2550132718Skan  int reloc = compute_reloc_for_constant (exp);
2551132718Skan
255290075Sobrien  /* Align the location counter as required by EXP's data type.  */
2553132718Skan  int align = TYPE_ALIGN (TREE_TYPE (exp));
255490075Sobrien#ifdef CONSTANT_ALIGNMENT
255590075Sobrien  align = CONSTANT_ALIGNMENT (exp, align);
255690075Sobrien#endif
255790075Sobrien
2558132718Skan  output_addressed_constants (exp);
2559132718Skan
2560132718Skan  /* We are no longer deferring this constant.  */
2561132718Skan  TREE_ASM_WRITTEN (exp) = 1;
2562132718Skan
256318334Speter  if (IN_NAMED_SECTION (exp))
256450397Sobrien    named_section (exp, NULL, reloc);
256518334Speter  else
2566117395Skan    (*targetm.asm_out.select_section) (exp, reloc, align);
256718334Speter
256818334Speter  if (align > BITS_PER_UNIT)
256990075Sobrien    {
257090075Sobrien      ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (align / BITS_PER_UNIT));
257190075Sobrien    }
257218334Speter
2573122180Skan  size = int_size_in_bytes (TREE_TYPE (exp));
2574122180Skan  if (TREE_CODE (exp) == STRING_CST)
2575122180Skan    size = MAX (TREE_STRING_LENGTH (exp), size);
2576122180Skan
2577122180Skan  /* Do any machine/system dependent processing of the constant.  */
2578122180Skan#ifdef ASM_DECLARE_CONSTANT_NAME
2579132718Skan  ASM_DECLARE_CONSTANT_NAME (asm_out_file, label, exp, size);
2580122180Skan#else
2581122180Skan  /* Standard thing is just output label for the constant.  */
2582132718Skan  ASM_OUTPUT_LABEL (asm_out_file, label);
2583122180Skan#endif /* ASM_DECLARE_CONSTANT_NAME */
258418334Speter
258518334Speter  /* Output the value of EXP.  */
2586122180Skan  output_constant (exp, size, align);
258718334Speter}
2588132718Skan
2589132718Skan/* A constant which was deferred in its original location has been
2590132718Skan   inserted by the RTL inliner into a different function.  The
2591132718Skan   current function's deferred constant count must be incremented.  */
2592132718Skanvoid
2593132718Skannotice_rtl_inlining_of_deferred_constant (void)
2594132718Skan{
2595132718Skan  n_deferred_constants++;
2596132718Skan}
2597132718Skan
2598132718Skan/* Look up EXP in the table of constant descriptors.  Return the rtl
2599132718Skan   if it has been emitted, else null.  */
2600132718Skan
2601132718Skanrtx
2602132718Skanlookup_constant_def (tree exp)
2603132718Skan{
2604132718Skan  struct constant_descriptor_tree *desc;
2605132718Skan  struct constant_descriptor_tree key;
2606132718Skan
2607132718Skan  key.value = exp;
2608132718Skan  desc = htab_find (const_desc_htab, &key);
2609132718Skan
2610132718Skan  return (desc ? desc->rtl : NULL_RTX);
2611132718Skan}
261218334Speter
2613117395Skan/* Used in the hash tables to avoid outputting the same constant
2614117395Skan   twice.  Unlike 'struct constant_descriptor_tree', RTX constants
2615117395Skan   are output once per function, not once per file; there seems
2616117395Skan   to be no reason for the difference.  */
2617117395Skan
2618117395Skanstruct constant_descriptor_rtx GTY(())
2619117395Skan{
2620117395Skan  /* More constant_descriptors with the same hash code.  */
2621117395Skan  struct constant_descriptor_rtx *next;
2622117395Skan
2623117395Skan  /* A MEM for the constant.  */
2624117395Skan  rtx rtl;
2625117395Skan
2626117395Skan  /* The value of the constant.  */
2627117395Skan  struct rtx_const value;
2628117395Skan};
2629117395Skan
263018334Speter/* Structure to represent sufficient information about a constant so that
263118334Speter   it can be output when the constant pool is output, so that function
263218334Speter   integration can be done, and to simplify handling on machines that reference
263318334Speter   constant pool as base+displacement.  */
263418334Speter
2635117395Skanstruct pool_constant GTY(())
263618334Speter{
2637117395Skan  struct constant_descriptor_rtx *desc;
2638117395Skan  struct pool_constant *next;
2639117395Skan  struct pool_constant *next_sym;
264090075Sobrien  rtx constant;
264118334Speter  enum machine_mode mode;
264218334Speter  int labelno;
264390075Sobrien  unsigned int align;
264490075Sobrien  HOST_WIDE_INT offset;
264550397Sobrien  int mark;
264618334Speter};
264718334Speter
264818334Speter/* Hash code for a SYMBOL_REF with CONSTANT_POOL_ADDRESS_P true.
264918334Speter   The argument is XSTR (... , 0)  */
265018334Speter
2651117395Skan#define SYMHASH(LABEL)	(((unsigned long) (LABEL)) % MAX_RTX_HASH_TABLE)
265218334Speter
265390075Sobrien/* Initialize constant pool hashing for a new function.  */
265418334Speter
265518334Spetervoid
2656132718Skaninit_varasm_status (struct function *f)
265718334Speter{
265890075Sobrien  struct varasm_status *p;
2659132718Skan  p = ggc_alloc (sizeof (struct varasm_status));
266090075Sobrien  f->varasm = p;
266190075Sobrien  p->x_const_rtx_hash_table
2662132718Skan    = ggc_alloc_cleared (MAX_RTX_HASH_TABLE
2663132718Skan			 * sizeof (struct constant_descriptor_rtx *));
266490075Sobrien  p->x_const_rtx_sym_hash_table
2665132718Skan    = ggc_alloc_cleared (MAX_RTX_HASH_TABLE
2666132718Skan			 * sizeof (struct pool_constant *));
266718334Speter
266890075Sobrien  p->x_first_pool = p->x_last_pool = 0;
266990075Sobrien  p->x_pool_offset = 0;
2670132718Skan  p->deferred_constants = 0;
267118334Speter}
267218334Speter
267318334Speter
267418334Speter/* Express an rtx for a constant integer (perhaps symbolic)
267518334Speter   as the sum of a symbol or label plus an explicit integer.
267618334Speter   They are stored into VALUE.  */
267718334Speter
267818334Speterstatic void
2679132718Skandecode_rtx_const (enum machine_mode mode, rtx x, struct rtx_const *value)
268018334Speter{
268118334Speter  /* Clear the whole structure, including any gaps.  */
268290075Sobrien  memset (value, 0, sizeof (struct rtx_const));
268318334Speter
268450397Sobrien  value->kind = RTX_INT;	/* Most usual kind.  */
268518334Speter  value->mode = mode;
268618334Speter
268718334Speter  switch (GET_CODE (x))
268818334Speter    {
268918334Speter    case CONST_DOUBLE:
269018334Speter      value->kind = RTX_DOUBLE;
269118334Speter      if (GET_MODE (x) != VOIDmode)
269218334Speter	{
2693117395Skan	  const REAL_VALUE_TYPE *r = CONST_DOUBLE_REAL_VALUE (x);
2694117395Skan
269518334Speter	  value->mode = GET_MODE (x);
2696117395Skan
2697117395Skan	  /* Copy the REAL_VALUE_TYPE by members so that we don't
2698117395Skan	     copy garbage from the original structure into our
2699117395Skan	     carefully cleaned hashing structure.  */
2700117395Skan	  value->un.du.class = r->class;
2701117395Skan	  value->un.du.sign = r->sign;
2702117395Skan	  switch (r->class)
2703117395Skan	    {
2704117395Skan	    case rvc_zero:
2705117395Skan	    case rvc_inf:
2706117395Skan	      break;
2707117395Skan	    case rvc_normal:
2708117395Skan	      value->un.du.exp = r->exp;
2709132718Skan	      /* Fall through.  */
2710117395Skan	    case rvc_nan:
2711117395Skan	      memcpy (value->un.du.sig, r->sig, sizeof (r->sig));
2712117395Skan	      break;
2713117395Skan	    default:
2714117395Skan	      abort ();
2715117395Skan	    }
271618334Speter	}
271718334Speter      else
271818334Speter	{
271918334Speter	  value->un.di.low = CONST_DOUBLE_LOW (x);
272018334Speter	  value->un.di.high = CONST_DOUBLE_HIGH (x);
272118334Speter	}
272218334Speter      break;
272318334Speter
272496263Sobrien    case CONST_VECTOR:
272596263Sobrien      {
272696263Sobrien	int units, i;
272796263Sobrien
272896263Sobrien	units = CONST_VECTOR_NUNITS (x);
272996263Sobrien	value->kind = RTX_VECTOR;
273096263Sobrien	value->mode = mode;
273196263Sobrien
2732117395Skan	if (GET_MODE_CLASS (mode) == MODE_VECTOR_INT)
273396263Sobrien	  {
2734117395Skan	    for (i = 0; i < units; ++i)
273596263Sobrien	      {
2736117395Skan	        rtx elt = CONST_VECTOR_ELT (x, i);
2737117395Skan	        if (GET_CODE (elt) == CONST_INT)
2738117395Skan	          {
2739117395Skan		    value->un.int_vec[i].low = INTVAL (elt);
2740117395Skan		    value->un.int_vec[i].high = 0;
2741117395Skan	          }
2742117395Skan		else
2743117395Skan	          {
2744117395Skan		    value->un.int_vec[i].low = CONST_DOUBLE_LOW (elt);
2745117395Skan		    value->un.int_vec[i].high = CONST_DOUBLE_HIGH (elt);
2746117395Skan		  }
274796263Sobrien	      }
2748117395Skan	  }
2749117395Skan	else if (GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT)
2750117395Skan	  {
2751117395Skan	    for (i = 0; i < units; ++i)
275296263Sobrien	      {
2753117395Skan		const REAL_VALUE_TYPE *r
2754117395Skan		  = CONST_DOUBLE_REAL_VALUE (CONST_VECTOR_ELT (x, i));
2755117395Skan		REAL_VALUE_TYPE *d = &value->un.fp_vec[i];
2756117395Skan
2757117395Skan	        /* Copy the REAL_VALUE_TYPE by members so that we don't
2758117395Skan	           copy garbage from the original structure into our
2759117395Skan	           carefully cleaned hashing structure.  */
2760117395Skan	        d->class = r->class;
2761117395Skan	        d->sign = r->sign;
2762117395Skan	        switch (r->class)
2763117395Skan	          {
2764117395Skan	          case rvc_zero:
2765117395Skan	          case rvc_inf:
2766117395Skan	            break;
2767117395Skan	          case rvc_normal:
2768117395Skan	            d->exp = r->exp;
2769132718Skan	            /* Fall through.  */
2770117395Skan	          case rvc_nan:
2771117395Skan	            memcpy (d->sig, r->sig, sizeof (r->sig));
2772117395Skan	            break;
2773117395Skan	          default:
2774117395Skan	            abort ();
2775117395Skan	          }
277696263Sobrien	      }
277796263Sobrien	  }
2778117395Skan	else
2779117395Skan	  abort ();
278096263Sobrien      }
278196263Sobrien      break;
278296263Sobrien
278318334Speter    case CONST_INT:
278418334Speter      value->un.addr.offset = INTVAL (x);
278518334Speter      break;
278618334Speter
278718334Speter    case SYMBOL_REF:
278818334Speter    case LABEL_REF:
278918334Speter    case PC:
279018334Speter      value->un.addr.base = x;
279118334Speter      break;
279218334Speter
279318334Speter    case CONST:
279418334Speter      x = XEXP (x, 0);
279590075Sobrien      if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 1)) == CONST_INT)
279618334Speter	{
279718334Speter	  value->un.addr.base = XEXP (x, 0);
279818334Speter	  value->un.addr.offset = INTVAL (XEXP (x, 1));
279918334Speter	}
280090075Sobrien      else if (GET_CODE (x) == MINUS && GET_CODE (XEXP (x, 1)) == CONST_INT)
280118334Speter	{
280218334Speter	  value->un.addr.base = XEXP (x, 0);
280318334Speter	  value->un.addr.offset = - INTVAL (XEXP (x, 1));
280418334Speter	}
280518334Speter      else
280690075Sobrien	{
280790075Sobrien	  value->un.addr.base = x;
280890075Sobrien	  value->un.addr.offset = 0;
280990075Sobrien	}
281018334Speter      break;
281118334Speter
281218334Speter    default:
281396263Sobrien      value->kind = RTX_UNKNOWN;
281496263Sobrien      break;
281518334Speter    }
281618334Speter
281796263Sobrien  if (value->kind == RTX_INT && value->un.addr.base != 0
281896263Sobrien      && GET_CODE (value->un.addr.base) == UNSPEC)
2819117395Skan    {
282096263Sobrien      /* For a simple UNSPEC, the base is set to the
282196263Sobrien	 operand, the kind field is set to the index of
2822117395Skan	 the unspec expression.
282396263Sobrien	 Together with the code below, in case that
2824117395Skan	 the operand is a SYMBOL_REF or LABEL_REF,
2825117395Skan	 the address of the string or the code_label
282696263Sobrien	 is taken as base.  */
282796263Sobrien      if (XVECLEN (value->un.addr.base, 0) == 1)
2828117395Skan	{
282996263Sobrien	  value->kind = RTX_UNSPEC + XINT (value->un.addr.base, 1);
283096263Sobrien	  value->un.addr.base = XVECEXP (value->un.addr.base, 0, 0);
283196263Sobrien	}
283296263Sobrien    }
283396263Sobrien
2834117395Skan  if (value->kind >= RTX_INT && value->un.addr.base != 0)
283518334Speter    switch (GET_CODE (value->un.addr.base))
283618334Speter      {
283718334Speter      case SYMBOL_REF:
283890075Sobrien	/* Use the string's address, not the SYMBOL_REF's address,
283990075Sobrien	   for the sake of addresses of library routines.  */
2840117395Skan	value->un.addr.symbol = XSTR (value->un.addr.base, 0);
2841117395Skan	value->un.addr.base = NULL_RTX;
284290075Sobrien	break;
284390075Sobrien
284418334Speter      case LABEL_REF:
284590075Sobrien	/* For a LABEL_REF, compare labels.  */
284618334Speter	value->un.addr.base = XEXP (value->un.addr.base, 0);
284790075Sobrien
284850397Sobrien      default:
284950397Sobrien	break;
285018334Speter      }
285118334Speter}
285218334Speter
285318334Speter/* Given a MINUS expression, simplify it if both sides
285418334Speter   include the same symbol.  */
285518334Speter
285618334Speterrtx
2857132718Skansimplify_subtraction (rtx x)
285818334Speter{
285918334Speter  struct rtx_const val0, val1;
286018334Speter
286118334Speter  decode_rtx_const (GET_MODE (x), XEXP (x, 0), &val0);
286218334Speter  decode_rtx_const (GET_MODE (x), XEXP (x, 1), &val1);
286318334Speter
2864117395Skan  if (val0.kind >= RTX_INT
286596263Sobrien      && val0.kind == val1.kind
2866117395Skan      && val0.un.addr.base == val1.un.addr.base
2867117395Skan      && val0.un.addr.symbol == val1.un.addr.symbol)
286818334Speter    return GEN_INT (val0.un.addr.offset - val1.un.addr.offset);
286996263Sobrien
287018334Speter  return x;
287118334Speter}
287218334Speter
287318334Speter/* Compute a hash code for a constant RTL expression.  */
287418334Speter
2875117395Skanstatic unsigned int
2876132718Skanconst_hash_rtx (enum machine_mode mode, rtx x)
287718334Speter{
2878117395Skan  union {
2879117395Skan    struct rtx_const value;
2880117395Skan    unsigned int data[sizeof(struct rtx_const) / sizeof (unsigned int)];
2881117395Skan  } u;
2882117395Skan
2883117395Skan  unsigned int hi;
288490075Sobrien  size_t i;
288518334Speter
2886117395Skan  decode_rtx_const (mode, x, &u.value);
288718334Speter
2888132718Skan  /* Compute hashing function.  */
288918334Speter  hi = 0;
2890117395Skan  for (i = 0; i < ARRAY_SIZE (u.data); i++)
2891117395Skan    hi = hi * 613 + u.data[i];
289218334Speter
2893117395Skan  return hi % MAX_RTX_HASH_TABLE;
289418334Speter}
289518334Speter
289618334Speter/* Compare a constant rtl object X with a constant-descriptor DESC.
289718334Speter   Return 1 if DESC describes a constant with the same value as X.  */
289818334Speter
289918334Speterstatic int
2900132718Skancompare_constant_rtx (enum machine_mode mode, rtx x,
2901132718Skan		      struct constant_descriptor_rtx *desc)
290218334Speter{
290318334Speter  struct rtx_const value;
290418334Speter
290518334Speter  decode_rtx_const (mode, x, &value);
290618334Speter
290718334Speter  /* Compare constant contents.  */
2908117395Skan  return memcmp (&value, &desc->value, sizeof (struct rtx_const)) == 0;
290918334Speter}
291018334Speter
291118334Speter/* Construct a constant descriptor for the rtl-expression X.
291218334Speter   It is up to the caller to enter the descriptor in the hash table.  */
291318334Speter
2914117395Skanstatic struct constant_descriptor_rtx *
2915132718Skanrecord_constant_rtx (enum machine_mode mode, rtx x)
291618334Speter{
2917117395Skan  struct constant_descriptor_rtx *ptr;
291818334Speter
2919132718Skan  ptr = ggc_alloc (sizeof (*ptr));
2920117395Skan  decode_rtx_const (mode, x, &ptr->value);
292118334Speter
292290075Sobrien  return ptr;
292390075Sobrien}
292490075Sobrien
292518334Speter/* Given a constant rtx X, make (or find) a memory constant for its value
292618334Speter   and return a MEM rtx to refer to it in memory.  */
292718334Speter
292818334Speterrtx
2929132718Skanforce_const_mem (enum machine_mode mode, rtx x)
293018334Speter{
293190075Sobrien  int hash;
2932117395Skan  struct constant_descriptor_rtx *desc;
293318334Speter  char label[256];
2934132718Skan  rtx def, symbol;
293590075Sobrien  struct pool_constant *pool;
293690075Sobrien  unsigned int align;
293718334Speter
2938117395Skan  /* If we're not allowed to drop X into the constant pool, don't.  */
2939117395Skan  if ((*targetm.cannot_force_const_mem) (x))
2940117395Skan    return NULL_RTX;
2941117395Skan
294218334Speter  /* Compute hash code of X.  Search the descriptors for that hash code
294390075Sobrien     to see if any of them describes X.  If yes, we have an rtx to use.  */
294418334Speter  hash = const_hash_rtx (mode, x);
294518334Speter  for (desc = const_rtx_hash_table[hash]; desc; desc = desc->next)
294618334Speter    if (compare_constant_rtx (mode, x, desc))
2947132718Skan      return copy_rtx (desc->rtl);
294818334Speter
294990075Sobrien  /* No constant equal to X is known to have been output.
295090075Sobrien     Make a constant descriptor to enter X in the hash table
295190075Sobrien     and make a MEM for it.  */
295290075Sobrien  desc = record_constant_rtx (mode, x);
295390075Sobrien  desc->next = const_rtx_hash_table[hash];
295490075Sobrien  const_rtx_hash_table[hash] = desc;
2955117395Skan
295690075Sobrien  /* Align the location counter as required by EXP's data type.  */
295790075Sobrien  align = GET_MODE_ALIGNMENT (mode == VOIDmode ? word_mode : mode);
295850397Sobrien#ifdef CONSTANT_ALIGNMENT
2959132718Skan  {
2960132718Skan    tree type = (*lang_hooks.types.type_for_mode) (mode, 0);
2961132718Skan    if (type != NULL_TREE)
2962132718Skan      align = CONSTANT_ALIGNMENT (make_tree (type, x), align);
2963132718Skan  }
296450397Sobrien#endif
296518334Speter
296690075Sobrien  pool_offset += (align / BITS_PER_UNIT) - 1;
296790075Sobrien  pool_offset &= ~ ((align / BITS_PER_UNIT) - 1);
296818334Speter
296990075Sobrien  if (GET_CODE (x) == LABEL_REF)
297090075Sobrien    LABEL_PRESERVE_P (XEXP (x, 0)) = 1;
297118334Speter
297290075Sobrien  /* Allocate a pool constant descriptor, fill it in, and chain it in.  */
2973132718Skan  pool = ggc_alloc (sizeof (struct pool_constant));
297490075Sobrien  pool->desc = desc;
297590075Sobrien  pool->constant = x;
297690075Sobrien  pool->mode = mode;
297790075Sobrien  pool->labelno = const_labelno;
297890075Sobrien  pool->align = align;
297990075Sobrien  pool->offset = pool_offset;
298090075Sobrien  pool->mark = 1;
298190075Sobrien  pool->next = 0;
298250397Sobrien
298390075Sobrien  if (last_pool == 0)
298490075Sobrien    first_pool = pool;
298590075Sobrien  else
298690075Sobrien    last_pool->next = pool;
2987117395Skan
298890075Sobrien  last_pool = pool;
298990075Sobrien  pool_offset += GET_MODE_SIZE (mode);
299018334Speter
299190075Sobrien  /* Create a string containing the label name, in LABEL.  */
299290075Sobrien  ASM_GENERATE_INTERNAL_LABEL (label, "LC", const_labelno);
299374722Sobrien
299490075Sobrien  ++const_labelno;
299574722Sobrien
299690075Sobrien  /* Construct the SYMBOL_REF and the MEM.  */
299718334Speter
2998132718Skan  symbol = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (label));
2999132718Skan  SYMBOL_REF_FLAGS (symbol) = SYMBOL_FLAG_LOCAL;
3000132718Skan
3001132718Skan  pool->desc->rtl = def = gen_rtx_MEM (mode, symbol);
3002117395Skan  set_mem_attributes (def, (*lang_hooks.types.type_for_mode) (mode, 0), 1);
300390075Sobrien  RTX_UNCHANGING_P (def) = 1;
300418334Speter
300590075Sobrien  /* Add label to symbol hash table.  */
3006132718Skan  hash = SYMHASH (XSTR (symbol, 0));
300790075Sobrien  pool->next_sym = const_rtx_sym_hash_table[hash];
300890075Sobrien  const_rtx_sym_hash_table[hash] = pool;
300918334Speter
301018334Speter  /* Mark the symbol_ref as belonging to this constants pool.  */
3011132718Skan  CONSTANT_POOL_ADDRESS_P (symbol) = 1;
3012132718Skan  SYMBOL_REF_FLAGS (symbol) = SYMBOL_FLAG_LOCAL;
301318334Speter  current_function_uses_const_pool = 1;
301418334Speter
3015132718Skan  return copy_rtx (def);
301618334Speter}
301718334Speter
301818334Speter/* Given a SYMBOL_REF with CONSTANT_POOL_ADDRESS_P true, return a pointer to
301918334Speter   the corresponding pool_constant structure.  */
302018334Speter
302118334Speterstatic struct pool_constant *
3022132718Skanfind_pool_constant (struct function *f, rtx addr)
302318334Speter{
302490075Sobrien  struct pool_constant *pool;
302590075Sobrien  const char *label = XSTR (addr, 0);
302618334Speter
302790075Sobrien  for (pool = f->varasm->x_const_rtx_sym_hash_table[SYMHASH (label)]; pool;
302890075Sobrien       pool = pool->next_sym)
302990075Sobrien    if (XSTR (XEXP (pool->desc->rtl, 0), 0) == label)
303090075Sobrien      return pool;
303118334Speter
303218334Speter  abort ();
303318334Speter}
303418334Speter
303518334Speter/* Given a constant pool SYMBOL_REF, return the corresponding constant.  */
303618334Speter
303718334Speterrtx
3038132718Skanget_pool_constant (rtx addr)
303918334Speter{
304090075Sobrien  return (find_pool_constant (cfun, addr))->constant;
304118334Speter}
304218334Speter
304396263Sobrien/* Given a constant pool SYMBOL_REF, return the corresponding constant
304496263Sobrien   and whether it has been output or not.  */
304596263Sobrien
304696263Sobrienrtx
3047132718Skanget_pool_constant_mark (rtx addr, bool *pmarked)
304896263Sobrien{
304996263Sobrien  struct pool_constant *pool = find_pool_constant (cfun, addr);
305096263Sobrien  *pmarked = (pool->mark != 0);
305196263Sobrien  return pool->constant;
305296263Sobrien}
305396263Sobrien
305490075Sobrien/* Likewise, but for the constant pool of a specific function.  */
305590075Sobrien
305690075Sobrienrtx
3057132718Skanget_pool_constant_for_function (struct function *f, rtx addr)
305890075Sobrien{
305990075Sobrien  return (find_pool_constant (f, addr))->constant;
306090075Sobrien}
306190075Sobrien
306218334Speter/* Similar, return the mode.  */
306318334Speter
306418334Speterenum machine_mode
3065132718Skanget_pool_mode (rtx addr)
306618334Speter{
306790075Sobrien  return (find_pool_constant (cfun, addr))->mode;
306818334Speter}
306918334Speter
307090075Sobrienenum machine_mode
3071132718Skanget_pool_mode_for_function (struct function *f, rtx addr)
307290075Sobrien{
307390075Sobrien  return (find_pool_constant (f, addr))->mode;
307490075Sobrien}
307590075Sobrien
307618334Speter/* Similar, return the offset in the constant pool.  */
307718334Speter
307818334Speterint
3079132718Skanget_pool_offset (rtx addr)
308018334Speter{
308190075Sobrien  return (find_pool_constant (cfun, addr))->offset;
308218334Speter}
308318334Speter
308418334Speter/* Return the size of the constant pool.  */
308518334Speter
308618334Speterint
3087132718Skanget_pool_size (void)
308818334Speter{
308918334Speter  return pool_offset;
309018334Speter}
309118334Speter
309218334Speter/* Write all the constants in the constant pool.  */
309318334Speter
309418334Spetervoid
3095132718Skanoutput_constant_pool (const char *fnname ATTRIBUTE_UNUSED,
3096132718Skan		      tree fndecl ATTRIBUTE_UNUSED)
309718334Speter{
309818334Speter  struct pool_constant *pool;
309918334Speter  rtx x;
3100117395Skan  REAL_VALUE_TYPE r;
310118334Speter
310250397Sobrien  /* It is possible for gcc to call force_const_mem and then to later
310350397Sobrien     discard the instructions which refer to the constant.  In such a
310450397Sobrien     case we do not need to output the constant.  */
310552284Sobrien  mark_constant_pool ();
310650397Sobrien
310718334Speter#ifdef ASM_OUTPUT_POOL_PROLOGUE
310818334Speter  ASM_OUTPUT_POOL_PROLOGUE (asm_out_file, fnname, fndecl, pool_offset);
310918334Speter#endif
311018334Speter
311118334Speter  for (pool = first_pool; pool; pool = pool->next)
311218334Speter    {
311390075Sobrien      rtx tmp;
311490075Sobrien
311518334Speter      x = pool->constant;
311618334Speter
311750397Sobrien      if (! pool->mark)
311850397Sobrien	continue;
311950397Sobrien
312018334Speter      /* See if X is a LABEL_REF (or a CONST referring to a LABEL_REF)
312118334Speter	 whose CODE_LABEL has been deleted.  This can occur if a jump table
312218334Speter	 is eliminated by optimization.  If so, write a constant of zero
312318334Speter	 instead.  Note that this can also happen by turning the
312418334Speter	 CODE_LABEL into a NOTE.  */
312590075Sobrien      /* ??? This seems completely and utterly wrong.  Certainly it's
312690075Sobrien	 not true for NOTE_INSN_DELETED_LABEL, but I disbelieve proper
312790075Sobrien	 functioning even with INSN_DELETED_P and friends.  */
312818334Speter
312990075Sobrien      tmp = x;
313090075Sobrien      switch (GET_CODE (x))
313190075Sobrien	{
313290075Sobrien	case CONST:
313390075Sobrien	  if (GET_CODE (XEXP (x, 0)) != PLUS
313490075Sobrien	      || GET_CODE (XEXP (XEXP (x, 0), 0)) != LABEL_REF)
313590075Sobrien	    break;
313690075Sobrien	  tmp = XEXP (XEXP (x, 0), 0);
3137132718Skan	  /* Fall through.  */
313890075Sobrien
313990075Sobrien	case LABEL_REF:
314090075Sobrien	  tmp = XEXP (x, 0);
314190075Sobrien	  if (INSN_DELETED_P (tmp)
314290075Sobrien	      || (GET_CODE (tmp) == NOTE
314390075Sobrien		  && NOTE_LINE_NUMBER (tmp) == NOTE_INSN_DELETED))
314490075Sobrien	    {
314590075Sobrien	      abort ();
314690075Sobrien	      x = const0_rtx;
314790075Sobrien	    }
314890075Sobrien	  break;
314990075Sobrien
315090075Sobrien	default:
315190075Sobrien	  break;
315290075Sobrien	}
315390075Sobrien
315418334Speter      /* First switch to correct section.  */
3155117395Skan      (*targetm.asm_out.select_rtx_section) (pool->mode, x, pool->align);
315618334Speter
315718334Speter#ifdef ASM_OUTPUT_SPECIAL_POOL_ENTRY
315818334Speter      ASM_OUTPUT_SPECIAL_POOL_ENTRY (asm_out_file, x, pool->mode,
315918334Speter				     pool->align, pool->labelno, done);
316018334Speter#endif
316118334Speter
316290075Sobrien      assemble_align (pool->align);
316318334Speter
316418334Speter      /* Output the label.  */
3165132718Skan      (*targetm.asm_out.internal_label) (asm_out_file, "LC", pool->labelno);
316618334Speter
316718334Speter      /* Output the value of the constant itself.  */
316818334Speter      switch (GET_MODE_CLASS (pool->mode))
316918334Speter	{
317018334Speter	case MODE_FLOAT:
317118334Speter	  if (GET_CODE (x) != CONST_DOUBLE)
317218334Speter	    abort ();
317318334Speter
3174117395Skan	  REAL_VALUE_FROM_CONST_DOUBLE (r, x);
3175117395Skan	  assemble_real (r, pool->mode, pool->align);
317618334Speter	  break;
317718334Speter
317818334Speter	case MODE_INT:
317918334Speter	case MODE_PARTIAL_INT:
318090075Sobrien	  assemble_integer (x, GET_MODE_SIZE (pool->mode), pool->align, 1);
318118334Speter	  break;
318218334Speter
318396263Sobrien	case MODE_VECTOR_FLOAT:
318496263Sobrien	  {
318596263Sobrien	    int i, units;
318696263Sobrien	    rtx elt;
318796263Sobrien
318896263Sobrien	    if (GET_CODE (x) != CONST_VECTOR)
318996263Sobrien	      abort ();
319096263Sobrien
319196263Sobrien	    units = CONST_VECTOR_NUNITS (x);
319296263Sobrien
319396263Sobrien	    for (i = 0; i < units; i++)
319496263Sobrien	      {
319596263Sobrien		elt = CONST_VECTOR_ELT (x, i);
3196117395Skan		REAL_VALUE_FROM_CONST_DOUBLE (r, elt);
3197117395Skan		assemble_real (r, GET_MODE_INNER (pool->mode), pool->align);
319896263Sobrien	      }
319996263Sobrien	  }
320096263Sobrien	  break;
320196263Sobrien
3202117395Skan	case MODE_VECTOR_INT:
320396263Sobrien	  {
320496263Sobrien	    int i, units;
320596263Sobrien	    rtx elt;
320696263Sobrien
320796263Sobrien	    if (GET_CODE (x) != CONST_VECTOR)
320896263Sobrien	      abort ();
320996263Sobrien
321096263Sobrien	    units = CONST_VECTOR_NUNITS (x);
321196263Sobrien
321296263Sobrien	    for (i = 0; i < units; i++)
321396263Sobrien	      {
321496263Sobrien		elt = CONST_VECTOR_ELT (x, i);
321596263Sobrien		assemble_integer (elt, GET_MODE_UNIT_SIZE (pool->mode),
321696263Sobrien				  pool->align, 1);
321796263Sobrien	      }
321896263Sobrien	  }
321996263Sobrien	  break;
322096263Sobrien
322118334Speter	default:
322218334Speter	  abort ();
322318334Speter	}
322418334Speter
3225117395Skan      /* Make sure all constants in SECTION_MERGE and not SECTION_STRINGS
3226117395Skan	 sections have proper size.  */
3227117395Skan      if (pool->align > GET_MODE_BITSIZE (pool->mode)
3228117395Skan	  && in_section == in_named
3229117395Skan	  && get_named_section_flags (in_named_name) & SECTION_MERGE)
3230117395Skan	assemble_align (pool->align);
3231117395Skan
323250397Sobrien#ifdef ASM_OUTPUT_SPECIAL_POOL_ENTRY
323318334Speter    done: ;
323450397Sobrien#endif
323518334Speter    }
323618334Speter
323750397Sobrien#ifdef ASM_OUTPUT_POOL_EPILOGUE
323850397Sobrien  ASM_OUTPUT_POOL_EPILOGUE (asm_out_file, fnname, fndecl, pool_offset);
323950397Sobrien#endif
324050397Sobrien
324118334Speter  /* Done with this pool.  */
324218334Speter  first_pool = last_pool = 0;
324318334Speter}
324450397Sobrien
324550397Sobrien/* Look through the instructions for this function, and mark all the
3246132718Skan   entries in the constant pool which are actually being used.  Emit
3247132718Skan   deferred constants which have indeed been used.  */
324850397Sobrien
324950397Sobrienstatic void
3250132718Skanmark_constant_pool (void)
325150397Sobrien{
325290075Sobrien  rtx insn;
3253117395Skan  rtx link;
325450397Sobrien  struct pool_constant *pool;
325550397Sobrien
3256132718Skan  if (first_pool == 0 && n_deferred_constants == 0)
325750397Sobrien    return;
325850397Sobrien
325950397Sobrien  for (pool = first_pool; pool; pool = pool->next)
326050397Sobrien    pool->mark = 0;
326150397Sobrien
326250397Sobrien  for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
326390075Sobrien    if (INSN_P (insn))
326450397Sobrien      mark_constants (PATTERN (insn));
326550397Sobrien
3266117395Skan  for (link = current_function_epilogue_delay_list;
3267117395Skan       link;
3268117395Skan       link = XEXP (link, 1))
3269117395Skan    {
3270117395Skan      insn = XEXP (link, 0);
3271117395Skan
3272117395Skan      if (INSN_P (insn))
3273117395Skan	mark_constants (PATTERN (insn));
3274117395Skan    }
327590075Sobrien}
327652284Sobrien
327790075Sobrien/* Look through appropriate parts of X, marking all entries in the
327890075Sobrien   constant pool which are actually being used.  Entries that are only
327990075Sobrien   referenced by other constants are also marked as used.  Emit
328090075Sobrien   deferred strings that are used.  */
328152284Sobrien
328250397Sobrienstatic void
3283132718Skanmark_constants (rtx x)
328450397Sobrien{
328590075Sobrien  int i;
328690075Sobrien  const char *format_ptr;
328750397Sobrien
328850397Sobrien  if (x == 0)
328950397Sobrien    return;
329050397Sobrien
329150397Sobrien  if (GET_CODE (x) == SYMBOL_REF)
329250397Sobrien    {
329390075Sobrien      mark_constant (&x, NULL);
329450397Sobrien      return;
329550397Sobrien    }
329650397Sobrien
329750397Sobrien  /* Insns may appear inside a SEQUENCE.  Only check the patterns of
329850397Sobrien     insns, not any notes that may be attached.  We don't want to mark
329950397Sobrien     a constant just because it happens to appear in a REG_EQUIV note.  */
330090075Sobrien  if (INSN_P (x))
330150397Sobrien    {
330250397Sobrien      mark_constants (PATTERN (x));
330350397Sobrien      return;
330450397Sobrien    }
330550397Sobrien
330650397Sobrien  format_ptr = GET_RTX_FORMAT (GET_CODE (x));
330750397Sobrien
330850397Sobrien  for (i = 0; i < GET_RTX_LENGTH (GET_CODE (x)); i++)
330950397Sobrien    {
331050397Sobrien      switch (*format_ptr++)
331150397Sobrien	{
331250397Sobrien	case 'e':
331350397Sobrien	  mark_constants (XEXP (x, i));
331450397Sobrien	  break;
331550397Sobrien
331650397Sobrien	case 'E':
331750397Sobrien	  if (XVEC (x, i) != 0)
331850397Sobrien	    {
331990075Sobrien	      int j;
332050397Sobrien
332150397Sobrien	      for (j = 0; j < XVECLEN (x, i); j++)
332250397Sobrien		mark_constants (XVECEXP (x, i, j));
332350397Sobrien	    }
332450397Sobrien	  break;
332550397Sobrien
332650397Sobrien	case 'S':
332750397Sobrien	case 's':
332850397Sobrien	case '0':
332950397Sobrien	case 'i':
333050397Sobrien	case 'w':
333150397Sobrien	case 'n':
333250397Sobrien	case 'u':
3333117395Skan	case 'B':
333450397Sobrien	  break;
333550397Sobrien
333650397Sobrien	default:
333750397Sobrien	  abort ();
333850397Sobrien	}
333950397Sobrien    }
334050397Sobrien}
334190075Sobrien
334290075Sobrien/* Given a SYMBOL_REF CURRENT_RTX, mark it and all constants it refers
334390075Sobrien   to as used.  Emit referenced deferred strings.  This function can
334490075Sobrien   be used with for_each_rtx to mark all SYMBOL_REFs in an rtx.  */
334590075Sobrien
334690075Sobrienstatic int
3347132718Skanmark_constant (rtx *current_rtx, void *data ATTRIBUTE_UNUSED)
334890075Sobrien{
334990075Sobrien  rtx x = *current_rtx;
335090075Sobrien
335190075Sobrien  if (x == NULL_RTX)
335290075Sobrien    return 0;
335390075Sobrien
335490075Sobrien  else if (GET_CODE (x) == SYMBOL_REF)
335590075Sobrien    {
335690075Sobrien      if (CONSTANT_POOL_ADDRESS_P (x))
335790075Sobrien	{
335890075Sobrien	  struct pool_constant *pool = find_pool_constant (cfun, x);
3359117395Skan	  if (pool->mark == 0)
3360117395Skan	    {
3361117395Skan	      pool->mark = 1;
3362117395Skan	      for_each_rtx (&(pool->constant), &mark_constant, NULL);
3363117395Skan	    }
336490075Sobrien	  else
336590075Sobrien	    return -1;
336690075Sobrien	}
3367132718Skan      else if (TREE_CONSTANT_POOL_ADDRESS_P (x))
336890075Sobrien	{
3369132718Skan	  tree exp = SYMBOL_REF_DECL (x);
3370132718Skan	  if (!TREE_ASM_WRITTEN (exp))
337190075Sobrien	    {
3372132718Skan	      n_deferred_constants--;
3373132718Skan	      output_constant_def_contents (x);
337490075Sobrien	    }
337590075Sobrien	}
337690075Sobrien    }
337790075Sobrien  return 0;
337890075Sobrien}
337918334Speter
3380132718Skan/* Determine what kind of relocations EXP may need.  */
338118334Speter
3382132718Skanint
3383132718Skancompute_reloc_for_constant (tree exp)
338418334Speter{
3385117395Skan  int reloc = 0, reloc2;
338690075Sobrien  tree tem;
338718334Speter
338890075Sobrien  /* Give the front-end a chance to convert VALUE to something that
338990075Sobrien     looks more like a constant to the back-end.  */
339090075Sobrien  exp = (*lang_hooks.expand_constant) (exp);
339190075Sobrien
339218334Speter  switch (TREE_CODE (exp))
339318334Speter    {
339418334Speter    case ADDR_EXPR:
3395102780Skan    case FDESC_EXPR:
339690075Sobrien      /* Go inside any operations that get_inner_reference can handle and see
339790075Sobrien	 if what's inside is a constant: no need to do anything here for
339890075Sobrien	 addresses of variables or functions.  */
339990075Sobrien      for (tem = TREE_OPERAND (exp, 0); handled_component_p (tem);
340090075Sobrien	   tem = TREE_OPERAND (tem, 0))
340190075Sobrien	;
340218334Speter
340390075Sobrien      if (TREE_PUBLIC (tem))
340490075Sobrien	reloc |= 2;
340590075Sobrien      else
340690075Sobrien	reloc |= 1;
340718334Speter      break;
340818334Speter
340918334Speter    case PLUS_EXPR:
3410132718Skan      reloc = compute_reloc_for_constant (TREE_OPERAND (exp, 0));
3411132718Skan      reloc |= compute_reloc_for_constant (TREE_OPERAND (exp, 1));
341218334Speter      break;
341318334Speter
3414117395Skan    case MINUS_EXPR:
3415132718Skan      reloc = compute_reloc_for_constant (TREE_OPERAND (exp, 0));
3416132718Skan      reloc2 = compute_reloc_for_constant (TREE_OPERAND (exp, 1));
3417117395Skan      /* The difference of two local labels is computable at link time.  */
3418117395Skan      if (reloc == 1 && reloc2 == 1)
3419117395Skan	reloc = 0;
3420117395Skan      else
3421117395Skan	reloc |= reloc2;
3422117395Skan      break;
3423117395Skan
342418334Speter    case NOP_EXPR:
342518334Speter    case CONVERT_EXPR:
342618334Speter    case NON_LVALUE_EXPR:
3427132718Skan      reloc = compute_reloc_for_constant (TREE_OPERAND (exp, 0));
342818334Speter      break;
342918334Speter
343018334Speter    case CONSTRUCTOR:
343190075Sobrien      for (tem = CONSTRUCTOR_ELTS (exp); tem; tem = TREE_CHAIN (tem))
343290075Sobrien	if (TREE_VALUE (tem) != 0)
3433132718Skan	  reloc |= compute_reloc_for_constant (TREE_VALUE (tem));
343490075Sobrien
343518334Speter      break;
343618334Speter
343750397Sobrien    default:
343818334Speter      break;
343918334Speter    }
344018334Speter  return reloc;
344118334Speter}
3442132718Skan
3443132718Skan/* Find all the constants whose addresses are referenced inside of EXP,
3444132718Skan   and make sure assembler code with a label has been output for each one.
3445132718Skan   Indicate whether an ADDR_EXPR has been encountered.  */
3446132718Skan
3447132718Skanstatic void
3448132718Skanoutput_addressed_constants (tree exp)
3449132718Skan{
3450132718Skan  tree tem;
3451132718Skan
3452132718Skan  /* Give the front-end a chance to convert VALUE to something that
3453132718Skan     looks more like a constant to the back-end.  */
3454132718Skan  exp = (*lang_hooks.expand_constant) (exp);
3455132718Skan
3456132718Skan  switch (TREE_CODE (exp))
3457132718Skan    {
3458132718Skan    case ADDR_EXPR:
3459132718Skan    case FDESC_EXPR:
3460132718Skan      /* Go inside any operations that get_inner_reference can handle and see
3461132718Skan	 if what's inside is a constant: no need to do anything here for
3462132718Skan	 addresses of variables or functions.  */
3463132718Skan      for (tem = TREE_OPERAND (exp, 0); handled_component_p (tem);
3464132718Skan	   tem = TREE_OPERAND (tem, 0))
3465132718Skan	;
3466132718Skan
3467132718Skan      if (TREE_CODE_CLASS (TREE_CODE (tem)) == 'c'
3468132718Skan	  || TREE_CODE (tem) == CONSTRUCTOR)
3469132718Skan	output_constant_def (tem, 0);
3470132718Skan      break;
3471132718Skan
3472132718Skan    case PLUS_EXPR:
3473132718Skan    case MINUS_EXPR:
3474132718Skan      output_addressed_constants (TREE_OPERAND (exp, 1));
3475132718Skan      /* Fall through.  */
3476132718Skan
3477132718Skan    case NOP_EXPR:
3478132718Skan    case CONVERT_EXPR:
3479132718Skan    case NON_LVALUE_EXPR:
3480132718Skan      output_addressed_constants (TREE_OPERAND (exp, 0));
3481132718Skan      break;
3482132718Skan
3483132718Skan    case CONSTRUCTOR:
3484132718Skan      for (tem = CONSTRUCTOR_ELTS (exp); tem; tem = TREE_CHAIN (tem))
3485132718Skan	if (TREE_VALUE (tem) != 0)
3486132718Skan	  output_addressed_constants (TREE_VALUE (tem));
3487132718Skan
3488132718Skan      break;
3489132718Skan
3490132718Skan    default:
3491132718Skan      break;
3492132718Skan    }
3493132718Skan}
349418334Speter
349590075Sobrien/* Return nonzero if VALUE is a valid constant-valued expression
349690075Sobrien   for use in initializing a static variable; one that can be an
349790075Sobrien   element of a "constant" initializer.
349890075Sobrien
349990075Sobrien   Return null_pointer_node if the value is absolute;
350090075Sobrien   if it is relocatable, return the variable that determines the relocation.
350190075Sobrien   We assume that VALUE has been folded as much as possible;
350290075Sobrien   therefore, we do not need to check for such things as
350390075Sobrien   arithmetic-combinations of integers.  */
350490075Sobrien
350590075Sobrientree
3506132718Skaninitializer_constant_valid_p (tree value, tree endtype)
350790075Sobrien{
350890075Sobrien  /* Give the front-end a chance to convert VALUE to something that
350990075Sobrien     looks more like a constant to the back-end.  */
351090075Sobrien  value = (*lang_hooks.expand_constant) (value);
351190075Sobrien
351290075Sobrien  switch (TREE_CODE (value))
351390075Sobrien    {
351490075Sobrien    case CONSTRUCTOR:
351590075Sobrien      if ((TREE_CODE (TREE_TYPE (value)) == UNION_TYPE
351690075Sobrien	   || TREE_CODE (TREE_TYPE (value)) == RECORD_TYPE)
351790075Sobrien	  && TREE_CONSTANT (value)
351890075Sobrien	  && CONSTRUCTOR_ELTS (value))
3519122180Skan	{
3520122180Skan	  tree elt;
3521122180Skan	  bool absolute = true;
352290075Sobrien
3523122180Skan	  for (elt = CONSTRUCTOR_ELTS (value); elt; elt = TREE_CHAIN (elt))
3524122180Skan	    {
3525122180Skan	      tree reloc;
3526122180Skan	      value = TREE_VALUE (elt);
3527122180Skan	      reloc = initializer_constant_valid_p (value, TREE_TYPE (value));
3528122180Skan	      if (!reloc)
3529122180Skan		return NULL_TREE;
3530122180Skan	      if (reloc != null_pointer_node)
3531122180Skan		absolute = false;
3532122180Skan	    }
3533122180Skan	  /* For a non-absolute relocation, there is no single
3534122180Skan	     variable that can be "the variable that determines the
3535122180Skan	     relocation."  */
3536122180Skan	  return absolute ? null_pointer_node : error_mark_node;
3537122180Skan	}
353890075Sobrien
3539122180Skan      return TREE_STATIC (value) ? null_pointer_node : NULL_TREE;
3540122180Skan
354190075Sobrien    case INTEGER_CST:
354296263Sobrien    case VECTOR_CST:
354390075Sobrien    case REAL_CST:
354490075Sobrien    case STRING_CST:
354590075Sobrien    case COMPLEX_CST:
354690075Sobrien      return null_pointer_node;
354790075Sobrien
354890075Sobrien    case ADDR_EXPR:
354990075Sobrien    case FDESC_EXPR:
355090075Sobrien      return staticp (TREE_OPERAND (value, 0)) ? TREE_OPERAND (value, 0) : 0;
355190075Sobrien
355290075Sobrien    case VIEW_CONVERT_EXPR:
355390075Sobrien    case NON_LVALUE_EXPR:
355490075Sobrien      return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype);
355590075Sobrien
355690075Sobrien    case CONVERT_EXPR:
355790075Sobrien    case NOP_EXPR:
355890075Sobrien      /* Allow conversions between pointer types.  */
355990075Sobrien      if (POINTER_TYPE_P (TREE_TYPE (value))
356090075Sobrien	  && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (value, 0))))
356190075Sobrien	return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype);
356290075Sobrien
356390075Sobrien      /* Allow conversions between real types.  */
356490075Sobrien      if (FLOAT_TYPE_P (TREE_TYPE (value))
356590075Sobrien	  && FLOAT_TYPE_P (TREE_TYPE (TREE_OPERAND (value, 0))))
356690075Sobrien	return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype);
356790075Sobrien
356890075Sobrien      /* Allow length-preserving conversions between integer types.  */
356990075Sobrien      if (INTEGRAL_TYPE_P (TREE_TYPE (value))
357090075Sobrien	  && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (value, 0)))
357190075Sobrien	  && (TYPE_PRECISION (TREE_TYPE (value))
357290075Sobrien	      == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (value, 0)))))
357390075Sobrien	return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype);
357490075Sobrien
357590075Sobrien      /* Allow conversions between other integer types only if
357690075Sobrien	 explicit value.  */
357790075Sobrien      if (INTEGRAL_TYPE_P (TREE_TYPE (value))
357890075Sobrien	  && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (value, 0))))
357990075Sobrien	{
358090075Sobrien	  tree inner = initializer_constant_valid_p (TREE_OPERAND (value, 0),
358190075Sobrien						     endtype);
358290075Sobrien	  if (inner == null_pointer_node)
358390075Sobrien	    return null_pointer_node;
358490075Sobrien	  break;
358590075Sobrien	}
358690075Sobrien
358790075Sobrien      /* Allow (int) &foo provided int is as wide as a pointer.  */
358890075Sobrien      if (INTEGRAL_TYPE_P (TREE_TYPE (value))
358990075Sobrien	  && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (value, 0)))
359090075Sobrien	  && (TYPE_PRECISION (TREE_TYPE (value))
359190075Sobrien	      >= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (value, 0)))))
359290075Sobrien	return initializer_constant_valid_p (TREE_OPERAND (value, 0),
359390075Sobrien					     endtype);
359490075Sobrien
359590075Sobrien      /* Likewise conversions from int to pointers, but also allow
359690075Sobrien	 conversions from 0.  */
3597132718Skan      if ((POINTER_TYPE_P (TREE_TYPE (value))
3598132718Skan	   || TREE_CODE (TREE_TYPE (value)) == OFFSET_TYPE)
359990075Sobrien	  && INTEGRAL_TYPE_P (TREE_TYPE (TREE_OPERAND (value, 0))))
360090075Sobrien	{
360190075Sobrien	  if (integer_zerop (TREE_OPERAND (value, 0)))
360290075Sobrien	    return null_pointer_node;
360390075Sobrien	  else if (TYPE_PRECISION (TREE_TYPE (value))
360490075Sobrien		   <= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (value, 0))))
360590075Sobrien	    return initializer_constant_valid_p (TREE_OPERAND (value, 0),
360690075Sobrien						 endtype);
360790075Sobrien	}
360890075Sobrien
3609132718Skan      /* Allow conversions to struct or union types if the value
3610132718Skan	 inside is okay.  */
3611132718Skan      if (TREE_CODE (TREE_TYPE (value)) == RECORD_TYPE
3612132718Skan	  || TREE_CODE (TREE_TYPE (value)) == UNION_TYPE)
361390075Sobrien	return initializer_constant_valid_p (TREE_OPERAND (value, 0),
361490075Sobrien					     endtype);
361590075Sobrien      break;
361690075Sobrien
361790075Sobrien    case PLUS_EXPR:
361890075Sobrien      if (! INTEGRAL_TYPE_P (endtype)
361990075Sobrien	  || TYPE_PRECISION (endtype) >= POINTER_SIZE)
3620117395Skan	{
362190075Sobrien	  tree valid0 = initializer_constant_valid_p (TREE_OPERAND (value, 0),
362290075Sobrien						      endtype);
362390075Sobrien	  tree valid1 = initializer_constant_valid_p (TREE_OPERAND (value, 1),
362490075Sobrien						      endtype);
362590075Sobrien	  /* If either term is absolute, use the other terms relocation.  */
362690075Sobrien	  if (valid0 == null_pointer_node)
362790075Sobrien	    return valid1;
362890075Sobrien	  if (valid1 == null_pointer_node)
362990075Sobrien	    return valid0;
3630117395Skan	}
363190075Sobrien      break;
363290075Sobrien
363390075Sobrien    case MINUS_EXPR:
363490075Sobrien      if (! INTEGRAL_TYPE_P (endtype)
363590075Sobrien	  || TYPE_PRECISION (endtype) >= POINTER_SIZE)
363690075Sobrien	{
363790075Sobrien	  tree valid0 = initializer_constant_valid_p (TREE_OPERAND (value, 0),
363890075Sobrien						      endtype);
363990075Sobrien	  tree valid1 = initializer_constant_valid_p (TREE_OPERAND (value, 1),
364090075Sobrien						      endtype);
364190075Sobrien	  /* Win if second argument is absolute.  */
364290075Sobrien	  if (valid1 == null_pointer_node)
364390075Sobrien	    return valid0;
364490075Sobrien	  /* Win if both arguments have the same relocation.
364590075Sobrien	     Then the value is absolute.  */
364690075Sobrien	  if (valid0 == valid1 && valid0 != 0)
364790075Sobrien	    return null_pointer_node;
364890075Sobrien
364990075Sobrien	  /* Since GCC guarantees that string constants are unique in the
365090075Sobrien	     generated code, a subtraction between two copies of the same
365190075Sobrien	     constant string is absolute.  */
365290075Sobrien	  if (valid0 && TREE_CODE (valid0) == STRING_CST &&
365390075Sobrien	      valid1 && TREE_CODE (valid1) == STRING_CST &&
365490075Sobrien	      TREE_STRING_POINTER (valid0) == TREE_STRING_POINTER (valid1))
365590075Sobrien	    return null_pointer_node;
365690075Sobrien	}
365790075Sobrien
365890075Sobrien      /* Support differences between labels.  */
365990075Sobrien      if (INTEGRAL_TYPE_P (endtype))
366090075Sobrien	{
366190075Sobrien	  tree op0, op1;
366290075Sobrien	  op0 = TREE_OPERAND (value, 0);
366390075Sobrien	  op1 = TREE_OPERAND (value, 1);
366490075Sobrien
366596263Sobrien	  /* Like STRIP_NOPS except allow the operand mode to widen.
3666132718Skan	     This works around a feature of fold that simplifies
366796263Sobrien	     (int)(p1 - p2) to ((int)p1 - (int)p2) under the theory
366896263Sobrien	     that the narrower operation is cheaper.  */
366996263Sobrien
367096263Sobrien	  while (TREE_CODE (op0) == NOP_EXPR
367196263Sobrien		 || TREE_CODE (op0) == CONVERT_EXPR
367296263Sobrien		 || TREE_CODE (op0) == NON_LVALUE_EXPR)
367396263Sobrien	    {
367496263Sobrien	      tree inner = TREE_OPERAND (op0, 0);
367596263Sobrien	      if (inner == error_mark_node
367696263Sobrien	          || ! INTEGRAL_MODE_P (TYPE_MODE (TREE_TYPE (inner)))
367796263Sobrien		  || (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (op0)))
367896263Sobrien		      > GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (inner)))))
367996263Sobrien		break;
368096263Sobrien	      op0 = inner;
368196263Sobrien	    }
368296263Sobrien
368396263Sobrien	  while (TREE_CODE (op1) == NOP_EXPR
368496263Sobrien		 || TREE_CODE (op1) == CONVERT_EXPR
368596263Sobrien		 || TREE_CODE (op1) == NON_LVALUE_EXPR)
368696263Sobrien	    {
368796263Sobrien	      tree inner = TREE_OPERAND (op1, 0);
368896263Sobrien	      if (inner == error_mark_node
368996263Sobrien	          || ! INTEGRAL_MODE_P (TYPE_MODE (TREE_TYPE (inner)))
369096263Sobrien		  || (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (op1)))
369196263Sobrien		      > GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (inner)))))
369296263Sobrien		break;
369396263Sobrien	      op1 = inner;
369496263Sobrien	    }
369596263Sobrien
369690075Sobrien	  if (TREE_CODE (op0) == ADDR_EXPR
369790075Sobrien	      && TREE_CODE (TREE_OPERAND (op0, 0)) == LABEL_DECL
369890075Sobrien	      && TREE_CODE (op1) == ADDR_EXPR
369990075Sobrien	      && TREE_CODE (TREE_OPERAND (op1, 0)) == LABEL_DECL)
370090075Sobrien	    return null_pointer_node;
370190075Sobrien	}
370290075Sobrien      break;
370390075Sobrien
370490075Sobrien    default:
370590075Sobrien      break;
370690075Sobrien    }
370790075Sobrien
370890075Sobrien  return 0;
370990075Sobrien}
371090075Sobrien
371118334Speter/* Output assembler code for constant EXP to FILE, with no label.
371218334Speter   This includes the pseudo-op such as ".int" or ".byte", and a newline.
371318334Speter   Assumes output_addressed_constants has been done on EXP already.
371418334Speter
371518334Speter   Generate exactly SIZE bytes of assembler data, padding at the end
371618334Speter   with zeros if necessary.  SIZE must always be specified.
371718334Speter
371818334Speter   SIZE is important for structure constructors,
371918334Speter   since trailing members may have been omitted from the constructor.
372018334Speter   It is also important for initialization of arrays from string constants
372118334Speter   since the full length of the string constant might not be wanted.
372218334Speter   It is also needed for initialization of unions, where the initializer's
372318334Speter   type is just one member, and that may not be as long as the union.
372418334Speter
372518334Speter   There a case in which we would fail to output exactly SIZE bytes:
372618334Speter   for a structure constructor that wants to produce more than SIZE bytes.
372790075Sobrien   But such constructors will never be generated for any possible input.
372818334Speter
372990075Sobrien   ALIGN is the alignment of the data in bits.  */
373090075Sobrien
373118334Spetervoid
3732132718Skanoutput_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align)
373318334Speter{
373490075Sobrien  enum tree_code code;
3735132718Skan  unsigned HOST_WIDE_INT thissize;
373618334Speter
3737132718Skan  /* Some front-ends use constants other than the standard language-independent
373890075Sobrien     varieties, but which may still be output directly.  Give the front-end a
373990075Sobrien     chance to convert EXP to a language-independent representation.  */
374090075Sobrien  exp = (*lang_hooks.expand_constant) (exp);
374152284Sobrien
374252284Sobrien  if (size == 0 || flag_syntax_only)
374318334Speter    return;
374418334Speter
374590075Sobrien  /* Eliminate any conversions since we'll be outputting the underlying
374690075Sobrien     constant.  */
374790075Sobrien  while (TREE_CODE (exp) == NOP_EXPR || TREE_CODE (exp) == CONVERT_EXPR
374890075Sobrien	 || TREE_CODE (exp) == NON_LVALUE_EXPR
374990075Sobrien	 || TREE_CODE (exp) == VIEW_CONVERT_EXPR)
375018334Speter    exp = TREE_OPERAND (exp, 0);
375118334Speter
375290075Sobrien  code = TREE_CODE (TREE_TYPE (exp));
375390075Sobrien  thissize = int_size_in_bytes (TREE_TYPE (exp));
375490075Sobrien
375518334Speter  /* Allow a constructor with no elements for any data type.
375618334Speter     This means to fill the space with zeros.  */
375718334Speter  if (TREE_CODE (exp) == CONSTRUCTOR && CONSTRUCTOR_ELTS (exp) == 0)
375818334Speter    {
375950397Sobrien      assemble_zeros (size);
376018334Speter      return;
376118334Speter    }
376218334Speter
376390075Sobrien  if (TREE_CODE (exp) == FDESC_EXPR)
376490075Sobrien    {
376590075Sobrien#ifdef ASM_OUTPUT_FDESC
376690075Sobrien      HOST_WIDE_INT part = tree_low_cst (TREE_OPERAND (exp, 1), 0);
376790075Sobrien      tree decl = TREE_OPERAND (exp, 0);
376890075Sobrien      ASM_OUTPUT_FDESC (asm_out_file, decl, part);
376990075Sobrien#else
377090075Sobrien      abort ();
377190075Sobrien#endif
377290075Sobrien      return;
377390075Sobrien    }
377490075Sobrien
377590075Sobrien  /* Now output the underlying data.  If we've handling the padding, return.
377690075Sobrien     Otherwise, break and ensure THISSIZE is the size written.  */
377718334Speter  switch (code)
377818334Speter    {
377918334Speter    case CHAR_TYPE:
378018334Speter    case BOOLEAN_TYPE:
378118334Speter    case INTEGER_TYPE:
378218334Speter    case ENUMERAL_TYPE:
378318334Speter    case POINTER_TYPE:
378418334Speter    case REFERENCE_TYPE:
3785132718Skan    case OFFSET_TYPE:
378618334Speter      if (! assemble_integer (expand_expr (exp, NULL_RTX, VOIDmode,
378718334Speter					   EXPAND_INITIALIZER),
378890075Sobrien			      size, align, 0))
378918334Speter	error ("initializer for integer value is too complicated");
379018334Speter      break;
379118334Speter
379218334Speter    case REAL_TYPE:
379318334Speter      if (TREE_CODE (exp) != REAL_CST)
379418334Speter	error ("initializer for floating value is not a floating constant");
379518334Speter
3796132718Skan      assemble_real (TREE_REAL_CST (exp), TYPE_MODE (TREE_TYPE (exp)), align);
379718334Speter      break;
379818334Speter
379918334Speter    case COMPLEX_TYPE:
380090075Sobrien      output_constant (TREE_REALPART (exp), thissize / 2, align);
380190075Sobrien      output_constant (TREE_IMAGPART (exp), thissize / 2,
380290075Sobrien		       min_align (align, BITS_PER_UNIT * (thissize / 2)));
380318334Speter      break;
380418334Speter
380518334Speter    case ARRAY_TYPE:
380696263Sobrien    case VECTOR_TYPE:
380718334Speter      if (TREE_CODE (exp) == CONSTRUCTOR)
380818334Speter	{
380990075Sobrien	  output_constructor (exp, size, align);
381018334Speter	  return;
381118334Speter	}
381218334Speter      else if (TREE_CODE (exp) == STRING_CST)
381318334Speter	{
3814132718Skan	  thissize = MIN ((unsigned HOST_WIDE_INT)TREE_STRING_LENGTH (exp),
3815132718Skan			  size);
381690075Sobrien	  assemble_string (TREE_STRING_POINTER (exp), thissize);
381718334Speter	}
3818119256Skan      else if (TREE_CODE (exp) == VECTOR_CST)
3819119256Skan	{
3820119256Skan	  int elt_size;
3821119256Skan	  tree link;
3822119256Skan	  unsigned int nalign;
3823119256Skan	  enum machine_mode inner;
3824119256Skan
3825119256Skan	  inner = GET_MODE_INNER (TYPE_MODE (TREE_TYPE (exp)));
3826119256Skan	  nalign = MIN (align, GET_MODE_ALIGNMENT (inner));
3827119256Skan
3828119256Skan	  elt_size = GET_MODE_UNIT_SIZE (TYPE_MODE (TREE_TYPE (exp)));
3829119256Skan
3830119256Skan	  link = TREE_VECTOR_CST_ELTS (exp);
3831119256Skan	  output_constant (TREE_VALUE (link), elt_size, align);
3832119256Skan	  while ((link = TREE_CHAIN (link)) != NULL)
3833119256Skan	    output_constant (TREE_VALUE (link), elt_size, nalign);
3834119256Skan	}
383518334Speter      else
383618334Speter	abort ();
383718334Speter      break;
383818334Speter
383918334Speter    case RECORD_TYPE:
384018334Speter    case UNION_TYPE:
384118334Speter      if (TREE_CODE (exp) == CONSTRUCTOR)
384290075Sobrien	output_constructor (exp, size, align);
384318334Speter      else
384418334Speter	abort ();
384518334Speter      return;
384618334Speter
384718334Speter    case SET_TYPE:
384818334Speter      if (TREE_CODE (exp) == INTEGER_CST)
384918334Speter	assemble_integer (expand_expr (exp, NULL_RTX,
385018334Speter				       VOIDmode, EXPAND_INITIALIZER),
3851117395Skan			  thissize, align, 1);
385218334Speter      else if (TREE_CODE (exp) == CONSTRUCTOR)
385318334Speter	{
3854132718Skan	  unsigned char *buffer = alloca (thissize);
385590075Sobrien	  if (get_set_constructor_bytes (exp, buffer, thissize))
385618334Speter	    abort ();
385790075Sobrien	  assemble_string ((char *) buffer, thissize);
385818334Speter	}
385918334Speter      else
386018334Speter	error ("unknown set constructor type");
386118334Speter      return;
386250397Sobrien
386390075Sobrien    case ERROR_MARK:
386490075Sobrien      return;
386590075Sobrien
386650397Sobrien    default:
386790075Sobrien      abort ();
386818334Speter    }
386918334Speter
3870132718Skan  if (size > thissize)
3871132718Skan    assemble_zeros (size - thissize);
387218334Speter}
387318334Speter
387418334Speter
387590075Sobrien/* Subroutine of output_constructor, used for computing the size of
387690075Sobrien   arrays of unspecified length.  VAL must be a CONSTRUCTOR of an array
387790075Sobrien   type with an unspecified upper bound.  */
387890075Sobrien
387990075Sobrienstatic unsigned HOST_WIDE_INT
3880132718Skanarray_size_for_constructor (tree val)
388190075Sobrien{
388290075Sobrien  tree max_index, i;
388390075Sobrien
388490075Sobrien  /* This code used to attempt to handle string constants that are not
388590075Sobrien     arrays of single-bytes, but nothing else does, so there's no point in
388690075Sobrien     doing it here.  */
388790075Sobrien  if (TREE_CODE (val) == STRING_CST)
388890075Sobrien    return TREE_STRING_LENGTH (val);
388990075Sobrien
389090075Sobrien  max_index = NULL_TREE;
3891117395Skan  for (i = CONSTRUCTOR_ELTS (val); i; i = TREE_CHAIN (i))
389290075Sobrien    {
389390075Sobrien      tree index = TREE_PURPOSE (i);
389490075Sobrien
389590075Sobrien      if (TREE_CODE (index) == RANGE_EXPR)
389690075Sobrien	index = TREE_OPERAND (index, 1);
389790075Sobrien      if (max_index == NULL_TREE || tree_int_cst_lt (max_index, index))
389890075Sobrien	max_index = index;
389990075Sobrien    }
390090075Sobrien
390190075Sobrien  if (max_index == NULL_TREE)
390290075Sobrien    return 0;
390390075Sobrien
390490075Sobrien  /* Compute the total number of array elements.  */
390590075Sobrien  i = size_binop (MINUS_EXPR, convert (sizetype, max_index),
390690075Sobrien		  convert (sizetype,
390790075Sobrien			   TYPE_MIN_VALUE (TYPE_DOMAIN (TREE_TYPE (val)))));
390890075Sobrien  i = size_binop (PLUS_EXPR, i, convert (sizetype, integer_one_node));
390990075Sobrien
391090075Sobrien  /* Multiply by the array element unit size to find number of bytes.  */
391190075Sobrien  i = size_binop (MULT_EXPR, i, TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (val))));
391290075Sobrien
391390075Sobrien  return tree_low_cst (i, 1);
391490075Sobrien}
391590075Sobrien
391690075Sobrien/* Subroutine of output_constant, used for CONSTRUCTORs (aggregate constants).
391718334Speter   Generate at least SIZE bytes, padding if necessary.  */
391818334Speter
391918334Speterstatic void
3920132718Skanoutput_constructor (tree exp, unsigned HOST_WIDE_INT size,
3921132718Skan		    unsigned int align)
392218334Speter{
392390075Sobrien  tree type = TREE_TYPE (exp);
392490075Sobrien  tree link, field = 0;
392590075Sobrien  tree min_index = 0;
392618334Speter  /* Number of bytes output or skipped so far.
392718334Speter     In other words, current position within the constructor.  */
392890075Sobrien  HOST_WIDE_INT total_bytes = 0;
3929132718Skan  /* Nonzero means BYTE contains part of a byte, to be output.  */
393018334Speter  int byte_buffer_in_use = 0;
393190075Sobrien  int byte = 0;
393218334Speter
393318334Speter  if (HOST_BITS_PER_WIDE_INT < BITS_PER_UNIT)
393418334Speter    abort ();
393518334Speter
393690075Sobrien  if (TREE_CODE (type) == RECORD_TYPE)
393790075Sobrien    field = TYPE_FIELDS (type);
393818334Speter
393990075Sobrien  if (TREE_CODE (type) == ARRAY_TYPE
394090075Sobrien      && TYPE_DOMAIN (type) != 0)
394190075Sobrien    min_index = TYPE_MIN_VALUE (TYPE_DOMAIN (type));
394218334Speter
394318334Speter  /* As LINK goes through the elements of the constant,
394418334Speter     FIELD goes through the structure fields, if the constant is a structure.
394518334Speter     if the constant is a union, then we override this,
394618334Speter     by getting the field from the TREE_LIST element.
394752284Sobrien     But the constant could also be an array.  Then FIELD is zero.
394852284Sobrien
394952284Sobrien     There is always a maximum of one element in the chain LINK for unions
395052284Sobrien     (even if the initializer in a source program incorrectly contains
395190075Sobrien     more one).  */
395218334Speter  for (link = CONSTRUCTOR_ELTS (exp);
395318334Speter       link;
395418334Speter       link = TREE_CHAIN (link),
395518334Speter       field = field ? TREE_CHAIN (field) : 0)
395618334Speter    {
395718334Speter      tree val = TREE_VALUE (link);
395818334Speter      tree index = 0;
395918334Speter
396090075Sobrien      /* The element in a union constructor specifies the proper field
396190075Sobrien	 or index.  */
396290075Sobrien      if ((TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE
396390075Sobrien	   || TREE_CODE (type) == QUAL_UNION_TYPE)
396490075Sobrien	  && TREE_PURPOSE (link) != 0)
396590075Sobrien	field = TREE_PURPOSE (link);
396618334Speter
396790075Sobrien      else if (TREE_CODE (type) == ARRAY_TYPE)
396818334Speter	index = TREE_PURPOSE (link);
396918334Speter
3970132718Skan#ifdef ASM_COMMENT_START
3971132718Skan      if (field && flag_verbose_asm)
3972132718Skan	fprintf (asm_out_file, "%s %s:\n",
3973132718Skan		 ASM_COMMENT_START,
3974132718Skan		 DECL_NAME (field)
3975132718Skan		 ? IDENTIFIER_POINTER (DECL_NAME (field))
3976132718Skan		 : "<anonymous>");
3977132718Skan#endif
3978132718Skan
397918334Speter      /* Eliminate the marker that makes a cast not be an lvalue.  */
398018334Speter      if (val != 0)
398118334Speter	STRIP_NOPS (val);
398218334Speter
398350397Sobrien      if (index && TREE_CODE (index) == RANGE_EXPR)
398418334Speter	{
398590075Sobrien	  unsigned HOST_WIDE_INT fieldsize
398690075Sobrien	    = int_size_in_bytes (TREE_TYPE (type));
398790075Sobrien	  HOST_WIDE_INT lo_index = tree_low_cst (TREE_OPERAND (index, 0), 0);
398890075Sobrien	  HOST_WIDE_INT hi_index = tree_low_cst (TREE_OPERAND (index, 1), 0);
398950397Sobrien	  HOST_WIDE_INT index;
399090075Sobrien	  unsigned int align2 = min_align (align, fieldsize * BITS_PER_UNIT);
399190075Sobrien
399250397Sobrien	  for (index = lo_index; index <= hi_index; index++)
399350397Sobrien	    {
399450397Sobrien	      /* Output the element's initial value.  */
399550397Sobrien	      if (val == 0)
399650397Sobrien		assemble_zeros (fieldsize);
399750397Sobrien	      else
399890075Sobrien		output_constant (val, fieldsize, align2);
399950397Sobrien
400050397Sobrien	      /* Count its size.  */
400150397Sobrien	      total_bytes += fieldsize;
400250397Sobrien	    }
400350397Sobrien	}
400450397Sobrien      else if (field == 0 || !DECL_BIT_FIELD (field))
400550397Sobrien	{
400618334Speter	  /* An element that is not a bit-field.  */
400718334Speter
400890075Sobrien	  unsigned HOST_WIDE_INT fieldsize;
400918334Speter	  /* Since this structure is static,
401018334Speter	     we know the positions are constant.  */
401190075Sobrien	  HOST_WIDE_INT pos = field ? int_byte_position (field) : 0;
401290075Sobrien	  unsigned int align2;
401390075Sobrien
401418334Speter	  if (index != 0)
401590075Sobrien	    pos = (tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (val)), 1)
401690075Sobrien		   * (tree_low_cst (index, 0) - tree_low_cst (min_index, 0)));
401718334Speter
401818334Speter	  /* Output any buffered-up bit-fields preceding this element.  */
401918334Speter	  if (byte_buffer_in_use)
402018334Speter	    {
402190075Sobrien	      assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1);
402218334Speter	      total_bytes++;
402318334Speter	      byte_buffer_in_use = 0;
402418334Speter	    }
402518334Speter
402618334Speter	  /* Advance to offset of this element.
402718334Speter	     Note no alignment needed in an array, since that is guaranteed
402818334Speter	     if each element has the proper size.  */
402990075Sobrien	  if ((field != 0 || index != 0) && pos != total_bytes)
403018334Speter	    {
403190075Sobrien	      assemble_zeros (pos - total_bytes);
403290075Sobrien	      total_bytes = pos;
403318334Speter	    }
403418334Speter
403590075Sobrien	  /* Find the alignment of this element.  */
403690075Sobrien	  align2 = min_align (align, BITS_PER_UNIT * pos);
403790075Sobrien
403818334Speter	  /* Determine size this element should occupy.  */
403918334Speter	  if (field)
404018334Speter	    {
404190075Sobrien	      fieldsize = 0;
404290075Sobrien
404390075Sobrien	      /* If this is an array with an unspecified upper bound,
404490075Sobrien		 the initializer determines the size.  */
404590075Sobrien	      /* ??? This ought to only checked if DECL_SIZE_UNIT is NULL,
404690075Sobrien		 but we cannot do this until the deprecated support for
404790075Sobrien		 initializing zero-length array members is removed.  */
404890075Sobrien	      if (TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE
404990075Sobrien		  && TYPE_DOMAIN (TREE_TYPE (field))
405090075Sobrien		  && ! TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (field))))
405118334Speter		{
405290075Sobrien		  fieldsize = array_size_for_constructor (val);
405390075Sobrien		  /* Given a non-empty initialization, this field had
405490075Sobrien		     better be last.  */
405590075Sobrien		  if (fieldsize != 0 && TREE_CHAIN (field) != NULL_TREE)
405690075Sobrien		    abort ();
405718334Speter		}
405890075Sobrien	      else if (DECL_SIZE_UNIT (field))
405918334Speter		{
406090075Sobrien		  /* ??? This can't be right.  If the decl size overflows
406190075Sobrien		     a host integer we will silently emit no data.  */
406290075Sobrien		  if (host_integerp (DECL_SIZE_UNIT (field), 1))
406390075Sobrien		    fieldsize = tree_low_cst (DECL_SIZE_UNIT (field), 1);
406418334Speter		}
406518334Speter	    }
406618334Speter	  else
406790075Sobrien	    fieldsize = int_size_in_bytes (TREE_TYPE (type));
406818334Speter
406918334Speter	  /* Output the element's initial value.  */
407018334Speter	  if (val == 0)
407118334Speter	    assemble_zeros (fieldsize);
407218334Speter	  else
407390075Sobrien	    output_constant (val, fieldsize, align2);
407418334Speter
407518334Speter	  /* Count its size.  */
407618334Speter	  total_bytes += fieldsize;
407718334Speter	}
407818334Speter      else if (val != 0 && TREE_CODE (val) != INTEGER_CST)
407918334Speter	error ("invalid initial value for member `%s'",
408018334Speter	       IDENTIFIER_POINTER (DECL_NAME (field)));
408118334Speter      else
408218334Speter	{
408318334Speter	  /* Element that is a bit-field.  */
408418334Speter
408590075Sobrien	  HOST_WIDE_INT next_offset = int_bit_position (field);
408690075Sobrien	  HOST_WIDE_INT end_offset
408790075Sobrien	    = (next_offset + tree_low_cst (DECL_SIZE (field), 1));
408818334Speter
408918334Speter	  if (val == 0)
409018334Speter	    val = integer_zero_node;
409118334Speter
409218334Speter	  /* If this field does not start in this (or, next) byte,
409318334Speter	     skip some bytes.  */
409418334Speter	  if (next_offset / BITS_PER_UNIT != total_bytes)
409518334Speter	    {
409618334Speter	      /* Output remnant of any bit field in previous bytes.  */
409718334Speter	      if (byte_buffer_in_use)
409818334Speter		{
409990075Sobrien		  assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1);
410018334Speter		  total_bytes++;
410118334Speter		  byte_buffer_in_use = 0;
410218334Speter		}
410318334Speter
410418334Speter	      /* If still not at proper byte, advance to there.  */
410518334Speter	      if (next_offset / BITS_PER_UNIT != total_bytes)
410618334Speter		{
410718334Speter		  assemble_zeros (next_offset / BITS_PER_UNIT - total_bytes);
410818334Speter		  total_bytes = next_offset / BITS_PER_UNIT;
410918334Speter		}
411018334Speter	    }
411118334Speter
411218334Speter	  if (! byte_buffer_in_use)
411318334Speter	    byte = 0;
411418334Speter
411518334Speter	  /* We must split the element into pieces that fall within
411618334Speter	     separate bytes, and combine each byte with previous or
411718334Speter	     following bit-fields.  */
411818334Speter
411918334Speter	  /* next_offset is the offset n fbits from the beginning of
412018334Speter	     the structure to the next bit of this element to be processed.
412118334Speter	     end_offset is the offset of the first bit past the end of
412218334Speter	     this element.  */
412318334Speter	  while (next_offset < end_offset)
412418334Speter	    {
412518334Speter	      int this_time;
412618334Speter	      int shift;
412718334Speter	      HOST_WIDE_INT value;
412890075Sobrien	      HOST_WIDE_INT next_byte = next_offset / BITS_PER_UNIT;
412990075Sobrien	      HOST_WIDE_INT next_bit = next_offset % BITS_PER_UNIT;
413018334Speter
413118334Speter	      /* Advance from byte to byte
413218334Speter		 within this element when necessary.  */
413318334Speter	      while (next_byte != total_bytes)
413418334Speter		{
413590075Sobrien		  assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1);
413618334Speter		  total_bytes++;
413718334Speter		  byte = 0;
413818334Speter		}
413918334Speter
414018334Speter	      /* Number of bits we can process at once
414118334Speter		 (all part of the same byte).  */
414218334Speter	      this_time = MIN (end_offset - next_offset,
414318334Speter			       BITS_PER_UNIT - next_bit);
414418334Speter	      if (BYTES_BIG_ENDIAN)
414518334Speter		{
414618334Speter		  /* On big-endian machine, take the most significant bits
414718334Speter		     first (of the bits that are significant)
414818334Speter		     and put them into bytes from the most significant end.  */
414918334Speter		  shift = end_offset - next_offset - this_time;
415090075Sobrien
415118334Speter		  /* Don't try to take a bunch of bits that cross
415290075Sobrien		     the word boundary in the INTEGER_CST. We can
415390075Sobrien		     only select bits from the LOW or HIGH part
415490075Sobrien		     not from both.  */
415518334Speter		  if (shift < HOST_BITS_PER_WIDE_INT
415618334Speter		      && shift + this_time > HOST_BITS_PER_WIDE_INT)
415718334Speter		    {
415890075Sobrien		      this_time = shift + this_time - HOST_BITS_PER_WIDE_INT;
415918334Speter		      shift = HOST_BITS_PER_WIDE_INT;
416018334Speter		    }
416118334Speter
416218334Speter		  /* Now get the bits from the appropriate constant word.  */
416318334Speter		  if (shift < HOST_BITS_PER_WIDE_INT)
416490075Sobrien		    value = TREE_INT_CST_LOW (val);
416518334Speter		  else if (shift < 2 * HOST_BITS_PER_WIDE_INT)
416618334Speter		    {
416718334Speter		      value = TREE_INT_CST_HIGH (val);
416818334Speter		      shift -= HOST_BITS_PER_WIDE_INT;
416918334Speter		    }
417018334Speter		  else
417118334Speter		    abort ();
417290075Sobrien
417390075Sobrien		  /* Get the result. This works only when:
417490075Sobrien		     1 <= this_time <= HOST_BITS_PER_WIDE_INT.  */
417518334Speter		  byte |= (((value >> shift)
417690075Sobrien			    & (((HOST_WIDE_INT) 2 << (this_time - 1)) - 1))
417718334Speter			   << (BITS_PER_UNIT - this_time - next_bit));
417818334Speter		}
417918334Speter	      else
418018334Speter		{
418118334Speter		  /* On little-endian machines,
418218334Speter		     take first the least significant bits of the value
418318334Speter		     and pack them starting at the least significant
418418334Speter		     bits of the bytes.  */
418590075Sobrien		  shift = next_offset - int_bit_position (field);
418690075Sobrien
418718334Speter		  /* Don't try to take a bunch of bits that cross
418890075Sobrien		     the word boundary in the INTEGER_CST. We can
418990075Sobrien		     only select bits from the LOW or HIGH part
419090075Sobrien		     not from both.  */
419118334Speter		  if (shift < HOST_BITS_PER_WIDE_INT
419218334Speter		      && shift + this_time > HOST_BITS_PER_WIDE_INT)
419390075Sobrien		    this_time = (HOST_BITS_PER_WIDE_INT - shift);
419418334Speter
419518334Speter		  /* Now get the bits from the appropriate constant word.  */
419650397Sobrien		  if (shift < HOST_BITS_PER_WIDE_INT)
419718334Speter		    value = TREE_INT_CST_LOW (val);
419818334Speter		  else if (shift < 2 * HOST_BITS_PER_WIDE_INT)
419918334Speter		    {
420018334Speter		      value = TREE_INT_CST_HIGH (val);
420118334Speter		      shift -= HOST_BITS_PER_WIDE_INT;
420218334Speter		    }
420318334Speter		  else
420418334Speter		    abort ();
420590075Sobrien
420690075Sobrien		  /* Get the result. This works only when:
420790075Sobrien		     1 <= this_time <= HOST_BITS_PER_WIDE_INT.  */
420818334Speter		  byte |= (((value >> shift)
420990075Sobrien			    & (((HOST_WIDE_INT) 2 << (this_time - 1)) - 1))
421018334Speter			   << next_bit);
421118334Speter		}
421290075Sobrien
421318334Speter	      next_offset += this_time;
421418334Speter	      byte_buffer_in_use = 1;
421518334Speter	    }
421618334Speter	}
421718334Speter    }
421890075Sobrien
421918334Speter  if (byte_buffer_in_use)
422018334Speter    {
422190075Sobrien      assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1);
422218334Speter      total_bytes++;
422318334Speter    }
422490075Sobrien
4225132718Skan  if ((unsigned HOST_WIDE_INT)total_bytes < size)
422618334Speter    assemble_zeros (size - total_bytes);
422718334Speter}
422818334Speter
422996263Sobrien/* This TREE_LIST contains any weak symbol declarations waiting
423096263Sobrien   to be emitted.  */
4231117395Skanstatic GTY(()) tree weak_decls;
423290075Sobrien
423396263Sobrien/* Mark DECL as weak.  */
423496263Sobrien
423596263Sobrienstatic void
4236132718Skanmark_weak (tree decl)
423790075Sobrien{
423896263Sobrien  DECL_WEAK (decl) = 1;
423990075Sobrien
424096263Sobrien  if (DECL_RTL_SET_P (decl)
424196263Sobrien      && GET_CODE (DECL_RTL (decl)) == MEM
424296263Sobrien      && XEXP (DECL_RTL (decl), 0)
424396263Sobrien      && GET_CODE (XEXP (DECL_RTL (decl), 0)) == SYMBOL_REF)
424496263Sobrien    SYMBOL_REF_WEAK (XEXP (DECL_RTL (decl), 0)) = 1;
424596263Sobrien}
4246117395Skan
424796263Sobrien/* Merge weak status between NEWDECL and OLDDECL.  */
424890075Sobrien
424996263Sobrienvoid
4250132718Skanmerge_weak (tree newdecl, tree olddecl)
425118334Speter{
425296263Sobrien  if (DECL_WEAK (newdecl) == DECL_WEAK (olddecl))
425396263Sobrien    return;
425418334Speter
425596263Sobrien  if (DECL_WEAK (newdecl))
425696263Sobrien    {
425796263Sobrien      tree wd;
4258117395Skan
425996263Sobrien      /* NEWDECL is weak, but OLDDECL is not.  */
426018334Speter
426196263Sobrien      /* If we already output the OLDDECL, we're in trouble; we can't
426296263Sobrien	 go back and make it weak.  This error cannot caught in
426396263Sobrien	 declare_weak because the NEWDECL and OLDDECL was not yet
426496263Sobrien	 been merged; therefore, TREE_ASM_WRITTEN was not set.  */
4265102780Skan      if (TREE_ASM_WRITTEN (olddecl))
4266132718Skan	error ("%Jweak declaration of '%D' must precede definition",
4267132718Skan	       newdecl, newdecl);
4268102780Skan
4269102780Skan      /* If we've already generated rtl referencing OLDDECL, we may
4270102780Skan	 have done so in a way that will not function properly with
4271102780Skan	 a weak symbol.  */
4272102780Skan      else if (TREE_USED (olddecl)
4273102780Skan	       && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (olddecl)))
4274132718Skan	warning ("%Jweak declaration of '%D' after first use results "
4275132718Skan                 "in unspecified behavior", newdecl, newdecl);
4276102780Skan
427796263Sobrien      if (SUPPORTS_WEAK)
427896263Sobrien	{
427996263Sobrien	  /* We put the NEWDECL on the weak_decls list at some point.
428096263Sobrien	     Replace it with the OLDDECL.  */
428196263Sobrien	  for (wd = weak_decls; wd; wd = TREE_CHAIN (wd))
428296263Sobrien	    if (TREE_VALUE (wd) == newdecl)
428396263Sobrien	      {
428496263Sobrien		TREE_VALUE (wd) = olddecl;
428596263Sobrien		break;
428696263Sobrien	      }
428796263Sobrien	  /* We may not find the entry on the list.  If NEWDECL is a
428896263Sobrien	     weak alias, then we will have already called
428996263Sobrien	     globalize_decl to remove the entry; in that case, we do
429096263Sobrien	     not need to do anything.  */
429196263Sobrien	}
429252284Sobrien
429396263Sobrien      /* Make the OLDDECL weak; it's OLDDECL that we'll be keeping.  */
429496263Sobrien      mark_weak (olddecl);
429596263Sobrien    }
429696263Sobrien  else
429796263Sobrien    /* OLDDECL was weak, but NEWDECL was not explicitly marked as
429896263Sobrien       weak.  Just update NEWDECL to indicate that it's weak too.  */
429996263Sobrien    mark_weak (newdecl);
430052284Sobrien}
430118334Speter
430218334Speter/* Declare DECL to be a weak symbol.  */
430318334Speter
430418334Spetervoid
4305132718Skandeclare_weak (tree decl)
430618334Speter{
430718334Speter  if (! TREE_PUBLIC (decl))
4308132718Skan    error ("%Jweak declaration of '%D' must be public", decl, decl);
430996263Sobrien  else if (TREE_CODE (decl) == FUNCTION_DECL && TREE_ASM_WRITTEN (decl))
4310132718Skan    error ("%Jweak declaration of '%D' must precede definition", decl, decl);
431118334Speter  else if (SUPPORTS_WEAK)
431296263Sobrien    {
431396263Sobrien      if (! DECL_WEAK (decl))
431496263Sobrien	weak_decls = tree_cons (NULL, decl, weak_decls);
431596263Sobrien    }
431690075Sobrien  else
4317132718Skan    warning ("%Jweak declaration of '%D' not supported", decl, decl);
431890075Sobrien
431996263Sobrien  mark_weak (decl);
432018334Speter}
432118334Speter
432218334Speter/* Emit any pending weak declarations.  */
432318334Speter
432418334Spetervoid
4325132718Skanweak_finish (void)
432618334Speter{
432796263Sobrien  tree t;
432896263Sobrien
4329117395Skan  for (t = weak_decls; t; t = TREE_CHAIN (t))
433018334Speter    {
433196263Sobrien      tree decl = TREE_VALUE (t);
4332132718Skan#if defined (ASM_WEAKEN_DECL) || defined (ASM_WEAKEN_LABEL)
4333132718Skan      const char *const name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
4334132718Skan#endif
433596263Sobrien
433696263Sobrien      if (! TREE_USED (decl))
433796263Sobrien	continue;
433896263Sobrien
433996263Sobrien#ifdef ASM_WEAKEN_DECL
434096263Sobrien      ASM_WEAKEN_DECL (asm_out_file, decl, name, NULL);
434190075Sobrien#else
434290075Sobrien#ifdef ASM_WEAKEN_LABEL
434396263Sobrien      ASM_WEAKEN_LABEL (asm_out_file, name);
434496263Sobrien#else
434596263Sobrien#ifdef ASM_OUTPUT_WEAK_ALIAS
434696263Sobrien      warning ("only weak aliases are supported in this configuration");
434796263Sobrien      return;
434890075Sobrien#endif
434990075Sobrien#endif
435096263Sobrien#endif
435118334Speter    }
435218334Speter}
435318334Speter
435496263Sobrien/* Emit the assembly bits to indicate that DECL is globally visible.  */
435596263Sobrien
435652284Sobrienstatic void
4357132718Skanglobalize_decl (tree decl)
435852284Sobrien{
435996263Sobrien  const char *name = XSTR (XEXP (DECL_RTL (decl), 0), 0);
436090075Sobrien
436196263Sobrien#if defined (ASM_WEAKEN_LABEL) || defined (ASM_WEAKEN_DECL)
436296263Sobrien  if (DECL_WEAK (decl))
436352284Sobrien    {
436496263Sobrien      tree *p, t;
436596263Sobrien
436696263Sobrien#ifdef ASM_WEAKEN_DECL
436796263Sobrien      ASM_WEAKEN_DECL (asm_out_file, decl, name, 0);
436896263Sobrien#else
436996263Sobrien      ASM_WEAKEN_LABEL (asm_out_file, name);
437096263Sobrien#endif
437196263Sobrien
437296263Sobrien      /* Remove this function from the pending weak list so that
437396263Sobrien	 we do not emit multiple .weak directives for it.  */
437496263Sobrien      for (p = &weak_decls; (t = *p) ; )
437596263Sobrien	{
437696263Sobrien	  if (DECL_ASSEMBLER_NAME (decl) == DECL_ASSEMBLER_NAME (TREE_VALUE (t)))
437796263Sobrien	    *p = TREE_CHAIN (t);
437896263Sobrien	  else
437996263Sobrien	    p = &TREE_CHAIN (t);
438096263Sobrien	}
438196263Sobrien      return;
438252284Sobrien    }
438396263Sobrien#endif
438496263Sobrien
4385117395Skan  (*targetm.asm_out.globalize_label) (asm_out_file, name);
438652284Sobrien}
438752284Sobrien
438890075Sobrien/* Emit an assembler directive to make the symbol for DECL an alias to
438990075Sobrien   the symbol for TARGET.  */
439090075Sobrien
439118334Spetervoid
4392132718Skanassemble_alias (tree decl, tree target ATTRIBUTE_UNUSED)
439318334Speter{
439490075Sobrien  const char *name;
439518334Speter
439690075Sobrien  /* We must force creation of DECL_RTL for debug info generation, even though
439790075Sobrien     we don't use it here.  */
439890075Sobrien  make_decl_rtl (decl, NULL);
439918334Speter
440090075Sobrien  name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
440190075Sobrien
440250397Sobrien#ifdef ASM_OUTPUT_DEF
440318334Speter  /* Make name accessible from other files, if appropriate.  */
4404117395Skan
440518334Speter  if (TREE_PUBLIC (decl))
4406117395Skan    {
4407117395Skan      globalize_decl (decl);
4408117395Skan      maybe_assemble_visibility (decl);
4409117395Skan    }
441018334Speter
441190075Sobrien#ifdef ASM_OUTPUT_DEF_FROM_DECLS
441290075Sobrien  ASM_OUTPUT_DEF_FROM_DECLS (asm_out_file, decl, target);
441390075Sobrien#else
441418334Speter  ASM_OUTPUT_DEF (asm_out_file, name, IDENTIFIER_POINTER (target));
441590075Sobrien#endif
441696263Sobrien#else /* !ASM_OUTPUT_DEF */
441796263Sobrien#if defined (ASM_OUTPUT_WEAK_ALIAS) || defined (ASM_WEAKEN_DECL)
4418132718Skan  if (DECL_WEAK (decl))
4419132718Skan    {
4420132718Skan      tree *p, t;
442196263Sobrien#ifdef ASM_WEAKEN_DECL
4422132718Skan      ASM_WEAKEN_DECL (asm_out_file, decl, name, IDENTIFIER_POINTER (target));
442396263Sobrien#else
4424132718Skan      ASM_OUTPUT_WEAK_ALIAS (asm_out_file, name, IDENTIFIER_POINTER (target));
442596263Sobrien#endif
4426132718Skan      /* Remove this function from the pending weak list so that
4427132718Skan	 we do not emit multiple .weak directives for it.  */
4428132718Skan      for (p = &weak_decls; (t = *p) ; )
4429132718Skan	if (DECL_ASSEMBLER_NAME (decl)
4430132718Skan	    == DECL_ASSEMBLER_NAME (TREE_VALUE (t)))
4431132718Skan	  *p = TREE_CHAIN (t);
4432132718Skan	else
4433132718Skan	  p = &TREE_CHAIN (t);
4434132718Skan    }
4435132718Skan  else
4436132718Skan    warning ("only weak aliases are supported in this configuration");
4437132718Skan
443850397Sobrien#else
443950397Sobrien  warning ("alias definitions not supported in this configuration; ignored");
444018334Speter#endif
444150397Sobrien#endif
4442102780Skan
4443102780Skan  TREE_USED (decl) = 1;
4444102780Skan  TREE_ASM_WRITTEN (decl) = 1;
4445102780Skan  TREE_ASM_WRITTEN (DECL_ASSEMBLER_NAME (decl)) = 1;
444618334Speter}
444750397Sobrien
4448117395Skan/* Emit an assembler directive to set symbol for DECL visibility to
4449117395Skan   the visibility type VIS, which must not be VISIBILITY_DEFAULT.  */
4450117395Skan
4451117395Skanvoid
4452132718Skandefault_assemble_visibility (tree decl, int vis)
4453117395Skan{
4454117395Skan  static const char * const visibility_types[] = {
4455117395Skan    NULL, "internal", "hidden", "protected"
4456117395Skan  };
4457117395Skan
4458117395Skan  const char *name, *type;
4459117395Skan
4460117395Skan  name = (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
4461117395Skan  type = visibility_types[vis];
4462117395Skan
4463117395Skan#ifdef HAVE_GAS_HIDDEN
4464117395Skan  fprintf (asm_out_file, "\t.%s\t", type);
4465117395Skan  assemble_name (asm_out_file, name);
4466117395Skan  fprintf (asm_out_file, "\n");
4467117395Skan#else
4468117395Skan  warning ("visibility attribute not supported in this configuration; ignored");
4469117395Skan#endif
4470117395Skan}
4471117395Skan
4472117395Skan/* A helper function to call assemble_visibility when needed for a decl.  */
4473117395Skan
4474117395Skanstatic void
4475132718Skanmaybe_assemble_visibility (tree decl)
4476117395Skan{
4477132718Skan  enum symbol_visibility vis = DECL_VISIBILITY (decl);
4478117395Skan
4479117395Skan  if (vis != VISIBILITY_DEFAULT)
4480117395Skan    (* targetm.asm_out.visibility) (decl, vis);
4481117395Skan}
4482117395Skan
448350397Sobrien/* Returns 1 if the target configuration supports defining public symbols
448450397Sobrien   so that one of them will be chosen at link time instead of generating a
448550397Sobrien   multiply-defined symbol error, whether through the use of weak symbols or
448650397Sobrien   a target-specific mechanism for having duplicates discarded.  */
448750397Sobrien
448850397Sobrienint
4489132718Skansupports_one_only (void)
449050397Sobrien{
449150397Sobrien  if (SUPPORTS_ONE_ONLY)
449250397Sobrien    return 1;
449350397Sobrien  return SUPPORTS_WEAK;
449450397Sobrien}
449550397Sobrien
449650397Sobrien/* Set up DECL as a public symbol that can be defined in multiple
449750397Sobrien   translation units without generating a linker error.  */
449850397Sobrien
449950397Sobrienvoid
4500132718Skanmake_decl_one_only (tree decl)
450150397Sobrien{
450250397Sobrien  if (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != FUNCTION_DECL)
450350397Sobrien    abort ();
450450397Sobrien
450550397Sobrien  TREE_PUBLIC (decl) = 1;
450650397Sobrien
4507132718Skan  if (SUPPORTS_ONE_ONLY)
450850397Sobrien    {
450950397Sobrien#ifdef MAKE_DECL_ONE_ONLY
451050397Sobrien      MAKE_DECL_ONE_ONLY (decl);
451150397Sobrien#endif
451250397Sobrien      DECL_ONE_ONLY (decl) = 1;
451350397Sobrien    }
4514132718Skan  else if (TREE_CODE (decl) == VAR_DECL
4515132718Skan      && (DECL_INITIAL (decl) == 0 || DECL_INITIAL (decl) == error_mark_node))
4516132718Skan    DECL_COMMON (decl) = 1;
451750397Sobrien  else if (SUPPORTS_WEAK)
451850397Sobrien    DECL_WEAK (decl) = 1;
451950397Sobrien  else
452050397Sobrien    abort ();
452150397Sobrien}
452290075Sobrien
452390075Sobrienvoid
4524132718Skaninit_varasm_once (void)
452590075Sobrien{
4526132718Skan  in_named_htab = htab_create_ggc (31, in_named_entry_hash,
4527132718Skan				   in_named_entry_eq, NULL);
4528132718Skan  const_desc_htab = htab_create_ggc (1009, const_desc_hash,
4529132718Skan				     const_desc_eq, NULL);
453090075Sobrien
453190075Sobrien  const_alias_set = new_alias_set ();
453290075Sobrien}
453390075Sobrien
4534117395Skanenum tls_model
4535132718Skandecl_tls_model (tree decl)
4536117395Skan{
4537117395Skan  enum tls_model kind;
4538117395Skan  tree attr = lookup_attribute ("tls_model", DECL_ATTRIBUTES (decl));
4539117395Skan  bool is_local;
4540117395Skan
4541117395Skan  if (attr)
4542117395Skan    {
4543117395Skan      attr = TREE_VALUE (TREE_VALUE (attr));
4544117395Skan      if (TREE_CODE (attr) != STRING_CST)
4545117395Skan	abort ();
4546117395Skan      if (!strcmp (TREE_STRING_POINTER (attr), "local-exec"))
4547117395Skan	kind = TLS_MODEL_LOCAL_EXEC;
4548117395Skan      else if (!strcmp (TREE_STRING_POINTER (attr), "initial-exec"))
4549117395Skan	kind = TLS_MODEL_INITIAL_EXEC;
4550117395Skan      else if (!strcmp (TREE_STRING_POINTER (attr), "local-dynamic"))
4551117395Skan	kind = optimize ? TLS_MODEL_LOCAL_DYNAMIC : TLS_MODEL_GLOBAL_DYNAMIC;
4552117395Skan      else if (!strcmp (TREE_STRING_POINTER (attr), "global-dynamic"))
4553117395Skan	kind = TLS_MODEL_GLOBAL_DYNAMIC;
4554117395Skan      else
4555117395Skan	abort ();
4556117395Skan      return kind;
4557117395Skan    }
4558117395Skan
4559117395Skan  is_local = (*targetm.binds_local_p) (decl);
4560117395Skan  if (!flag_pic)
4561117395Skan    {
4562117395Skan      if (is_local)
4563117395Skan	kind = TLS_MODEL_LOCAL_EXEC;
4564117395Skan      else
4565117395Skan	kind = TLS_MODEL_INITIAL_EXEC;
4566117395Skan    }
4567117395Skan  /* Local dynamic is inefficient when we're not combining the
4568117395Skan     parts of the address.  */
4569117395Skan  else if (optimize && is_local)
4570117395Skan    kind = TLS_MODEL_LOCAL_DYNAMIC;
4571117395Skan  else
4572117395Skan    kind = TLS_MODEL_GLOBAL_DYNAMIC;
4573117395Skan  if (kind < flag_tls_default)
4574117395Skan    kind = flag_tls_default;
4575117395Skan
4576117395Skan  return kind;
4577117395Skan}
4578117395Skan
457990075Sobrien/* Select a set of attributes for section NAME based on the properties
458090075Sobrien   of DECL and whether or not RELOC indicates that DECL's initializer
458190075Sobrien   might contain runtime relocations.
458290075Sobrien
458390075Sobrien   We make the section read-only and executable for a function decl,
458490075Sobrien   read-only for a const data decl, and writable for a non-const data decl.  */
458590075Sobrien
458690075Sobrienunsigned int
4587132718Skandefault_section_type_flags (tree decl, const char *name, int reloc)
458890075Sobrien{
4589117395Skan  return default_section_type_flags_1 (decl, name, reloc, flag_pic);
4590117395Skan}
4591117395Skan
4592117395Skanunsigned int
4593132718Skandefault_section_type_flags_1 (tree decl, const char *name, int reloc,
4594132718Skan			      int shlib)
4595117395Skan{
459690075Sobrien  unsigned int flags;
459790075Sobrien
459890075Sobrien  if (decl && TREE_CODE (decl) == FUNCTION_DECL)
459990075Sobrien    flags = SECTION_CODE;
4600117395Skan  else if (decl && decl_readonly_section_1 (decl, reloc, shlib))
460190075Sobrien    flags = 0;
460290075Sobrien  else
460390075Sobrien    flags = SECTION_WRITE;
460490075Sobrien
460590075Sobrien  if (decl && DECL_ONE_ONLY (decl))
460690075Sobrien    flags |= SECTION_LINKONCE;
460790075Sobrien
4608117395Skan  if (decl && TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL (decl))
4609117395Skan    flags |= SECTION_TLS | SECTION_WRITE;
4610117395Skan
461190075Sobrien  if (strcmp (name, ".bss") == 0
461290075Sobrien      || strncmp (name, ".bss.", 5) == 0
461390075Sobrien      || strncmp (name, ".gnu.linkonce.b.", 16) == 0
461490075Sobrien      || strcmp (name, ".sbss") == 0
461590075Sobrien      || strncmp (name, ".sbss.", 6) == 0
4616117395Skan      || strncmp (name, ".gnu.linkonce.sb.", 17) == 0
4617117395Skan      || strcmp (name, ".tbss") == 0
4618117395Skan      || strncmp (name, ".gnu.linkonce.tb.", 17) == 0)
461990075Sobrien    flags |= SECTION_BSS;
462090075Sobrien
4621117395Skan  if (strcmp (name, ".tdata") == 0
4622117395Skan      || strcmp (name, ".tbss") == 0
4623117395Skan      || strncmp (name, ".gnu.linkonce.td.", 17) == 0
4624117395Skan      || strncmp (name, ".gnu.linkonce.tb.", 17) == 0)
4625117395Skan    flags |= SECTION_TLS;
4626117395Skan
4627117395Skan  /* These three sections have special ELF types.  They are neither
4628117395Skan     SHT_PROGBITS nor SHT_NOBITS, so when changing sections we don't
4629117395Skan     want to print a section type (@progbits or @nobits).  If someone
4630117395Skan     is silly enough to emit code or TLS variables to one of these
4631117395Skan     sections, then don't handle them specially.  */
4632117395Skan  if (!(flags & (SECTION_CODE | SECTION_BSS | SECTION_TLS))
4633117395Skan      && (strcmp (name, ".init_array") == 0
4634117395Skan	  || strcmp (name, ".fini_array") == 0
4635117395Skan	  || strcmp (name, ".preinit_array") == 0))
4636117395Skan    flags |= SECTION_NOTYPE;
4637117395Skan
463890075Sobrien  return flags;
463990075Sobrien}
464090075Sobrien
464190075Sobrien/* Output assembly to switch to section NAME with attribute FLAGS.
464290075Sobrien   Four variants for common object file formats.  */
464390075Sobrien
464490075Sobrienvoid
4645132718Skandefault_no_named_section (const char *name ATTRIBUTE_UNUSED,
4646132718Skan			  unsigned int flags ATTRIBUTE_UNUSED)
464790075Sobrien{
464890075Sobrien  /* Some object formats don't support named sections at all.  The
464990075Sobrien     front-end should already have flagged this as an error.  */
465090075Sobrien  abort ();
465190075Sobrien}
465290075Sobrien
465390075Sobrienvoid
4654132718Skandefault_elf_asm_named_section (const char *name, unsigned int flags)
465590075Sobrien{
465690075Sobrien  char flagchars[10], *f = flagchars;
465790075Sobrien
465890075Sobrien  if (! named_section_first_declaration (name))
465990075Sobrien    {
466090075Sobrien      fprintf (asm_out_file, "\t.section\t%s\n", name);
466190075Sobrien      return;
466290075Sobrien    }
466390075Sobrien
466490075Sobrien  if (!(flags & SECTION_DEBUG))
466590075Sobrien    *f++ = 'a';
466690075Sobrien  if (flags & SECTION_WRITE)
466790075Sobrien    *f++ = 'w';
466890075Sobrien  if (flags & SECTION_CODE)
466990075Sobrien    *f++ = 'x';
467090075Sobrien  if (flags & SECTION_SMALL)
467190075Sobrien    *f++ = 's';
467290075Sobrien  if (flags & SECTION_MERGE)
467390075Sobrien    *f++ = 'M';
467490075Sobrien  if (flags & SECTION_STRINGS)
467590075Sobrien    *f++ = 'S';
4676117395Skan  if (flags & SECTION_TLS)
4677117395Skan    *f++ = 'T';
467890075Sobrien  *f = '\0';
467990075Sobrien
4680117395Skan  fprintf (asm_out_file, "\t.section\t%s,\"%s\"", name, flagchars);
468190075Sobrien
4682117395Skan  if (!(flags & SECTION_NOTYPE))
4683117395Skan    {
4684117395Skan      const char *type;
4685117395Skan
4686117395Skan      if (flags & SECTION_BSS)
4687117395Skan	type = "nobits";
4688117395Skan      else
4689117395Skan	type = "progbits";
4690117395Skan
4691117395Skan      fprintf (asm_out_file, ",@%s", type);
4692117395Skan
4693117395Skan      if (flags & SECTION_ENTSIZE)
4694117395Skan	fprintf (asm_out_file, ",%d", flags & SECTION_ENTSIZE);
4695117395Skan    }
4696117395Skan
4697117395Skan  putc ('\n', asm_out_file);
469890075Sobrien}
469990075Sobrien
470090075Sobrienvoid
4701132718Skandefault_coff_asm_named_section (const char *name, unsigned int flags)
470290075Sobrien{
470390075Sobrien  char flagchars[8], *f = flagchars;
470490075Sobrien
470590075Sobrien  if (flags & SECTION_WRITE)
470690075Sobrien    *f++ = 'w';
470790075Sobrien  if (flags & SECTION_CODE)
470890075Sobrien    *f++ = 'x';
470990075Sobrien  *f = '\0';
471090075Sobrien
471190075Sobrien  fprintf (asm_out_file, "\t.section\t%s,\"%s\"\n", name, flagchars);
471290075Sobrien}
471390075Sobrien
471490075Sobrienvoid
4715132718Skandefault_pe_asm_named_section (const char *name, unsigned int flags)
471690075Sobrien{
471790075Sobrien  default_coff_asm_named_section (name, flags);
471890075Sobrien
471990075Sobrien  if (flags & SECTION_LINKONCE)
472090075Sobrien    {
472190075Sobrien      /* Functions may have been compiled at various levels of
472290075Sobrien         optimization so we can't use `same_size' here.
472390075Sobrien         Instead, have the linker pick one.  */
472490075Sobrien      fprintf (asm_out_file, "\t.linkonce %s\n",
472590075Sobrien	       (flags & SECTION_CODE ? "discard" : "same_size"));
472690075Sobrien    }
472790075Sobrien}
472890075Sobrien
4729117395Skan/* The lame default section selector.  */
4730117395Skan
4731117395Skanvoid
4732132718Skandefault_select_section (tree decl, int reloc,
4733132718Skan			unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
4734117395Skan{
4735117395Skan  bool readonly = false;
4736117395Skan
4737117395Skan  if (DECL_P (decl))
4738117395Skan    {
4739117395Skan      if (decl_readonly_section (decl, reloc))
4740117395Skan	readonly = true;
4741117395Skan    }
4742117395Skan  else if (TREE_CODE (decl) == CONSTRUCTOR)
4743117395Skan    {
4744117395Skan      if (! ((flag_pic && reloc)
4745117395Skan	     || !TREE_READONLY (decl)
4746117395Skan	     || TREE_SIDE_EFFECTS (decl)
4747117395Skan	     || !TREE_CONSTANT (decl)))
4748117395Skan	readonly = true;
4749117395Skan    }
4750117395Skan  else if (TREE_CODE (decl) == STRING_CST)
4751117395Skan    readonly = !flag_writable_strings;
4752117395Skan  else if (! (flag_pic && reloc))
4753117395Skan    readonly = true;
4754117395Skan
4755117395Skan  if (readonly)
4756117395Skan    readonly_data_section ();
4757117395Skan  else
4758117395Skan    data_section ();
4759117395Skan}
4760117395Skan
4761117395Skan/* A helper function for default_elf_select_section and
4762117395Skan   default_elf_unique_section.  Categorizes the DECL.  */
4763117395Skan
4764117395Skanenum section_category
4765117395Skan{
4766117395Skan  SECCAT_TEXT,
4767117395Skan
4768117395Skan  SECCAT_RODATA,
4769117395Skan  SECCAT_RODATA_MERGE_STR,
4770117395Skan  SECCAT_RODATA_MERGE_STR_INIT,
4771117395Skan  SECCAT_RODATA_MERGE_CONST,
4772117395Skan  SECCAT_SRODATA,
4773117395Skan
4774117395Skan  SECCAT_DATA,
4775117395Skan
4776117395Skan  /* To optimize loading of shared programs, define following subsections
4777117395Skan     of data section:
4778117395Skan	_REL	Contains data that has relocations, so they get grouped
4779117395Skan		together and dynamic linker will visit fewer pages in memory.
4780117395Skan	_RO	Contains data that is otherwise read-only.  This is useful
4781117395Skan		with prelinking as most relocations won't be dynamically
4782117395Skan		linked and thus stay read only.
4783117395Skan	_LOCAL	Marks data containing relocations only to local objects.
4784117395Skan		These relocations will get fully resolved by prelinking.  */
4785117395Skan  SECCAT_DATA_REL,
4786117395Skan  SECCAT_DATA_REL_LOCAL,
4787117395Skan  SECCAT_DATA_REL_RO,
4788117395Skan  SECCAT_DATA_REL_RO_LOCAL,
4789117395Skan
4790117395Skan  SECCAT_SDATA,
4791117395Skan  SECCAT_TDATA,
4792117395Skan
4793117395Skan  SECCAT_BSS,
4794117395Skan  SECCAT_SBSS,
4795117395Skan  SECCAT_TBSS
4796117395Skan};
4797117395Skan
4798117395Skanstatic enum section_category
4799132718Skancategorize_decl_for_section (tree, int, int);
4800117395Skan
4801117395Skanstatic enum section_category
4802132718Skancategorize_decl_for_section (tree decl, int reloc, int shlib)
4803117395Skan{
4804117395Skan  enum section_category ret;
4805117395Skan
4806117395Skan  if (TREE_CODE (decl) == FUNCTION_DECL)
4807117395Skan    return SECCAT_TEXT;
4808117395Skan  else if (TREE_CODE (decl) == STRING_CST)
4809117395Skan    {
4810117395Skan      if (flag_writable_strings)
4811117395Skan	return SECCAT_DATA;
4812117395Skan      else
4813117395Skan	return SECCAT_RODATA_MERGE_STR;
4814117395Skan    }
4815117395Skan  else if (TREE_CODE (decl) == VAR_DECL)
4816117395Skan    {
4817117395Skan      if (DECL_INITIAL (decl) == NULL
4818117395Skan	  || DECL_INITIAL (decl) == error_mark_node)
4819117395Skan	ret = SECCAT_BSS;
4820117395Skan      else if (! TREE_READONLY (decl)
4821117395Skan	       || TREE_SIDE_EFFECTS (decl)
4822117395Skan	       || ! TREE_CONSTANT (DECL_INITIAL (decl)))
4823117395Skan	{
4824117395Skan	  if (shlib && (reloc & 2))
4825117395Skan	    ret = SECCAT_DATA_REL;
4826117395Skan	  else if (shlib && reloc)
4827117395Skan	    ret = SECCAT_DATA_REL_LOCAL;
4828117395Skan	  else
4829117395Skan	    ret = SECCAT_DATA;
4830117395Skan	}
4831117395Skan      else if (shlib && (reloc & 2))
4832117395Skan	ret = SECCAT_DATA_REL_RO;
4833117395Skan      else if (shlib && reloc)
4834117395Skan	ret = SECCAT_DATA_REL_RO_LOCAL;
4835117395Skan      else if (reloc || flag_merge_constants < 2)
4836117395Skan	/* C and C++ don't allow different variables to share the same
4837117395Skan	   location.  -fmerge-all-constants allows even that (at the
4838117395Skan	   expense of not conforming).  */
4839117395Skan	ret = SECCAT_RODATA;
4840117395Skan      else if (TREE_CODE (DECL_INITIAL (decl)) == STRING_CST)
4841117395Skan	ret = SECCAT_RODATA_MERGE_STR_INIT;
4842117395Skan      else
4843117395Skan	ret = SECCAT_RODATA_MERGE_CONST;
4844117395Skan    }
4845117395Skan  else if (TREE_CODE (decl) == CONSTRUCTOR)
4846117395Skan    {
4847117395Skan      if ((shlib && reloc)
4848117395Skan	  || TREE_SIDE_EFFECTS (decl)
4849117395Skan	  || ! TREE_CONSTANT (decl))
4850117395Skan	ret = SECCAT_DATA;
4851117395Skan      else
4852117395Skan	ret = SECCAT_RODATA;
4853117395Skan    }
4854117395Skan  else
4855117395Skan    ret = SECCAT_RODATA;
4856117395Skan
4857117395Skan  /* There are no read-only thread-local sections.  */
4858117395Skan  if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL (decl))
4859117395Skan    {
4860117395Skan      if (ret == SECCAT_BSS)
4861117395Skan	ret = SECCAT_TBSS;
4862117395Skan      else
4863117395Skan	ret = SECCAT_TDATA;
4864117395Skan    }
4865117395Skan
4866117395Skan  /* If the target uses small data sections, select it.  */
4867117395Skan  else if ((*targetm.in_small_data_p) (decl))
4868117395Skan    {
4869117395Skan      if (ret == SECCAT_BSS)
4870117395Skan	ret = SECCAT_SBSS;
4871117395Skan      else if (targetm.have_srodata_section && ret == SECCAT_RODATA)
4872117395Skan	ret = SECCAT_SRODATA;
4873117395Skan      else
4874117395Skan	ret = SECCAT_SDATA;
4875117395Skan    }
4876117395Skan
4877117395Skan  return ret;
4878117395Skan}
4879117395Skan
4880117395Skanbool
4881132718Skandecl_readonly_section (tree decl, int reloc)
4882117395Skan{
4883117395Skan  return decl_readonly_section_1 (decl, reloc, flag_pic);
4884117395Skan}
4885117395Skan
4886117395Skanbool
4887132718Skandecl_readonly_section_1 (tree decl, int reloc, int shlib)
4888117395Skan{
4889117395Skan  switch (categorize_decl_for_section (decl, reloc, shlib))
4890117395Skan    {
4891117395Skan    case SECCAT_RODATA:
4892117395Skan    case SECCAT_RODATA_MERGE_STR:
4893117395Skan    case SECCAT_RODATA_MERGE_STR_INIT:
4894117395Skan    case SECCAT_RODATA_MERGE_CONST:
4895117395Skan    case SECCAT_SRODATA:
4896117395Skan      return true;
4897117395Skan      break;
4898117395Skan    default:
4899117395Skan      return false;
4900117395Skan      break;
4901117395Skan    }
4902117395Skan}
4903117395Skan
4904117395Skan/* Select a section based on the above categorization.  */
4905117395Skan
4906117395Skanvoid
4907132718Skandefault_elf_select_section (tree decl, int reloc,
4908132718Skan			    unsigned HOST_WIDE_INT align)
4909117395Skan{
4910117395Skan  default_elf_select_section_1 (decl, reloc, align, flag_pic);
4911117395Skan}
4912117395Skan
4913117395Skanvoid
4914132718Skandefault_elf_select_section_1 (tree decl, int reloc,
4915132718Skan			      unsigned HOST_WIDE_INT align, int shlib)
4916117395Skan{
4917117395Skan  switch (categorize_decl_for_section (decl, reloc, shlib))
4918117395Skan    {
4919117395Skan    case SECCAT_TEXT:
4920117395Skan      /* We're not supposed to be called on FUNCTION_DECLs.  */
4921117395Skan      abort ();
4922117395Skan    case SECCAT_RODATA:
4923117395Skan      readonly_data_section ();
4924117395Skan      break;
4925117395Skan    case SECCAT_RODATA_MERGE_STR:
4926117395Skan      mergeable_string_section (decl, align, 0);
4927117395Skan      break;
4928117395Skan    case SECCAT_RODATA_MERGE_STR_INIT:
4929117395Skan      mergeable_string_section (DECL_INITIAL (decl), align, 0);
4930117395Skan      break;
4931117395Skan    case SECCAT_RODATA_MERGE_CONST:
4932117395Skan      mergeable_constant_section (DECL_MODE (decl), align, 0);
4933117395Skan      break;
4934117395Skan    case SECCAT_SRODATA:
4935117395Skan      named_section (NULL_TREE, ".sdata2", reloc);
4936117395Skan      break;
4937117395Skan    case SECCAT_DATA:
4938117395Skan      data_section ();
4939117395Skan      break;
4940117395Skan    case SECCAT_DATA_REL:
4941117395Skan      named_section (NULL_TREE, ".data.rel", reloc);
4942117395Skan      break;
4943117395Skan    case SECCAT_DATA_REL_LOCAL:
4944117395Skan      named_section (NULL_TREE, ".data.rel.local", reloc);
4945117395Skan      break;
4946117395Skan    case SECCAT_DATA_REL_RO:
4947117395Skan      named_section (NULL_TREE, ".data.rel.ro", reloc);
4948117395Skan      break;
4949117395Skan    case SECCAT_DATA_REL_RO_LOCAL:
4950117395Skan      named_section (NULL_TREE, ".data.rel.ro.local", reloc);
4951117395Skan      break;
4952117395Skan    case SECCAT_SDATA:
4953117395Skan      named_section (NULL_TREE, ".sdata", reloc);
4954117395Skan      break;
4955117395Skan    case SECCAT_TDATA:
4956117395Skan      named_section (NULL_TREE, ".tdata", reloc);
4957117395Skan      break;
4958117395Skan    case SECCAT_BSS:
4959117395Skan#ifdef BSS_SECTION_ASM_OP
4960117395Skan      bss_section ();
4961117395Skan#else
4962117395Skan      named_section (NULL_TREE, ".bss", reloc);
4963117395Skan#endif
4964117395Skan      break;
4965117395Skan    case SECCAT_SBSS:
4966117395Skan      named_section (NULL_TREE, ".sbss", reloc);
4967117395Skan      break;
4968117395Skan    case SECCAT_TBSS:
4969117395Skan      named_section (NULL_TREE, ".tbss", reloc);
4970117395Skan      break;
4971117395Skan    default:
4972117395Skan      abort ();
4973117395Skan    }
4974117395Skan}
4975117395Skan
4976117395Skan/* Construct a unique section name based on the decl name and the
4977117395Skan   categorization performed above.  */
4978117395Skan
4979117395Skanvoid
4980132718Skandefault_unique_section (tree decl, int reloc)
4981117395Skan{
4982117395Skan  default_unique_section_1 (decl, reloc, flag_pic);
4983117395Skan}
4984117395Skan
4985117395Skanvoid
4986132718Skandefault_unique_section_1 (tree decl, int reloc, int shlib)
4987117395Skan{
4988117395Skan  bool one_only = DECL_ONE_ONLY (decl);
4989117395Skan  const char *prefix, *name;
4990117395Skan  size_t nlen, plen;
4991117395Skan  char *string;
4992117395Skan
4993117395Skan  switch (categorize_decl_for_section (decl, reloc, shlib))
4994117395Skan    {
4995117395Skan    case SECCAT_TEXT:
4996117395Skan      prefix = one_only ? ".gnu.linkonce.t." : ".text.";
4997117395Skan      break;
4998117395Skan    case SECCAT_RODATA:
4999117395Skan    case SECCAT_RODATA_MERGE_STR:
5000117395Skan    case SECCAT_RODATA_MERGE_STR_INIT:
5001117395Skan    case SECCAT_RODATA_MERGE_CONST:
5002117395Skan      prefix = one_only ? ".gnu.linkonce.r." : ".rodata.";
5003117395Skan      break;
5004117395Skan    case SECCAT_SRODATA:
5005117395Skan      prefix = one_only ? ".gnu.linkonce.s2." : ".sdata2.";
5006117395Skan      break;
5007117395Skan    case SECCAT_DATA:
5008117395Skan    case SECCAT_DATA_REL:
5009117395Skan    case SECCAT_DATA_REL_LOCAL:
5010117395Skan    case SECCAT_DATA_REL_RO:
5011117395Skan    case SECCAT_DATA_REL_RO_LOCAL:
5012117395Skan      prefix = one_only ? ".gnu.linkonce.d." : ".data.";
5013117395Skan      break;
5014117395Skan    case SECCAT_SDATA:
5015117395Skan      prefix = one_only ? ".gnu.linkonce.s." : ".sdata.";
5016117395Skan      break;
5017117395Skan    case SECCAT_BSS:
5018117395Skan      prefix = one_only ? ".gnu.linkonce.b." : ".bss.";
5019117395Skan      break;
5020117395Skan    case SECCAT_SBSS:
5021117395Skan      prefix = one_only ? ".gnu.linkonce.sb." : ".sbss.";
5022117395Skan      break;
5023117395Skan    case SECCAT_TDATA:
5024117395Skan      prefix = one_only ? ".gnu.linkonce.td." : ".tdata.";
5025117395Skan      break;
5026117395Skan    case SECCAT_TBSS:
5027117395Skan      prefix = one_only ? ".gnu.linkonce.tb." : ".tbss.";
5028117395Skan      break;
5029117395Skan    default:
5030117395Skan      abort ();
5031117395Skan    }
5032117395Skan  plen = strlen (prefix);
5033117395Skan
5034117395Skan  name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
5035117395Skan  name = (* targetm.strip_name_encoding) (name);
5036117395Skan  nlen = strlen (name);
5037117395Skan
5038117395Skan  string = alloca (nlen + plen + 1);
5039117395Skan  memcpy (string, prefix, plen);
5040117395Skan  memcpy (string + plen, name, nlen + 1);
5041117395Skan
5042117395Skan  DECL_SECTION_NAME (decl) = build_string (nlen + plen, string);
5043117395Skan}
5044117395Skan
5045117395Skanvoid
5046132718Skandefault_select_rtx_section (enum machine_mode mode ATTRIBUTE_UNUSED,
5047132718Skan			    rtx x,
5048132718Skan			    unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
5049117395Skan{
5050117395Skan  if (flag_pic)
5051117395Skan    switch (GET_CODE (x))
5052117395Skan      {
5053117395Skan      case CONST:
5054117395Skan      case SYMBOL_REF:
5055117395Skan      case LABEL_REF:
5056117395Skan	data_section ();
5057117395Skan	return;
5058117395Skan
5059117395Skan      default:
5060117395Skan	break;
5061117395Skan      }
5062117395Skan
5063117395Skan  readonly_data_section ();
5064117395Skan}
5065117395Skan
5066117395Skanvoid
5067132718Skandefault_elf_select_rtx_section (enum machine_mode mode, rtx x,
5068132718Skan				unsigned HOST_WIDE_INT align)
5069117395Skan{
5070117395Skan  /* ??? Handle small data here somehow.  */
5071117395Skan
5072117395Skan  if (flag_pic)
5073117395Skan    switch (GET_CODE (x))
5074117395Skan      {
5075117395Skan      case CONST:
5076117395Skan      case SYMBOL_REF:
5077117395Skan	named_section (NULL_TREE, ".data.rel.ro", 3);
5078117395Skan	return;
5079117395Skan
5080117395Skan      case LABEL_REF:
5081117395Skan	named_section (NULL_TREE, ".data.rel.ro.local", 1);
5082117395Skan	return;
5083117395Skan
5084117395Skan      default:
5085117395Skan	break;
5086117395Skan      }
5087117395Skan
5088117395Skan  mergeable_constant_section (mode, align, 0);
5089117395Skan}
5090117395Skan
5091132718Skan/* Set the generally applicable flags on the SYMBOL_REF for EXP.  */
5092132718Skan
5093132718Skanvoid
5094132718Skandefault_encode_section_info (tree decl, rtx rtl, int first ATTRIBUTE_UNUSED)
5095132718Skan{
5096132718Skan  rtx symbol;
5097132718Skan  int flags;
5098132718Skan
5099132718Skan  /* Careful not to prod global register variables.  */
5100132718Skan  if (GET_CODE (rtl) != MEM)
5101132718Skan    return;
5102132718Skan  symbol = XEXP (rtl, 0);
5103132718Skan  if (GET_CODE (symbol) != SYMBOL_REF)
5104132718Skan    return;
5105132718Skan
5106132718Skan  flags = 0;
5107132718Skan  if (TREE_CODE (decl) == FUNCTION_DECL)
5108132718Skan    flags |= SYMBOL_FLAG_FUNCTION;
5109132718Skan  if ((*targetm.binds_local_p) (decl))
5110132718Skan    flags |= SYMBOL_FLAG_LOCAL;
5111132718Skan  if ((*targetm.in_small_data_p) (decl))
5112132718Skan    flags |= SYMBOL_FLAG_SMALL;
5113132718Skan  if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL (decl))
5114132718Skan    flags |= decl_tls_model (decl) << SYMBOL_FLAG_TLS_SHIFT;
5115132718Skan  /* ??? Why is DECL_EXTERNAL ever set for non-PUBLIC names?  Without
5116132718Skan     being PUBLIC, the thing *must* be defined in this translation unit.
5117132718Skan     Prevent this buglet from being propagated into rtl code as well.  */
5118132718Skan  if (DECL_P (decl) && DECL_EXTERNAL (decl) && TREE_PUBLIC (decl))
5119132718Skan    flags |= SYMBOL_FLAG_EXTERNAL;
5120132718Skan
5121132718Skan  SYMBOL_REF_FLAGS (symbol) = flags;
5122132718Skan}
5123132718Skan
5124117395Skan/* By default, we do nothing for encode_section_info, so we need not
5125117395Skan   do anything but discard the '*' marker.  */
5126117395Skan
5127117395Skanconst char *
5128132718Skandefault_strip_name_encoding (const char *str)
5129117395Skan{
5130117395Skan  return str + (*str == '*');
5131117395Skan}
5132117395Skan
5133117395Skan/* Assume ELF-ish defaults, since that's pretty much the most liberal
5134117395Skan   wrt cross-module name binding.  */
5135117395Skan
5136117395Skanbool
5137132718Skandefault_binds_local_p (tree exp)
5138117395Skan{
5139132718Skan  return default_binds_local_p_1 (exp, flag_shlib);
5140117395Skan}
5141117395Skan
5142117395Skanbool
5143132718Skandefault_binds_local_p_1 (tree exp, int shlib)
5144117395Skan{
5145117395Skan  bool local_p;
5146117395Skan
5147117395Skan  /* A non-decl is an entry in the constant pool.  */
5148117395Skan  if (!DECL_P (exp))
5149117395Skan    local_p = true;
5150117395Skan  /* Static variables are always local.  */
5151117395Skan  else if (! TREE_PUBLIC (exp))
5152117395Skan    local_p = true;
5153117395Skan  /* A variable is local if the user tells us so.  */
5154132718Skan  else if (DECL_VISIBILITY (exp) != VISIBILITY_DEFAULT)
5155117395Skan    local_p = true;
5156117395Skan  /* Otherwise, variables defined outside this object may not be local.  */
5157117395Skan  else if (DECL_EXTERNAL (exp))
5158117395Skan    local_p = false;
5159117395Skan  /* Linkonce and weak data are never local.  */
5160117395Skan  else if (DECL_ONE_ONLY (exp) || DECL_WEAK (exp))
5161117395Skan    local_p = false;
5162117395Skan  /* If PIC, then assume that any global name can be overridden by
5163117395Skan     symbols resolved from other modules.  */
5164117395Skan  else if (shlib)
5165117395Skan    local_p = false;
5166117395Skan  /* Uninitialized COMMON variable may be unified with symbols
5167117395Skan     resolved from other modules.  */
5168117395Skan  else if (DECL_COMMON (exp)
5169117395Skan	   && (DECL_INITIAL (exp) == NULL
5170117395Skan	       || DECL_INITIAL (exp) == error_mark_node))
5171117395Skan    local_p = false;
5172117395Skan  /* Otherwise we're left with initialized (or non-common) global data
5173117395Skan     which is of necessity defined locally.  */
5174117395Skan  else
5175117395Skan    local_p = true;
5176117395Skan
5177117395Skan  return local_p;
5178117395Skan}
5179117395Skan
5180132718Skan/* Determine whether or not a pointer mode is valid. Assume defaults
5181132718Skan   of ptr_mode or Pmode - can be overridden.  */
5182132718Skanbool
5183132718Skandefault_valid_pointer_mode (enum machine_mode mode)
5184132718Skan{
5185132718Skan  return (mode == ptr_mode || mode == Pmode);
5186132718Skan}
5187132718Skan
5188117395Skan/* Default function to output code that will globalize a label.  A
5189117395Skan   target must define GLOBAL_ASM_OP or provide it's own function to
5190117395Skan   globalize a label.  */
5191117395Skan#ifdef GLOBAL_ASM_OP
5192117395Skanvoid
5193132718Skandefault_globalize_label (FILE * stream, const char *name)
5194117395Skan{
5195117395Skan  fputs (GLOBAL_ASM_OP, stream);
5196117395Skan  assemble_name (stream, name);
5197117395Skan  putc ('\n', stream);
5198117395Skan}
5199117395Skan#endif /* GLOBAL_ASM_OP */
5200132718Skan
5201132718Skan/* This is how to output an internal numbered label where PREFIX is
5202132718Skan   the class of label and LABELNO is the number within the class.  */
5203132718Skan
5204132718Skanvoid
5205132718Skandefault_internal_label (FILE *stream, const char *prefix,
5206132718Skan			unsigned long labelno)
5207132718Skan{
5208132718Skan  char *const buf = alloca (40 + strlen (prefix));
5209132718Skan  ASM_GENERATE_INTERNAL_LABEL (buf, prefix, labelno);
5210132718Skan  ASM_OUTPUT_LABEL (stream, buf);
5211132718Skan}
5212132718Skan
5213132718Skan/* This is the default behavior at the beginning of a file.  It's
5214132718Skan   controlled by two other target-hook toggles.  */
5215132718Skanvoid
5216132718Skandefault_file_start (void)
5217132718Skan{
5218132718Skan  if (targetm.file_start_app_off && !flag_verbose_asm)
5219132718Skan    fputs (ASM_APP_OFF, asm_out_file);
5220132718Skan
5221132718Skan  if (targetm.file_start_file_directive)
5222132718Skan    output_file_directive (asm_out_file, main_input_filename);
5223132718Skan}
5224132718Skan
5225132718Skan/* This is a generic routine suitable for use as TARGET_ASM_FILE_END
5226132718Skan   which emits a special section directive used to indicate whether or
5227132718Skan   not this object file needs an executable stack.  This is primarily
5228132718Skan   a GNU extension to ELF but could be used on other targets.  */
5229132718Skanvoid
5230132718Skanfile_end_indicate_exec_stack (void)
5231132718Skan{
5232132718Skan  unsigned int flags = SECTION_DEBUG;
5233132718Skan  if (trampolines_created)
5234132718Skan    flags |= SECTION_CODE;
5235132718Skan
5236132718Skan  named_section_flags (".note.GNU-stack", flags);
5237132718Skan}
5238132718Skan
5239117395Skan#include "gt-varasm.h"
5240