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