varasm.c revision 146895
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
2353146895Skan   handles the same types of nodes that compare_constant handles.
2354146895Skan   Writable string constants are never copied.  */
235518334Speter
235618334Speterstatic tree
2357132718Skancopy_constant (tree exp)
235818334Speter{
235918334Speter  switch (TREE_CODE (exp))
236018334Speter    {
236118334Speter    case ADDR_EXPR:
236218334Speter      /* For ADDR_EXPR, we do not want to copy the decl whose address
236318334Speter	 is requested.  We do want to copy constants though.  */
236418334Speter      if (TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (exp, 0))) == 'c')
236518334Speter	return build1 (TREE_CODE (exp), TREE_TYPE (exp),
236618334Speter		       copy_constant (TREE_OPERAND (exp, 0)));
236718334Speter      else
236818334Speter	return copy_node (exp);
236918334Speter
2370146895Skan    case STRING_CST:
2371146895Skan      if (flag_writable_strings)
2372146895Skan	return exp;
2373146895Skan      /* FALLTHROUGH */
237418334Speter    case INTEGER_CST:
237518334Speter    case REAL_CST:
237618334Speter      return copy_node (exp);
237718334Speter
237818334Speter    case COMPLEX_CST:
237950397Sobrien      return build_complex (TREE_TYPE (exp),
238050397Sobrien			    copy_constant (TREE_REALPART (exp)),
238118334Speter			    copy_constant (TREE_IMAGPART (exp)));
238218334Speter
238318334Speter    case PLUS_EXPR:
238418334Speter    case MINUS_EXPR:
238518334Speter      return build (TREE_CODE (exp), TREE_TYPE (exp),
238618334Speter		    copy_constant (TREE_OPERAND (exp, 0)),
238718334Speter		    copy_constant (TREE_OPERAND (exp, 1)));
238818334Speter
238918334Speter    case NOP_EXPR:
239018334Speter    case CONVERT_EXPR:
239150397Sobrien    case NON_LVALUE_EXPR:
2392132718Skan    case VIEW_CONVERT_EXPR:
239318334Speter      return build1 (TREE_CODE (exp), TREE_TYPE (exp),
239418334Speter		     copy_constant (TREE_OPERAND (exp, 0)));
239518334Speter
239618334Speter    case CONSTRUCTOR:
239718334Speter      {
239818334Speter	tree copy = copy_node (exp);
239918334Speter	tree list = copy_list (CONSTRUCTOR_ELTS (exp));
240018334Speter	tree tail;
240118334Speter
240218334Speter	CONSTRUCTOR_ELTS (copy) = list;
240318334Speter	for (tail = list; tail; tail = TREE_CHAIN (tail))
240418334Speter	  TREE_VALUE (tail) = copy_constant (TREE_VALUE (tail));
240518334Speter	if (TREE_CODE (TREE_TYPE (exp)) == SET_TYPE)
240618334Speter	  for (tail = list; tail; tail = TREE_CHAIN (tail))
240718334Speter	    TREE_PURPOSE (tail) = copy_constant (TREE_PURPOSE (tail));
240818334Speter
240918334Speter	return copy;
241018334Speter      }
241118334Speter
241218334Speter    default:
2413117395Skan      {
2414117395Skan	tree t;
2415117395Skan	t = (*lang_hooks.expand_constant) (exp);
2416117395Skan	if (t != exp)
2417117395Skan	  return copy_constant (t);
2418117395Skan	else
2419117395Skan	  abort ();
2420117395Skan      }
242118334Speter    }
242218334Speter}
242318334Speter
2424132718Skan/* Subroutine of output_constant_def:
2425132718Skan   No constant equal to EXP is known to have been output.
2426132718Skan   Make a constant descriptor to enter EXP in the hash table.
2427132718Skan   Assign the label number and construct RTL to refer to the
2428132718Skan   constant's location in memory.
2429132718Skan   Caller is responsible for updating the hash table.  */
243018334Speter
2431132718Skanstatic struct constant_descriptor_tree *
2432132718Skanbuild_constant_desc (tree exp)
243318334Speter{
2434132718Skan  rtx symbol;
2435132718Skan  rtx rtl;
2436132718Skan  char label[256];
2437132718Skan  int labelno;
2438117395Skan  struct constant_descriptor_tree *desc;
243918334Speter
2440132718Skan  desc = ggc_alloc (sizeof (*desc));
2441146895Skan  desc->value = copy_constant (exp);
2442122180Skan
2443132718Skan  /* Create a string containing the label name, in LABEL.  */
2444132718Skan  labelno = const_labelno++;
2445132718Skan  ASM_GENERATE_INTERNAL_LABEL (label, "LC", labelno);
244618334Speter
2447132718Skan  /* We have a symbol name; construct the SYMBOL_REF and the MEM.  */
2448132718Skan  symbol = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (label));
2449132718Skan  SYMBOL_REF_FLAGS (symbol) = SYMBOL_FLAG_LOCAL;
2450132718Skan  SYMBOL_REF_DECL (symbol) = desc->value;
2451132718Skan  TREE_CONSTANT_POOL_ADDRESS_P (symbol) = 1;
245218334Speter
2453132718Skan  rtl = gen_rtx_MEM (TYPE_MODE (TREE_TYPE (exp)), symbol);
2454132718Skan  set_mem_attributes (rtl, exp, 1);
2455132718Skan  set_mem_alias_set (rtl, 0);
2456132718Skan  set_mem_alias_set (rtl, const_alias_set);
245718334Speter
2458132718Skan  /* Set flags or add text to the name to record information, such as
2459132718Skan     that it is a local symbol.  If the name is changed, the macro
2460132718Skan     ASM_OUTPUT_LABELREF will have to know how to strip this
2461132718Skan     information.  This call might invalidate our local variable
2462132718Skan     SYMBOL; we can't use it afterward.  */
246318334Speter
2464132718Skan  (*targetm.encode_section_info) (exp, rtl, true);
246590075Sobrien
2466132718Skan  desc->rtl = rtl;
246790075Sobrien
2468132718Skan  return desc;
2469132718Skan}
247090075Sobrien
2471132718Skan/* Return an rtx representing a reference to constant data in memory
2472132718Skan   for the constant expression EXP.
247318334Speter
2474132718Skan   If assembler code for such a constant has already been output,
2475132718Skan   return an rtx to refer to it.
2476132718Skan   Otherwise, output such a constant in memory
2477132718Skan   and generate an rtx for it.
247890075Sobrien
2479132718Skan   If DEFER is nonzero, this constant can be deferred and output only
2480132718Skan   if referenced in the function after all optimizations.
248190075Sobrien
2482132718Skan   `const_desc_table' records which constants already have label strings.  */
248390075Sobrien
2484132718Skanrtx
2485132718Skanoutput_constant_def (tree exp, int defer)
2486132718Skan{
2487132718Skan  struct constant_descriptor_tree *desc;
2488132718Skan  struct constant_descriptor_tree key;
2489132718Skan  void **loc;
249018334Speter
2491132718Skan  /* Look up EXP in the table of constant descriptors.  If we didn't find
2492132718Skan     it, create a new one.  */
2493132718Skan  key.value = exp;
2494132718Skan  loc = htab_find_slot (const_desc_htab, &key, INSERT);
249518334Speter
2496132718Skan  desc = *loc;
2497132718Skan  if (desc == 0)
249890075Sobrien    {
2499132718Skan      desc = build_constant_desc (exp);
2500132718Skan      *loc = desc;
250190075Sobrien    }
250218334Speter
2503132718Skan  maybe_output_constant_def_contents (desc, defer);
2504132718Skan  return desc->rtl;
2505132718Skan}
250690075Sobrien
2507132718Skan/* Subroutine of output_constant_def: Decide whether or not we need to
2508132718Skan   output the constant DESC now, and if so, do it.  */
2509132718Skanstatic void
2510132718Skanmaybe_output_constant_def_contents (struct constant_descriptor_tree *desc,
2511132718Skan				    int defer)
2512132718Skan{
2513132718Skan  rtx symbol = XEXP (desc->rtl, 0);
2514132718Skan  tree exp = desc->value;
251590075Sobrien
2516132718Skan  if (flag_syntax_only)
2517132718Skan    return;
251818334Speter
2519132718Skan  if (TREE_ASM_WRITTEN (exp))
2520132718Skan    /* Already output; don't do it again.  */
2521132718Skan    return;
252290075Sobrien
2523132718Skan  /* The only constants that cannot safely be deferred, assuming the
2524132718Skan     context allows it, are strings under flag_writable_strings.  */
2525132718Skan  if (defer && (TREE_CODE (exp) != STRING_CST || !flag_writable_strings))
2526132718Skan    {
2527132718Skan      /* Increment n_deferred_constants if it exists.  It needs to be at
2528132718Skan	 least as large as the number of constants actually referred to
2529132718Skan	 by the function.  If it's too small we'll stop looking too early
2530132718Skan	 and fail to emit constants; if it's too large we'll only look
2531132718Skan	 through the entire function when we could have stopped earlier.  */
2532132718Skan      if (cfun)
2533132718Skan	n_deferred_constants++;
2534132718Skan      return;
253518334Speter    }
253618334Speter
2537132718Skan  output_constant_def_contents (symbol);
253818334Speter}
253918334Speter
2540132718Skan/* We must output the constant data referred to by SYMBOL; do so.  */
254118334Speter
254218334Speterstatic void
2543132718Skanoutput_constant_def_contents (rtx symbol)
254418334Speter{
2545132718Skan  tree exp = SYMBOL_REF_DECL (symbol);
2546132718Skan  const char *label = XSTR (symbol, 0);
2547122180Skan  HOST_WIDE_INT size;
254818334Speter
2549132718Skan  /* Make sure any other constants whose addresses appear in EXP
2550132718Skan     are assigned label numbers.  */
2551132718Skan  int reloc = compute_reloc_for_constant (exp);
2552132718Skan
255390075Sobrien  /* Align the location counter as required by EXP's data type.  */
2554132718Skan  int align = TYPE_ALIGN (TREE_TYPE (exp));
255590075Sobrien#ifdef CONSTANT_ALIGNMENT
255690075Sobrien  align = CONSTANT_ALIGNMENT (exp, align);
255790075Sobrien#endif
255890075Sobrien
2559132718Skan  output_addressed_constants (exp);
2560132718Skan
2561132718Skan  /* We are no longer deferring this constant.  */
2562132718Skan  TREE_ASM_WRITTEN (exp) = 1;
2563132718Skan
256418334Speter  if (IN_NAMED_SECTION (exp))
256550397Sobrien    named_section (exp, NULL, reloc);
256618334Speter  else
2567117395Skan    (*targetm.asm_out.select_section) (exp, reloc, align);
256818334Speter
256918334Speter  if (align > BITS_PER_UNIT)
257090075Sobrien    {
257190075Sobrien      ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (align / BITS_PER_UNIT));
257290075Sobrien    }
257318334Speter
2574122180Skan  size = int_size_in_bytes (TREE_TYPE (exp));
2575122180Skan  if (TREE_CODE (exp) == STRING_CST)
2576122180Skan    size = MAX (TREE_STRING_LENGTH (exp), size);
2577122180Skan
2578122180Skan  /* Do any machine/system dependent processing of the constant.  */
2579122180Skan#ifdef ASM_DECLARE_CONSTANT_NAME
2580132718Skan  ASM_DECLARE_CONSTANT_NAME (asm_out_file, label, exp, size);
2581122180Skan#else
2582122180Skan  /* Standard thing is just output label for the constant.  */
2583132718Skan  ASM_OUTPUT_LABEL (asm_out_file, label);
2584122180Skan#endif /* ASM_DECLARE_CONSTANT_NAME */
258518334Speter
258618334Speter  /* Output the value of EXP.  */
2587122180Skan  output_constant (exp, size, align);
258818334Speter}
2589132718Skan
2590132718Skan/* A constant which was deferred in its original location has been
2591132718Skan   inserted by the RTL inliner into a different function.  The
2592132718Skan   current function's deferred constant count must be incremented.  */
2593132718Skanvoid
2594132718Skannotice_rtl_inlining_of_deferred_constant (void)
2595132718Skan{
2596132718Skan  n_deferred_constants++;
2597132718Skan}
2598132718Skan
2599132718Skan/* Look up EXP in the table of constant descriptors.  Return the rtl
2600132718Skan   if it has been emitted, else null.  */
2601132718Skan
2602132718Skanrtx
2603132718Skanlookup_constant_def (tree exp)
2604132718Skan{
2605132718Skan  struct constant_descriptor_tree *desc;
2606132718Skan  struct constant_descriptor_tree key;
2607132718Skan
2608132718Skan  key.value = exp;
2609132718Skan  desc = htab_find (const_desc_htab, &key);
2610132718Skan
2611132718Skan  return (desc ? desc->rtl : NULL_RTX);
2612132718Skan}
261318334Speter
2614117395Skan/* Used in the hash tables to avoid outputting the same constant
2615117395Skan   twice.  Unlike 'struct constant_descriptor_tree', RTX constants
2616117395Skan   are output once per function, not once per file; there seems
2617117395Skan   to be no reason for the difference.  */
2618117395Skan
2619117395Skanstruct constant_descriptor_rtx GTY(())
2620117395Skan{
2621117395Skan  /* More constant_descriptors with the same hash code.  */
2622117395Skan  struct constant_descriptor_rtx *next;
2623117395Skan
2624117395Skan  /* A MEM for the constant.  */
2625117395Skan  rtx rtl;
2626117395Skan
2627117395Skan  /* The value of the constant.  */
2628117395Skan  struct rtx_const value;
2629117395Skan};
2630117395Skan
263118334Speter/* Structure to represent sufficient information about a constant so that
263218334Speter   it can be output when the constant pool is output, so that function
263318334Speter   integration can be done, and to simplify handling on machines that reference
263418334Speter   constant pool as base+displacement.  */
263518334Speter
2636117395Skanstruct pool_constant GTY(())
263718334Speter{
2638117395Skan  struct constant_descriptor_rtx *desc;
2639117395Skan  struct pool_constant *next;
2640117395Skan  struct pool_constant *next_sym;
264190075Sobrien  rtx constant;
264218334Speter  enum machine_mode mode;
264318334Speter  int labelno;
264490075Sobrien  unsigned int align;
264590075Sobrien  HOST_WIDE_INT offset;
264650397Sobrien  int mark;
264718334Speter};
264818334Speter
264918334Speter/* Hash code for a SYMBOL_REF with CONSTANT_POOL_ADDRESS_P true.
265018334Speter   The argument is XSTR (... , 0)  */
265118334Speter
2652117395Skan#define SYMHASH(LABEL)	(((unsigned long) (LABEL)) % MAX_RTX_HASH_TABLE)
265318334Speter
265490075Sobrien/* Initialize constant pool hashing for a new function.  */
265518334Speter
265618334Spetervoid
2657132718Skaninit_varasm_status (struct function *f)
265818334Speter{
265990075Sobrien  struct varasm_status *p;
2660132718Skan  p = ggc_alloc (sizeof (struct varasm_status));
266190075Sobrien  f->varasm = p;
266290075Sobrien  p->x_const_rtx_hash_table
2663132718Skan    = ggc_alloc_cleared (MAX_RTX_HASH_TABLE
2664132718Skan			 * sizeof (struct constant_descriptor_rtx *));
266590075Sobrien  p->x_const_rtx_sym_hash_table
2666132718Skan    = ggc_alloc_cleared (MAX_RTX_HASH_TABLE
2667132718Skan			 * sizeof (struct pool_constant *));
266818334Speter
266990075Sobrien  p->x_first_pool = p->x_last_pool = 0;
267090075Sobrien  p->x_pool_offset = 0;
2671132718Skan  p->deferred_constants = 0;
267218334Speter}
267318334Speter
267418334Speter
267518334Speter/* Express an rtx for a constant integer (perhaps symbolic)
267618334Speter   as the sum of a symbol or label plus an explicit integer.
267718334Speter   They are stored into VALUE.  */
267818334Speter
267918334Speterstatic void
2680132718Skandecode_rtx_const (enum machine_mode mode, rtx x, struct rtx_const *value)
268118334Speter{
268218334Speter  /* Clear the whole structure, including any gaps.  */
268390075Sobrien  memset (value, 0, sizeof (struct rtx_const));
268418334Speter
268550397Sobrien  value->kind = RTX_INT;	/* Most usual kind.  */
268618334Speter  value->mode = mode;
268718334Speter
268818334Speter  switch (GET_CODE (x))
268918334Speter    {
269018334Speter    case CONST_DOUBLE:
269118334Speter      value->kind = RTX_DOUBLE;
269218334Speter      if (GET_MODE (x) != VOIDmode)
269318334Speter	{
2694117395Skan	  const REAL_VALUE_TYPE *r = CONST_DOUBLE_REAL_VALUE (x);
2695117395Skan
269618334Speter	  value->mode = GET_MODE (x);
2697117395Skan
2698117395Skan	  /* Copy the REAL_VALUE_TYPE by members so that we don't
2699117395Skan	     copy garbage from the original structure into our
2700117395Skan	     carefully cleaned hashing structure.  */
2701117395Skan	  value->un.du.class = r->class;
2702117395Skan	  value->un.du.sign = r->sign;
2703117395Skan	  switch (r->class)
2704117395Skan	    {
2705117395Skan	    case rvc_zero:
2706117395Skan	    case rvc_inf:
2707117395Skan	      break;
2708117395Skan	    case rvc_normal:
2709117395Skan	      value->un.du.exp = r->exp;
2710132718Skan	      /* Fall through.  */
2711117395Skan	    case rvc_nan:
2712117395Skan	      memcpy (value->un.du.sig, r->sig, sizeof (r->sig));
2713117395Skan	      break;
2714117395Skan	    default:
2715117395Skan	      abort ();
2716117395Skan	    }
271718334Speter	}
271818334Speter      else
271918334Speter	{
272018334Speter	  value->un.di.low = CONST_DOUBLE_LOW (x);
272118334Speter	  value->un.di.high = CONST_DOUBLE_HIGH (x);
272218334Speter	}
272318334Speter      break;
272418334Speter
272596263Sobrien    case CONST_VECTOR:
272696263Sobrien      {
272796263Sobrien	int units, i;
272896263Sobrien
272996263Sobrien	units = CONST_VECTOR_NUNITS (x);
273096263Sobrien	value->kind = RTX_VECTOR;
273196263Sobrien	value->mode = mode;
273296263Sobrien
2733117395Skan	if (GET_MODE_CLASS (mode) == MODE_VECTOR_INT)
273496263Sobrien	  {
2735117395Skan	    for (i = 0; i < units; ++i)
273696263Sobrien	      {
2737117395Skan	        rtx elt = CONST_VECTOR_ELT (x, i);
2738117395Skan	        if (GET_CODE (elt) == CONST_INT)
2739117395Skan	          {
2740117395Skan		    value->un.int_vec[i].low = INTVAL (elt);
2741117395Skan		    value->un.int_vec[i].high = 0;
2742117395Skan	          }
2743117395Skan		else
2744117395Skan	          {
2745117395Skan		    value->un.int_vec[i].low = CONST_DOUBLE_LOW (elt);
2746117395Skan		    value->un.int_vec[i].high = CONST_DOUBLE_HIGH (elt);
2747117395Skan		  }
274896263Sobrien	      }
2749117395Skan	  }
2750117395Skan	else if (GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT)
2751117395Skan	  {
2752117395Skan	    for (i = 0; i < units; ++i)
275396263Sobrien	      {
2754117395Skan		const REAL_VALUE_TYPE *r
2755117395Skan		  = CONST_DOUBLE_REAL_VALUE (CONST_VECTOR_ELT (x, i));
2756117395Skan		REAL_VALUE_TYPE *d = &value->un.fp_vec[i];
2757117395Skan
2758117395Skan	        /* Copy the REAL_VALUE_TYPE by members so that we don't
2759117395Skan	           copy garbage from the original structure into our
2760117395Skan	           carefully cleaned hashing structure.  */
2761117395Skan	        d->class = r->class;
2762117395Skan	        d->sign = r->sign;
2763117395Skan	        switch (r->class)
2764117395Skan	          {
2765117395Skan	          case rvc_zero:
2766117395Skan	          case rvc_inf:
2767117395Skan	            break;
2768117395Skan	          case rvc_normal:
2769117395Skan	            d->exp = r->exp;
2770132718Skan	            /* Fall through.  */
2771117395Skan	          case rvc_nan:
2772117395Skan	            memcpy (d->sig, r->sig, sizeof (r->sig));
2773117395Skan	            break;
2774117395Skan	          default:
2775117395Skan	            abort ();
2776117395Skan	          }
277796263Sobrien	      }
277896263Sobrien	  }
2779117395Skan	else
2780117395Skan	  abort ();
278196263Sobrien      }
278296263Sobrien      break;
278396263Sobrien
278418334Speter    case CONST_INT:
278518334Speter      value->un.addr.offset = INTVAL (x);
278618334Speter      break;
278718334Speter
278818334Speter    case SYMBOL_REF:
278918334Speter    case LABEL_REF:
279018334Speter    case PC:
279118334Speter      value->un.addr.base = x;
279218334Speter      break;
279318334Speter
279418334Speter    case CONST:
279518334Speter      x = XEXP (x, 0);
279690075Sobrien      if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 1)) == CONST_INT)
279718334Speter	{
279818334Speter	  value->un.addr.base = XEXP (x, 0);
279918334Speter	  value->un.addr.offset = INTVAL (XEXP (x, 1));
280018334Speter	}
280190075Sobrien      else if (GET_CODE (x) == MINUS && GET_CODE (XEXP (x, 1)) == CONST_INT)
280218334Speter	{
280318334Speter	  value->un.addr.base = XEXP (x, 0);
280418334Speter	  value->un.addr.offset = - INTVAL (XEXP (x, 1));
280518334Speter	}
280618334Speter      else
280790075Sobrien	{
280890075Sobrien	  value->un.addr.base = x;
280990075Sobrien	  value->un.addr.offset = 0;
281090075Sobrien	}
281118334Speter      break;
281218334Speter
281318334Speter    default:
281496263Sobrien      value->kind = RTX_UNKNOWN;
281596263Sobrien      break;
281618334Speter    }
281718334Speter
281896263Sobrien  if (value->kind == RTX_INT && value->un.addr.base != 0
281996263Sobrien      && GET_CODE (value->un.addr.base) == UNSPEC)
2820117395Skan    {
282196263Sobrien      /* For a simple UNSPEC, the base is set to the
282296263Sobrien	 operand, the kind field is set to the index of
2823117395Skan	 the unspec expression.
282496263Sobrien	 Together with the code below, in case that
2825117395Skan	 the operand is a SYMBOL_REF or LABEL_REF,
2826117395Skan	 the address of the string or the code_label
282796263Sobrien	 is taken as base.  */
282896263Sobrien      if (XVECLEN (value->un.addr.base, 0) == 1)
2829117395Skan	{
283096263Sobrien	  value->kind = RTX_UNSPEC + XINT (value->un.addr.base, 1);
283196263Sobrien	  value->un.addr.base = XVECEXP (value->un.addr.base, 0, 0);
283296263Sobrien	}
283396263Sobrien    }
283496263Sobrien
2835117395Skan  if (value->kind >= RTX_INT && value->un.addr.base != 0)
283618334Speter    switch (GET_CODE (value->un.addr.base))
283718334Speter      {
283818334Speter      case SYMBOL_REF:
283990075Sobrien	/* Use the string's address, not the SYMBOL_REF's address,
284090075Sobrien	   for the sake of addresses of library routines.  */
2841117395Skan	value->un.addr.symbol = XSTR (value->un.addr.base, 0);
2842117395Skan	value->un.addr.base = NULL_RTX;
284390075Sobrien	break;
284490075Sobrien
284518334Speter      case LABEL_REF:
284690075Sobrien	/* For a LABEL_REF, compare labels.  */
284718334Speter	value->un.addr.base = XEXP (value->un.addr.base, 0);
284890075Sobrien
284950397Sobrien      default:
285050397Sobrien	break;
285118334Speter      }
285218334Speter}
285318334Speter
285418334Speter/* Given a MINUS expression, simplify it if both sides
285518334Speter   include the same symbol.  */
285618334Speter
285718334Speterrtx
2858132718Skansimplify_subtraction (rtx x)
285918334Speter{
286018334Speter  struct rtx_const val0, val1;
286118334Speter
286218334Speter  decode_rtx_const (GET_MODE (x), XEXP (x, 0), &val0);
286318334Speter  decode_rtx_const (GET_MODE (x), XEXP (x, 1), &val1);
286418334Speter
2865117395Skan  if (val0.kind >= RTX_INT
286696263Sobrien      && val0.kind == val1.kind
2867117395Skan      && val0.un.addr.base == val1.un.addr.base
2868117395Skan      && val0.un.addr.symbol == val1.un.addr.symbol)
286918334Speter    return GEN_INT (val0.un.addr.offset - val1.un.addr.offset);
287096263Sobrien
287118334Speter  return x;
287218334Speter}
287318334Speter
287418334Speter/* Compute a hash code for a constant RTL expression.  */
287518334Speter
2876117395Skanstatic unsigned int
2877132718Skanconst_hash_rtx (enum machine_mode mode, rtx x)
287818334Speter{
2879117395Skan  union {
2880117395Skan    struct rtx_const value;
2881117395Skan    unsigned int data[sizeof(struct rtx_const) / sizeof (unsigned int)];
2882117395Skan  } u;
2883117395Skan
2884117395Skan  unsigned int hi;
288590075Sobrien  size_t i;
288618334Speter
2887117395Skan  decode_rtx_const (mode, x, &u.value);
288818334Speter
2889132718Skan  /* Compute hashing function.  */
289018334Speter  hi = 0;
2891117395Skan  for (i = 0; i < ARRAY_SIZE (u.data); i++)
2892117395Skan    hi = hi * 613 + u.data[i];
289318334Speter
2894117395Skan  return hi % MAX_RTX_HASH_TABLE;
289518334Speter}
289618334Speter
289718334Speter/* Compare a constant rtl object X with a constant-descriptor DESC.
289818334Speter   Return 1 if DESC describes a constant with the same value as X.  */
289918334Speter
290018334Speterstatic int
2901132718Skancompare_constant_rtx (enum machine_mode mode, rtx x,
2902132718Skan		      struct constant_descriptor_rtx *desc)
290318334Speter{
290418334Speter  struct rtx_const value;
290518334Speter
290618334Speter  decode_rtx_const (mode, x, &value);
290718334Speter
290818334Speter  /* Compare constant contents.  */
2909117395Skan  return memcmp (&value, &desc->value, sizeof (struct rtx_const)) == 0;
291018334Speter}
291118334Speter
291218334Speter/* Construct a constant descriptor for the rtl-expression X.
291318334Speter   It is up to the caller to enter the descriptor in the hash table.  */
291418334Speter
2915117395Skanstatic struct constant_descriptor_rtx *
2916132718Skanrecord_constant_rtx (enum machine_mode mode, rtx x)
291718334Speter{
2918117395Skan  struct constant_descriptor_rtx *ptr;
291918334Speter
2920132718Skan  ptr = ggc_alloc (sizeof (*ptr));
2921117395Skan  decode_rtx_const (mode, x, &ptr->value);
292218334Speter
292390075Sobrien  return ptr;
292490075Sobrien}
292590075Sobrien
292618334Speter/* Given a constant rtx X, make (or find) a memory constant for its value
292718334Speter   and return a MEM rtx to refer to it in memory.  */
292818334Speter
292918334Speterrtx
2930132718Skanforce_const_mem (enum machine_mode mode, rtx x)
293118334Speter{
293290075Sobrien  int hash;
2933117395Skan  struct constant_descriptor_rtx *desc;
293418334Speter  char label[256];
2935132718Skan  rtx def, symbol;
293690075Sobrien  struct pool_constant *pool;
293790075Sobrien  unsigned int align;
293818334Speter
2939117395Skan  /* If we're not allowed to drop X into the constant pool, don't.  */
2940117395Skan  if ((*targetm.cannot_force_const_mem) (x))
2941117395Skan    return NULL_RTX;
2942117395Skan
294318334Speter  /* Compute hash code of X.  Search the descriptors for that hash code
294490075Sobrien     to see if any of them describes X.  If yes, we have an rtx to use.  */
294518334Speter  hash = const_hash_rtx (mode, x);
294618334Speter  for (desc = const_rtx_hash_table[hash]; desc; desc = desc->next)
294718334Speter    if (compare_constant_rtx (mode, x, desc))
2948132718Skan      return copy_rtx (desc->rtl);
294918334Speter
295090075Sobrien  /* No constant equal to X is known to have been output.
295190075Sobrien     Make a constant descriptor to enter X in the hash table
295290075Sobrien     and make a MEM for it.  */
295390075Sobrien  desc = record_constant_rtx (mode, x);
295490075Sobrien  desc->next = const_rtx_hash_table[hash];
295590075Sobrien  const_rtx_hash_table[hash] = desc;
2956117395Skan
295790075Sobrien  /* Align the location counter as required by EXP's data type.  */
295890075Sobrien  align = GET_MODE_ALIGNMENT (mode == VOIDmode ? word_mode : mode);
295950397Sobrien#ifdef CONSTANT_ALIGNMENT
2960132718Skan  {
2961132718Skan    tree type = (*lang_hooks.types.type_for_mode) (mode, 0);
2962132718Skan    if (type != NULL_TREE)
2963132718Skan      align = CONSTANT_ALIGNMENT (make_tree (type, x), align);
2964132718Skan  }
296550397Sobrien#endif
296618334Speter
296790075Sobrien  pool_offset += (align / BITS_PER_UNIT) - 1;
296890075Sobrien  pool_offset &= ~ ((align / BITS_PER_UNIT) - 1);
296918334Speter
297090075Sobrien  if (GET_CODE (x) == LABEL_REF)
297190075Sobrien    LABEL_PRESERVE_P (XEXP (x, 0)) = 1;
297218334Speter
297390075Sobrien  /* Allocate a pool constant descriptor, fill it in, and chain it in.  */
2974132718Skan  pool = ggc_alloc (sizeof (struct pool_constant));
297590075Sobrien  pool->desc = desc;
297690075Sobrien  pool->constant = x;
297790075Sobrien  pool->mode = mode;
297890075Sobrien  pool->labelno = const_labelno;
297990075Sobrien  pool->align = align;
298090075Sobrien  pool->offset = pool_offset;
298190075Sobrien  pool->mark = 1;
298290075Sobrien  pool->next = 0;
298350397Sobrien
298490075Sobrien  if (last_pool == 0)
298590075Sobrien    first_pool = pool;
298690075Sobrien  else
298790075Sobrien    last_pool->next = pool;
2988117395Skan
298990075Sobrien  last_pool = pool;
299090075Sobrien  pool_offset += GET_MODE_SIZE (mode);
299118334Speter
299290075Sobrien  /* Create a string containing the label name, in LABEL.  */
299390075Sobrien  ASM_GENERATE_INTERNAL_LABEL (label, "LC", const_labelno);
299474722Sobrien
299590075Sobrien  ++const_labelno;
299674722Sobrien
299790075Sobrien  /* Construct the SYMBOL_REF and the MEM.  */
299818334Speter
2999132718Skan  symbol = gen_rtx_SYMBOL_REF (Pmode, ggc_strdup (label));
3000132718Skan  SYMBOL_REF_FLAGS (symbol) = SYMBOL_FLAG_LOCAL;
3001132718Skan
3002132718Skan  pool->desc->rtl = def = gen_rtx_MEM (mode, symbol);
3003117395Skan  set_mem_attributes (def, (*lang_hooks.types.type_for_mode) (mode, 0), 1);
300490075Sobrien  RTX_UNCHANGING_P (def) = 1;
300518334Speter
300690075Sobrien  /* Add label to symbol hash table.  */
3007132718Skan  hash = SYMHASH (XSTR (symbol, 0));
300890075Sobrien  pool->next_sym = const_rtx_sym_hash_table[hash];
300990075Sobrien  const_rtx_sym_hash_table[hash] = pool;
301018334Speter
301118334Speter  /* Mark the symbol_ref as belonging to this constants pool.  */
3012132718Skan  CONSTANT_POOL_ADDRESS_P (symbol) = 1;
3013132718Skan  SYMBOL_REF_FLAGS (symbol) = SYMBOL_FLAG_LOCAL;
301418334Speter  current_function_uses_const_pool = 1;
301518334Speter
3016132718Skan  return copy_rtx (def);
301718334Speter}
301818334Speter
301918334Speter/* Given a SYMBOL_REF with CONSTANT_POOL_ADDRESS_P true, return a pointer to
302018334Speter   the corresponding pool_constant structure.  */
302118334Speter
302218334Speterstatic struct pool_constant *
3023132718Skanfind_pool_constant (struct function *f, rtx addr)
302418334Speter{
302590075Sobrien  struct pool_constant *pool;
302690075Sobrien  const char *label = XSTR (addr, 0);
302718334Speter
302890075Sobrien  for (pool = f->varasm->x_const_rtx_sym_hash_table[SYMHASH (label)]; pool;
302990075Sobrien       pool = pool->next_sym)
303090075Sobrien    if (XSTR (XEXP (pool->desc->rtl, 0), 0) == label)
303190075Sobrien      return pool;
303218334Speter
303318334Speter  abort ();
303418334Speter}
303518334Speter
303618334Speter/* Given a constant pool SYMBOL_REF, return the corresponding constant.  */
303718334Speter
303818334Speterrtx
3039132718Skanget_pool_constant (rtx addr)
304018334Speter{
304190075Sobrien  return (find_pool_constant (cfun, addr))->constant;
304218334Speter}
304318334Speter
304496263Sobrien/* Given a constant pool SYMBOL_REF, return the corresponding constant
304596263Sobrien   and whether it has been output or not.  */
304696263Sobrien
304796263Sobrienrtx
3048132718Skanget_pool_constant_mark (rtx addr, bool *pmarked)
304996263Sobrien{
305096263Sobrien  struct pool_constant *pool = find_pool_constant (cfun, addr);
305196263Sobrien  *pmarked = (pool->mark != 0);
305296263Sobrien  return pool->constant;
305396263Sobrien}
305496263Sobrien
305590075Sobrien/* Likewise, but for the constant pool of a specific function.  */
305690075Sobrien
305790075Sobrienrtx
3058132718Skanget_pool_constant_for_function (struct function *f, rtx addr)
305990075Sobrien{
306090075Sobrien  return (find_pool_constant (f, addr))->constant;
306190075Sobrien}
306290075Sobrien
306318334Speter/* Similar, return the mode.  */
306418334Speter
306518334Speterenum machine_mode
3066132718Skanget_pool_mode (rtx addr)
306718334Speter{
306890075Sobrien  return (find_pool_constant (cfun, addr))->mode;
306918334Speter}
307018334Speter
307190075Sobrienenum machine_mode
3072132718Skanget_pool_mode_for_function (struct function *f, rtx addr)
307390075Sobrien{
307490075Sobrien  return (find_pool_constant (f, addr))->mode;
307590075Sobrien}
307690075Sobrien
307718334Speter/* Similar, return the offset in the constant pool.  */
307818334Speter
307918334Speterint
3080132718Skanget_pool_offset (rtx addr)
308118334Speter{
308290075Sobrien  return (find_pool_constant (cfun, addr))->offset;
308318334Speter}
308418334Speter
308518334Speter/* Return the size of the constant pool.  */
308618334Speter
308718334Speterint
3088132718Skanget_pool_size (void)
308918334Speter{
309018334Speter  return pool_offset;
309118334Speter}
309218334Speter
309318334Speter/* Write all the constants in the constant pool.  */
309418334Speter
309518334Spetervoid
3096132718Skanoutput_constant_pool (const char *fnname ATTRIBUTE_UNUSED,
3097132718Skan		      tree fndecl ATTRIBUTE_UNUSED)
309818334Speter{
309918334Speter  struct pool_constant *pool;
310018334Speter  rtx x;
3101117395Skan  REAL_VALUE_TYPE r;
310218334Speter
310350397Sobrien  /* It is possible for gcc to call force_const_mem and then to later
310450397Sobrien     discard the instructions which refer to the constant.  In such a
310550397Sobrien     case we do not need to output the constant.  */
310652284Sobrien  mark_constant_pool ();
310750397Sobrien
310818334Speter#ifdef ASM_OUTPUT_POOL_PROLOGUE
310918334Speter  ASM_OUTPUT_POOL_PROLOGUE (asm_out_file, fnname, fndecl, pool_offset);
311018334Speter#endif
311118334Speter
311218334Speter  for (pool = first_pool; pool; pool = pool->next)
311318334Speter    {
311490075Sobrien      rtx tmp;
311590075Sobrien
311618334Speter      x = pool->constant;
311718334Speter
311850397Sobrien      if (! pool->mark)
311950397Sobrien	continue;
312050397Sobrien
312118334Speter      /* See if X is a LABEL_REF (or a CONST referring to a LABEL_REF)
312218334Speter	 whose CODE_LABEL has been deleted.  This can occur if a jump table
312318334Speter	 is eliminated by optimization.  If so, write a constant of zero
312418334Speter	 instead.  Note that this can also happen by turning the
312518334Speter	 CODE_LABEL into a NOTE.  */
312690075Sobrien      /* ??? This seems completely and utterly wrong.  Certainly it's
312790075Sobrien	 not true for NOTE_INSN_DELETED_LABEL, but I disbelieve proper
312890075Sobrien	 functioning even with INSN_DELETED_P and friends.  */
312918334Speter
313090075Sobrien      tmp = x;
313190075Sobrien      switch (GET_CODE (x))
313290075Sobrien	{
313390075Sobrien	case CONST:
313490075Sobrien	  if (GET_CODE (XEXP (x, 0)) != PLUS
313590075Sobrien	      || GET_CODE (XEXP (XEXP (x, 0), 0)) != LABEL_REF)
313690075Sobrien	    break;
313790075Sobrien	  tmp = XEXP (XEXP (x, 0), 0);
3138132718Skan	  /* Fall through.  */
313990075Sobrien
314090075Sobrien	case LABEL_REF:
314190075Sobrien	  tmp = XEXP (x, 0);
314290075Sobrien	  if (INSN_DELETED_P (tmp)
314390075Sobrien	      || (GET_CODE (tmp) == NOTE
314490075Sobrien		  && NOTE_LINE_NUMBER (tmp) == NOTE_INSN_DELETED))
314590075Sobrien	    {
314690075Sobrien	      abort ();
314790075Sobrien	      x = const0_rtx;
314890075Sobrien	    }
314990075Sobrien	  break;
315090075Sobrien
315190075Sobrien	default:
315290075Sobrien	  break;
315390075Sobrien	}
315490075Sobrien
315518334Speter      /* First switch to correct section.  */
3156117395Skan      (*targetm.asm_out.select_rtx_section) (pool->mode, x, pool->align);
315718334Speter
315818334Speter#ifdef ASM_OUTPUT_SPECIAL_POOL_ENTRY
315918334Speter      ASM_OUTPUT_SPECIAL_POOL_ENTRY (asm_out_file, x, pool->mode,
316018334Speter				     pool->align, pool->labelno, done);
316118334Speter#endif
316218334Speter
316390075Sobrien      assemble_align (pool->align);
316418334Speter
316518334Speter      /* Output the label.  */
3166132718Skan      (*targetm.asm_out.internal_label) (asm_out_file, "LC", pool->labelno);
316718334Speter
316818334Speter      /* Output the value of the constant itself.  */
316918334Speter      switch (GET_MODE_CLASS (pool->mode))
317018334Speter	{
317118334Speter	case MODE_FLOAT:
317218334Speter	  if (GET_CODE (x) != CONST_DOUBLE)
317318334Speter	    abort ();
317418334Speter
3175117395Skan	  REAL_VALUE_FROM_CONST_DOUBLE (r, x);
3176117395Skan	  assemble_real (r, pool->mode, pool->align);
317718334Speter	  break;
317818334Speter
317918334Speter	case MODE_INT:
318018334Speter	case MODE_PARTIAL_INT:
318190075Sobrien	  assemble_integer (x, GET_MODE_SIZE (pool->mode), pool->align, 1);
318218334Speter	  break;
318318334Speter
318496263Sobrien	case MODE_VECTOR_FLOAT:
318596263Sobrien	  {
318696263Sobrien	    int i, units;
318796263Sobrien	    rtx elt;
318896263Sobrien
318996263Sobrien	    if (GET_CODE (x) != CONST_VECTOR)
319096263Sobrien	      abort ();
319196263Sobrien
319296263Sobrien	    units = CONST_VECTOR_NUNITS (x);
319396263Sobrien
319496263Sobrien	    for (i = 0; i < units; i++)
319596263Sobrien	      {
319696263Sobrien		elt = CONST_VECTOR_ELT (x, i);
3197117395Skan		REAL_VALUE_FROM_CONST_DOUBLE (r, elt);
3198117395Skan		assemble_real (r, GET_MODE_INNER (pool->mode), pool->align);
319996263Sobrien	      }
320096263Sobrien	  }
320196263Sobrien	  break;
320296263Sobrien
3203117395Skan	case MODE_VECTOR_INT:
320496263Sobrien	  {
320596263Sobrien	    int i, units;
320696263Sobrien	    rtx elt;
320796263Sobrien
320896263Sobrien	    if (GET_CODE (x) != CONST_VECTOR)
320996263Sobrien	      abort ();
321096263Sobrien
321196263Sobrien	    units = CONST_VECTOR_NUNITS (x);
321296263Sobrien
321396263Sobrien	    for (i = 0; i < units; i++)
321496263Sobrien	      {
321596263Sobrien		elt = CONST_VECTOR_ELT (x, i);
321696263Sobrien		assemble_integer (elt, GET_MODE_UNIT_SIZE (pool->mode),
321796263Sobrien				  pool->align, 1);
321896263Sobrien	      }
321996263Sobrien	  }
322096263Sobrien	  break;
322196263Sobrien
322218334Speter	default:
322318334Speter	  abort ();
322418334Speter	}
322518334Speter
3226117395Skan      /* Make sure all constants in SECTION_MERGE and not SECTION_STRINGS
3227117395Skan	 sections have proper size.  */
3228117395Skan      if (pool->align > GET_MODE_BITSIZE (pool->mode)
3229117395Skan	  && in_section == in_named
3230117395Skan	  && get_named_section_flags (in_named_name) & SECTION_MERGE)
3231117395Skan	assemble_align (pool->align);
3232117395Skan
323350397Sobrien#ifdef ASM_OUTPUT_SPECIAL_POOL_ENTRY
323418334Speter    done: ;
323550397Sobrien#endif
323618334Speter    }
323718334Speter
323850397Sobrien#ifdef ASM_OUTPUT_POOL_EPILOGUE
323950397Sobrien  ASM_OUTPUT_POOL_EPILOGUE (asm_out_file, fnname, fndecl, pool_offset);
324050397Sobrien#endif
324150397Sobrien
324218334Speter  /* Done with this pool.  */
324318334Speter  first_pool = last_pool = 0;
324418334Speter}
324550397Sobrien
324650397Sobrien/* Look through the instructions for this function, and mark all the
3247132718Skan   entries in the constant pool which are actually being used.  Emit
3248132718Skan   deferred constants which have indeed been used.  */
324950397Sobrien
325050397Sobrienstatic void
3251132718Skanmark_constant_pool (void)
325250397Sobrien{
325390075Sobrien  rtx insn;
3254117395Skan  rtx link;
325550397Sobrien  struct pool_constant *pool;
325650397Sobrien
3257132718Skan  if (first_pool == 0 && n_deferred_constants == 0)
325850397Sobrien    return;
325950397Sobrien
326050397Sobrien  for (pool = first_pool; pool; pool = pool->next)
326150397Sobrien    pool->mark = 0;
326250397Sobrien
326350397Sobrien  for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
326490075Sobrien    if (INSN_P (insn))
326550397Sobrien      mark_constants (PATTERN (insn));
326650397Sobrien
3267117395Skan  for (link = current_function_epilogue_delay_list;
3268117395Skan       link;
3269117395Skan       link = XEXP (link, 1))
3270117395Skan    {
3271117395Skan      insn = XEXP (link, 0);
3272117395Skan
3273117395Skan      if (INSN_P (insn))
3274117395Skan	mark_constants (PATTERN (insn));
3275117395Skan    }
327690075Sobrien}
327752284Sobrien
327890075Sobrien/* Look through appropriate parts of X, marking all entries in the
327990075Sobrien   constant pool which are actually being used.  Entries that are only
328090075Sobrien   referenced by other constants are also marked as used.  Emit
328190075Sobrien   deferred strings that are used.  */
328252284Sobrien
328350397Sobrienstatic void
3284132718Skanmark_constants (rtx x)
328550397Sobrien{
328690075Sobrien  int i;
328790075Sobrien  const char *format_ptr;
328850397Sobrien
328950397Sobrien  if (x == 0)
329050397Sobrien    return;
329150397Sobrien
329250397Sobrien  if (GET_CODE (x) == SYMBOL_REF)
329350397Sobrien    {
329490075Sobrien      mark_constant (&x, NULL);
329550397Sobrien      return;
329650397Sobrien    }
329750397Sobrien
329850397Sobrien  /* Insns may appear inside a SEQUENCE.  Only check the patterns of
329950397Sobrien     insns, not any notes that may be attached.  We don't want to mark
330050397Sobrien     a constant just because it happens to appear in a REG_EQUIV note.  */
330190075Sobrien  if (INSN_P (x))
330250397Sobrien    {
330350397Sobrien      mark_constants (PATTERN (x));
330450397Sobrien      return;
330550397Sobrien    }
330650397Sobrien
330750397Sobrien  format_ptr = GET_RTX_FORMAT (GET_CODE (x));
330850397Sobrien
330950397Sobrien  for (i = 0; i < GET_RTX_LENGTH (GET_CODE (x)); i++)
331050397Sobrien    {
331150397Sobrien      switch (*format_ptr++)
331250397Sobrien	{
331350397Sobrien	case 'e':
331450397Sobrien	  mark_constants (XEXP (x, i));
331550397Sobrien	  break;
331650397Sobrien
331750397Sobrien	case 'E':
331850397Sobrien	  if (XVEC (x, i) != 0)
331950397Sobrien	    {
332090075Sobrien	      int j;
332150397Sobrien
332250397Sobrien	      for (j = 0; j < XVECLEN (x, i); j++)
332350397Sobrien		mark_constants (XVECEXP (x, i, j));
332450397Sobrien	    }
332550397Sobrien	  break;
332650397Sobrien
332750397Sobrien	case 'S':
332850397Sobrien	case 's':
332950397Sobrien	case '0':
333050397Sobrien	case 'i':
333150397Sobrien	case 'w':
333250397Sobrien	case 'n':
333350397Sobrien	case 'u':
3334117395Skan	case 'B':
333550397Sobrien	  break;
333650397Sobrien
333750397Sobrien	default:
333850397Sobrien	  abort ();
333950397Sobrien	}
334050397Sobrien    }
334150397Sobrien}
334290075Sobrien
334390075Sobrien/* Given a SYMBOL_REF CURRENT_RTX, mark it and all constants it refers
334490075Sobrien   to as used.  Emit referenced deferred strings.  This function can
334590075Sobrien   be used with for_each_rtx to mark all SYMBOL_REFs in an rtx.  */
334690075Sobrien
334790075Sobrienstatic int
3348132718Skanmark_constant (rtx *current_rtx, void *data ATTRIBUTE_UNUSED)
334990075Sobrien{
335090075Sobrien  rtx x = *current_rtx;
335190075Sobrien
335290075Sobrien  if (x == NULL_RTX)
335390075Sobrien    return 0;
335490075Sobrien
335590075Sobrien  else if (GET_CODE (x) == SYMBOL_REF)
335690075Sobrien    {
335790075Sobrien      if (CONSTANT_POOL_ADDRESS_P (x))
335890075Sobrien	{
335990075Sobrien	  struct pool_constant *pool = find_pool_constant (cfun, x);
3360117395Skan	  if (pool->mark == 0)
3361117395Skan	    {
3362117395Skan	      pool->mark = 1;
3363117395Skan	      for_each_rtx (&(pool->constant), &mark_constant, NULL);
3364117395Skan	    }
336590075Sobrien	  else
336690075Sobrien	    return -1;
336790075Sobrien	}
3368132718Skan      else if (TREE_CONSTANT_POOL_ADDRESS_P (x))
336990075Sobrien	{
3370132718Skan	  tree exp = SYMBOL_REF_DECL (x);
3371132718Skan	  if (!TREE_ASM_WRITTEN (exp))
337290075Sobrien	    {
3373132718Skan	      n_deferred_constants--;
3374132718Skan	      output_constant_def_contents (x);
337590075Sobrien	    }
337690075Sobrien	}
337790075Sobrien    }
337890075Sobrien  return 0;
337990075Sobrien}
338018334Speter
3381132718Skan/* Determine what kind of relocations EXP may need.  */
338218334Speter
3383132718Skanint
3384132718Skancompute_reloc_for_constant (tree exp)
338518334Speter{
3386117395Skan  int reloc = 0, reloc2;
338790075Sobrien  tree tem;
338818334Speter
338990075Sobrien  /* Give the front-end a chance to convert VALUE to something that
339090075Sobrien     looks more like a constant to the back-end.  */
339190075Sobrien  exp = (*lang_hooks.expand_constant) (exp);
339290075Sobrien
339318334Speter  switch (TREE_CODE (exp))
339418334Speter    {
339518334Speter    case ADDR_EXPR:
3396102780Skan    case FDESC_EXPR:
339790075Sobrien      /* Go inside any operations that get_inner_reference can handle and see
339890075Sobrien	 if what's inside is a constant: no need to do anything here for
339990075Sobrien	 addresses of variables or functions.  */
340090075Sobrien      for (tem = TREE_OPERAND (exp, 0); handled_component_p (tem);
340190075Sobrien	   tem = TREE_OPERAND (tem, 0))
340290075Sobrien	;
340318334Speter
340490075Sobrien      if (TREE_PUBLIC (tem))
340590075Sobrien	reloc |= 2;
340690075Sobrien      else
340790075Sobrien	reloc |= 1;
340818334Speter      break;
340918334Speter
341018334Speter    case PLUS_EXPR:
3411132718Skan      reloc = compute_reloc_for_constant (TREE_OPERAND (exp, 0));
3412132718Skan      reloc |= compute_reloc_for_constant (TREE_OPERAND (exp, 1));
341318334Speter      break;
341418334Speter
3415117395Skan    case MINUS_EXPR:
3416132718Skan      reloc = compute_reloc_for_constant (TREE_OPERAND (exp, 0));
3417132718Skan      reloc2 = compute_reloc_for_constant (TREE_OPERAND (exp, 1));
3418117395Skan      /* The difference of two local labels is computable at link time.  */
3419117395Skan      if (reloc == 1 && reloc2 == 1)
3420117395Skan	reloc = 0;
3421117395Skan      else
3422117395Skan	reloc |= reloc2;
3423117395Skan      break;
3424117395Skan
342518334Speter    case NOP_EXPR:
342618334Speter    case CONVERT_EXPR:
342718334Speter    case NON_LVALUE_EXPR:
3428132718Skan      reloc = compute_reloc_for_constant (TREE_OPERAND (exp, 0));
342918334Speter      break;
343018334Speter
343118334Speter    case CONSTRUCTOR:
343290075Sobrien      for (tem = CONSTRUCTOR_ELTS (exp); tem; tem = TREE_CHAIN (tem))
343390075Sobrien	if (TREE_VALUE (tem) != 0)
3434132718Skan	  reloc |= compute_reloc_for_constant (TREE_VALUE (tem));
343590075Sobrien
343618334Speter      break;
343718334Speter
343850397Sobrien    default:
343918334Speter      break;
344018334Speter    }
344118334Speter  return reloc;
344218334Speter}
3443132718Skan
3444132718Skan/* Find all the constants whose addresses are referenced inside of EXP,
3445132718Skan   and make sure assembler code with a label has been output for each one.
3446132718Skan   Indicate whether an ADDR_EXPR has been encountered.  */
3447132718Skan
3448132718Skanstatic void
3449132718Skanoutput_addressed_constants (tree exp)
3450132718Skan{
3451132718Skan  tree tem;
3452132718Skan
3453132718Skan  /* Give the front-end a chance to convert VALUE to something that
3454132718Skan     looks more like a constant to the back-end.  */
3455132718Skan  exp = (*lang_hooks.expand_constant) (exp);
3456132718Skan
3457132718Skan  switch (TREE_CODE (exp))
3458132718Skan    {
3459132718Skan    case ADDR_EXPR:
3460132718Skan    case FDESC_EXPR:
3461132718Skan      /* Go inside any operations that get_inner_reference can handle and see
3462132718Skan	 if what's inside is a constant: no need to do anything here for
3463132718Skan	 addresses of variables or functions.  */
3464132718Skan      for (tem = TREE_OPERAND (exp, 0); handled_component_p (tem);
3465132718Skan	   tem = TREE_OPERAND (tem, 0))
3466132718Skan	;
3467132718Skan
3468132718Skan      if (TREE_CODE_CLASS (TREE_CODE (tem)) == 'c'
3469132718Skan	  || TREE_CODE (tem) == CONSTRUCTOR)
3470132718Skan	output_constant_def (tem, 0);
3471132718Skan      break;
3472132718Skan
3473132718Skan    case PLUS_EXPR:
3474132718Skan    case MINUS_EXPR:
3475132718Skan      output_addressed_constants (TREE_OPERAND (exp, 1));
3476132718Skan      /* Fall through.  */
3477132718Skan
3478132718Skan    case NOP_EXPR:
3479132718Skan    case CONVERT_EXPR:
3480132718Skan    case NON_LVALUE_EXPR:
3481132718Skan      output_addressed_constants (TREE_OPERAND (exp, 0));
3482132718Skan      break;
3483132718Skan
3484132718Skan    case CONSTRUCTOR:
3485132718Skan      for (tem = CONSTRUCTOR_ELTS (exp); tem; tem = TREE_CHAIN (tem))
3486132718Skan	if (TREE_VALUE (tem) != 0)
3487132718Skan	  output_addressed_constants (TREE_VALUE (tem));
3488132718Skan
3489132718Skan      break;
3490132718Skan
3491132718Skan    default:
3492132718Skan      break;
3493132718Skan    }
3494132718Skan}
349518334Speter
349690075Sobrien/* Return nonzero if VALUE is a valid constant-valued expression
349790075Sobrien   for use in initializing a static variable; one that can be an
349890075Sobrien   element of a "constant" initializer.
349990075Sobrien
350090075Sobrien   Return null_pointer_node if the value is absolute;
350190075Sobrien   if it is relocatable, return the variable that determines the relocation.
350290075Sobrien   We assume that VALUE has been folded as much as possible;
350390075Sobrien   therefore, we do not need to check for such things as
350490075Sobrien   arithmetic-combinations of integers.  */
350590075Sobrien
350690075Sobrientree
3507132718Skaninitializer_constant_valid_p (tree value, tree endtype)
350890075Sobrien{
350990075Sobrien  /* Give the front-end a chance to convert VALUE to something that
351090075Sobrien     looks more like a constant to the back-end.  */
351190075Sobrien  value = (*lang_hooks.expand_constant) (value);
351290075Sobrien
351390075Sobrien  switch (TREE_CODE (value))
351490075Sobrien    {
351590075Sobrien    case CONSTRUCTOR:
351690075Sobrien      if ((TREE_CODE (TREE_TYPE (value)) == UNION_TYPE
351790075Sobrien	   || TREE_CODE (TREE_TYPE (value)) == RECORD_TYPE)
351890075Sobrien	  && TREE_CONSTANT (value)
351990075Sobrien	  && CONSTRUCTOR_ELTS (value))
3520122180Skan	{
3521122180Skan	  tree elt;
3522122180Skan	  bool absolute = true;
352390075Sobrien
3524122180Skan	  for (elt = CONSTRUCTOR_ELTS (value); elt; elt = TREE_CHAIN (elt))
3525122180Skan	    {
3526122180Skan	      tree reloc;
3527122180Skan	      value = TREE_VALUE (elt);
3528122180Skan	      reloc = initializer_constant_valid_p (value, TREE_TYPE (value));
3529122180Skan	      if (!reloc)
3530122180Skan		return NULL_TREE;
3531122180Skan	      if (reloc != null_pointer_node)
3532122180Skan		absolute = false;
3533122180Skan	    }
3534122180Skan	  /* For a non-absolute relocation, there is no single
3535122180Skan	     variable that can be "the variable that determines the
3536122180Skan	     relocation."  */
3537122180Skan	  return absolute ? null_pointer_node : error_mark_node;
3538122180Skan	}
353990075Sobrien
3540122180Skan      return TREE_STATIC (value) ? null_pointer_node : NULL_TREE;
3541122180Skan
354290075Sobrien    case INTEGER_CST:
354396263Sobrien    case VECTOR_CST:
354490075Sobrien    case REAL_CST:
354590075Sobrien    case STRING_CST:
354690075Sobrien    case COMPLEX_CST:
354790075Sobrien      return null_pointer_node;
354890075Sobrien
354990075Sobrien    case ADDR_EXPR:
355090075Sobrien    case FDESC_EXPR:
355190075Sobrien      return staticp (TREE_OPERAND (value, 0)) ? TREE_OPERAND (value, 0) : 0;
355290075Sobrien
355390075Sobrien    case VIEW_CONVERT_EXPR:
355490075Sobrien    case NON_LVALUE_EXPR:
355590075Sobrien      return initializer_constant_valid_p (TREE_OPERAND (value, 0), endtype);
355690075Sobrien
355790075Sobrien    case CONVERT_EXPR:
355890075Sobrien    case NOP_EXPR:
3559146895Skan      {
3560146895Skan	tree src;
3561146895Skan	tree src_type;
3562146895Skan	tree dest_type;
356390075Sobrien
3564146895Skan	src = TREE_OPERAND (value, 0);
3565146895Skan	src_type = TREE_TYPE (src);
3566146895Skan	dest_type = TREE_TYPE (value);
356790075Sobrien
3568146895Skan	/* Allow conversions between pointer types, floating-point
3569146895Skan	   types, and offset types.  */
3570146895Skan	if ((POINTER_TYPE_P (dest_type) && POINTER_TYPE_P (src_type))
3571146895Skan	    || (FLOAT_TYPE_P (dest_type) && FLOAT_TYPE_P (src_type))
3572146895Skan	    || (TREE_CODE (dest_type) == OFFSET_TYPE
3573146895Skan		&& TREE_CODE (src_type) == OFFSET_TYPE))
3574146895Skan	  return initializer_constant_valid_p (src, endtype);
357590075Sobrien
3576146895Skan	/* Allow length-preserving conversions between integer types.  */
3577146895Skan	if (INTEGRAL_TYPE_P (dest_type) && INTEGRAL_TYPE_P (src_type)
3578146895Skan	    && (TYPE_PRECISION (dest_type) == TYPE_PRECISION (src_type)))
3579146895Skan	  return initializer_constant_valid_p (src, endtype);
358090075Sobrien
3581146895Skan	/* Allow conversions between other integer types only if
3582146895Skan	   explicit value.  */
3583146895Skan	if (INTEGRAL_TYPE_P (dest_type) && INTEGRAL_TYPE_P (src_type))
3584146895Skan	  {
3585146895Skan	    tree inner = initializer_constant_valid_p (src, endtype);
3586146895Skan	    if (inner == null_pointer_node)
3587146895Skan	      return null_pointer_node;
3588146895Skan	    break;
3589146895Skan	  }
359090075Sobrien
3591146895Skan	/* Allow (int) &foo provided int is as wide as a pointer.  */
3592146895Skan	if (INTEGRAL_TYPE_P (dest_type) && POINTER_TYPE_P (src_type)
3593146895Skan	    && (TYPE_PRECISION (dest_type) >= TYPE_PRECISION (src_type)))
3594146895Skan	  return initializer_constant_valid_p (src, endtype);
359590075Sobrien
3596146895Skan	/* Likewise conversions from int to pointers, but also allow
3597146895Skan	   conversions from 0.  */
3598146895Skan	if ((POINTER_TYPE_P (dest_type)
3599146895Skan	     || TREE_CODE (dest_type) == OFFSET_TYPE)
3600146895Skan	    && INTEGRAL_TYPE_P (src_type))
3601146895Skan	  {
3602146895Skan	    if (integer_zerop (src))
3603146895Skan	      return null_pointer_node;
3604146895Skan	    else if (TYPE_PRECISION (dest_type) <= TYPE_PRECISION (src_type))
3605146895Skan	      return initializer_constant_valid_p (src, endtype);
3606146895Skan	  }
3607146895Skan
3608146895Skan	/* Allow conversions to struct or union types if the value
3609146895Skan	   inside is okay.  */
3610146895Skan	if (TREE_CODE (dest_type) == RECORD_TYPE
3611146895Skan	    || TREE_CODE (dest_type) == UNION_TYPE)
3612146895Skan	  return initializer_constant_valid_p (src, endtype);
3613146895Skan      }
361490075Sobrien      break;
361590075Sobrien
361690075Sobrien    case PLUS_EXPR:
361790075Sobrien      if (! INTEGRAL_TYPE_P (endtype)
361890075Sobrien	  || TYPE_PRECISION (endtype) >= POINTER_SIZE)
3619117395Skan	{
362090075Sobrien	  tree valid0 = initializer_constant_valid_p (TREE_OPERAND (value, 0),
362190075Sobrien						      endtype);
362290075Sobrien	  tree valid1 = initializer_constant_valid_p (TREE_OPERAND (value, 1),
362390075Sobrien						      endtype);
362490075Sobrien	  /* If either term is absolute, use the other terms relocation.  */
362590075Sobrien	  if (valid0 == null_pointer_node)
362690075Sobrien	    return valid1;
362790075Sobrien	  if (valid1 == null_pointer_node)
362890075Sobrien	    return valid0;
3629117395Skan	}
363090075Sobrien      break;
363190075Sobrien
363290075Sobrien    case MINUS_EXPR:
363390075Sobrien      if (! INTEGRAL_TYPE_P (endtype)
363490075Sobrien	  || TYPE_PRECISION (endtype) >= POINTER_SIZE)
363590075Sobrien	{
363690075Sobrien	  tree valid0 = initializer_constant_valid_p (TREE_OPERAND (value, 0),
363790075Sobrien						      endtype);
363890075Sobrien	  tree valid1 = initializer_constant_valid_p (TREE_OPERAND (value, 1),
363990075Sobrien						      endtype);
364090075Sobrien	  /* Win if second argument is absolute.  */
364190075Sobrien	  if (valid1 == null_pointer_node)
364290075Sobrien	    return valid0;
364390075Sobrien	  /* Win if both arguments have the same relocation.
364490075Sobrien	     Then the value is absolute.  */
364590075Sobrien	  if (valid0 == valid1 && valid0 != 0)
364690075Sobrien	    return null_pointer_node;
364790075Sobrien
364890075Sobrien	  /* Since GCC guarantees that string constants are unique in the
364990075Sobrien	     generated code, a subtraction between two copies of the same
365090075Sobrien	     constant string is absolute.  */
365190075Sobrien	  if (valid0 && TREE_CODE (valid0) == STRING_CST &&
365290075Sobrien	      valid1 && TREE_CODE (valid1) == STRING_CST &&
365390075Sobrien	      TREE_STRING_POINTER (valid0) == TREE_STRING_POINTER (valid1))
365490075Sobrien	    return null_pointer_node;
365590075Sobrien	}
365690075Sobrien
365790075Sobrien      /* Support differences between labels.  */
365890075Sobrien      if (INTEGRAL_TYPE_P (endtype))
365990075Sobrien	{
366090075Sobrien	  tree op0, op1;
366190075Sobrien	  op0 = TREE_OPERAND (value, 0);
366290075Sobrien	  op1 = TREE_OPERAND (value, 1);
366390075Sobrien
366496263Sobrien	  /* Like STRIP_NOPS except allow the operand mode to widen.
3665132718Skan	     This works around a feature of fold that simplifies
366696263Sobrien	     (int)(p1 - p2) to ((int)p1 - (int)p2) under the theory
366796263Sobrien	     that the narrower operation is cheaper.  */
366896263Sobrien
366996263Sobrien	  while (TREE_CODE (op0) == NOP_EXPR
367096263Sobrien		 || TREE_CODE (op0) == CONVERT_EXPR
367196263Sobrien		 || TREE_CODE (op0) == NON_LVALUE_EXPR)
367296263Sobrien	    {
367396263Sobrien	      tree inner = TREE_OPERAND (op0, 0);
367496263Sobrien	      if (inner == error_mark_node
367596263Sobrien	          || ! INTEGRAL_MODE_P (TYPE_MODE (TREE_TYPE (inner)))
367696263Sobrien		  || (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (op0)))
367796263Sobrien		      > GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (inner)))))
367896263Sobrien		break;
367996263Sobrien	      op0 = inner;
368096263Sobrien	    }
368196263Sobrien
368296263Sobrien	  while (TREE_CODE (op1) == NOP_EXPR
368396263Sobrien		 || TREE_CODE (op1) == CONVERT_EXPR
368496263Sobrien		 || TREE_CODE (op1) == NON_LVALUE_EXPR)
368596263Sobrien	    {
368696263Sobrien	      tree inner = TREE_OPERAND (op1, 0);
368796263Sobrien	      if (inner == error_mark_node
368896263Sobrien	          || ! INTEGRAL_MODE_P (TYPE_MODE (TREE_TYPE (inner)))
368996263Sobrien		  || (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (op1)))
369096263Sobrien		      > GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (inner)))))
369196263Sobrien		break;
369296263Sobrien	      op1 = inner;
369396263Sobrien	    }
369496263Sobrien
369590075Sobrien	  if (TREE_CODE (op0) == ADDR_EXPR
369690075Sobrien	      && TREE_CODE (TREE_OPERAND (op0, 0)) == LABEL_DECL
369790075Sobrien	      && TREE_CODE (op1) == ADDR_EXPR
369890075Sobrien	      && TREE_CODE (TREE_OPERAND (op1, 0)) == LABEL_DECL)
369990075Sobrien	    return null_pointer_node;
370090075Sobrien	}
370190075Sobrien      break;
370290075Sobrien
370390075Sobrien    default:
370490075Sobrien      break;
370590075Sobrien    }
370690075Sobrien
370790075Sobrien  return 0;
370890075Sobrien}
370990075Sobrien
371018334Speter/* Output assembler code for constant EXP to FILE, with no label.
371118334Speter   This includes the pseudo-op such as ".int" or ".byte", and a newline.
371218334Speter   Assumes output_addressed_constants has been done on EXP already.
371318334Speter
371418334Speter   Generate exactly SIZE bytes of assembler data, padding at the end
371518334Speter   with zeros if necessary.  SIZE must always be specified.
371618334Speter
371718334Speter   SIZE is important for structure constructors,
371818334Speter   since trailing members may have been omitted from the constructor.
371918334Speter   It is also important for initialization of arrays from string constants
372018334Speter   since the full length of the string constant might not be wanted.
372118334Speter   It is also needed for initialization of unions, where the initializer's
372218334Speter   type is just one member, and that may not be as long as the union.
372318334Speter
372418334Speter   There a case in which we would fail to output exactly SIZE bytes:
372518334Speter   for a structure constructor that wants to produce more than SIZE bytes.
372690075Sobrien   But such constructors will never be generated for any possible input.
372718334Speter
372890075Sobrien   ALIGN is the alignment of the data in bits.  */
372990075Sobrien
373018334Spetervoid
3731132718Skanoutput_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align)
373218334Speter{
373390075Sobrien  enum tree_code code;
3734132718Skan  unsigned HOST_WIDE_INT thissize;
373518334Speter
3736132718Skan  /* Some front-ends use constants other than the standard language-independent
373790075Sobrien     varieties, but which may still be output directly.  Give the front-end a
373890075Sobrien     chance to convert EXP to a language-independent representation.  */
373990075Sobrien  exp = (*lang_hooks.expand_constant) (exp);
374052284Sobrien
374152284Sobrien  if (size == 0 || flag_syntax_only)
374218334Speter    return;
374318334Speter
374490075Sobrien  /* Eliminate any conversions since we'll be outputting the underlying
374590075Sobrien     constant.  */
374690075Sobrien  while (TREE_CODE (exp) == NOP_EXPR || TREE_CODE (exp) == CONVERT_EXPR
374790075Sobrien	 || TREE_CODE (exp) == NON_LVALUE_EXPR
374890075Sobrien	 || TREE_CODE (exp) == VIEW_CONVERT_EXPR)
374918334Speter    exp = TREE_OPERAND (exp, 0);
375018334Speter
375190075Sobrien  code = TREE_CODE (TREE_TYPE (exp));
375290075Sobrien  thissize = int_size_in_bytes (TREE_TYPE (exp));
375390075Sobrien
375418334Speter  /* Allow a constructor with no elements for any data type.
375518334Speter     This means to fill the space with zeros.  */
375618334Speter  if (TREE_CODE (exp) == CONSTRUCTOR && CONSTRUCTOR_ELTS (exp) == 0)
375718334Speter    {
375850397Sobrien      assemble_zeros (size);
375918334Speter      return;
376018334Speter    }
376118334Speter
376290075Sobrien  if (TREE_CODE (exp) == FDESC_EXPR)
376390075Sobrien    {
376490075Sobrien#ifdef ASM_OUTPUT_FDESC
376590075Sobrien      HOST_WIDE_INT part = tree_low_cst (TREE_OPERAND (exp, 1), 0);
376690075Sobrien      tree decl = TREE_OPERAND (exp, 0);
376790075Sobrien      ASM_OUTPUT_FDESC (asm_out_file, decl, part);
376890075Sobrien#else
376990075Sobrien      abort ();
377090075Sobrien#endif
377190075Sobrien      return;
377290075Sobrien    }
377390075Sobrien
377490075Sobrien  /* Now output the underlying data.  If we've handling the padding, return.
377590075Sobrien     Otherwise, break and ensure THISSIZE is the size written.  */
377618334Speter  switch (code)
377718334Speter    {
377818334Speter    case CHAR_TYPE:
377918334Speter    case BOOLEAN_TYPE:
378018334Speter    case INTEGER_TYPE:
378118334Speter    case ENUMERAL_TYPE:
378218334Speter    case POINTER_TYPE:
378318334Speter    case REFERENCE_TYPE:
3784132718Skan    case OFFSET_TYPE:
378518334Speter      if (! assemble_integer (expand_expr (exp, NULL_RTX, VOIDmode,
378618334Speter					   EXPAND_INITIALIZER),
378790075Sobrien			      size, align, 0))
378818334Speter	error ("initializer for integer value is too complicated");
378918334Speter      break;
379018334Speter
379118334Speter    case REAL_TYPE:
379218334Speter      if (TREE_CODE (exp) != REAL_CST)
379318334Speter	error ("initializer for floating value is not a floating constant");
379418334Speter
3795132718Skan      assemble_real (TREE_REAL_CST (exp), TYPE_MODE (TREE_TYPE (exp)), align);
379618334Speter      break;
379718334Speter
379818334Speter    case COMPLEX_TYPE:
379990075Sobrien      output_constant (TREE_REALPART (exp), thissize / 2, align);
380090075Sobrien      output_constant (TREE_IMAGPART (exp), thissize / 2,
380190075Sobrien		       min_align (align, BITS_PER_UNIT * (thissize / 2)));
380218334Speter      break;
380318334Speter
380418334Speter    case ARRAY_TYPE:
380596263Sobrien    case VECTOR_TYPE:
380618334Speter      if (TREE_CODE (exp) == CONSTRUCTOR)
380718334Speter	{
380890075Sobrien	  output_constructor (exp, size, align);
380918334Speter	  return;
381018334Speter	}
381118334Speter      else if (TREE_CODE (exp) == STRING_CST)
381218334Speter	{
3813132718Skan	  thissize = MIN ((unsigned HOST_WIDE_INT)TREE_STRING_LENGTH (exp),
3814132718Skan			  size);
381590075Sobrien	  assemble_string (TREE_STRING_POINTER (exp), thissize);
381618334Speter	}
3817119256Skan      else if (TREE_CODE (exp) == VECTOR_CST)
3818119256Skan	{
3819119256Skan	  int elt_size;
3820119256Skan	  tree link;
3821119256Skan	  unsigned int nalign;
3822119256Skan	  enum machine_mode inner;
3823119256Skan
3824119256Skan	  inner = GET_MODE_INNER (TYPE_MODE (TREE_TYPE (exp)));
3825119256Skan	  nalign = MIN (align, GET_MODE_ALIGNMENT (inner));
3826119256Skan
3827119256Skan	  elt_size = GET_MODE_UNIT_SIZE (TYPE_MODE (TREE_TYPE (exp)));
3828119256Skan
3829119256Skan	  link = TREE_VECTOR_CST_ELTS (exp);
3830119256Skan	  output_constant (TREE_VALUE (link), elt_size, align);
3831119256Skan	  while ((link = TREE_CHAIN (link)) != NULL)
3832119256Skan	    output_constant (TREE_VALUE (link), elt_size, nalign);
3833119256Skan	}
383418334Speter      else
383518334Speter	abort ();
383618334Speter      break;
383718334Speter
383818334Speter    case RECORD_TYPE:
383918334Speter    case UNION_TYPE:
384018334Speter      if (TREE_CODE (exp) == CONSTRUCTOR)
384190075Sobrien	output_constructor (exp, size, align);
384218334Speter      else
384318334Speter	abort ();
384418334Speter      return;
384518334Speter
384618334Speter    case SET_TYPE:
384718334Speter      if (TREE_CODE (exp) == INTEGER_CST)
384818334Speter	assemble_integer (expand_expr (exp, NULL_RTX,
384918334Speter				       VOIDmode, EXPAND_INITIALIZER),
3850117395Skan			  thissize, align, 1);
385118334Speter      else if (TREE_CODE (exp) == CONSTRUCTOR)
385218334Speter	{
3853132718Skan	  unsigned char *buffer = alloca (thissize);
385490075Sobrien	  if (get_set_constructor_bytes (exp, buffer, thissize))
385518334Speter	    abort ();
385690075Sobrien	  assemble_string ((char *) buffer, thissize);
385718334Speter	}
385818334Speter      else
385918334Speter	error ("unknown set constructor type");
386018334Speter      return;
386150397Sobrien
386290075Sobrien    case ERROR_MARK:
386390075Sobrien      return;
386490075Sobrien
386550397Sobrien    default:
386690075Sobrien      abort ();
386718334Speter    }
386818334Speter
3869132718Skan  if (size > thissize)
3870132718Skan    assemble_zeros (size - thissize);
387118334Speter}
387218334Speter
387318334Speter
387490075Sobrien/* Subroutine of output_constructor, used for computing the size of
387590075Sobrien   arrays of unspecified length.  VAL must be a CONSTRUCTOR of an array
387690075Sobrien   type with an unspecified upper bound.  */
387790075Sobrien
387890075Sobrienstatic unsigned HOST_WIDE_INT
3879132718Skanarray_size_for_constructor (tree val)
388090075Sobrien{
388190075Sobrien  tree max_index, i;
388290075Sobrien
388390075Sobrien  /* This code used to attempt to handle string constants that are not
388490075Sobrien     arrays of single-bytes, but nothing else does, so there's no point in
388590075Sobrien     doing it here.  */
388690075Sobrien  if (TREE_CODE (val) == STRING_CST)
388790075Sobrien    return TREE_STRING_LENGTH (val);
388890075Sobrien
388990075Sobrien  max_index = NULL_TREE;
3890117395Skan  for (i = CONSTRUCTOR_ELTS (val); i; i = TREE_CHAIN (i))
389190075Sobrien    {
389290075Sobrien      tree index = TREE_PURPOSE (i);
389390075Sobrien
389490075Sobrien      if (TREE_CODE (index) == RANGE_EXPR)
389590075Sobrien	index = TREE_OPERAND (index, 1);
389690075Sobrien      if (max_index == NULL_TREE || tree_int_cst_lt (max_index, index))
389790075Sobrien	max_index = index;
389890075Sobrien    }
389990075Sobrien
390090075Sobrien  if (max_index == NULL_TREE)
390190075Sobrien    return 0;
390290075Sobrien
390390075Sobrien  /* Compute the total number of array elements.  */
390490075Sobrien  i = size_binop (MINUS_EXPR, convert (sizetype, max_index),
390590075Sobrien		  convert (sizetype,
390690075Sobrien			   TYPE_MIN_VALUE (TYPE_DOMAIN (TREE_TYPE (val)))));
390790075Sobrien  i = size_binop (PLUS_EXPR, i, convert (sizetype, integer_one_node));
390890075Sobrien
390990075Sobrien  /* Multiply by the array element unit size to find number of bytes.  */
391090075Sobrien  i = size_binop (MULT_EXPR, i, TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (val))));
391190075Sobrien
391290075Sobrien  return tree_low_cst (i, 1);
391390075Sobrien}
391490075Sobrien
391590075Sobrien/* Subroutine of output_constant, used for CONSTRUCTORs (aggregate constants).
391618334Speter   Generate at least SIZE bytes, padding if necessary.  */
391718334Speter
391818334Speterstatic void
3919132718Skanoutput_constructor (tree exp, unsigned HOST_WIDE_INT size,
3920132718Skan		    unsigned int align)
392118334Speter{
392290075Sobrien  tree type = TREE_TYPE (exp);
392390075Sobrien  tree link, field = 0;
392490075Sobrien  tree min_index = 0;
392518334Speter  /* Number of bytes output or skipped so far.
392618334Speter     In other words, current position within the constructor.  */
392790075Sobrien  HOST_WIDE_INT total_bytes = 0;
3928132718Skan  /* Nonzero means BYTE contains part of a byte, to be output.  */
392918334Speter  int byte_buffer_in_use = 0;
393090075Sobrien  int byte = 0;
393118334Speter
393218334Speter  if (HOST_BITS_PER_WIDE_INT < BITS_PER_UNIT)
393318334Speter    abort ();
393418334Speter
393590075Sobrien  if (TREE_CODE (type) == RECORD_TYPE)
393690075Sobrien    field = TYPE_FIELDS (type);
393718334Speter
393890075Sobrien  if (TREE_CODE (type) == ARRAY_TYPE
393990075Sobrien      && TYPE_DOMAIN (type) != 0)
394090075Sobrien    min_index = TYPE_MIN_VALUE (TYPE_DOMAIN (type));
394118334Speter
394218334Speter  /* As LINK goes through the elements of the constant,
394318334Speter     FIELD goes through the structure fields, if the constant is a structure.
394418334Speter     if the constant is a union, then we override this,
394518334Speter     by getting the field from the TREE_LIST element.
394652284Sobrien     But the constant could also be an array.  Then FIELD is zero.
394752284Sobrien
394852284Sobrien     There is always a maximum of one element in the chain LINK for unions
394952284Sobrien     (even if the initializer in a source program incorrectly contains
395090075Sobrien     more one).  */
395118334Speter  for (link = CONSTRUCTOR_ELTS (exp);
395218334Speter       link;
395318334Speter       link = TREE_CHAIN (link),
395418334Speter       field = field ? TREE_CHAIN (field) : 0)
395518334Speter    {
395618334Speter      tree val = TREE_VALUE (link);
395718334Speter      tree index = 0;
395818334Speter
395990075Sobrien      /* The element in a union constructor specifies the proper field
396090075Sobrien	 or index.  */
396190075Sobrien      if ((TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE
396290075Sobrien	   || TREE_CODE (type) == QUAL_UNION_TYPE)
396390075Sobrien	  && TREE_PURPOSE (link) != 0)
396490075Sobrien	field = TREE_PURPOSE (link);
396518334Speter
396690075Sobrien      else if (TREE_CODE (type) == ARRAY_TYPE)
396718334Speter	index = TREE_PURPOSE (link);
396818334Speter
3969132718Skan#ifdef ASM_COMMENT_START
3970132718Skan      if (field && flag_verbose_asm)
3971132718Skan	fprintf (asm_out_file, "%s %s:\n",
3972132718Skan		 ASM_COMMENT_START,
3973132718Skan		 DECL_NAME (field)
3974132718Skan		 ? IDENTIFIER_POINTER (DECL_NAME (field))
3975132718Skan		 : "<anonymous>");
3976132718Skan#endif
3977132718Skan
397818334Speter      /* Eliminate the marker that makes a cast not be an lvalue.  */
397918334Speter      if (val != 0)
398018334Speter	STRIP_NOPS (val);
398118334Speter
398250397Sobrien      if (index && TREE_CODE (index) == RANGE_EXPR)
398318334Speter	{
398490075Sobrien	  unsigned HOST_WIDE_INT fieldsize
398590075Sobrien	    = int_size_in_bytes (TREE_TYPE (type));
398690075Sobrien	  HOST_WIDE_INT lo_index = tree_low_cst (TREE_OPERAND (index, 0), 0);
398790075Sobrien	  HOST_WIDE_INT hi_index = tree_low_cst (TREE_OPERAND (index, 1), 0);
398850397Sobrien	  HOST_WIDE_INT index;
398990075Sobrien	  unsigned int align2 = min_align (align, fieldsize * BITS_PER_UNIT);
399090075Sobrien
399150397Sobrien	  for (index = lo_index; index <= hi_index; index++)
399250397Sobrien	    {
399350397Sobrien	      /* Output the element's initial value.  */
399450397Sobrien	      if (val == 0)
399550397Sobrien		assemble_zeros (fieldsize);
399650397Sobrien	      else
399790075Sobrien		output_constant (val, fieldsize, align2);
399850397Sobrien
399950397Sobrien	      /* Count its size.  */
400050397Sobrien	      total_bytes += fieldsize;
400150397Sobrien	    }
400250397Sobrien	}
400350397Sobrien      else if (field == 0 || !DECL_BIT_FIELD (field))
400450397Sobrien	{
400518334Speter	  /* An element that is not a bit-field.  */
400618334Speter
400790075Sobrien	  unsigned HOST_WIDE_INT fieldsize;
400818334Speter	  /* Since this structure is static,
400918334Speter	     we know the positions are constant.  */
401090075Sobrien	  HOST_WIDE_INT pos = field ? int_byte_position (field) : 0;
401190075Sobrien	  unsigned int align2;
401290075Sobrien
401318334Speter	  if (index != 0)
401490075Sobrien	    pos = (tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (val)), 1)
401590075Sobrien		   * (tree_low_cst (index, 0) - tree_low_cst (min_index, 0)));
401618334Speter
401718334Speter	  /* Output any buffered-up bit-fields preceding this element.  */
401818334Speter	  if (byte_buffer_in_use)
401918334Speter	    {
402090075Sobrien	      assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1);
402118334Speter	      total_bytes++;
402218334Speter	      byte_buffer_in_use = 0;
402318334Speter	    }
402418334Speter
402518334Speter	  /* Advance to offset of this element.
402618334Speter	     Note no alignment needed in an array, since that is guaranteed
402718334Speter	     if each element has the proper size.  */
402890075Sobrien	  if ((field != 0 || index != 0) && pos != total_bytes)
402918334Speter	    {
403090075Sobrien	      assemble_zeros (pos - total_bytes);
403190075Sobrien	      total_bytes = pos;
403218334Speter	    }
403318334Speter
403490075Sobrien	  /* Find the alignment of this element.  */
403590075Sobrien	  align2 = min_align (align, BITS_PER_UNIT * pos);
403690075Sobrien
403718334Speter	  /* Determine size this element should occupy.  */
403818334Speter	  if (field)
403918334Speter	    {
404090075Sobrien	      fieldsize = 0;
404190075Sobrien
404290075Sobrien	      /* If this is an array with an unspecified upper bound,
404390075Sobrien		 the initializer determines the size.  */
404490075Sobrien	      /* ??? This ought to only checked if DECL_SIZE_UNIT is NULL,
404590075Sobrien		 but we cannot do this until the deprecated support for
404690075Sobrien		 initializing zero-length array members is removed.  */
404790075Sobrien	      if (TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE
404890075Sobrien		  && TYPE_DOMAIN (TREE_TYPE (field))
404990075Sobrien		  && ! TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (field))))
405018334Speter		{
405190075Sobrien		  fieldsize = array_size_for_constructor (val);
405290075Sobrien		  /* Given a non-empty initialization, this field had
405390075Sobrien		     better be last.  */
405490075Sobrien		  if (fieldsize != 0 && TREE_CHAIN (field) != NULL_TREE)
405590075Sobrien		    abort ();
405618334Speter		}
405790075Sobrien	      else if (DECL_SIZE_UNIT (field))
405818334Speter		{
405990075Sobrien		  /* ??? This can't be right.  If the decl size overflows
406090075Sobrien		     a host integer we will silently emit no data.  */
406190075Sobrien		  if (host_integerp (DECL_SIZE_UNIT (field), 1))
406290075Sobrien		    fieldsize = tree_low_cst (DECL_SIZE_UNIT (field), 1);
406318334Speter		}
406418334Speter	    }
406518334Speter	  else
406690075Sobrien	    fieldsize = int_size_in_bytes (TREE_TYPE (type));
406718334Speter
406818334Speter	  /* Output the element's initial value.  */
406918334Speter	  if (val == 0)
407018334Speter	    assemble_zeros (fieldsize);
407118334Speter	  else
407290075Sobrien	    output_constant (val, fieldsize, align2);
407318334Speter
407418334Speter	  /* Count its size.  */
407518334Speter	  total_bytes += fieldsize;
407618334Speter	}
407718334Speter      else if (val != 0 && TREE_CODE (val) != INTEGER_CST)
407818334Speter	error ("invalid initial value for member `%s'",
407918334Speter	       IDENTIFIER_POINTER (DECL_NAME (field)));
408018334Speter      else
408118334Speter	{
408218334Speter	  /* Element that is a bit-field.  */
408318334Speter
408490075Sobrien	  HOST_WIDE_INT next_offset = int_bit_position (field);
408590075Sobrien	  HOST_WIDE_INT end_offset
408690075Sobrien	    = (next_offset + tree_low_cst (DECL_SIZE (field), 1));
408718334Speter
408818334Speter	  if (val == 0)
408918334Speter	    val = integer_zero_node;
409018334Speter
409118334Speter	  /* If this field does not start in this (or, next) byte,
409218334Speter	     skip some bytes.  */
409318334Speter	  if (next_offset / BITS_PER_UNIT != total_bytes)
409418334Speter	    {
409518334Speter	      /* Output remnant of any bit field in previous bytes.  */
409618334Speter	      if (byte_buffer_in_use)
409718334Speter		{
409890075Sobrien		  assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1);
409918334Speter		  total_bytes++;
410018334Speter		  byte_buffer_in_use = 0;
410118334Speter		}
410218334Speter
410318334Speter	      /* If still not at proper byte, advance to there.  */
410418334Speter	      if (next_offset / BITS_PER_UNIT != total_bytes)
410518334Speter		{
410618334Speter		  assemble_zeros (next_offset / BITS_PER_UNIT - total_bytes);
410718334Speter		  total_bytes = next_offset / BITS_PER_UNIT;
410818334Speter		}
410918334Speter	    }
411018334Speter
411118334Speter	  if (! byte_buffer_in_use)
411218334Speter	    byte = 0;
411318334Speter
411418334Speter	  /* We must split the element into pieces that fall within
411518334Speter	     separate bytes, and combine each byte with previous or
411618334Speter	     following bit-fields.  */
411718334Speter
411818334Speter	  /* next_offset is the offset n fbits from the beginning of
411918334Speter	     the structure to the next bit of this element to be processed.
412018334Speter	     end_offset is the offset of the first bit past the end of
412118334Speter	     this element.  */
412218334Speter	  while (next_offset < end_offset)
412318334Speter	    {
412418334Speter	      int this_time;
412518334Speter	      int shift;
412618334Speter	      HOST_WIDE_INT value;
412790075Sobrien	      HOST_WIDE_INT next_byte = next_offset / BITS_PER_UNIT;
412890075Sobrien	      HOST_WIDE_INT next_bit = next_offset % BITS_PER_UNIT;
412918334Speter
413018334Speter	      /* Advance from byte to byte
413118334Speter		 within this element when necessary.  */
413218334Speter	      while (next_byte != total_bytes)
413318334Speter		{
413490075Sobrien		  assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1);
413518334Speter		  total_bytes++;
413618334Speter		  byte = 0;
413718334Speter		}
413818334Speter
413918334Speter	      /* Number of bits we can process at once
414018334Speter		 (all part of the same byte).  */
414118334Speter	      this_time = MIN (end_offset - next_offset,
414218334Speter			       BITS_PER_UNIT - next_bit);
414318334Speter	      if (BYTES_BIG_ENDIAN)
414418334Speter		{
414518334Speter		  /* On big-endian machine, take the most significant bits
414618334Speter		     first (of the bits that are significant)
414718334Speter		     and put them into bytes from the most significant end.  */
414818334Speter		  shift = end_offset - next_offset - this_time;
414990075Sobrien
415018334Speter		  /* Don't try to take a bunch of bits that cross
415190075Sobrien		     the word boundary in the INTEGER_CST. We can
415290075Sobrien		     only select bits from the LOW or HIGH part
415390075Sobrien		     not from both.  */
415418334Speter		  if (shift < HOST_BITS_PER_WIDE_INT
415518334Speter		      && shift + this_time > HOST_BITS_PER_WIDE_INT)
415618334Speter		    {
415790075Sobrien		      this_time = shift + this_time - HOST_BITS_PER_WIDE_INT;
415818334Speter		      shift = HOST_BITS_PER_WIDE_INT;
415918334Speter		    }
416018334Speter
416118334Speter		  /* Now get the bits from the appropriate constant word.  */
416218334Speter		  if (shift < HOST_BITS_PER_WIDE_INT)
416390075Sobrien		    value = TREE_INT_CST_LOW (val);
416418334Speter		  else if (shift < 2 * HOST_BITS_PER_WIDE_INT)
416518334Speter		    {
416618334Speter		      value = TREE_INT_CST_HIGH (val);
416718334Speter		      shift -= HOST_BITS_PER_WIDE_INT;
416818334Speter		    }
416918334Speter		  else
417018334Speter		    abort ();
417190075Sobrien
417290075Sobrien		  /* Get the result. This works only when:
417390075Sobrien		     1 <= this_time <= HOST_BITS_PER_WIDE_INT.  */
417418334Speter		  byte |= (((value >> shift)
417590075Sobrien			    & (((HOST_WIDE_INT) 2 << (this_time - 1)) - 1))
417618334Speter			   << (BITS_PER_UNIT - this_time - next_bit));
417718334Speter		}
417818334Speter	      else
417918334Speter		{
418018334Speter		  /* On little-endian machines,
418118334Speter		     take first the least significant bits of the value
418218334Speter		     and pack them starting at the least significant
418318334Speter		     bits of the bytes.  */
418490075Sobrien		  shift = next_offset - int_bit_position (field);
418590075Sobrien
418618334Speter		  /* Don't try to take a bunch of bits that cross
418790075Sobrien		     the word boundary in the INTEGER_CST. We can
418890075Sobrien		     only select bits from the LOW or HIGH part
418990075Sobrien		     not from both.  */
419018334Speter		  if (shift < HOST_BITS_PER_WIDE_INT
419118334Speter		      && shift + this_time > HOST_BITS_PER_WIDE_INT)
419290075Sobrien		    this_time = (HOST_BITS_PER_WIDE_INT - shift);
419318334Speter
419418334Speter		  /* Now get the bits from the appropriate constant word.  */
419550397Sobrien		  if (shift < HOST_BITS_PER_WIDE_INT)
419618334Speter		    value = TREE_INT_CST_LOW (val);
419718334Speter		  else if (shift < 2 * HOST_BITS_PER_WIDE_INT)
419818334Speter		    {
419918334Speter		      value = TREE_INT_CST_HIGH (val);
420018334Speter		      shift -= HOST_BITS_PER_WIDE_INT;
420118334Speter		    }
420218334Speter		  else
420318334Speter		    abort ();
420490075Sobrien
420590075Sobrien		  /* Get the result. This works only when:
420690075Sobrien		     1 <= this_time <= HOST_BITS_PER_WIDE_INT.  */
420718334Speter		  byte |= (((value >> shift)
420890075Sobrien			    & (((HOST_WIDE_INT) 2 << (this_time - 1)) - 1))
420918334Speter			   << next_bit);
421018334Speter		}
421190075Sobrien
421218334Speter	      next_offset += this_time;
421318334Speter	      byte_buffer_in_use = 1;
421418334Speter	    }
421518334Speter	}
421618334Speter    }
421790075Sobrien
421818334Speter  if (byte_buffer_in_use)
421918334Speter    {
422090075Sobrien      assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1);
422118334Speter      total_bytes++;
422218334Speter    }
422390075Sobrien
4224132718Skan  if ((unsigned HOST_WIDE_INT)total_bytes < size)
422518334Speter    assemble_zeros (size - total_bytes);
422618334Speter}
422718334Speter
422896263Sobrien/* This TREE_LIST contains any weak symbol declarations waiting
422996263Sobrien   to be emitted.  */
4230117395Skanstatic GTY(()) tree weak_decls;
423190075Sobrien
423296263Sobrien/* Mark DECL as weak.  */
423396263Sobrien
423496263Sobrienstatic void
4235132718Skanmark_weak (tree decl)
423690075Sobrien{
423796263Sobrien  DECL_WEAK (decl) = 1;
423890075Sobrien
423996263Sobrien  if (DECL_RTL_SET_P (decl)
424096263Sobrien      && GET_CODE (DECL_RTL (decl)) == MEM
424196263Sobrien      && XEXP (DECL_RTL (decl), 0)
424296263Sobrien      && GET_CODE (XEXP (DECL_RTL (decl), 0)) == SYMBOL_REF)
424396263Sobrien    SYMBOL_REF_WEAK (XEXP (DECL_RTL (decl), 0)) = 1;
424496263Sobrien}
4245117395Skan
424696263Sobrien/* Merge weak status between NEWDECL and OLDDECL.  */
424790075Sobrien
424896263Sobrienvoid
4249132718Skanmerge_weak (tree newdecl, tree olddecl)
425018334Speter{
425196263Sobrien  if (DECL_WEAK (newdecl) == DECL_WEAK (olddecl))
425296263Sobrien    return;
425318334Speter
425496263Sobrien  if (DECL_WEAK (newdecl))
425596263Sobrien    {
425696263Sobrien      tree wd;
4257117395Skan
425896263Sobrien      /* NEWDECL is weak, but OLDDECL is not.  */
425918334Speter
426096263Sobrien      /* If we already output the OLDDECL, we're in trouble; we can't
426196263Sobrien	 go back and make it weak.  This error cannot caught in
426296263Sobrien	 declare_weak because the NEWDECL and OLDDECL was not yet
426396263Sobrien	 been merged; therefore, TREE_ASM_WRITTEN was not set.  */
4264102780Skan      if (TREE_ASM_WRITTEN (olddecl))
4265132718Skan	error ("%Jweak declaration of '%D' must precede definition",
4266132718Skan	       newdecl, newdecl);
4267102780Skan
4268102780Skan      /* If we've already generated rtl referencing OLDDECL, we may
4269102780Skan	 have done so in a way that will not function properly with
4270102780Skan	 a weak symbol.  */
4271102780Skan      else if (TREE_USED (olddecl)
4272102780Skan	       && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (olddecl)))
4273132718Skan	warning ("%Jweak declaration of '%D' after first use results "
4274132718Skan                 "in unspecified behavior", newdecl, newdecl);
4275102780Skan
427696263Sobrien      if (SUPPORTS_WEAK)
427796263Sobrien	{
427896263Sobrien	  /* We put the NEWDECL on the weak_decls list at some point.
427996263Sobrien	     Replace it with the OLDDECL.  */
428096263Sobrien	  for (wd = weak_decls; wd; wd = TREE_CHAIN (wd))
428196263Sobrien	    if (TREE_VALUE (wd) == newdecl)
428296263Sobrien	      {
428396263Sobrien		TREE_VALUE (wd) = olddecl;
428496263Sobrien		break;
428596263Sobrien	      }
428696263Sobrien	  /* We may not find the entry on the list.  If NEWDECL is a
428796263Sobrien	     weak alias, then we will have already called
428896263Sobrien	     globalize_decl to remove the entry; in that case, we do
428996263Sobrien	     not need to do anything.  */
429096263Sobrien	}
429152284Sobrien
429296263Sobrien      /* Make the OLDDECL weak; it's OLDDECL that we'll be keeping.  */
429396263Sobrien      mark_weak (olddecl);
429496263Sobrien    }
429596263Sobrien  else
429696263Sobrien    /* OLDDECL was weak, but NEWDECL was not explicitly marked as
429796263Sobrien       weak.  Just update NEWDECL to indicate that it's weak too.  */
429896263Sobrien    mark_weak (newdecl);
429952284Sobrien}
430018334Speter
430118334Speter/* Declare DECL to be a weak symbol.  */
430218334Speter
430318334Spetervoid
4304132718Skandeclare_weak (tree decl)
430518334Speter{
430618334Speter  if (! TREE_PUBLIC (decl))
4307132718Skan    error ("%Jweak declaration of '%D' must be public", decl, decl);
430896263Sobrien  else if (TREE_CODE (decl) == FUNCTION_DECL && TREE_ASM_WRITTEN (decl))
4309132718Skan    error ("%Jweak declaration of '%D' must precede definition", decl, decl);
431018334Speter  else if (SUPPORTS_WEAK)
431196263Sobrien    {
431296263Sobrien      if (! DECL_WEAK (decl))
431396263Sobrien	weak_decls = tree_cons (NULL, decl, weak_decls);
431496263Sobrien    }
431590075Sobrien  else
4316132718Skan    warning ("%Jweak declaration of '%D' not supported", decl, decl);
431790075Sobrien
431896263Sobrien  mark_weak (decl);
431918334Speter}
432018334Speter
432118334Speter/* Emit any pending weak declarations.  */
432218334Speter
432318334Spetervoid
4324132718Skanweak_finish (void)
432518334Speter{
432696263Sobrien  tree t;
432796263Sobrien
4328117395Skan  for (t = weak_decls; t; t = TREE_CHAIN (t))
432918334Speter    {
433096263Sobrien      tree decl = TREE_VALUE (t);
4331132718Skan#if defined (ASM_WEAKEN_DECL) || defined (ASM_WEAKEN_LABEL)
4332132718Skan      const char *const name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
4333132718Skan#endif
433496263Sobrien
433596263Sobrien      if (! TREE_USED (decl))
433696263Sobrien	continue;
433796263Sobrien
433896263Sobrien#ifdef ASM_WEAKEN_DECL
433996263Sobrien      ASM_WEAKEN_DECL (asm_out_file, decl, name, NULL);
434090075Sobrien#else
434190075Sobrien#ifdef ASM_WEAKEN_LABEL
434296263Sobrien      ASM_WEAKEN_LABEL (asm_out_file, name);
434396263Sobrien#else
434496263Sobrien#ifdef ASM_OUTPUT_WEAK_ALIAS
434596263Sobrien      warning ("only weak aliases are supported in this configuration");
434696263Sobrien      return;
434790075Sobrien#endif
434890075Sobrien#endif
434996263Sobrien#endif
435018334Speter    }
435118334Speter}
435218334Speter
435396263Sobrien/* Emit the assembly bits to indicate that DECL is globally visible.  */
435496263Sobrien
435552284Sobrienstatic void
4356132718Skanglobalize_decl (tree decl)
435752284Sobrien{
435896263Sobrien  const char *name = XSTR (XEXP (DECL_RTL (decl), 0), 0);
435990075Sobrien
436096263Sobrien#if defined (ASM_WEAKEN_LABEL) || defined (ASM_WEAKEN_DECL)
436196263Sobrien  if (DECL_WEAK (decl))
436252284Sobrien    {
436396263Sobrien      tree *p, t;
436496263Sobrien
436596263Sobrien#ifdef ASM_WEAKEN_DECL
436696263Sobrien      ASM_WEAKEN_DECL (asm_out_file, decl, name, 0);
436796263Sobrien#else
436896263Sobrien      ASM_WEAKEN_LABEL (asm_out_file, name);
436996263Sobrien#endif
437096263Sobrien
437196263Sobrien      /* Remove this function from the pending weak list so that
437296263Sobrien	 we do not emit multiple .weak directives for it.  */
437396263Sobrien      for (p = &weak_decls; (t = *p) ; )
437496263Sobrien	{
437596263Sobrien	  if (DECL_ASSEMBLER_NAME (decl) == DECL_ASSEMBLER_NAME (TREE_VALUE (t)))
437696263Sobrien	    *p = TREE_CHAIN (t);
437796263Sobrien	  else
437896263Sobrien	    p = &TREE_CHAIN (t);
437996263Sobrien	}
438096263Sobrien      return;
438152284Sobrien    }
438296263Sobrien#endif
438396263Sobrien
4384117395Skan  (*targetm.asm_out.globalize_label) (asm_out_file, name);
438552284Sobrien}
438652284Sobrien
4387146895Skan/* Some targets do not allow a forward or undefined reference in a
4388146895Skan   ASM_OUTPUT_DEF.  Thus, a mechanism is needed to defer the output
4389146895Skan   of this assembler code.  The output_def_pair struct holds the
4390146895Skan   declaration and target for a deferred output define.  */
4391146895Skanstruct output_def_pair GTY(())
4392146895Skan{
4393146895Skan  tree decl;
4394146895Skan  tree target;
4395146895Skan};
4396146895Skantypedef struct output_def_pair *output_def_pair;
4397146895Skan
4398146895Skan/* Variable array of deferred output defines.  */
4399146895Skanstatic GTY ((param_is (struct output_def_pair))) varray_type output_defs;
4400146895Skan
4401146895Skan#ifdef ASM_OUTPUT_DEF
4402146895Skan/* Output the assembler code for a define (equate) using ASM_OUTPUT_DEF
4403146895Skan   or ASM_OUTPUT_DEF_FROM_DECLS.  The function defines the symbol whose
4404146895Skan   tree node is DECL to have the value of the tree node TARGET.  */
4405146895Skan
4406146895Skanstatic void
4407146895Skanassemble_output_def (tree decl ATTRIBUTE_UNUSED, tree target ATTRIBUTE_UNUSED)
4408146895Skan{
4409146895Skan#ifdef ASM_OUTPUT_DEF_FROM_DECLS
4410146895Skan  ASM_OUTPUT_DEF_FROM_DECLS (asm_out_file, decl, target);
4411146895Skan#else
4412146895Skan  ASM_OUTPUT_DEF (asm_out_file,
4413146895Skan		  IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)),
4414146895Skan		  IDENTIFIER_POINTER (target));
4415146895Skan#endif
4416146895Skan}
4417146895Skan#endif
4418146895Skan
4419146895Skan/* Process the varray of pending assembler defines.  */
4420146895Skan
4421146895Skanvoid
4422146895Skanprocess_pending_assemble_output_defs (void)
4423146895Skan{
4424146895Skan#ifdef ASM_OUTPUT_DEF
4425146895Skan  size_t i;
4426146895Skan  output_def_pair p;
4427146895Skan
4428146895Skan  if (!output_defs)
4429146895Skan    return;
4430146895Skan
4431146895Skan  for (i = 0; i < VARRAY_ACTIVE_SIZE (output_defs); i++)
4432146895Skan    {
4433146895Skan      p = VARRAY_GENERIC_PTR (output_defs, i);
4434146895Skan      assemble_output_def (p->decl, p->target);
4435146895Skan    }
4436146895Skan
4437146895Skan  output_defs = NULL;
4438146895Skan#endif
4439146895Skan}
4440146895Skan
444190075Sobrien/* Emit an assembler directive to make the symbol for DECL an alias to
444290075Sobrien   the symbol for TARGET.  */
444390075Sobrien
444418334Spetervoid
4445132718Skanassemble_alias (tree decl, tree target ATTRIBUTE_UNUSED)
444618334Speter{
444790075Sobrien  /* We must force creation of DECL_RTL for debug info generation, even though
444890075Sobrien     we don't use it here.  */
444990075Sobrien  make_decl_rtl (decl, NULL);
445018334Speter
445150397Sobrien#ifdef ASM_OUTPUT_DEF
445218334Speter  /* Make name accessible from other files, if appropriate.  */
4453117395Skan
445418334Speter  if (TREE_PUBLIC (decl))
4455117395Skan    {
4456117395Skan      globalize_decl (decl);
4457117395Skan      maybe_assemble_visibility (decl);
4458117395Skan    }
445918334Speter
4460146895Skan  if (TARGET_DEFERRED_OUTPUT_DEFS (decl, target))
4461146895Skan    {
4462146895Skan      output_def_pair p;
4463146895Skan
4464146895Skan      if (!output_defs)
4465146895Skan	VARRAY_GENERIC_PTR_INIT (output_defs, 10, "output defs");
4466146895Skan
4467146895Skan      p = ggc_alloc (sizeof (struct output_def_pair));
4468146895Skan      p->decl = decl;
4469146895Skan      p->target = target;
4470146895Skan      VARRAY_PUSH_GENERIC_PTR (output_defs, p);
4471146895Skan    }
4472146895Skan  else
4473146895Skan    assemble_output_def (decl, target);
447496263Sobrien#else /* !ASM_OUTPUT_DEF */
447596263Sobrien#if defined (ASM_OUTPUT_WEAK_ALIAS) || defined (ASM_WEAKEN_DECL)
4476132718Skan  if (DECL_WEAK (decl))
4477132718Skan    {
4478146895Skan      const char *name;
4479132718Skan      tree *p, t;
4480146895Skan
4481146895Skan      name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
448296263Sobrien#ifdef ASM_WEAKEN_DECL
4483132718Skan      ASM_WEAKEN_DECL (asm_out_file, decl, name, IDENTIFIER_POINTER (target));
448496263Sobrien#else
4485132718Skan      ASM_OUTPUT_WEAK_ALIAS (asm_out_file, name, IDENTIFIER_POINTER (target));
448696263Sobrien#endif
4487132718Skan      /* Remove this function from the pending weak list so that
4488132718Skan	 we do not emit multiple .weak directives for it.  */
4489132718Skan      for (p = &weak_decls; (t = *p) ; )
4490132718Skan	if (DECL_ASSEMBLER_NAME (decl)
4491132718Skan	    == DECL_ASSEMBLER_NAME (TREE_VALUE (t)))
4492132718Skan	  *p = TREE_CHAIN (t);
4493132718Skan	else
4494132718Skan	  p = &TREE_CHAIN (t);
4495132718Skan    }
4496132718Skan  else
4497132718Skan    warning ("only weak aliases are supported in this configuration");
4498132718Skan
449950397Sobrien#else
450050397Sobrien  warning ("alias definitions not supported in this configuration; ignored");
450118334Speter#endif
450250397Sobrien#endif
4503102780Skan
4504102780Skan  TREE_USED (decl) = 1;
4505102780Skan  TREE_ASM_WRITTEN (decl) = 1;
4506102780Skan  TREE_ASM_WRITTEN (DECL_ASSEMBLER_NAME (decl)) = 1;
450718334Speter}
450850397Sobrien
4509117395Skan/* Emit an assembler directive to set symbol for DECL visibility to
4510117395Skan   the visibility type VIS, which must not be VISIBILITY_DEFAULT.  */
4511117395Skan
4512117395Skanvoid
4513132718Skandefault_assemble_visibility (tree decl, int vis)
4514117395Skan{
4515117395Skan  static const char * const visibility_types[] = {
4516117395Skan    NULL, "internal", "hidden", "protected"
4517117395Skan  };
4518117395Skan
4519117395Skan  const char *name, *type;
4520117395Skan
4521117395Skan  name = (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
4522117395Skan  type = visibility_types[vis];
4523117395Skan
4524117395Skan#ifdef HAVE_GAS_HIDDEN
4525117395Skan  fprintf (asm_out_file, "\t.%s\t", type);
4526117395Skan  assemble_name (asm_out_file, name);
4527117395Skan  fprintf (asm_out_file, "\n");
4528117395Skan#else
4529117395Skan  warning ("visibility attribute not supported in this configuration; ignored");
4530117395Skan#endif
4531117395Skan}
4532117395Skan
4533117395Skan/* A helper function to call assemble_visibility when needed for a decl.  */
4534117395Skan
4535117395Skanstatic void
4536132718Skanmaybe_assemble_visibility (tree decl)
4537117395Skan{
4538132718Skan  enum symbol_visibility vis = DECL_VISIBILITY (decl);
4539117395Skan
4540117395Skan  if (vis != VISIBILITY_DEFAULT)
4541117395Skan    (* targetm.asm_out.visibility) (decl, vis);
4542117395Skan}
4543117395Skan
454450397Sobrien/* Returns 1 if the target configuration supports defining public symbols
454550397Sobrien   so that one of them will be chosen at link time instead of generating a
454650397Sobrien   multiply-defined symbol error, whether through the use of weak symbols or
454750397Sobrien   a target-specific mechanism for having duplicates discarded.  */
454850397Sobrien
454950397Sobrienint
4550132718Skansupports_one_only (void)
455150397Sobrien{
455250397Sobrien  if (SUPPORTS_ONE_ONLY)
455350397Sobrien    return 1;
455450397Sobrien  return SUPPORTS_WEAK;
455550397Sobrien}
455650397Sobrien
455750397Sobrien/* Set up DECL as a public symbol that can be defined in multiple
455850397Sobrien   translation units without generating a linker error.  */
455950397Sobrien
456050397Sobrienvoid
4561132718Skanmake_decl_one_only (tree decl)
456250397Sobrien{
456350397Sobrien  if (TREE_CODE (decl) != VAR_DECL && TREE_CODE (decl) != FUNCTION_DECL)
456450397Sobrien    abort ();
456550397Sobrien
456650397Sobrien  TREE_PUBLIC (decl) = 1;
456750397Sobrien
4568132718Skan  if (SUPPORTS_ONE_ONLY)
456950397Sobrien    {
457050397Sobrien#ifdef MAKE_DECL_ONE_ONLY
457150397Sobrien      MAKE_DECL_ONE_ONLY (decl);
457250397Sobrien#endif
457350397Sobrien      DECL_ONE_ONLY (decl) = 1;
457450397Sobrien    }
4575132718Skan  else if (TREE_CODE (decl) == VAR_DECL
4576132718Skan      && (DECL_INITIAL (decl) == 0 || DECL_INITIAL (decl) == error_mark_node))
4577132718Skan    DECL_COMMON (decl) = 1;
457850397Sobrien  else if (SUPPORTS_WEAK)
457950397Sobrien    DECL_WEAK (decl) = 1;
458050397Sobrien  else
458150397Sobrien    abort ();
458250397Sobrien}
458390075Sobrien
458490075Sobrienvoid
4585132718Skaninit_varasm_once (void)
458690075Sobrien{
4587132718Skan  in_named_htab = htab_create_ggc (31, in_named_entry_hash,
4588132718Skan				   in_named_entry_eq, NULL);
4589132718Skan  const_desc_htab = htab_create_ggc (1009, const_desc_hash,
4590132718Skan				     const_desc_eq, NULL);
459190075Sobrien
459290075Sobrien  const_alias_set = new_alias_set ();
459390075Sobrien}
459490075Sobrien
4595117395Skanenum tls_model
4596132718Skandecl_tls_model (tree decl)
4597117395Skan{
4598117395Skan  enum tls_model kind;
4599117395Skan  tree attr = lookup_attribute ("tls_model", DECL_ATTRIBUTES (decl));
4600117395Skan  bool is_local;
4601117395Skan
4602117395Skan  if (attr)
4603117395Skan    {
4604117395Skan      attr = TREE_VALUE (TREE_VALUE (attr));
4605117395Skan      if (TREE_CODE (attr) != STRING_CST)
4606117395Skan	abort ();
4607117395Skan      if (!strcmp (TREE_STRING_POINTER (attr), "local-exec"))
4608117395Skan	kind = TLS_MODEL_LOCAL_EXEC;
4609117395Skan      else if (!strcmp (TREE_STRING_POINTER (attr), "initial-exec"))
4610117395Skan	kind = TLS_MODEL_INITIAL_EXEC;
4611117395Skan      else if (!strcmp (TREE_STRING_POINTER (attr), "local-dynamic"))
4612117395Skan	kind = optimize ? TLS_MODEL_LOCAL_DYNAMIC : TLS_MODEL_GLOBAL_DYNAMIC;
4613117395Skan      else if (!strcmp (TREE_STRING_POINTER (attr), "global-dynamic"))
4614117395Skan	kind = TLS_MODEL_GLOBAL_DYNAMIC;
4615117395Skan      else
4616117395Skan	abort ();
4617117395Skan      return kind;
4618117395Skan    }
4619117395Skan
4620117395Skan  is_local = (*targetm.binds_local_p) (decl);
4621117395Skan  if (!flag_pic)
4622117395Skan    {
4623117395Skan      if (is_local)
4624117395Skan	kind = TLS_MODEL_LOCAL_EXEC;
4625117395Skan      else
4626117395Skan	kind = TLS_MODEL_INITIAL_EXEC;
4627117395Skan    }
4628117395Skan  /* Local dynamic is inefficient when we're not combining the
4629117395Skan     parts of the address.  */
4630117395Skan  else if (optimize && is_local)
4631117395Skan    kind = TLS_MODEL_LOCAL_DYNAMIC;
4632117395Skan  else
4633117395Skan    kind = TLS_MODEL_GLOBAL_DYNAMIC;
4634117395Skan  if (kind < flag_tls_default)
4635117395Skan    kind = flag_tls_default;
4636117395Skan
4637117395Skan  return kind;
4638117395Skan}
4639117395Skan
464090075Sobrien/* Select a set of attributes for section NAME based on the properties
464190075Sobrien   of DECL and whether or not RELOC indicates that DECL's initializer
464290075Sobrien   might contain runtime relocations.
464390075Sobrien
464490075Sobrien   We make the section read-only and executable for a function decl,
464590075Sobrien   read-only for a const data decl, and writable for a non-const data decl.  */
464690075Sobrien
464790075Sobrienunsigned int
4648132718Skandefault_section_type_flags (tree decl, const char *name, int reloc)
464990075Sobrien{
4650117395Skan  return default_section_type_flags_1 (decl, name, reloc, flag_pic);
4651117395Skan}
4652117395Skan
4653117395Skanunsigned int
4654132718Skandefault_section_type_flags_1 (tree decl, const char *name, int reloc,
4655132718Skan			      int shlib)
4656117395Skan{
465790075Sobrien  unsigned int flags;
465890075Sobrien
465990075Sobrien  if (decl && TREE_CODE (decl) == FUNCTION_DECL)
466090075Sobrien    flags = SECTION_CODE;
4661117395Skan  else if (decl && decl_readonly_section_1 (decl, reloc, shlib))
466290075Sobrien    flags = 0;
466390075Sobrien  else
466490075Sobrien    flags = SECTION_WRITE;
466590075Sobrien
466690075Sobrien  if (decl && DECL_ONE_ONLY (decl))
466790075Sobrien    flags |= SECTION_LINKONCE;
466890075Sobrien
4669117395Skan  if (decl && TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL (decl))
4670117395Skan    flags |= SECTION_TLS | SECTION_WRITE;
4671117395Skan
467290075Sobrien  if (strcmp (name, ".bss") == 0
467390075Sobrien      || strncmp (name, ".bss.", 5) == 0
467490075Sobrien      || strncmp (name, ".gnu.linkonce.b.", 16) == 0
467590075Sobrien      || strcmp (name, ".sbss") == 0
467690075Sobrien      || strncmp (name, ".sbss.", 6) == 0
4677117395Skan      || strncmp (name, ".gnu.linkonce.sb.", 17) == 0
4678117395Skan      || strcmp (name, ".tbss") == 0
4679117395Skan      || strncmp (name, ".gnu.linkonce.tb.", 17) == 0)
468090075Sobrien    flags |= SECTION_BSS;
468190075Sobrien
4682117395Skan  if (strcmp (name, ".tdata") == 0
4683117395Skan      || strcmp (name, ".tbss") == 0
4684117395Skan      || strncmp (name, ".gnu.linkonce.td.", 17) == 0
4685117395Skan      || strncmp (name, ".gnu.linkonce.tb.", 17) == 0)
4686117395Skan    flags |= SECTION_TLS;
4687117395Skan
4688117395Skan  /* These three sections have special ELF types.  They are neither
4689117395Skan     SHT_PROGBITS nor SHT_NOBITS, so when changing sections we don't
4690117395Skan     want to print a section type (@progbits or @nobits).  If someone
4691117395Skan     is silly enough to emit code or TLS variables to one of these
4692117395Skan     sections, then don't handle them specially.  */
4693117395Skan  if (!(flags & (SECTION_CODE | SECTION_BSS | SECTION_TLS))
4694117395Skan      && (strcmp (name, ".init_array") == 0
4695117395Skan	  || strcmp (name, ".fini_array") == 0
4696117395Skan	  || strcmp (name, ".preinit_array") == 0))
4697117395Skan    flags |= SECTION_NOTYPE;
4698117395Skan
469990075Sobrien  return flags;
470090075Sobrien}
470190075Sobrien
470290075Sobrien/* Output assembly to switch to section NAME with attribute FLAGS.
470390075Sobrien   Four variants for common object file formats.  */
470490075Sobrien
470590075Sobrienvoid
4706132718Skandefault_no_named_section (const char *name ATTRIBUTE_UNUSED,
4707132718Skan			  unsigned int flags ATTRIBUTE_UNUSED)
470890075Sobrien{
470990075Sobrien  /* Some object formats don't support named sections at all.  The
471090075Sobrien     front-end should already have flagged this as an error.  */
471190075Sobrien  abort ();
471290075Sobrien}
471390075Sobrien
471490075Sobrienvoid
4715132718Skandefault_elf_asm_named_section (const char *name, unsigned int flags)
471690075Sobrien{
471790075Sobrien  char flagchars[10], *f = flagchars;
471890075Sobrien
471990075Sobrien  if (! named_section_first_declaration (name))
472090075Sobrien    {
472190075Sobrien      fprintf (asm_out_file, "\t.section\t%s\n", name);
472290075Sobrien      return;
472390075Sobrien    }
472490075Sobrien
472590075Sobrien  if (!(flags & SECTION_DEBUG))
472690075Sobrien    *f++ = 'a';
472790075Sobrien  if (flags & SECTION_WRITE)
472890075Sobrien    *f++ = 'w';
472990075Sobrien  if (flags & SECTION_CODE)
473090075Sobrien    *f++ = 'x';
473190075Sobrien  if (flags & SECTION_SMALL)
473290075Sobrien    *f++ = 's';
473390075Sobrien  if (flags & SECTION_MERGE)
473490075Sobrien    *f++ = 'M';
473590075Sobrien  if (flags & SECTION_STRINGS)
473690075Sobrien    *f++ = 'S';
4737117395Skan  if (flags & SECTION_TLS)
4738117395Skan    *f++ = 'T';
473990075Sobrien  *f = '\0';
474090075Sobrien
4741117395Skan  fprintf (asm_out_file, "\t.section\t%s,\"%s\"", name, flagchars);
474290075Sobrien
4743117395Skan  if (!(flags & SECTION_NOTYPE))
4744117395Skan    {
4745117395Skan      const char *type;
4746117395Skan
4747117395Skan      if (flags & SECTION_BSS)
4748117395Skan	type = "nobits";
4749117395Skan      else
4750117395Skan	type = "progbits";
4751117395Skan
4752117395Skan      fprintf (asm_out_file, ",@%s", type);
4753117395Skan
4754117395Skan      if (flags & SECTION_ENTSIZE)
4755117395Skan	fprintf (asm_out_file, ",%d", flags & SECTION_ENTSIZE);
4756117395Skan    }
4757117395Skan
4758117395Skan  putc ('\n', asm_out_file);
475990075Sobrien}
476090075Sobrien
476190075Sobrienvoid
4762132718Skandefault_coff_asm_named_section (const char *name, unsigned int flags)
476390075Sobrien{
476490075Sobrien  char flagchars[8], *f = flagchars;
476590075Sobrien
476690075Sobrien  if (flags & SECTION_WRITE)
476790075Sobrien    *f++ = 'w';
476890075Sobrien  if (flags & SECTION_CODE)
476990075Sobrien    *f++ = 'x';
477090075Sobrien  *f = '\0';
477190075Sobrien
477290075Sobrien  fprintf (asm_out_file, "\t.section\t%s,\"%s\"\n", name, flagchars);
477390075Sobrien}
477490075Sobrien
477590075Sobrienvoid
4776132718Skandefault_pe_asm_named_section (const char *name, unsigned int flags)
477790075Sobrien{
477890075Sobrien  default_coff_asm_named_section (name, flags);
477990075Sobrien
478090075Sobrien  if (flags & SECTION_LINKONCE)
478190075Sobrien    {
478290075Sobrien      /* Functions may have been compiled at various levels of
478390075Sobrien         optimization so we can't use `same_size' here.
478490075Sobrien         Instead, have the linker pick one.  */
478590075Sobrien      fprintf (asm_out_file, "\t.linkonce %s\n",
478690075Sobrien	       (flags & SECTION_CODE ? "discard" : "same_size"));
478790075Sobrien    }
478890075Sobrien}
478990075Sobrien
4790117395Skan/* The lame default section selector.  */
4791117395Skan
4792117395Skanvoid
4793132718Skandefault_select_section (tree decl, int reloc,
4794132718Skan			unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
4795117395Skan{
4796117395Skan  bool readonly = false;
4797117395Skan
4798117395Skan  if (DECL_P (decl))
4799117395Skan    {
4800117395Skan      if (decl_readonly_section (decl, reloc))
4801117395Skan	readonly = true;
4802117395Skan    }
4803117395Skan  else if (TREE_CODE (decl) == CONSTRUCTOR)
4804117395Skan    {
4805117395Skan      if (! ((flag_pic && reloc)
4806117395Skan	     || !TREE_READONLY (decl)
4807117395Skan	     || TREE_SIDE_EFFECTS (decl)
4808117395Skan	     || !TREE_CONSTANT (decl)))
4809117395Skan	readonly = true;
4810117395Skan    }
4811117395Skan  else if (TREE_CODE (decl) == STRING_CST)
4812117395Skan    readonly = !flag_writable_strings;
4813117395Skan  else if (! (flag_pic && reloc))
4814117395Skan    readonly = true;
4815117395Skan
4816117395Skan  if (readonly)
4817117395Skan    readonly_data_section ();
4818117395Skan  else
4819117395Skan    data_section ();
4820117395Skan}
4821117395Skan
4822117395Skan/* A helper function for default_elf_select_section and
4823117395Skan   default_elf_unique_section.  Categorizes the DECL.  */
4824117395Skan
4825117395Skanenum section_category
4826117395Skan{
4827117395Skan  SECCAT_TEXT,
4828117395Skan
4829117395Skan  SECCAT_RODATA,
4830117395Skan  SECCAT_RODATA_MERGE_STR,
4831117395Skan  SECCAT_RODATA_MERGE_STR_INIT,
4832117395Skan  SECCAT_RODATA_MERGE_CONST,
4833117395Skan  SECCAT_SRODATA,
4834117395Skan
4835117395Skan  SECCAT_DATA,
4836117395Skan
4837117395Skan  /* To optimize loading of shared programs, define following subsections
4838117395Skan     of data section:
4839117395Skan	_REL	Contains data that has relocations, so they get grouped
4840117395Skan		together and dynamic linker will visit fewer pages in memory.
4841117395Skan	_RO	Contains data that is otherwise read-only.  This is useful
4842117395Skan		with prelinking as most relocations won't be dynamically
4843117395Skan		linked and thus stay read only.
4844117395Skan	_LOCAL	Marks data containing relocations only to local objects.
4845117395Skan		These relocations will get fully resolved by prelinking.  */
4846117395Skan  SECCAT_DATA_REL,
4847117395Skan  SECCAT_DATA_REL_LOCAL,
4848117395Skan  SECCAT_DATA_REL_RO,
4849117395Skan  SECCAT_DATA_REL_RO_LOCAL,
4850117395Skan
4851117395Skan  SECCAT_SDATA,
4852117395Skan  SECCAT_TDATA,
4853117395Skan
4854117395Skan  SECCAT_BSS,
4855117395Skan  SECCAT_SBSS,
4856117395Skan  SECCAT_TBSS
4857117395Skan};
4858117395Skan
4859117395Skanstatic enum section_category
4860132718Skancategorize_decl_for_section (tree, int, int);
4861117395Skan
4862117395Skanstatic enum section_category
4863132718Skancategorize_decl_for_section (tree decl, int reloc, int shlib)
4864117395Skan{
4865117395Skan  enum section_category ret;
4866117395Skan
4867117395Skan  if (TREE_CODE (decl) == FUNCTION_DECL)
4868117395Skan    return SECCAT_TEXT;
4869117395Skan  else if (TREE_CODE (decl) == STRING_CST)
4870117395Skan    {
4871117395Skan      if (flag_writable_strings)
4872117395Skan	return SECCAT_DATA;
4873117395Skan      else
4874117395Skan	return SECCAT_RODATA_MERGE_STR;
4875117395Skan    }
4876117395Skan  else if (TREE_CODE (decl) == VAR_DECL)
4877117395Skan    {
4878117395Skan      if (DECL_INITIAL (decl) == NULL
4879117395Skan	  || DECL_INITIAL (decl) == error_mark_node)
4880117395Skan	ret = SECCAT_BSS;
4881117395Skan      else if (! TREE_READONLY (decl)
4882117395Skan	       || TREE_SIDE_EFFECTS (decl)
4883117395Skan	       || ! TREE_CONSTANT (DECL_INITIAL (decl)))
4884117395Skan	{
4885117395Skan	  if (shlib && (reloc & 2))
4886117395Skan	    ret = SECCAT_DATA_REL;
4887117395Skan	  else if (shlib && reloc)
4888117395Skan	    ret = SECCAT_DATA_REL_LOCAL;
4889117395Skan	  else
4890117395Skan	    ret = SECCAT_DATA;
4891117395Skan	}
4892117395Skan      else if (shlib && (reloc & 2))
4893117395Skan	ret = SECCAT_DATA_REL_RO;
4894117395Skan      else if (shlib && reloc)
4895117395Skan	ret = SECCAT_DATA_REL_RO_LOCAL;
4896117395Skan      else if (reloc || flag_merge_constants < 2)
4897117395Skan	/* C and C++ don't allow different variables to share the same
4898117395Skan	   location.  -fmerge-all-constants allows even that (at the
4899117395Skan	   expense of not conforming).  */
4900117395Skan	ret = SECCAT_RODATA;
4901117395Skan      else if (TREE_CODE (DECL_INITIAL (decl)) == STRING_CST)
4902117395Skan	ret = SECCAT_RODATA_MERGE_STR_INIT;
4903117395Skan      else
4904117395Skan	ret = SECCAT_RODATA_MERGE_CONST;
4905117395Skan    }
4906117395Skan  else if (TREE_CODE (decl) == CONSTRUCTOR)
4907117395Skan    {
4908117395Skan      if ((shlib && reloc)
4909117395Skan	  || TREE_SIDE_EFFECTS (decl)
4910117395Skan	  || ! TREE_CONSTANT (decl))
4911117395Skan	ret = SECCAT_DATA;
4912117395Skan      else
4913117395Skan	ret = SECCAT_RODATA;
4914117395Skan    }
4915117395Skan  else
4916117395Skan    ret = SECCAT_RODATA;
4917117395Skan
4918117395Skan  /* There are no read-only thread-local sections.  */
4919117395Skan  if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL (decl))
4920117395Skan    {
4921117395Skan      if (ret == SECCAT_BSS)
4922117395Skan	ret = SECCAT_TBSS;
4923117395Skan      else
4924117395Skan	ret = SECCAT_TDATA;
4925117395Skan    }
4926117395Skan
4927117395Skan  /* If the target uses small data sections, select it.  */
4928117395Skan  else if ((*targetm.in_small_data_p) (decl))
4929117395Skan    {
4930117395Skan      if (ret == SECCAT_BSS)
4931117395Skan	ret = SECCAT_SBSS;
4932117395Skan      else if (targetm.have_srodata_section && ret == SECCAT_RODATA)
4933117395Skan	ret = SECCAT_SRODATA;
4934117395Skan      else
4935117395Skan	ret = SECCAT_SDATA;
4936117395Skan    }
4937117395Skan
4938117395Skan  return ret;
4939117395Skan}
4940117395Skan
4941117395Skanbool
4942132718Skandecl_readonly_section (tree decl, int reloc)
4943117395Skan{
4944117395Skan  return decl_readonly_section_1 (decl, reloc, flag_pic);
4945117395Skan}
4946117395Skan
4947117395Skanbool
4948132718Skandecl_readonly_section_1 (tree decl, int reloc, int shlib)
4949117395Skan{
4950117395Skan  switch (categorize_decl_for_section (decl, reloc, shlib))
4951117395Skan    {
4952117395Skan    case SECCAT_RODATA:
4953117395Skan    case SECCAT_RODATA_MERGE_STR:
4954117395Skan    case SECCAT_RODATA_MERGE_STR_INIT:
4955117395Skan    case SECCAT_RODATA_MERGE_CONST:
4956117395Skan    case SECCAT_SRODATA:
4957117395Skan      return true;
4958117395Skan      break;
4959117395Skan    default:
4960117395Skan      return false;
4961117395Skan      break;
4962117395Skan    }
4963117395Skan}
4964117395Skan
4965117395Skan/* Select a section based on the above categorization.  */
4966117395Skan
4967117395Skanvoid
4968132718Skandefault_elf_select_section (tree decl, int reloc,
4969132718Skan			    unsigned HOST_WIDE_INT align)
4970117395Skan{
4971117395Skan  default_elf_select_section_1 (decl, reloc, align, flag_pic);
4972117395Skan}
4973117395Skan
4974117395Skanvoid
4975132718Skandefault_elf_select_section_1 (tree decl, int reloc,
4976132718Skan			      unsigned HOST_WIDE_INT align, int shlib)
4977117395Skan{
4978117395Skan  switch (categorize_decl_for_section (decl, reloc, shlib))
4979117395Skan    {
4980117395Skan    case SECCAT_TEXT:
4981117395Skan      /* We're not supposed to be called on FUNCTION_DECLs.  */
4982117395Skan      abort ();
4983117395Skan    case SECCAT_RODATA:
4984117395Skan      readonly_data_section ();
4985117395Skan      break;
4986117395Skan    case SECCAT_RODATA_MERGE_STR:
4987117395Skan      mergeable_string_section (decl, align, 0);
4988117395Skan      break;
4989117395Skan    case SECCAT_RODATA_MERGE_STR_INIT:
4990117395Skan      mergeable_string_section (DECL_INITIAL (decl), align, 0);
4991117395Skan      break;
4992117395Skan    case SECCAT_RODATA_MERGE_CONST:
4993117395Skan      mergeable_constant_section (DECL_MODE (decl), align, 0);
4994117395Skan      break;
4995117395Skan    case SECCAT_SRODATA:
4996117395Skan      named_section (NULL_TREE, ".sdata2", reloc);
4997117395Skan      break;
4998117395Skan    case SECCAT_DATA:
4999117395Skan      data_section ();
5000117395Skan      break;
5001117395Skan    case SECCAT_DATA_REL:
5002117395Skan      named_section (NULL_TREE, ".data.rel", reloc);
5003117395Skan      break;
5004117395Skan    case SECCAT_DATA_REL_LOCAL:
5005117395Skan      named_section (NULL_TREE, ".data.rel.local", reloc);
5006117395Skan      break;
5007117395Skan    case SECCAT_DATA_REL_RO:
5008117395Skan      named_section (NULL_TREE, ".data.rel.ro", reloc);
5009117395Skan      break;
5010117395Skan    case SECCAT_DATA_REL_RO_LOCAL:
5011117395Skan      named_section (NULL_TREE, ".data.rel.ro.local", reloc);
5012117395Skan      break;
5013117395Skan    case SECCAT_SDATA:
5014117395Skan      named_section (NULL_TREE, ".sdata", reloc);
5015117395Skan      break;
5016117395Skan    case SECCAT_TDATA:
5017117395Skan      named_section (NULL_TREE, ".tdata", reloc);
5018117395Skan      break;
5019117395Skan    case SECCAT_BSS:
5020117395Skan#ifdef BSS_SECTION_ASM_OP
5021117395Skan      bss_section ();
5022117395Skan#else
5023117395Skan      named_section (NULL_TREE, ".bss", reloc);
5024117395Skan#endif
5025117395Skan      break;
5026117395Skan    case SECCAT_SBSS:
5027117395Skan      named_section (NULL_TREE, ".sbss", reloc);
5028117395Skan      break;
5029117395Skan    case SECCAT_TBSS:
5030117395Skan      named_section (NULL_TREE, ".tbss", reloc);
5031117395Skan      break;
5032117395Skan    default:
5033117395Skan      abort ();
5034117395Skan    }
5035117395Skan}
5036117395Skan
5037117395Skan/* Construct a unique section name based on the decl name and the
5038117395Skan   categorization performed above.  */
5039117395Skan
5040117395Skanvoid
5041132718Skandefault_unique_section (tree decl, int reloc)
5042117395Skan{
5043117395Skan  default_unique_section_1 (decl, reloc, flag_pic);
5044117395Skan}
5045117395Skan
5046117395Skanvoid
5047132718Skandefault_unique_section_1 (tree decl, int reloc, int shlib)
5048117395Skan{
5049117395Skan  bool one_only = DECL_ONE_ONLY (decl);
5050117395Skan  const char *prefix, *name;
5051117395Skan  size_t nlen, plen;
5052117395Skan  char *string;
5053117395Skan
5054117395Skan  switch (categorize_decl_for_section (decl, reloc, shlib))
5055117395Skan    {
5056117395Skan    case SECCAT_TEXT:
5057117395Skan      prefix = one_only ? ".gnu.linkonce.t." : ".text.";
5058117395Skan      break;
5059117395Skan    case SECCAT_RODATA:
5060117395Skan    case SECCAT_RODATA_MERGE_STR:
5061117395Skan    case SECCAT_RODATA_MERGE_STR_INIT:
5062117395Skan    case SECCAT_RODATA_MERGE_CONST:
5063117395Skan      prefix = one_only ? ".gnu.linkonce.r." : ".rodata.";
5064117395Skan      break;
5065117395Skan    case SECCAT_SRODATA:
5066117395Skan      prefix = one_only ? ".gnu.linkonce.s2." : ".sdata2.";
5067117395Skan      break;
5068117395Skan    case SECCAT_DATA:
5069117395Skan    case SECCAT_DATA_REL:
5070117395Skan    case SECCAT_DATA_REL_LOCAL:
5071117395Skan    case SECCAT_DATA_REL_RO:
5072117395Skan    case SECCAT_DATA_REL_RO_LOCAL:
5073117395Skan      prefix = one_only ? ".gnu.linkonce.d." : ".data.";
5074117395Skan      break;
5075117395Skan    case SECCAT_SDATA:
5076117395Skan      prefix = one_only ? ".gnu.linkonce.s." : ".sdata.";
5077117395Skan      break;
5078117395Skan    case SECCAT_BSS:
5079117395Skan      prefix = one_only ? ".gnu.linkonce.b." : ".bss.";
5080117395Skan      break;
5081117395Skan    case SECCAT_SBSS:
5082117395Skan      prefix = one_only ? ".gnu.linkonce.sb." : ".sbss.";
5083117395Skan      break;
5084117395Skan    case SECCAT_TDATA:
5085117395Skan      prefix = one_only ? ".gnu.linkonce.td." : ".tdata.";
5086117395Skan      break;
5087117395Skan    case SECCAT_TBSS:
5088117395Skan      prefix = one_only ? ".gnu.linkonce.tb." : ".tbss.";
5089117395Skan      break;
5090117395Skan    default:
5091117395Skan      abort ();
5092117395Skan    }
5093117395Skan  plen = strlen (prefix);
5094117395Skan
5095117395Skan  name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
5096117395Skan  name = (* targetm.strip_name_encoding) (name);
5097117395Skan  nlen = strlen (name);
5098117395Skan
5099117395Skan  string = alloca (nlen + plen + 1);
5100117395Skan  memcpy (string, prefix, plen);
5101117395Skan  memcpy (string + plen, name, nlen + 1);
5102117395Skan
5103117395Skan  DECL_SECTION_NAME (decl) = build_string (nlen + plen, string);
5104117395Skan}
5105117395Skan
5106117395Skanvoid
5107132718Skandefault_select_rtx_section (enum machine_mode mode ATTRIBUTE_UNUSED,
5108132718Skan			    rtx x,
5109132718Skan			    unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED)
5110117395Skan{
5111117395Skan  if (flag_pic)
5112117395Skan    switch (GET_CODE (x))
5113117395Skan      {
5114117395Skan      case CONST:
5115117395Skan      case SYMBOL_REF:
5116117395Skan      case LABEL_REF:
5117117395Skan	data_section ();
5118117395Skan	return;
5119117395Skan
5120117395Skan      default:
5121117395Skan	break;
5122117395Skan      }
5123117395Skan
5124117395Skan  readonly_data_section ();
5125117395Skan}
5126117395Skan
5127117395Skanvoid
5128132718Skandefault_elf_select_rtx_section (enum machine_mode mode, rtx x,
5129132718Skan				unsigned HOST_WIDE_INT align)
5130117395Skan{
5131117395Skan  /* ??? Handle small data here somehow.  */
5132117395Skan
5133117395Skan  if (flag_pic)
5134117395Skan    switch (GET_CODE (x))
5135117395Skan      {
5136117395Skan      case CONST:
5137117395Skan      case SYMBOL_REF:
5138117395Skan	named_section (NULL_TREE, ".data.rel.ro", 3);
5139117395Skan	return;
5140117395Skan
5141117395Skan      case LABEL_REF:
5142117395Skan	named_section (NULL_TREE, ".data.rel.ro.local", 1);
5143117395Skan	return;
5144117395Skan
5145117395Skan      default:
5146117395Skan	break;
5147117395Skan      }
5148117395Skan
5149117395Skan  mergeable_constant_section (mode, align, 0);
5150117395Skan}
5151117395Skan
5152132718Skan/* Set the generally applicable flags on the SYMBOL_REF for EXP.  */
5153132718Skan
5154132718Skanvoid
5155132718Skandefault_encode_section_info (tree decl, rtx rtl, int first ATTRIBUTE_UNUSED)
5156132718Skan{
5157132718Skan  rtx symbol;
5158132718Skan  int flags;
5159132718Skan
5160132718Skan  /* Careful not to prod global register variables.  */
5161132718Skan  if (GET_CODE (rtl) != MEM)
5162132718Skan    return;
5163132718Skan  symbol = XEXP (rtl, 0);
5164132718Skan  if (GET_CODE (symbol) != SYMBOL_REF)
5165132718Skan    return;
5166132718Skan
5167132718Skan  flags = 0;
5168132718Skan  if (TREE_CODE (decl) == FUNCTION_DECL)
5169132718Skan    flags |= SYMBOL_FLAG_FUNCTION;
5170132718Skan  if ((*targetm.binds_local_p) (decl))
5171132718Skan    flags |= SYMBOL_FLAG_LOCAL;
5172132718Skan  if ((*targetm.in_small_data_p) (decl))
5173132718Skan    flags |= SYMBOL_FLAG_SMALL;
5174132718Skan  if (TREE_CODE (decl) == VAR_DECL && DECL_THREAD_LOCAL (decl))
5175132718Skan    flags |= decl_tls_model (decl) << SYMBOL_FLAG_TLS_SHIFT;
5176132718Skan  /* ??? Why is DECL_EXTERNAL ever set for non-PUBLIC names?  Without
5177132718Skan     being PUBLIC, the thing *must* be defined in this translation unit.
5178132718Skan     Prevent this buglet from being propagated into rtl code as well.  */
5179132718Skan  if (DECL_P (decl) && DECL_EXTERNAL (decl) && TREE_PUBLIC (decl))
5180132718Skan    flags |= SYMBOL_FLAG_EXTERNAL;
5181132718Skan
5182132718Skan  SYMBOL_REF_FLAGS (symbol) = flags;
5183132718Skan}
5184132718Skan
5185117395Skan/* By default, we do nothing for encode_section_info, so we need not
5186117395Skan   do anything but discard the '*' marker.  */
5187117395Skan
5188117395Skanconst char *
5189132718Skandefault_strip_name_encoding (const char *str)
5190117395Skan{
5191117395Skan  return str + (*str == '*');
5192117395Skan}
5193117395Skan
5194117395Skan/* Assume ELF-ish defaults, since that's pretty much the most liberal
5195117395Skan   wrt cross-module name binding.  */
5196117395Skan
5197117395Skanbool
5198132718Skandefault_binds_local_p (tree exp)
5199117395Skan{
5200132718Skan  return default_binds_local_p_1 (exp, flag_shlib);
5201117395Skan}
5202117395Skan
5203117395Skanbool
5204132718Skandefault_binds_local_p_1 (tree exp, int shlib)
5205117395Skan{
5206117395Skan  bool local_p;
5207117395Skan
5208117395Skan  /* A non-decl is an entry in the constant pool.  */
5209117395Skan  if (!DECL_P (exp))
5210117395Skan    local_p = true;
5211117395Skan  /* Static variables are always local.  */
5212117395Skan  else if (! TREE_PUBLIC (exp))
5213117395Skan    local_p = true;
5214117395Skan  /* A variable is local if the user tells us so.  */
5215132718Skan  else if (DECL_VISIBILITY (exp) != VISIBILITY_DEFAULT)
5216117395Skan    local_p = true;
5217117395Skan  /* Otherwise, variables defined outside this object may not be local.  */
5218117395Skan  else if (DECL_EXTERNAL (exp))
5219117395Skan    local_p = false;
5220117395Skan  /* Linkonce and weak data are never local.  */
5221117395Skan  else if (DECL_ONE_ONLY (exp) || DECL_WEAK (exp))
5222117395Skan    local_p = false;
5223117395Skan  /* If PIC, then assume that any global name can be overridden by
5224117395Skan     symbols resolved from other modules.  */
5225117395Skan  else if (shlib)
5226117395Skan    local_p = false;
5227117395Skan  /* Uninitialized COMMON variable may be unified with symbols
5228117395Skan     resolved from other modules.  */
5229117395Skan  else if (DECL_COMMON (exp)
5230117395Skan	   && (DECL_INITIAL (exp) == NULL
5231117395Skan	       || DECL_INITIAL (exp) == error_mark_node))
5232117395Skan    local_p = false;
5233117395Skan  /* Otherwise we're left with initialized (or non-common) global data
5234117395Skan     which is of necessity defined locally.  */
5235117395Skan  else
5236117395Skan    local_p = true;
5237117395Skan
5238117395Skan  return local_p;
5239117395Skan}
5240117395Skan
5241132718Skan/* Determine whether or not a pointer mode is valid. Assume defaults
5242132718Skan   of ptr_mode or Pmode - can be overridden.  */
5243132718Skanbool
5244132718Skandefault_valid_pointer_mode (enum machine_mode mode)
5245132718Skan{
5246132718Skan  return (mode == ptr_mode || mode == Pmode);
5247132718Skan}
5248132718Skan
5249117395Skan/* Default function to output code that will globalize a label.  A
5250117395Skan   target must define GLOBAL_ASM_OP or provide it's own function to
5251117395Skan   globalize a label.  */
5252117395Skan#ifdef GLOBAL_ASM_OP
5253117395Skanvoid
5254132718Skandefault_globalize_label (FILE * stream, const char *name)
5255117395Skan{
5256117395Skan  fputs (GLOBAL_ASM_OP, stream);
5257117395Skan  assemble_name (stream, name);
5258117395Skan  putc ('\n', stream);
5259117395Skan}
5260117395Skan#endif /* GLOBAL_ASM_OP */
5261132718Skan
5262132718Skan/* This is how to output an internal numbered label where PREFIX is
5263132718Skan   the class of label and LABELNO is the number within the class.  */
5264132718Skan
5265132718Skanvoid
5266132718Skandefault_internal_label (FILE *stream, const char *prefix,
5267132718Skan			unsigned long labelno)
5268132718Skan{
5269132718Skan  char *const buf = alloca (40 + strlen (prefix));
5270132718Skan  ASM_GENERATE_INTERNAL_LABEL (buf, prefix, labelno);
5271132718Skan  ASM_OUTPUT_LABEL (stream, buf);
5272132718Skan}
5273132718Skan
5274132718Skan/* This is the default behavior at the beginning of a file.  It's
5275132718Skan   controlled by two other target-hook toggles.  */
5276132718Skanvoid
5277132718Skandefault_file_start (void)
5278132718Skan{
5279132718Skan  if (targetm.file_start_app_off && !flag_verbose_asm)
5280132718Skan    fputs (ASM_APP_OFF, asm_out_file);
5281132718Skan
5282132718Skan  if (targetm.file_start_file_directive)
5283132718Skan    output_file_directive (asm_out_file, main_input_filename);
5284132718Skan}
5285132718Skan
5286132718Skan/* This is a generic routine suitable for use as TARGET_ASM_FILE_END
5287132718Skan   which emits a special section directive used to indicate whether or
5288132718Skan   not this object file needs an executable stack.  This is primarily
5289132718Skan   a GNU extension to ELF but could be used on other targets.  */
5290132718Skanvoid
5291132718Skanfile_end_indicate_exec_stack (void)
5292132718Skan{
5293132718Skan  unsigned int flags = SECTION_DEBUG;
5294132718Skan  if (trampolines_created)
5295132718Skan    flags |= SECTION_CODE;
5296132718Skan
5297132718Skan  named_section_flags (".note.GNU-stack", flags);
5298132718Skan}
5299132718Skan
5300117395Skan#include "gt-varasm.h"
5301