sdbout.c revision 90075
118334Speter/* Output sdb-format symbol table information from GNU compiler.
290075Sobrien   Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
390075Sobrien   2000, 2001, 2002 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/*  mike@tredysvr.Tredydev.Unisys.COM says:
2318334SpeterI modified the struct.c example and have a nm of a .o resulting from the
2418334SpeterAT&T C compiler.  From the example below I would conclude the following:
2518334Speter
2618334Speter1. All .defs from structures are emitted as scanned.  The example below
2718334Speter   clearly shows the symbol table entries for BoxRec2 are after the first
2818334Speter   function.
2918334Speter
3018334Speter2. All functions and their locals (including statics) are emitted as scanned.
3118334Speter
3218334Speter3. All nested unnamed union and structure .defs must be emitted before
3318334Speter   the structure in which they are nested.  The AT&T assembler is a
3418334Speter   one pass beast as far as symbolics are concerned.
3518334Speter
3618334Speter4. All structure .defs are emitted before the typedefs that refer to them.
3718334Speter
3818334Speter5. All top level static and external variable definitions are moved to the
3918334Speter   end of file with all top level statics occurring first before externs.
4018334Speter
4118334Speter6. All undefined references are at the end of the file.
4218334Speter*/
4318334Speter
4418334Speter#include "config.h"
4518334Speter
4618334Speter#ifdef SDB_DEBUGGING_INFO
4718334Speter
4850397Sobrien#include "system.h"
4918334Speter#include "tree.h"
5018334Speter#include "rtl.h"
5118334Speter#include "regs.h"
5218334Speter#include "flags.h"
5318334Speter#include "insn-config.h"
5418334Speter#include "reload.h"
5550397Sobrien#include "output.h"
5650397Sobrien#include "toplev.h"
5790075Sobrien#include "ggc.h"
5890075Sobrien#include "tm_p.h"
5918334Speter#include "gsyms.h"
6090075Sobrien#include "debug.h"
6118334Speter
6218334Speter/* 1 if PARM is passed to this function in memory.  */
6318334Speter
6418334Speter#define PARM_PASSED_IN_MEMORY(PARM) \
6518334Speter (GET_CODE (DECL_INCOMING_RTL (PARM)) == MEM)
6618334Speter
6718334Speter/* A C expression for the integer offset value of an automatic variable
6818334Speter   (C_AUTO) having address X (an RTX).  */
6918334Speter#ifndef DEBUGGER_AUTO_OFFSET
7018334Speter#define DEBUGGER_AUTO_OFFSET(X) \
7118334Speter  (GET_CODE (X) == PLUS ? INTVAL (XEXP (X, 1)) : 0)
7218334Speter#endif
7318334Speter
7418334Speter/* A C expression for the integer offset value of an argument (C_ARG)
7518334Speter   having address X (an RTX).  The nominal offset is OFFSET.  */
7618334Speter#ifndef DEBUGGER_ARG_OFFSET
7718334Speter#define DEBUGGER_ARG_OFFSET(OFFSET, X) (OFFSET)
7818334Speter#endif
7918334Speter
8018334Speter/* Line number of beginning of current function, minus one.
8118334Speter   Negative means not in a function or not using sdb.  */
8218334Speter
8318334Speterint sdb_begin_function_line = -1;
8418334Speter
8518334Speter/* Counter to generate unique "names" for nameless struct members.  */
8618334Speter
8718334Speterstatic int unnamed_struct_number = 0;
8818334Speter
8918334Speterextern FILE *asm_out_file;
9018334Speter
9118334Speterextern tree current_function_decl;
9218334Speter
9350397Sobrien#include "sdbout.h"
9418334Speter
9590075Sobrienstatic void sdbout_init			PARAMS ((const char *));
9690075Sobrienstatic void sdbout_finish		PARAMS ((const char *));
9790075Sobrienstatic void sdbout_start_source_file	PARAMS ((unsigned int, const char *));
9890075Sobrienstatic void sdbout_end_source_file	PARAMS ((unsigned int));
9990075Sobrienstatic void sdbout_begin_block		PARAMS ((unsigned int, unsigned int));
10090075Sobrienstatic void sdbout_end_block		PARAMS ((unsigned int, unsigned int));
10190075Sobrienstatic void sdbout_source_line		PARAMS ((unsigned int, const char *));
10290075Sobrienstatic void sdbout_end_epilogue		PARAMS ((void));
10390075Sobrienstatic void sdbout_global_decl		PARAMS ((tree));
10490075Sobrien#ifndef MIPS_DEBUGGING_INFO
10590075Sobrienstatic void sdbout_begin_prologue	PARAMS ((unsigned int, const char *));
10618334Speter#endif
10790075Sobrienstatic void sdbout_end_prologue		PARAMS ((unsigned int));
10890075Sobrienstatic void sdbout_begin_function	PARAMS ((tree));
10990075Sobrienstatic void sdbout_end_function		PARAMS ((unsigned int));
11090075Sobrienstatic void sdbout_toplevel_data	PARAMS ((tree));
11190075Sobrienstatic void sdbout_label		PARAMS ((rtx));
11290075Sobrienstatic char *gen_fake_label		PARAMS ((void));
11390075Sobrienstatic int plain_type			PARAMS ((tree));
11490075Sobrienstatic int template_name_p		PARAMS ((tree));
11590075Sobrienstatic void sdbout_record_type_name	PARAMS ((tree));
11690075Sobrienstatic int plain_type_1			PARAMS ((tree, int));
11790075Sobrienstatic void sdbout_block		PARAMS ((tree));
11890075Sobrienstatic void sdbout_syms			PARAMS ((tree));
11990075Sobrien#ifdef SDB_ALLOW_FORWARD_REFERENCES
12090075Sobrienstatic void sdbout_queue_anonymous_type	PARAMS ((tree));
12190075Sobrienstatic void sdbout_dequeue_anonymous_types PARAMS ((void));
12218334Speter#endif
12390075Sobrienstatic void sdbout_type			PARAMS ((tree));
12490075Sobrienstatic void sdbout_field_types		PARAMS ((tree));
12590075Sobrienstatic void sdbout_one_type		PARAMS ((tree));
12690075Sobrienstatic void sdbout_parms		PARAMS ((tree));
12790075Sobrienstatic void sdbout_reg_parms		PARAMS ((tree));
12890075Sobrienstatic void sdbout_global_decl		PARAMS ((tree));
12918334Speter
13018334Speter/* Random macros describing parts of SDB data.  */
13118334Speter
13218334Speter/* Put something here if lines get too long */
13318334Speter#define CONTIN
13418334Speter
13518334Speter/* Default value of delimiter is ";".  */
13618334Speter#ifndef SDB_DELIM
13718334Speter#define SDB_DELIM	";"
13818334Speter#endif
13918334Speter
14018334Speter/* Maximum number of dimensions the assembler will allow.  */
14118334Speter#ifndef SDB_MAX_DIM
14218334Speter#define SDB_MAX_DIM 4
14318334Speter#endif
14418334Speter
14518334Speter#ifndef PUT_SDB_SCL
14618334Speter#define PUT_SDB_SCL(a) fprintf(asm_out_file, "\t.scl\t%d%s", (a), SDB_DELIM)
14718334Speter#endif
14818334Speter
14918334Speter#ifndef PUT_SDB_INT_VAL
15050397Sobrien#define PUT_SDB_INT_VAL(a) \
15150397Sobrien do {									\
15250397Sobrien   fputs ("\t.val\t", asm_out_file);		       			\
15390075Sobrien   fprintf (asm_out_file, HOST_WIDE_INT_PRINT_DEC, (HOST_WIDE_INT) (a)); \
15450397Sobrien   fprintf (asm_out_file, "%s", SDB_DELIM);				\
15550397Sobrien } while (0)
15650397Sobrien
15718334Speter#endif
15818334Speter
15918334Speter#ifndef PUT_SDB_VAL
16018334Speter#define PUT_SDB_VAL(a)				\
16118334Speter( fputs ("\t.val\t", asm_out_file),		\
16218334Speter  output_addr_const (asm_out_file, (a)),	\
16318334Speter  fprintf (asm_out_file, SDB_DELIM))
16418334Speter#endif
16518334Speter
16618334Speter#ifndef PUT_SDB_DEF
16718334Speter#define PUT_SDB_DEF(a)				\
16818334Speterdo { fprintf (asm_out_file, "\t.def\t");	\
16990075Sobrien     assemble_name (asm_out_file, a); 	\
17018334Speter     fprintf (asm_out_file, SDB_DELIM); } while (0)
17118334Speter#endif
17218334Speter
17318334Speter#ifndef PUT_SDB_PLAIN_DEF
17418334Speter#define PUT_SDB_PLAIN_DEF(a) fprintf(asm_out_file,"\t.def\t.%s%s",a, SDB_DELIM)
17518334Speter#endif
17618334Speter
17718334Speter#ifndef PUT_SDB_ENDEF
17818334Speter#define PUT_SDB_ENDEF fputs("\t.endef\n", asm_out_file)
17918334Speter#endif
18018334Speter
18118334Speter#ifndef PUT_SDB_TYPE
18218334Speter#define PUT_SDB_TYPE(a) fprintf(asm_out_file, "\t.type\t0%o%s", a, SDB_DELIM)
18318334Speter#endif
18418334Speter
18518334Speter#ifndef PUT_SDB_SIZE
18650397Sobrien#define PUT_SDB_SIZE(a) \
18750397Sobrien do {									\
18850397Sobrien   fputs ("\t.size\t", asm_out_file);					\
18990075Sobrien   fprintf (asm_out_file, HOST_WIDE_INT_PRINT_DEC, (HOST_WIDE_INT) (a)); \
19050397Sobrien   fprintf (asm_out_file, "%s", SDB_DELIM);				\
19150397Sobrien } while(0)
19218334Speter#endif
19318334Speter
19418334Speter#ifndef PUT_SDB_START_DIM
19518334Speter#define PUT_SDB_START_DIM fprintf(asm_out_file, "\t.dim\t")
19618334Speter#endif
19718334Speter
19818334Speter#ifndef PUT_SDB_NEXT_DIM
19918334Speter#define PUT_SDB_NEXT_DIM(a) fprintf(asm_out_file, "%d,", a)
20018334Speter#endif
20118334Speter
20218334Speter#ifndef PUT_SDB_LAST_DIM
20318334Speter#define PUT_SDB_LAST_DIM(a) fprintf(asm_out_file, "%d%s", a, SDB_DELIM)
20418334Speter#endif
20518334Speter
20618334Speter#ifndef PUT_SDB_TAG
20718334Speter#define PUT_SDB_TAG(a)				\
20818334Speterdo { fprintf (asm_out_file, "\t.tag\t");	\
20990075Sobrien     assemble_name (asm_out_file, a);	\
21018334Speter     fprintf (asm_out_file, SDB_DELIM); } while (0)
21118334Speter#endif
21218334Speter
21318334Speter#ifndef PUT_SDB_BLOCK_START
21418334Speter#define PUT_SDB_BLOCK_START(LINE)		\
21518334Speter  fprintf (asm_out_file,			\
21618334Speter	   "\t.def\t.bb%s\t.val\t.%s\t.scl\t100%s\t.line\t%d%s\t.endef\n", \
21718334Speter	   SDB_DELIM, SDB_DELIM, SDB_DELIM, (LINE), SDB_DELIM)
21818334Speter#endif
21918334Speter
22018334Speter#ifndef PUT_SDB_BLOCK_END
22118334Speter#define PUT_SDB_BLOCK_END(LINE)			\
22218334Speter  fprintf (asm_out_file,			\
22318334Speter	   "\t.def\t.eb%s\t.val\t.%s\t.scl\t100%s\t.line\t%d%s\t.endef\n",  \
22418334Speter	   SDB_DELIM, SDB_DELIM, SDB_DELIM, (LINE), SDB_DELIM)
22518334Speter#endif
22618334Speter
22718334Speter#ifndef PUT_SDB_FUNCTION_START
22818334Speter#define PUT_SDB_FUNCTION_START(LINE)		\
22918334Speter  fprintf (asm_out_file,			\
23018334Speter	   "\t.def\t.bf%s\t.val\t.%s\t.scl\t101%s\t.line\t%d%s\t.endef\n", \
23118334Speter	   SDB_DELIM, SDB_DELIM, SDB_DELIM, (LINE), SDB_DELIM)
23218334Speter#endif
23318334Speter
23418334Speter#ifndef PUT_SDB_FUNCTION_END
23518334Speter#define PUT_SDB_FUNCTION_END(LINE)		\
23618334Speter  fprintf (asm_out_file,			\
23718334Speter	   "\t.def\t.ef%s\t.val\t.%s\t.scl\t101%s\t.line\t%d%s\t.endef\n", \
23818334Speter	   SDB_DELIM, SDB_DELIM, SDB_DELIM, (LINE), SDB_DELIM)
23918334Speter#endif
24018334Speter
24118334Speter#ifndef SDB_GENERATE_FAKE
24218334Speter#define SDB_GENERATE_FAKE(BUFFER, NUMBER) \
24318334Speter  sprintf ((BUFFER), ".%dfake", (NUMBER));
24418334Speter#endif
24518334Speter
24618334Speter/* Return the sdb tag identifier string for TYPE
24790075Sobrien   if TYPE has already been defined; otherwise return a null pointer.  */
24818334Speter
24918334Speter#define KNOWN_TYPE_TAG(type)  TYPE_SYMTAB_POINTER (type)
25018334Speter
25118334Speter/* Set the sdb tag identifier string for TYPE to NAME.  */
25218334Speter
25318334Speter#define SET_KNOWN_TYPE_TAG(TYPE, NAME) \
25418334Speter  TYPE_SYMTAB_POINTER (TYPE) = (NAME)
25518334Speter
25618334Speter/* Return the name (a string) of the struct, union or enum tag
25718334Speter   described by the TREE_LIST node LINK.  This is 0 for an anonymous one.  */
25818334Speter
25918334Speter#define TAG_NAME(link) \
26018334Speter  (((link) && TREE_PURPOSE ((link)) \
26118334Speter    && IDENTIFIER_POINTER (TREE_PURPOSE ((link)))) \
26218334Speter   ? IDENTIFIER_POINTER (TREE_PURPOSE ((link))) : (char *) 0)
26318334Speter
26418334Speter/* Ensure we don't output a negative line number.  */
26518334Speter#define MAKE_LINE_SAFE(line)  \
26690075Sobrien  if ((int) line <= sdb_begin_function_line) \
26790075Sobrien    line = sdb_begin_function_line + 1
26850397Sobrien
26950397Sobrien/* Perform linker optimization of merging header file definitions together
27050397Sobrien   for targets with MIPS_DEBUGGING_INFO defined.  This won't work without a
27150397Sobrien   post 960826 version of GAS.  Nothing breaks with earlier versions of GAS,
27250397Sobrien   the optimization just won't be done.  The native assembler already has the
27350397Sobrien   necessary support.  */
27450397Sobrien
27550397Sobrien#ifdef MIPS_DEBUGGING_INFO
27650397Sobrien
27750397Sobrien#ifndef PUT_SDB_SRC_FILE
27850397Sobrien#define PUT_SDB_SRC_FILE(FILENAME) \
27950397Sobrienoutput_file_directive (asm_out_file, (FILENAME))
28050397Sobrien#endif
28150397Sobrien
28250397Sobrien/* ECOFF linkers have an optimization that does the same kind of thing as
28350397Sobrien   N_BINCL/E_INCL in stabs: eliminate duplicate debug information in the
28450397Sobrien   executable.  To achieve this, GCC must output a .file for each file
28550397Sobrien   name change.  */
28650397Sobrien
28750397Sobrien/* This is a stack of input files.  */
28850397Sobrien
28950397Sobrienstruct sdb_file
29050397Sobrien{
29150397Sobrien  struct sdb_file *next;
29290075Sobrien  const char *name;
29350397Sobrien};
29450397Sobrien
29550397Sobrien/* This is the top of the stack.  */
29650397Sobrien
29750397Sobrienstatic struct sdb_file *current_file;
29850397Sobrien
29950397Sobrien#endif /* MIPS_DEBUGGING_INFO */
30018334Speter
30190075Sobrien/* The debug hooks structure.  */
30290075Sobrienstruct gcc_debug_hooks sdb_debug_hooks =
30318334Speter{
30490075Sobrien  sdbout_init,			/* init */
30590075Sobrien  sdbout_finish,		/* finish */
30690075Sobrien  debug_nothing_int_charstar,	/* define */
30790075Sobrien  debug_nothing_int_charstar,	/* undef */
30890075Sobrien  sdbout_start_source_file,	/* start_source_file */
30990075Sobrien  sdbout_end_source_file,	/* end_source_file */
31090075Sobrien  sdbout_begin_block,		/* begin_block */
31190075Sobrien  sdbout_end_block,		/* end_block */
31290075Sobrien  debug_true_tree,		/* ignore_block */
31390075Sobrien  sdbout_source_line,		/* source_line */
31450397Sobrien#ifdef MIPS_DEBUGGING_INFO
31590075Sobrien  /* Defer on MIPS systems so that parameter descriptions follow
31690075Sobrien     function entry.  */
31790075Sobrien  debug_nothing_int_charstar,	/* begin_prologue */
31890075Sobrien  sdbout_end_prologue,		/* end_prologue */
31990075Sobrien#else
32090075Sobrien  sdbout_begin_prologue,	/* begin_prologue */
32190075Sobrien  debug_nothing_int,		/* end_prologue */
32250397Sobrien#endif
32390075Sobrien  sdbout_end_epilogue,		/* end_epilogue */
32490075Sobrien  sdbout_begin_function,	/* begin_function */
32590075Sobrien  sdbout_end_function,		/* end_function */
32690075Sobrien  debug_nothing_tree,		/* function_decl */
32790075Sobrien  sdbout_global_decl,		/* global_decl */
32890075Sobrien  debug_nothing_tree,		/* deferred_inline_function */
32990075Sobrien  debug_nothing_tree,		/* outlining_inline_function */
33090075Sobrien  sdbout_label
33190075Sobrien};
33290075Sobrien
33318334Speter#if 0
33418334Speter
33518334Speter/* return the tag identifier for type
33618334Speter */
33718334Speter
33818334Speterchar *
33918334Spetertag_of_ru_type (type,link)
34018334Speter     tree type,link;
34118334Speter{
34218334Speter  if (TYPE_SYMTAB_ADDRESS (type))
34318334Speter    return TYPE_SYMTAB_ADDRESS (type);
34418334Speter  if (link && TREE_PURPOSE (link)
34518334Speter      && IDENTIFIER_POINTER (TREE_PURPOSE (link)))
34618334Speter    TYPE_SYMTAB_ADDRESS (type) = IDENTIFIER_POINTER (TREE_PURPOSE (link));
34718334Speter  else
34818334Speter    return (char *) TYPE_SYMTAB_ADDRESS (type);
34918334Speter}
35018334Speter#endif
35118334Speter
35218334Speter/* Return a unique string to name an anonymous type.  */
35318334Speter
35418334Speterstatic char *
35518334Spetergen_fake_label ()
35618334Speter{
35718334Speter  char label[10];
35818334Speter  char *labelstr;
35918334Speter  SDB_GENERATE_FAKE (label, unnamed_struct_number);
36018334Speter  unnamed_struct_number++;
36118334Speter  labelstr = (char *) permalloc (strlen (label) + 1);
36218334Speter  strcpy (labelstr, label);
36318334Speter  return labelstr;
36418334Speter}
36518334Speter
36618334Speter/* Return the number which describes TYPE for SDB.
36718334Speter   For pointers, etc., this function is recursive.
36818334Speter   Each record, union or enumeral type must already have had a
36918334Speter   tag number output.  */
37018334Speter
37118334Speter/* The number is given by d6d5d4d3d2d1bbbb
37218334Speter   where bbbb is 4 bit basic type, and di indicate  one of notype,ptr,fn,array.
37318334Speter   Thus, char *foo () has bbbb=T_CHAR
37418334Speter			  d1=D_FCN
37518334Speter			  d2=D_PTR
37618334Speter N_BTMASK=     017       1111     basic type field.
37718334Speter N_TSHIFT=       2                derived type shift
37818334Speter N_BTSHFT=       4                Basic type shift */
37918334Speter
38018334Speter/* Produce the number that describes a pointer, function or array type.
38118334Speter   PREV is the number describing the target, value or element type.
38218334Speter   DT_type describes how to transform that type.  */
38318334Speter#define PUSH_DERIVED_LEVEL(DT_type,PREV)		\
38490075Sobrien  ((((PREV) & ~(int) N_BTMASK) << (int) N_TSHIFT)		\
38590075Sobrien   | ((int) DT_type << (int) N_BTSHFT)			\
38690075Sobrien   | ((PREV) & (int) N_BTMASK))
38718334Speter
38818334Speter/* Number of elements used in sdb_dims.  */
38918334Speterstatic int sdb_n_dims = 0;
39018334Speter
39118334Speter/* Table of array dimensions of current type.  */
39218334Speterstatic int sdb_dims[SDB_MAX_DIM];
39318334Speter
39418334Speter/* Size of outermost array currently being processed.  */
39518334Speterstatic int sdb_type_size = -1;
39618334Speter
39718334Speterstatic int
39818334Speterplain_type (type)
39918334Speter     tree type;
40018334Speter{
40118334Speter  int val = plain_type_1 (type, 0);
40218334Speter
40318334Speter  /* If we have already saved up some array dimensions, print them now.  */
40418334Speter  if (sdb_n_dims > 0)
40518334Speter    {
40618334Speter      int i;
40718334Speter      PUT_SDB_START_DIM;
40818334Speter      for (i = sdb_n_dims - 1; i > 0; i--)
40918334Speter	PUT_SDB_NEXT_DIM (sdb_dims[i]);
41018334Speter      PUT_SDB_LAST_DIM (sdb_dims[0]);
41118334Speter      sdb_n_dims = 0;
41218334Speter
41318334Speter      sdb_type_size = int_size_in_bytes (type);
41418334Speter      /* Don't kill sdb if type is not laid out or has variable size.  */
41518334Speter      if (sdb_type_size < 0)
41618334Speter	sdb_type_size = 0;
41718334Speter    }
41818334Speter  /* If we have computed the size of an array containing this type,
41918334Speter     print it now.  */
42018334Speter  if (sdb_type_size >= 0)
42118334Speter    {
42218334Speter      PUT_SDB_SIZE (sdb_type_size);
42318334Speter      sdb_type_size = -1;
42418334Speter    }
42518334Speter  return val;
42618334Speter}
42718334Speter
42818334Speterstatic int
42918334Spetertemplate_name_p (name)
43018334Speter     tree name;
43118334Speter{
43290075Sobrien  const char *ptr = IDENTIFIER_POINTER (name);
43318334Speter  while (*ptr && *ptr != '<')
43418334Speter    ptr++;
43518334Speter
43618334Speter  return *ptr != '\0';
43718334Speter}
43818334Speter
43918334Speterstatic void
44018334Spetersdbout_record_type_name (type)
44118334Speter     tree type;
44218334Speter{
44390075Sobrien  const char *name = 0;
44418334Speter  int no_name;
44518334Speter
44618334Speter  if (KNOWN_TYPE_TAG (type))
44718334Speter    return;
44818334Speter
44918334Speter  if (TYPE_NAME (type) != 0)
45018334Speter    {
45118334Speter      tree t = 0;
45290075Sobrien
45318334Speter      /* Find the IDENTIFIER_NODE for the type name.  */
45418334Speter      if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
45518334Speter	t = TYPE_NAME (type);
45618334Speter      else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL)
45718334Speter	{
45818334Speter	  t = DECL_NAME (TYPE_NAME (type));
45918334Speter	  /* The DECL_NAME for templates includes "<>", which breaks
46018334Speter	     most assemblers.  Use its assembler name instead, which
46118334Speter	     has been mangled into being safe.  */
46218334Speter	  if (t && template_name_p (t))
46318334Speter	    t = DECL_ASSEMBLER_NAME (TYPE_NAME (type));
46418334Speter	}
46518334Speter
46618334Speter      /* Now get the name as a string, or invent one.  */
46718334Speter      if (t != NULL_TREE)
46818334Speter	name = IDENTIFIER_POINTER (t);
46918334Speter    }
47018334Speter
47118334Speter  no_name = (name == 0 || *name == 0);
47218334Speter  if (no_name)
47318334Speter    name = gen_fake_label ();
47418334Speter
47518334Speter  SET_KNOWN_TYPE_TAG (type, name);
47618334Speter#ifdef SDB_ALLOW_FORWARD_REFERENCES
47718334Speter  if (no_name)
47818334Speter    sdbout_queue_anonymous_type (type);
47918334Speter#endif
48018334Speter}
48118334Speter
48218334Speter/* Return the .type value for type TYPE.
48318334Speter
48418334Speter   LEVEL indicates how many levels deep we have recursed into the type.
48518334Speter   The SDB debug format can only represent 6 derived levels of types.
48618334Speter   After that, we must output inaccurate debug info.  We deliberately
48718334Speter   stop before the 7th level, so that ADA recursive types will not give an
48818334Speter   infinite loop.  */
48918334Speter
49018334Speterstatic int
49118334Speterplain_type_1 (type, level)
49218334Speter     tree type;
49318334Speter     int level;
49418334Speter{
49518334Speter  if (type == 0)
49618334Speter    type = void_type_node;
49718334Speter  else if (type == error_mark_node)
49818334Speter    type = integer_type_node;
49918334Speter  else
50018334Speter    type = TYPE_MAIN_VARIANT (type);
50118334Speter
50218334Speter  switch (TREE_CODE (type))
50318334Speter    {
50418334Speter    case VOID_TYPE:
50518334Speter      return T_VOID;
50652284Sobrien    case BOOLEAN_TYPE:
50718334Speter    case INTEGER_TYPE:
50818334Speter      {
50918334Speter	int size = int_size_in_bytes (type) * BITS_PER_UNIT;
51018334Speter
51118334Speter	/* Carefully distinguish all the standard types of C,
51218334Speter	   without messing up if the language is not C.
51318334Speter	   Note that we check only for the names that contain spaces;
51418334Speter	   other names might occur by coincidence in other languages.  */
51518334Speter	if (TYPE_NAME (type) != 0
51618334Speter	    && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
51718334Speter	    && DECL_NAME (TYPE_NAME (type)) != 0
51818334Speter	    && TREE_CODE (DECL_NAME (TYPE_NAME (type))) == IDENTIFIER_NODE)
51918334Speter	  {
52090075Sobrien	    const char *const name
52190075Sobrien	      = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
52218334Speter
52350397Sobrien	    if (!strcmp (name, "char"))
52450397Sobrien	      return T_CHAR;
52518334Speter	    if (!strcmp (name, "unsigned char"))
52618334Speter	      return T_UCHAR;
52718334Speter	    if (!strcmp (name, "signed char"))
52818334Speter	      return T_CHAR;
52950397Sobrien	    if (!strcmp (name, "int"))
53050397Sobrien	      return T_INT;
53118334Speter	    if (!strcmp (name, "unsigned int"))
53218334Speter	      return T_UINT;
53318334Speter	    if (!strcmp (name, "short int"))
53418334Speter	      return T_SHORT;
53518334Speter	    if (!strcmp (name, "short unsigned int"))
53618334Speter	      return T_USHORT;
53718334Speter	    if (!strcmp (name, "long int"))
53818334Speter	      return T_LONG;
53918334Speter	    if (!strcmp (name, "long unsigned int"))
54018334Speter	      return T_ULONG;
54118334Speter	  }
54218334Speter
54350397Sobrien	if (size == INT_TYPE_SIZE)
54450397Sobrien	  return (TREE_UNSIGNED (type) ? T_UINT : T_INT);
54518334Speter	if (size == CHAR_TYPE_SIZE)
54618334Speter	  return (TREE_UNSIGNED (type) ? T_UCHAR : T_CHAR);
54718334Speter	if (size == SHORT_TYPE_SIZE)
54818334Speter	  return (TREE_UNSIGNED (type) ? T_USHORT : T_SHORT);
54918334Speter	if (size == LONG_TYPE_SIZE)
55018334Speter	  return (TREE_UNSIGNED (type) ? T_ULONG : T_LONG);
55118334Speter	if (size == LONG_LONG_TYPE_SIZE)	/* better than nothing */
55218334Speter	  return (TREE_UNSIGNED (type) ? T_ULONG : T_LONG);
55318334Speter	return 0;
55418334Speter      }
55518334Speter
55618334Speter    case REAL_TYPE:
55718334Speter      {
55850397Sobrien	int precision = TYPE_PRECISION (type);
55950397Sobrien	if (precision == FLOAT_TYPE_SIZE)
56018334Speter	  return T_FLOAT;
56150397Sobrien	if (precision == DOUBLE_TYPE_SIZE)
56218334Speter	  return T_DOUBLE;
56350397Sobrien#ifdef EXTENDED_SDB_BASIC_TYPES
56450397Sobrien	if (precision == LONG_DOUBLE_TYPE_SIZE)
56550397Sobrien	  return T_LNGDBL;
56650397Sobrien#else
56750397Sobrien	if (precision == LONG_DOUBLE_TYPE_SIZE)
56850397Sobrien	  return T_DOUBLE;	/* better than nothing */
56950397Sobrien#endif
57018334Speter	return 0;
57118334Speter      }
57218334Speter
57318334Speter    case ARRAY_TYPE:
57418334Speter      {
57518334Speter	int m;
57618334Speter	if (level >= 6)
57718334Speter	  return T_VOID;
57818334Speter	else
57918334Speter	  m = plain_type_1 (TREE_TYPE (type), level+1);
58018334Speter	if (sdb_n_dims < SDB_MAX_DIM)
58118334Speter	  sdb_dims[sdb_n_dims++]
58218334Speter	    = (TYPE_DOMAIN (type)
58390075Sobrien	       && TYPE_MIN_VALUE (TYPE_DOMAIN (type)) != 0
58490075Sobrien	       && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) != 0
58590075Sobrien	       && host_integerp (TYPE_MAX_VALUE (TYPE_DOMAIN (type)), 0)
58690075Sobrien	       && host_integerp (TYPE_MIN_VALUE (TYPE_DOMAIN (type)), 0)
58790075Sobrien	       ? (tree_low_cst (TYPE_MAX_VALUE (TYPE_DOMAIN (type)), 0)
58890075Sobrien		  - tree_low_cst (TYPE_MIN_VALUE (TYPE_DOMAIN (type)), 0) + 1)
58918334Speter	       : 0);
59090075Sobrien
59118334Speter	return PUSH_DERIVED_LEVEL (DT_ARY, m);
59218334Speter      }
59318334Speter
59418334Speter    case RECORD_TYPE:
59518334Speter    case UNION_TYPE:
59618334Speter    case QUAL_UNION_TYPE:
59718334Speter    case ENUMERAL_TYPE:
59818334Speter      {
59918334Speter	char *tag;
60018334Speter#ifdef SDB_ALLOW_FORWARD_REFERENCES
60118334Speter	sdbout_record_type_name (type);
60218334Speter#endif
60318334Speter#ifndef SDB_ALLOW_UNKNOWN_REFERENCES
60418334Speter	if ((TREE_ASM_WRITTEN (type) && KNOWN_TYPE_TAG (type) != 0)
60518334Speter#ifdef SDB_ALLOW_FORWARD_REFERENCES
60618334Speter	    || TYPE_MODE (type) != VOIDmode
60718334Speter#endif
60818334Speter	    )
60918334Speter#endif
61018334Speter	  {
61118334Speter	    /* Output the referenced structure tag name
61218334Speter	       only if the .def has already been finished.
61318334Speter	       At least on 386, the Unix assembler
61418334Speter	       cannot handle forward references to tags.  */
61550397Sobrien	    /* But the 88100, it requires them, sigh...  */
61650397Sobrien	    /* And the MIPS requires unknown refs as well...  */
61718334Speter	    tag = KNOWN_TYPE_TAG (type);
61818334Speter	    PUT_SDB_TAG (tag);
61918334Speter	    /* These 3 lines used to follow the close brace.
62018334Speter	       However, a size of 0 without a tag implies a tag of 0,
62118334Speter	       so if we don't know a tag, we can't mention the size.  */
62218334Speter	    sdb_type_size = int_size_in_bytes (type);
62318334Speter	    if (sdb_type_size < 0)
62418334Speter	      sdb_type_size = 0;
62518334Speter	  }
62618334Speter	return ((TREE_CODE (type) == RECORD_TYPE) ? T_STRUCT
62718334Speter		: (TREE_CODE (type) == UNION_TYPE) ? T_UNION
62818334Speter		: (TREE_CODE (type) == QUAL_UNION_TYPE) ? T_UNION
62918334Speter		: T_ENUM);
63018334Speter      }
63118334Speter    case POINTER_TYPE:
63218334Speter    case REFERENCE_TYPE:
63318334Speter      {
63418334Speter	int m;
63518334Speter	if (level >= 6)
63618334Speter	  return T_VOID;
63718334Speter	else
63818334Speter	  m = plain_type_1 (TREE_TYPE (type), level+1);
63918334Speter	return PUSH_DERIVED_LEVEL (DT_PTR, m);
64018334Speter      }
64118334Speter    case FUNCTION_TYPE:
64218334Speter    case METHOD_TYPE:
64318334Speter      {
64418334Speter	int m;
64518334Speter	if (level >= 6)
64618334Speter	  return T_VOID;
64718334Speter	else
64818334Speter	  m = plain_type_1 (TREE_TYPE (type), level+1);
64918334Speter	return PUSH_DERIVED_LEVEL (DT_FCN, m);
65018334Speter      }
65118334Speter    default:
65218334Speter      return 0;
65318334Speter    }
65418334Speter}
65518334Speter
65618334Speter/* Output the symbols defined in block number DO_BLOCK.
65718334Speter
65818334Speter   This function works by walking the tree structure of blocks,
65918334Speter   counting blocks until it finds the desired block.  */
66018334Speter
66118334Speterstatic int do_block = 0;
66218334Speter
66318334Speterstatic void
66418334Spetersdbout_block (block)
66590075Sobrien     tree block;
66618334Speter{
66718334Speter  while (block)
66818334Speter    {
66918334Speter      /* Ignore blocks never expanded or otherwise marked as real.  */
67018334Speter      if (TREE_USED (block))
67118334Speter	{
67218334Speter	  /* When we reach the specified block, output its symbols.  */
67390075Sobrien	  if (BLOCK_NUMBER (block) == do_block)
67490075Sobrien	    sdbout_syms (BLOCK_VARS (block));
67518334Speter
67618334Speter	  /* If we are past the specified block, stop the scan.  */
67790075Sobrien	  if (BLOCK_NUMBER (block) > do_block)
67818334Speter	    return;
67918334Speter
68018334Speter	  /* Scan the blocks within this block.  */
68118334Speter	  sdbout_block (BLOCK_SUBBLOCKS (block));
68218334Speter	}
68318334Speter
68418334Speter      block = BLOCK_CHAIN (block);
68518334Speter    }
68618334Speter}
68718334Speter
68818334Speter/* Call sdbout_symbol on each decl in the chain SYMS.  */
68918334Speter
69018334Speterstatic void
69118334Spetersdbout_syms (syms)
69218334Speter     tree syms;
69318334Speter{
69418334Speter  while (syms)
69518334Speter    {
69618334Speter      if (TREE_CODE (syms) != LABEL_DECL)
69718334Speter	sdbout_symbol (syms, 1);
69818334Speter      syms = TREE_CHAIN (syms);
69918334Speter    }
70018334Speter}
70118334Speter
70218334Speter/* Output SDB information for a symbol described by DECL.
70318334Speter   LOCAL is nonzero if the symbol is not file-scope.  */
70418334Speter
70518334Spetervoid
70618334Spetersdbout_symbol (decl, local)
70718334Speter     tree decl;
70818334Speter     int local;
70918334Speter{
71018334Speter  tree type = TREE_TYPE (decl);
71118334Speter  tree context = NULL_TREE;
71218334Speter  rtx value;
71318334Speter  int regno = -1;
71490075Sobrien  const char *name;
71518334Speter
71618334Speter  sdbout_one_type (type);
71718334Speter
71818334Speter#if 0 /* This loses when functions are marked to be ignored,
71918334Speter	 which happens in the C++ front end.  */
72018334Speter  if (DECL_IGNORED_P (decl))
72118334Speter    return;
72218334Speter#endif
72318334Speter
72418334Speter  switch (TREE_CODE (decl))
72518334Speter    {
72618334Speter    case CONST_DECL:
72718334Speter      /* Enum values are defined by defining the enum type.  */
72818334Speter      return;
72918334Speter
73018334Speter    case FUNCTION_DECL:
73118334Speter      /* Don't mention a nested function under its parent.  */
73218334Speter      context = decl_function_context (decl);
73318334Speter      if (context == current_function_decl)
73418334Speter	return;
73550397Sobrien      /* Check DECL_INITIAL to distinguish declarations from definitions.
73650397Sobrien	 Don't output debug info here for declarations; they will have
73750397Sobrien	 a DECL_INITIAL value of 0.  */
73850397Sobrien      if (! DECL_INITIAL (decl))
73918334Speter	return;
74018334Speter      if (GET_CODE (DECL_RTL (decl)) != MEM
74118334Speter	  || GET_CODE (XEXP (DECL_RTL (decl), 0)) != SYMBOL_REF)
74218334Speter	return;
74318334Speter      PUT_SDB_DEF (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
74418334Speter      PUT_SDB_VAL (XEXP (DECL_RTL (decl), 0));
74518334Speter      PUT_SDB_SCL (TREE_PUBLIC (decl) ? C_EXT : C_STAT);
74618334Speter      break;
74718334Speter
74818334Speter    case TYPE_DECL:
74918334Speter      /* Done with tagged types.  */
75018334Speter      if (DECL_NAME (decl) == 0)
75118334Speter	return;
75218334Speter      if (DECL_IGNORED_P (decl))
75318334Speter	return;
75418334Speter
75518334Speter      /* Output typedef name.  */
75618334Speter      if (template_name_p (DECL_NAME (decl)))
75718334Speter	PUT_SDB_DEF (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
75818334Speter      else
75918334Speter	PUT_SDB_DEF (IDENTIFIER_POINTER (DECL_NAME (decl)));
76018334Speter      PUT_SDB_SCL (C_TPDEF);
76118334Speter      break;
76218334Speter
76318334Speter    case PARM_DECL:
76418334Speter      /* Parm decls go in their own separate chains
76518334Speter	 and are output by sdbout_reg_parms and sdbout_parms.  */
76618334Speter      abort ();
76718334Speter
76818334Speter    case VAR_DECL:
76918334Speter      /* Don't mention a variable that is external.
77018334Speter	 Let the file that defines it describe it.  */
77118334Speter      if (DECL_EXTERNAL (decl))
77218334Speter	return;
77318334Speter
77418334Speter      /* Ignore __FUNCTION__, etc.  */
77518334Speter      if (DECL_IGNORED_P (decl))
77618334Speter	return;
77718334Speter
77818334Speter      /* If there was an error in the declaration, don't dump core
77918334Speter	 if there is no RTL associated with the variable doesn't
78018334Speter	 exist.  */
78190075Sobrien      if (!DECL_RTL_SET_P (decl))
78218334Speter	return;
78318334Speter
78490075Sobrien      SET_DECL_RTL (decl,
78590075Sobrien		    eliminate_regs (DECL_RTL (decl), 0, NULL_RTX));
78618334Speter#ifdef LEAF_REG_REMAP
78752284Sobrien      if (current_function_uses_only_leaf_regs)
78818334Speter	leaf_renumber_regs_insn (DECL_RTL (decl));
78918334Speter#endif
79018334Speter      value = DECL_RTL (decl);
79118334Speter
79218334Speter      /* Don't mention a variable at all
79318334Speter	 if it was completely optimized into nothingness.
79418334Speter
79518334Speter	 If DECL was from an inline function, then its rtl
79618334Speter	 is not identically the rtl that was used in this
79718334Speter	 particular compilation.  */
79818334Speter      if (GET_CODE (value) == REG)
79918334Speter	{
80090075Sobrien	  regno = REGNO (value);
80118334Speter	  if (regno >= FIRST_PSEUDO_REGISTER)
80218334Speter	    return;
80318334Speter	}
80418334Speter      else if (GET_CODE (value) == SUBREG)
80518334Speter	{
80618334Speter	  while (GET_CODE (value) == SUBREG)
80790075Sobrien	    value = SUBREG_REG (value);
80818334Speter	  if (GET_CODE (value) == REG)
80918334Speter	    {
81090075Sobrien	      if (REGNO (value) >= FIRST_PSEUDO_REGISTER)
81118334Speter		return;
81218334Speter	    }
81390075Sobrien	  regno = REGNO (alter_subreg (&value));
81490075Sobrien	  SET_DECL_RTL (decl, value);
81518334Speter	}
81618334Speter      /* Don't output anything if an auto variable
81718334Speter	 gets RTL that is static.
81818334Speter	 GAS version 2.2 can't handle such output.  */
81918334Speter      else if (GET_CODE (value) == MEM && CONSTANT_P (XEXP (value, 0))
82018334Speter	       && ! TREE_STATIC (decl))
82118334Speter	return;
82218334Speter
82318334Speter      /* Emit any structure, union, or enum type that has not been output.
82418334Speter	 This occurs for tag-less structs (et al) used to declare variables
82518334Speter	 within functions.  */
82618334Speter      if (TREE_CODE (type) == ENUMERAL_TYPE
82718334Speter	  || TREE_CODE (type) == RECORD_TYPE
82818334Speter	  || TREE_CODE (type) == UNION_TYPE
82918334Speter	  || TREE_CODE (type) == QUAL_UNION_TYPE)
83018334Speter	{
83190075Sobrien	  if (COMPLETE_TYPE_P (type)		/* not a forward reference */
83218334Speter	      && KNOWN_TYPE_TAG (type) == 0)	/* not yet declared */
83318334Speter	    sdbout_one_type (type);
83418334Speter	}
83518334Speter
83618334Speter      /* Defer SDB information for top-level initialized variables! */
83718334Speter      if (! local
83818334Speter	  && GET_CODE (value) == MEM
83918334Speter	  && DECL_INITIAL (decl))
84018334Speter	return;
84118334Speter
84218334Speter      /* C++ in 2.3 makes nameless symbols.  That will be fixed later.
84318334Speter	 For now, avoid crashing.  */
84418334Speter      if (DECL_NAME (decl) == NULL_TREE)
84518334Speter	return;
84618334Speter
84718334Speter      /* Record the name for, starting a symtab entry.  */
84890075Sobrien      if (local)
84990075Sobrien	name = IDENTIFIER_POINTER (DECL_NAME (decl));
85090075Sobrien      else
85190075Sobrien	name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
85218334Speter
85318334Speter      if (GET_CODE (value) == MEM
85418334Speter	  && GET_CODE (XEXP (value, 0)) == SYMBOL_REF)
85518334Speter	{
85618334Speter	  PUT_SDB_DEF (name);
85718334Speter	  if (TREE_PUBLIC (decl))
85818334Speter	    {
85918334Speter	      PUT_SDB_VAL (XEXP (value, 0));
86018334Speter              PUT_SDB_SCL (C_EXT);
86118334Speter	    }
86218334Speter	  else
86318334Speter	    {
86418334Speter	      PUT_SDB_VAL (XEXP (value, 0));
86518334Speter              PUT_SDB_SCL (C_STAT);
86618334Speter	    }
86718334Speter	}
86818334Speter      else if (regno >= 0)
86918334Speter	{
87018334Speter	  PUT_SDB_DEF (name);
87118334Speter	  PUT_SDB_INT_VAL (DBX_REGISTER_NUMBER (regno));
87218334Speter	  PUT_SDB_SCL (C_REG);
87318334Speter	}
87418334Speter      else if (GET_CODE (value) == MEM
87518334Speter	       && (GET_CODE (XEXP (value, 0)) == MEM
87618334Speter		   || (GET_CODE (XEXP (value, 0)) == REG
87718334Speter		       && REGNO (XEXP (value, 0)) != HARD_FRAME_POINTER_REGNUM
87818334Speter		       && REGNO (XEXP (value, 0)) != STACK_POINTER_REGNUM)))
87918334Speter	/* If the value is indirect by memory or by a register
88018334Speter	   that isn't the frame pointer
88118334Speter	   then it means the object is variable-sized and address through
88218334Speter	   that register or stack slot.  COFF has no way to represent this
88318334Speter	   so all we can do is output the variable as a pointer.  */
88418334Speter	{
88518334Speter	  PUT_SDB_DEF (name);
88618334Speter	  if (GET_CODE (XEXP (value, 0)) == REG)
88718334Speter	    {
88818334Speter	      PUT_SDB_INT_VAL (DBX_REGISTER_NUMBER (REGNO (XEXP (value, 0))));
88918334Speter	      PUT_SDB_SCL (C_REG);
89018334Speter	    }
89118334Speter	  else
89218334Speter	    {
89318334Speter	      /* DECL_RTL looks like (MEM (MEM (PLUS (REG...)
89418334Speter		 (CONST_INT...)))).
89518334Speter		 We want the value of that CONST_INT.  */
89618334Speter	      /* Encore compiler hates a newline in a macro arg, it seems.  */
89718334Speter	      PUT_SDB_INT_VAL (DEBUGGER_AUTO_OFFSET
89818334Speter			       (XEXP (XEXP (value, 0), 0)));
89918334Speter	      PUT_SDB_SCL (C_AUTO);
90018334Speter	    }
90118334Speter
90252284Sobrien	  /* Effectively do build_pointer_type, but don't cache this type,
90352284Sobrien	     since it might be temporary whereas the type it points to
90452284Sobrien	     might have been saved for inlining.  */
90552284Sobrien	  /* Don't use REFERENCE_TYPE because dbx can't handle that.  */
90652284Sobrien	  type = make_node (POINTER_TYPE);
90752284Sobrien	  TREE_TYPE (type) = TREE_TYPE (decl);
90818334Speter	}
90918334Speter      else if (GET_CODE (value) == MEM
91018334Speter	       && ((GET_CODE (XEXP (value, 0)) == PLUS
91118334Speter		    && GET_CODE (XEXP (XEXP (value, 0), 0)) == REG
91218334Speter		    && GET_CODE (XEXP (XEXP (value, 0), 1)) == CONST_INT)
91318334Speter		   /* This is for variables which are at offset zero from
91418334Speter		      the frame pointer.  This happens on the Alpha.
91518334Speter		      Non-frame pointer registers are excluded above.  */
91618334Speter		   || (GET_CODE (XEXP (value, 0)) == REG)))
91718334Speter	{
91818334Speter	  /* DECL_RTL looks like (MEM (PLUS (REG...) (CONST_INT...)))
91918334Speter	     or (MEM (REG...)).  We want the value of that CONST_INT
92018334Speter	     or zero.  */
92118334Speter	  PUT_SDB_DEF (name);
92218334Speter	  PUT_SDB_INT_VAL (DEBUGGER_AUTO_OFFSET (XEXP (value, 0)));
92318334Speter	  PUT_SDB_SCL (C_AUTO);
92418334Speter	}
92518334Speter      else if (GET_CODE (value) == MEM && GET_CODE (XEXP (value, 0)) == CONST)
92618334Speter	{
92718334Speter	  /* Handle an obscure case which can arise when optimizing and
92818334Speter	     when there are few available registers.  (This is *always*
92918334Speter	     the case for i386/i486 targets).  The DECL_RTL looks like
93018334Speter	     (MEM (CONST ...)) even though this variable is a local `auto'
93118334Speter	     or a local `register' variable.  In effect, what has happened
93218334Speter	     is that the reload pass has seen that all assignments and
93318334Speter	     references for one such a local variable can be replaced by
93418334Speter	     equivalent assignments and references to some static storage
93518334Speter	     variable, thereby avoiding the need for a register.  In such
93618334Speter	     cases we're forced to lie to debuggers and tell them that
93718334Speter	     this variable was itself `static'.  */
93818334Speter	  PUT_SDB_DEF (name);
93918334Speter	  PUT_SDB_VAL (XEXP (XEXP (value, 0), 0));
94018334Speter	  PUT_SDB_SCL (C_STAT);
94118334Speter	}
94218334Speter      else
94318334Speter	{
94418334Speter	  /* It is something we don't know how to represent for SDB.  */
94518334Speter	  return;
94618334Speter	}
94718334Speter      break;
94850397Sobrien
94950397Sobrien    default:
95050397Sobrien      break;
95118334Speter    }
95218334Speter  PUT_SDB_TYPE (plain_type (type));
95318334Speter  PUT_SDB_ENDEF;
95418334Speter}
95518334Speter
95618334Speter/* Output SDB information for a top-level initialized variable
95718334Speter   that has been delayed.  */
95818334Speter
95990075Sobrienstatic void
96018334Spetersdbout_toplevel_data (decl)
96118334Speter     tree decl;
96218334Speter{
96318334Speter  tree type = TREE_TYPE (decl);
96418334Speter
96518334Speter  if (DECL_IGNORED_P (decl))
96618334Speter    return;
96718334Speter
96818334Speter  if (! (TREE_CODE (decl) == VAR_DECL
96918334Speter	 && GET_CODE (DECL_RTL (decl)) == MEM
97018334Speter	 && DECL_INITIAL (decl)))
97118334Speter    abort ();
97218334Speter
97318334Speter  PUT_SDB_DEF (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
97418334Speter  PUT_SDB_VAL (XEXP (DECL_RTL (decl), 0));
97518334Speter  if (TREE_PUBLIC (decl))
97618334Speter    {
97718334Speter      PUT_SDB_SCL (C_EXT);
97818334Speter    }
97918334Speter  else
98018334Speter    {
98118334Speter      PUT_SDB_SCL (C_STAT);
98218334Speter    }
98318334Speter  PUT_SDB_TYPE (plain_type (type));
98418334Speter  PUT_SDB_ENDEF;
98518334Speter}
98618334Speter
98718334Speter#ifdef SDB_ALLOW_FORWARD_REFERENCES
98818334Speter
98950397Sobrien/* Machinery to record and output anonymous types.  */
99018334Speter
99118334Speterstatic tree anonymous_types;
99218334Speter
99318334Speterstatic void
99418334Spetersdbout_queue_anonymous_type (type)
99518334Speter     tree type;
99618334Speter{
99790075Sobrien  anonymous_types = tree_cons (NULL_TREE, type, anonymous_types);
99818334Speter}
99918334Speter
100018334Speterstatic void
100118334Spetersdbout_dequeue_anonymous_types ()
100218334Speter{
100390075Sobrien  tree types, link;
100418334Speter
100518334Speter  while (anonymous_types)
100618334Speter    {
100718334Speter      types = nreverse (anonymous_types);
100818334Speter      anonymous_types = NULL_TREE;
100918334Speter
101018334Speter      for (link = types; link; link = TREE_CHAIN (link))
101118334Speter	{
101290075Sobrien	  tree type = TREE_VALUE (link);
101318334Speter
101418334Speter	  if (type && ! TREE_ASM_WRITTEN (type))
101518334Speter	    sdbout_one_type (type);
101618334Speter	}
101718334Speter    }
101818334Speter}
101918334Speter
102018334Speter#endif
102118334Speter
102218334Speter/* Given a chain of ..._TYPE nodes, all of which have names,
102318334Speter   output definitions of those names, as typedefs.  */
102418334Speter
102518334Spetervoid
102618334Spetersdbout_types (types)
102790075Sobrien     tree types;
102818334Speter{
102990075Sobrien  tree link;
103018334Speter
103118334Speter  for (link = types; link; link = TREE_CHAIN (link))
103218334Speter    sdbout_one_type (link);
103318334Speter
103418334Speter#ifdef SDB_ALLOW_FORWARD_REFERENCES
103518334Speter  sdbout_dequeue_anonymous_types ();
103618334Speter#endif
103718334Speter}
103818334Speter
103918334Speterstatic void
104018334Spetersdbout_type (type)
104118334Speter     tree type;
104218334Speter{
104318334Speter  if (type == error_mark_node)
104418334Speter    type = integer_type_node;
104518334Speter  PUT_SDB_TYPE (plain_type (type));
104618334Speter}
104718334Speter
104818334Speter/* Output types of the fields of type TYPE, if they are structs.
104918334Speter
105018334Speter   Formerly did not chase through pointer types, since that could be circular.
105118334Speter   They must come before TYPE, since forward refs are not allowed.
105218334Speter   Now james@bigtex.cactus.org says to try them.  */
105318334Speter
105418334Speterstatic void
105518334Spetersdbout_field_types (type)
105618334Speter     tree type;
105718334Speter{
105818334Speter  tree tail;
105950397Sobrien
106018334Speter  for (tail = TYPE_FIELDS (type); tail; tail = TREE_CHAIN (tail))
106190075Sobrien    /* This condition should match the one for emitting the actual
106290075Sobrien       members below.  */
106352284Sobrien    if (TREE_CODE (tail) == FIELD_DECL
106490075Sobrien	&& DECL_NAME (tail)
106590075Sobrien	&& DECL_SIZE (tail)
106690075Sobrien	&& host_integerp (DECL_SIZE (tail), 1)
106790075Sobrien	&& host_integerp (bit_position (tail), 0))
106852284Sobrien      {
106952284Sobrien	if (POINTER_TYPE_P (TREE_TYPE (tail)))
107052284Sobrien	  sdbout_one_type (TREE_TYPE (TREE_TYPE (tail)));
107152284Sobrien	else
107252284Sobrien	  sdbout_one_type (TREE_TYPE (tail));
107352284Sobrien      }
107418334Speter}
107518334Speter
107618334Speter/* Use this to put out the top level defined record and union types
107718334Speter   for later reference.  If this is a struct with a name, then put that
107818334Speter   name out.  Other unnamed structs will have .xxfake labels generated so
107918334Speter   that they may be referred to later.
108018334Speter   The label will be stored in the KNOWN_TYPE_TAG slot of a type.
108118334Speter   It may NOT be called recursively.  */
108218334Speter
108318334Speterstatic void
108418334Spetersdbout_one_type (type)
108518334Speter     tree type;
108618334Speter{
108718334Speter  if (current_function_decl != NULL_TREE
108818334Speter      && DECL_SECTION_NAME (current_function_decl) != NULL_TREE)
108918334Speter    ; /* Don't change section amid function.  */
109018334Speter  else
109118334Speter    text_section ();
109218334Speter
109318334Speter  switch (TREE_CODE (type))
109418334Speter    {
109518334Speter    case RECORD_TYPE:
109618334Speter    case UNION_TYPE:
109718334Speter    case QUAL_UNION_TYPE:
109818334Speter    case ENUMERAL_TYPE:
109918334Speter      type = TYPE_MAIN_VARIANT (type);
110018334Speter      /* Don't output a type twice.  */
110118334Speter      if (TREE_ASM_WRITTEN (type))
110218334Speter	/* James said test TREE_ASM_BEING_WRITTEN here.  */
110318334Speter	return;
110418334Speter
110518334Speter      /* Output nothing if type is not yet defined.  */
110690075Sobrien      if (!COMPLETE_TYPE_P (type))
110718334Speter	return;
110818334Speter
110918334Speter      TREE_ASM_WRITTEN (type) = 1;
111018334Speter#if 1
111118334Speter      /* This is reputed to cause trouble with the following case,
111218334Speter	 but perhaps checking TYPE_SIZE above will fix it.  */
111318334Speter
111418334Speter      /* Here is a test case:
111518334Speter
111618334Speter	struct foo {
111718334Speter	  struct badstr *bbb;
111818334Speter	} forwardref;
111918334Speter
112018334Speter	typedef struct intermediate {
112118334Speter	  int aaaa;
112218334Speter	} intermediate_ref;
112318334Speter
112418334Speter	typedef struct badstr {
112518334Speter	  int ccccc;
112618334Speter	} badtype;   */
112718334Speter
112818334Speter#if 0
112918334Speter      TREE_ASM_BEING_WRITTEN (type) = 1;
113018334Speter#endif
113118334Speter      /* This change, which ought to make better output,
113218334Speter	 used to make the COFF assembler unhappy.
113318334Speter	 Changes involving KNOWN_TYPE_TAG may fix the problem.  */
113418334Speter      /* Before really doing anything, output types we want to refer to.  */
113518334Speter      /* Note that in version 1 the following two lines
113618334Speter	 are not used if forward references are in use.  */
113718334Speter      if (TREE_CODE (type) != ENUMERAL_TYPE)
113818334Speter	sdbout_field_types (type);
113918334Speter#if 0
114018334Speter      TREE_ASM_WRITTEN (type) = 1;
114118334Speter#endif
114218334Speter#endif
114318334Speter
114418334Speter      /* Output a structure type.  */
114518334Speter      {
114618334Speter	int size = int_size_in_bytes (type);
114790075Sobrien	int member_scl = 0;
114818334Speter	tree tem;
114918334Speter	int i, n_baseclasses = 0;
115018334Speter
115118334Speter	/* Record the type tag, but not in its permanent place just yet.  */
115218334Speter	sdbout_record_type_name (type);
115318334Speter
115418334Speter	PUT_SDB_DEF (KNOWN_TYPE_TAG (type));
115518334Speter
115618334Speter	switch (TREE_CODE (type))
115718334Speter	  {
115818334Speter	  case UNION_TYPE:
115918334Speter	  case QUAL_UNION_TYPE:
116018334Speter	    PUT_SDB_SCL (C_UNTAG);
116118334Speter	    PUT_SDB_TYPE (T_UNION);
116218334Speter	    member_scl = C_MOU;
116318334Speter	    break;
116418334Speter
116518334Speter	  case RECORD_TYPE:
116618334Speter	    PUT_SDB_SCL (C_STRTAG);
116718334Speter	    PUT_SDB_TYPE (T_STRUCT);
116818334Speter	    member_scl = C_MOS;
116918334Speter	    break;
117018334Speter
117118334Speter	  case ENUMERAL_TYPE:
117218334Speter	    PUT_SDB_SCL (C_ENTAG);
117318334Speter	    PUT_SDB_TYPE (T_ENUM);
117418334Speter	    member_scl = C_MOE;
117518334Speter	    break;
117650397Sobrien
117750397Sobrien	  default:
117850397Sobrien	    break;
117918334Speter	  }
118018334Speter
118118334Speter	PUT_SDB_SIZE (size);
118218334Speter	PUT_SDB_ENDEF;
118318334Speter
118418334Speter	/* Print out the base class information with fields
118518334Speter	   named after the types they hold.  */
118690075Sobrien	/* This is only relevant to aggregate types.  TYPE_BINFO is used
118752284Sobrien	   for other purposes in an ENUMERAL_TYPE, so we must exclude that
118852284Sobrien	   case.  */
118952284Sobrien	if (TREE_CODE (type) != ENUMERAL_TYPE)
119018334Speter	  {
119152284Sobrien	    if (TYPE_BINFO (type)
119252284Sobrien		&& TYPE_BINFO_BASETYPES (type))
119352284Sobrien	      n_baseclasses = TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (type));
119452284Sobrien	    for (i = 0; i < n_baseclasses; i++)
119518334Speter	      {
119652284Sobrien		tree child = TREE_VEC_ELT (BINFO_BASETYPES (TYPE_BINFO (type)),
119752284Sobrien					   i);
119852284Sobrien		tree child_type = BINFO_TYPE (child);
119952284Sobrien		tree child_type_name;
120052284Sobrien		if (TYPE_NAME (child_type) == 0)
120152284Sobrien		  continue;
120252284Sobrien		if (TREE_CODE (TYPE_NAME (child_type)) == IDENTIFIER_NODE)
120352284Sobrien		  child_type_name = TYPE_NAME (child_type);
120452284Sobrien		else if (TREE_CODE (TYPE_NAME (child_type)) == TYPE_DECL)
120552284Sobrien		  {
120652284Sobrien		    child_type_name = DECL_NAME (TYPE_NAME (child_type));
120752284Sobrien		    if (child_type_name && template_name_p (child_type_name))
120852284Sobrien		      child_type_name
120952284Sobrien			= DECL_ASSEMBLER_NAME (TYPE_NAME (child_type));
121052284Sobrien		  }
121152284Sobrien		else
121252284Sobrien		  continue;
121352284Sobrien
121452284Sobrien		CONTIN;
121552284Sobrien		PUT_SDB_DEF (IDENTIFIER_POINTER (child_type_name));
121690075Sobrien		PUT_SDB_INT_VAL (tree_low_cst (BINFO_OFFSET (child), 0));
121752284Sobrien		PUT_SDB_SCL (member_scl);
121852284Sobrien		sdbout_type (BINFO_TYPE (child));
121952284Sobrien		PUT_SDB_ENDEF;
122018334Speter	      }
122118334Speter	  }
122218334Speter
122318334Speter	/* output the individual fields */
122418334Speter
122518334Speter	if (TREE_CODE (type) == ENUMERAL_TYPE)
122690075Sobrien	  {
122790075Sobrien	    for (tem = TYPE_FIELDS (type); tem; tem = TREE_CHAIN (tem))
122890075Sobrien	      if (host_integerp (TREE_VALUE (tem), 0))
122990075Sobrien		{
123090075Sobrien		  PUT_SDB_DEF (IDENTIFIER_POINTER (TREE_PURPOSE (tem)));
123190075Sobrien		  PUT_SDB_INT_VAL (tree_low_cst (TREE_VALUE (tem), 0));
123290075Sobrien		  PUT_SDB_SCL (C_MOE);
123390075Sobrien		  PUT_SDB_TYPE (T_MOE);
123490075Sobrien		  PUT_SDB_ENDEF;
123590075Sobrien		}
123690075Sobrien	  }
123718334Speter	else			/* record or union type */
123818334Speter	  for (tem = TYPE_FIELDS (type); tem; tem = TREE_CHAIN (tem))
123918334Speter	    /* Output the name, type, position (in bits), size (in bits)
124018334Speter	       of each field.  */
124118334Speter
124218334Speter	    /* Omit here the nameless fields that are used to skip bits.
124318334Speter	       Also omit fields with variable size or position.
124418334Speter	       Also omit non FIELD_DECL nodes that GNU C++ may put here.  */
124518334Speter	    if (TREE_CODE (tem) == FIELD_DECL
124690075Sobrien		&& DECL_NAME (tem)
124790075Sobrien		&& DECL_SIZE (tem)
124890075Sobrien		&& host_integerp (DECL_SIZE (tem), 1)
124990075Sobrien		&& host_integerp (bit_position (tem), 0))
125018334Speter	      {
125190075Sobrien		const char *name;
125218334Speter
125318334Speter		CONTIN;
125490075Sobrien		name = IDENTIFIER_POINTER (DECL_NAME (tem));
125518334Speter		PUT_SDB_DEF (name);
125618334Speter		if (DECL_BIT_FIELD_TYPE (tem))
125718334Speter		  {
125890075Sobrien		    PUT_SDB_INT_VAL (int_bit_position (tem));
125918334Speter		    PUT_SDB_SCL (C_FIELD);
126018334Speter		    sdbout_type (DECL_BIT_FIELD_TYPE (tem));
126190075Sobrien		    PUT_SDB_SIZE (tree_low_cst (DECL_SIZE (tem), 1));
126218334Speter		  }
126318334Speter		else
126418334Speter		  {
126590075Sobrien		    PUT_SDB_INT_VAL (int_bit_position (tem) / BITS_PER_UNIT);
126618334Speter		    PUT_SDB_SCL (member_scl);
126718334Speter		    sdbout_type (TREE_TYPE (tem));
126818334Speter		  }
126918334Speter		PUT_SDB_ENDEF;
127018334Speter	      }
127118334Speter	/* output end of a structure,union, or enumeral definition */
127218334Speter
127318334Speter	PUT_SDB_PLAIN_DEF ("eos");
127418334Speter	PUT_SDB_INT_VAL (size);
127518334Speter	PUT_SDB_SCL (C_EOS);
127618334Speter	PUT_SDB_TAG (KNOWN_TYPE_TAG (type));
127718334Speter	PUT_SDB_SIZE (size);
127818334Speter	PUT_SDB_ENDEF;
127918334Speter	break;
128050397Sobrien
128150397Sobrien      default:
128250397Sobrien	break;
128318334Speter      }
128418334Speter    }
128518334Speter}
128618334Speter
128718334Speter/* The following two functions output definitions of function parameters.
128818334Speter   Each parameter gets a definition locating it in the parameter list.
128918334Speter   Each parameter that is a register variable gets a second definition
129018334Speter   locating it in the register.
129118334Speter
129218334Speter   Printing or argument lists in gdb uses the definitions that
129318334Speter   locate in the parameter list.  But reference to the variable in
129418334Speter   expressions uses preferentially the definition as a register.  */
129518334Speter
129618334Speter/* Output definitions, referring to storage in the parmlist,
129718334Speter   of all the parms in PARMS, which is a chain of PARM_DECL nodes.  */
129818334Speter
129918334Speterstatic void
130018334Spetersdbout_parms (parms)
130118334Speter     tree parms;
130218334Speter{
130318334Speter  for (; parms; parms = TREE_CHAIN (parms))
130418334Speter    if (DECL_NAME (parms))
130518334Speter      {
130618334Speter	int current_sym_value = 0;
130790075Sobrien	const char *name = IDENTIFIER_POINTER (DECL_NAME (parms));
130818334Speter
130918334Speter	if (name == 0 || *name == 0)
131018334Speter	  name = gen_fake_label ();
131118334Speter
131218334Speter	/* Perform any necessary register eliminations on the parameter's rtl,
131318334Speter	   so that the debugging output will be accurate.  */
131450397Sobrien	DECL_INCOMING_RTL (parms)
131550397Sobrien	  = eliminate_regs (DECL_INCOMING_RTL (parms), 0, NULL_RTX);
131690075Sobrien	SET_DECL_RTL (parms,
131790075Sobrien		      eliminate_regs (DECL_RTL (parms), 0, NULL_RTX));
131818334Speter
131918334Speter	if (PARM_PASSED_IN_MEMORY (parms))
132018334Speter	  {
132118334Speter	    rtx addr = XEXP (DECL_INCOMING_RTL (parms), 0);
132218334Speter	    tree type;
132318334Speter
132418334Speter	    /* ??? Here we assume that the parm address is indexed
132518334Speter	       off the frame pointer or arg pointer.
132618334Speter	       If that is not true, we produce meaningless results,
132718334Speter	       but do not crash.  */
132818334Speter	    if (GET_CODE (addr) == PLUS
132918334Speter		&& GET_CODE (XEXP (addr, 1)) == CONST_INT)
133018334Speter	      current_sym_value = INTVAL (XEXP (addr, 1));
133118334Speter	    else
133218334Speter	      current_sym_value = 0;
133318334Speter
133418334Speter	    if (GET_CODE (DECL_RTL (parms)) == REG
133518334Speter		&& REGNO (DECL_RTL (parms)) < FIRST_PSEUDO_REGISTER)
133618334Speter	      type = DECL_ARG_TYPE (parms);
133718334Speter	    else
133818334Speter	      {
133918334Speter		int original_sym_value = current_sym_value;
134018334Speter
134118334Speter		/* This is the case where the parm is passed as an int or
134218334Speter		   double and it is converted to a char, short or float
134318334Speter		   and stored back in the parmlist.  In this case, describe
134418334Speter		   the parm with the variable's declared type, and adjust
134518334Speter		   the address if the least significant bytes (which we are
134618334Speter		   using) are not the first ones.  */
134718334Speter		if (BYTES_BIG_ENDIAN
134818334Speter		    && TREE_TYPE (parms) != DECL_ARG_TYPE (parms))
134918334Speter		  current_sym_value +=
135018334Speter		    (GET_MODE_SIZE (TYPE_MODE (DECL_ARG_TYPE (parms)))
135118334Speter		     - GET_MODE_SIZE (GET_MODE (DECL_RTL (parms))));
135218334Speter
135318334Speter		if (GET_CODE (DECL_RTL (parms)) == MEM
135418334Speter		    && GET_CODE (XEXP (DECL_RTL (parms), 0)) == PLUS
135518334Speter		    && (GET_CODE (XEXP (XEXP (DECL_RTL (parms), 0), 1))
135618334Speter			== CONST_INT)
135718334Speter		    && (INTVAL (XEXP (XEXP (DECL_RTL (parms), 0), 1))
135818334Speter			== current_sym_value))
135918334Speter		  type = TREE_TYPE (parms);
136018334Speter		else
136118334Speter		  {
136218334Speter		    current_sym_value = original_sym_value;
136318334Speter		    type = DECL_ARG_TYPE (parms);
136418334Speter		  }
136518334Speter	      }
136618334Speter
136718334Speter	    PUT_SDB_DEF (name);
136818334Speter	    PUT_SDB_INT_VAL (DEBUGGER_ARG_OFFSET (current_sym_value, addr));
136918334Speter	    PUT_SDB_SCL (C_ARG);
137018334Speter	    PUT_SDB_TYPE (plain_type (type));
137118334Speter	    PUT_SDB_ENDEF;
137218334Speter	  }
137318334Speter	else if (GET_CODE (DECL_RTL (parms)) == REG)
137418334Speter	  {
137518334Speter	    rtx best_rtl;
137618334Speter	    /* Parm passed in registers and lives in registers or nowhere.  */
137718334Speter
137818334Speter	    /* If parm lives in a register, use that register;
137918334Speter	       pretend the parm was passed there.  It would be more consistent
138018334Speter	       to describe the register where the parm was passed,
138118334Speter	       but in practice that register usually holds something else.  */
138290075Sobrien	    if (REGNO (DECL_RTL (parms)) < FIRST_PSEUDO_REGISTER)
138318334Speter	      best_rtl = DECL_RTL (parms);
138418334Speter	    /* If the parm lives nowhere,
138518334Speter	       use the register where it was passed.  */
138618334Speter	    else
138718334Speter	      best_rtl = DECL_INCOMING_RTL (parms);
138818334Speter
138918334Speter	    PUT_SDB_DEF (name);
139018334Speter	    PUT_SDB_INT_VAL (DBX_REGISTER_NUMBER (REGNO (best_rtl)));
139118334Speter	    PUT_SDB_SCL (C_REGPARM);
139250397Sobrien	    PUT_SDB_TYPE (plain_type (TREE_TYPE (parms)));
139318334Speter	    PUT_SDB_ENDEF;
139418334Speter	  }
139518334Speter	else if (GET_CODE (DECL_RTL (parms)) == MEM
139618334Speter		 && XEXP (DECL_RTL (parms), 0) != const0_rtx)
139718334Speter	  {
139818334Speter	    /* Parm was passed in registers but lives on the stack.  */
139918334Speter
140018334Speter	    /* DECL_RTL looks like (MEM (PLUS (REG...) (CONST_INT...))),
140118334Speter	       in which case we want the value of that CONST_INT,
140218334Speter	       or (MEM (REG ...)) or (MEM (MEM ...)),
140318334Speter	       in which case we use a value of zero.  */
140418334Speter	    if (GET_CODE (XEXP (DECL_RTL (parms), 0)) == REG
140518334Speter		|| GET_CODE (XEXP (DECL_RTL (parms), 0)) == MEM)
140618334Speter	      current_sym_value = 0;
140718334Speter	    else
140818334Speter	      current_sym_value = INTVAL (XEXP (XEXP (DECL_RTL (parms), 0), 1));
140918334Speter
141018334Speter	    /* Again, this assumes the offset is based on the arg pointer.  */
141118334Speter	    PUT_SDB_DEF (name);
141218334Speter	    PUT_SDB_INT_VAL (DEBUGGER_ARG_OFFSET (current_sym_value,
141318334Speter						  XEXP (DECL_RTL (parms), 0)));
141418334Speter	    PUT_SDB_SCL (C_ARG);
141550397Sobrien	    PUT_SDB_TYPE (plain_type (TREE_TYPE (parms)));
141618334Speter	    PUT_SDB_ENDEF;
141718334Speter	  }
141818334Speter      }
141918334Speter}
142018334Speter
142118334Speter/* Output definitions for the places where parms live during the function,
142218334Speter   when different from where they were passed, when the parms were passed
142318334Speter   in memory.
142418334Speter
142518334Speter   It is not useful to do this for parms passed in registers
142618334Speter   that live during the function in different registers, because it is
142718334Speter   impossible to look in the passed register for the passed value,
142818334Speter   so we use the within-the-function register to begin with.
142918334Speter
143018334Speter   PARMS is a chain of PARM_DECL nodes.  */
143118334Speter
143218334Speterstatic void
143318334Spetersdbout_reg_parms (parms)
143418334Speter     tree parms;
143518334Speter{
143618334Speter  for (; parms; parms = TREE_CHAIN (parms))
143718334Speter    if (DECL_NAME (parms))
143818334Speter      {
143990075Sobrien	const char *name = IDENTIFIER_POINTER (DECL_NAME (parms));
144018334Speter
144118334Speter	/* Report parms that live in registers during the function
144218334Speter	   but were passed in memory.  */
144318334Speter	if (GET_CODE (DECL_RTL (parms)) == REG
144418334Speter	    && REGNO (DECL_RTL (parms)) < FIRST_PSEUDO_REGISTER
144518334Speter	    && PARM_PASSED_IN_MEMORY (parms))
144618334Speter	  {
144718334Speter	    if (name == 0 || *name == 0)
144818334Speter	      name = gen_fake_label ();
144918334Speter	    PUT_SDB_DEF (name);
145018334Speter	    PUT_SDB_INT_VAL (DBX_REGISTER_NUMBER (REGNO (DECL_RTL (parms))));
145118334Speter	    PUT_SDB_SCL (C_REG);
145250397Sobrien	    PUT_SDB_TYPE (plain_type (TREE_TYPE (parms)));
145318334Speter	    PUT_SDB_ENDEF;
145418334Speter	  }
145518334Speter	/* Report parms that live in memory but not where they were passed.  */
145618334Speter	else if (GET_CODE (DECL_RTL (parms)) == MEM
145718334Speter		 && GET_CODE (XEXP (DECL_RTL (parms), 0)) == PLUS
145818334Speter		 && GET_CODE (XEXP (XEXP (DECL_RTL (parms), 0), 1)) == CONST_INT
145918334Speter		 && PARM_PASSED_IN_MEMORY (parms)
146018334Speter		 && ! rtx_equal_p (DECL_RTL (parms), DECL_INCOMING_RTL (parms)))
146118334Speter	  {
146218334Speter#if 0 /* ??? It is not clear yet what should replace this.  */
146318334Speter	    int offset = DECL_OFFSET (parms) / BITS_PER_UNIT;
146418334Speter	    /* A parm declared char is really passed as an int,
146518334Speter	       so it occupies the least significant bytes.
146618334Speter	       On a big-endian machine those are not the low-numbered ones.  */
146718334Speter	    if (BYTES_BIG_ENDIAN
146818334Speter		&& offset != -1
146918334Speter		&& TREE_TYPE (parms) != DECL_ARG_TYPE (parms))
147018334Speter	      offset += (GET_MODE_SIZE (TYPE_MODE (DECL_ARG_TYPE (parms)))
147118334Speter			 - GET_MODE_SIZE (GET_MODE (DECL_RTL (parms))));
147218334Speter	    if (INTVAL (XEXP (XEXP (DECL_RTL (parms), 0), 1)) != offset) {...}
147318334Speter#endif
147418334Speter	      {
147518334Speter		if (name == 0 || *name == 0)
147618334Speter		  name = gen_fake_label ();
147718334Speter		PUT_SDB_DEF (name);
147818334Speter		PUT_SDB_INT_VAL (DEBUGGER_AUTO_OFFSET
147918334Speter				 (XEXP (DECL_RTL (parms), 0)));
148018334Speter		PUT_SDB_SCL (C_AUTO);
148118334Speter		PUT_SDB_TYPE (plain_type (TREE_TYPE (parms)));
148218334Speter		PUT_SDB_ENDEF;
148318334Speter	      }
148418334Speter	  }
148518334Speter      }
148618334Speter}
148718334Speter
148890075Sobrien/* Output debug information for a global DECL.  Called from toplev.c
148990075Sobrien   after compilation proper has finished.  */
149090075Sobrien
149190075Sobrienstatic void
149290075Sobriensdbout_global_decl (decl)
149390075Sobrien     tree decl;
149490075Sobrien{
149590075Sobrien  if (TREE_CODE (decl) == VAR_DECL
149690075Sobrien      && !DECL_EXTERNAL (decl)
149790075Sobrien      && DECL_RTL_SET_P (decl))
149890075Sobrien    {
149990075Sobrien      /* The COFF linker can move initialized global vars to the end.
150090075Sobrien	 And that can screw up the symbol ordering.  Defer those for
150190075Sobrien	 sdbout_finish ().  */
150290075Sobrien      if (!DECL_INITIAL (decl) || !TREE_PUBLIC (decl))
150390075Sobrien	sdbout_symbol (decl, 0);
150490075Sobrien
150590075Sobrien      /* Output COFF information for non-global file-scope initialized
150690075Sobrien	 variables.  */
150790075Sobrien      if (DECL_INITIAL (decl) && GET_CODE (DECL_RTL (decl)) == MEM)
150890075Sobrien	sdbout_toplevel_data (decl);
150990075Sobrien    }
151090075Sobrien}
151190075Sobrien
151290075Sobrien/* Output initialized global vars at the end, in the order of
151390075Sobrien   definition.  See comment in sdbout_global_decl.  */
151490075Sobrien
151590075Sobrienstatic void
151690075Sobriensdbout_finish (main_filename)
151790075Sobrien     const char *main_filename ATTRIBUTE_UNUSED;
151890075Sobrien{
151990075Sobrien  tree decl = getdecls ();
152090075Sobrien  unsigned int len = list_length (decl);
152190075Sobrien  tree *vec = (tree *) xmalloc (sizeof (tree) * len);
152290075Sobrien  unsigned int i;
152390075Sobrien
152490075Sobrien  /* Process the decls in reverse order--earliest first.  Put them
152590075Sobrien     into VEC from back to front, then take out from front.  */
152690075Sobrien
152790075Sobrien  for (i = 0; i < len; i++, decl = TREE_CHAIN (decl))
152890075Sobrien    vec[len - i - 1] = decl;
152990075Sobrien
153090075Sobrien  for (i = 0; i < len; i++)
153190075Sobrien    {
153290075Sobrien      decl = vec[i];
153390075Sobrien      if (TREE_CODE (decl) == VAR_DECL
153490075Sobrien	  && ! DECL_EXTERNAL (decl)
153590075Sobrien	  && DECL_INITIAL (decl)
153690075Sobrien	  && TREE_PUBLIC (decl)
153790075Sobrien	  && DECL_RTL_SET_P (decl))
153890075Sobrien	sdbout_symbol (decl, 0);
153990075Sobrien    }
154090075Sobrien
154190075Sobrien  free (vec);
154290075Sobrien}
154390075Sobrien
154418334Speter/* Describe the beginning of an internal block within a function.
154518334Speter   Also output descriptions of variables defined in this block.
154618334Speter
154718334Speter   N is the number of the block, by order of beginning, counting from 1,
154818334Speter   and not counting the outermost (function top-level) block.
154918334Speter   The blocks match the BLOCKs in DECL_INITIAL (current_function_decl),
155018334Speter   if the count starts at 0 for the outermost one.  */
155118334Speter
155290075Sobrienstatic void
155390075Sobriensdbout_begin_block (line, n)
155490075Sobrien     unsigned int line;
155590075Sobrien     unsigned int n;
155618334Speter{
155718334Speter  tree decl = current_function_decl;
155818334Speter  MAKE_LINE_SAFE (line);
155918334Speter
156018334Speter  /* The SCO compiler does not emit a separate block for the function level
156118334Speter     scope, so we avoid it here also.  However, mips ECOFF compilers do emit
156218334Speter     a separate block, so we retain it when MIPS_DEBUGGING_INFO is defined.  */
156318334Speter#ifndef MIPS_DEBUGGING_INFO
156418334Speter  if (n != 1)
156518334Speter#endif
156618334Speter    PUT_SDB_BLOCK_START (line - sdb_begin_function_line);
156718334Speter
156818334Speter  if (n == 1)
156918334Speter    {
157018334Speter      /* Include the outermost BLOCK's variables in block 1.  */
157190075Sobrien      do_block = BLOCK_NUMBER (DECL_INITIAL (decl));
157218334Speter      sdbout_block (DECL_INITIAL (decl));
157318334Speter    }
157418334Speter  /* If -g1, suppress all the internal symbols of functions
157518334Speter     except for arguments.  */
157618334Speter  if (debug_info_level != DINFO_LEVEL_TERSE)
157718334Speter    {
157818334Speter      do_block = n;
157918334Speter      sdbout_block (DECL_INITIAL (decl));
158018334Speter    }
158118334Speter
158218334Speter#ifdef SDB_ALLOW_FORWARD_REFERENCES
158318334Speter  sdbout_dequeue_anonymous_types ();
158418334Speter#endif
158518334Speter}
158618334Speter
158718334Speter/* Describe the end line-number of an internal block within a function.  */
158818334Speter
158990075Sobrienstatic void
159090075Sobriensdbout_end_block (line, n)
159190075Sobrien     unsigned int line;
159290075Sobrien     unsigned int n ATTRIBUTE_UNUSED;
159318334Speter{
159418334Speter  MAKE_LINE_SAFE (line);
159518334Speter
159618334Speter  /* The SCO compiler does not emit a separate block for the function level
159718334Speter     scope, so we avoid it here also.  However, mips ECOFF compilers do emit
159818334Speter     a separate block, so we retain it when MIPS_DEBUGGING_INFO is defined.  */
159918334Speter#ifndef MIPS_DEBUGGING_INFO
160018334Speter  if (n != 1)
160118334Speter#endif
160218334Speter  PUT_SDB_BLOCK_END (line - sdb_begin_function_line);
160318334Speter}
160418334Speter
160590075Sobrienstatic void
160690075Sobriensdbout_source_line (line, filename)
160790075Sobrien     unsigned int line;
160890075Sobrien     const char *filename ATTRIBUTE_UNUSED;
160990075Sobrien{
161090075Sobrien  /* COFF relative line numbers must be positive.  */
161190075Sobrien  if ((int) line > sdb_begin_function_line)
161290075Sobrien    {
161390075Sobrien#ifdef ASM_OUTPUT_SOURCE_LINE
161490075Sobrien      ASM_OUTPUT_SOURCE_LINE (asm_out_file, line);
161590075Sobrien#else
161690075Sobrien      fprintf (asm_out_file, "\t.ln\t%d\n",
161790075Sobrien	       ((sdb_begin_function_line > -1)
161890075Sobrien		? line - sdb_begin_function_line : 1));
161990075Sobrien#endif
162090075Sobrien    }
162190075Sobrien}
162290075Sobrien
162318334Speter/* Output sdb info for the current function name.
162418334Speter   Called from assemble_start_function.  */
162518334Speter
162690075Sobrienstatic void
162790075Sobriensdbout_begin_function (decl)
162890075Sobrien     tree decl ATTRIBUTE_UNUSED;
162918334Speter{
163018334Speter  sdbout_symbol (current_function_decl, 0);
163118334Speter}
163218334Speter
163390075Sobrien/* Called at beginning of function body (before or after prologue,
163490075Sobrien   depending on MIPS_DEBUGGING_INFO).  Record the function's starting
163590075Sobrien   line number, so we can output relative line numbers for the other
163690075Sobrien   lines.  Describe beginning of outermost block.  Also describe the
163790075Sobrien   parameter list.  */
163818334Speter
163990075Sobrien#ifndef MIPS_DEBUGGING_INFO
164090075Sobrienstatic void
164190075Sobriensdbout_begin_prologue (line, file)
164290075Sobrien     unsigned int line;
164390075Sobrien     const char *file ATTRIBUTE_UNUSED;
164418334Speter{
164590075Sobrien  sdbout_end_prologue (line);
164690075Sobrien}
164790075Sobrien#endif
164890075Sobrien
164990075Sobrienstatic void
165090075Sobriensdbout_end_prologue (line)
165190075Sobrien     unsigned int line;
165290075Sobrien{
165318334Speter  sdb_begin_function_line = line - 1;
165418334Speter  PUT_SDB_FUNCTION_START (line);
165518334Speter  sdbout_parms (DECL_ARGUMENTS (current_function_decl));
165618334Speter  sdbout_reg_parms (DECL_ARGUMENTS (current_function_decl));
165718334Speter}
165818334Speter
165918334Speter/* Called at end of function (before epilogue).
166018334Speter   Describe end of outermost block.  */
166118334Speter
166290075Sobrienstatic void
166318334Spetersdbout_end_function (line)
166490075Sobrien     unsigned int line;
166518334Speter{
166618334Speter#ifdef SDB_ALLOW_FORWARD_REFERENCES
166718334Speter  sdbout_dequeue_anonymous_types ();
166818334Speter#endif
166918334Speter
167018334Speter  MAKE_LINE_SAFE (line);
167118334Speter  PUT_SDB_FUNCTION_END (line - sdb_begin_function_line);
167218334Speter
167318334Speter  /* Indicate we are between functions, for line-number output.  */
167418334Speter  sdb_begin_function_line = -1;
167518334Speter}
167618334Speter
167718334Speter/* Output sdb info for the absolute end of a function.
167818334Speter   Called after the epilogue is output.  */
167918334Speter
168090075Sobrienstatic void
168118334Spetersdbout_end_epilogue ()
168218334Speter{
168390075Sobrien  const char *const name ATTRIBUTE_UNUSED
168490075Sobrien    = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl));
168590075Sobrien
168690075Sobrien#ifdef PUT_SDB_EPILOGUE_END
168718334Speter  PUT_SDB_EPILOGUE_END (name);
168890075Sobrien#else
168990075Sobrien  fprintf (asm_out_file, "\t.def\t");
169090075Sobrien  assemble_name (asm_out_file, name);
169190075Sobrien  fprintf (asm_out_file, "%s\t.val\t.%s\t.scl\t-1%s\t.endef\n",
169290075Sobrien	   SDB_DELIM, SDB_DELIM, SDB_DELIM);
169390075Sobrien#endif
169418334Speter}
169518334Speter
169618334Speter/* Output sdb info for the given label.  Called only if LABEL_NAME (insn)
169718334Speter   is present.  */
169818334Speter
169990075Sobrienstatic void
170018334Spetersdbout_label (insn)
170190075Sobrien     rtx insn;
170218334Speter{
170318334Speter  PUT_SDB_DEF (LABEL_NAME (insn));
170418334Speter  PUT_SDB_VAL (insn);
170518334Speter  PUT_SDB_SCL (C_LABEL);
170618334Speter  PUT_SDB_TYPE (T_NULL);
170718334Speter  PUT_SDB_ENDEF;
170818334Speter}
170918334Speter
171050397Sobrien/* Change to reading from a new source file.  */
171150397Sobrien
171290075Sobrienstatic void
171390075Sobriensdbout_start_source_file (line, filename)
171490075Sobrien     unsigned int line ATTRIBUTE_UNUSED;
171590075Sobrien     const char *filename ATTRIBUTE_UNUSED;
171650397Sobrien{
171750397Sobrien#ifdef MIPS_DEBUGGING_INFO
171850397Sobrien  struct sdb_file *n = (struct sdb_file *) xmalloc (sizeof *n);
171950397Sobrien
172050397Sobrien  n->next = current_file;
172150397Sobrien  n->name = filename;
172250397Sobrien  current_file = n;
172350397Sobrien  PUT_SDB_SRC_FILE (filename);
172450397Sobrien#endif
172550397Sobrien}
172650397Sobrien
172750397Sobrien/* Revert to reading a previous source file.  */
172850397Sobrien
172990075Sobrienstatic void
173090075Sobriensdbout_end_source_file (line)
173190075Sobrien     unsigned int line ATTRIBUTE_UNUSED;
173250397Sobrien{
173350397Sobrien#ifdef MIPS_DEBUGGING_INFO
173450397Sobrien  struct sdb_file *next;
173550397Sobrien
173650397Sobrien  next = current_file->next;
173750397Sobrien  free (current_file);
173850397Sobrien  current_file = next;
173950397Sobrien  PUT_SDB_SRC_FILE (current_file->name);
174050397Sobrien#endif
174150397Sobrien}
174250397Sobrien
174390075Sobrien/* Set up for SDB output at the start of compilation.  */
174490075Sobrien
174590075Sobrienstatic void
174690075Sobriensdbout_init (input_file_name)
174790075Sobrien     const char *input_file_name ATTRIBUTE_UNUSED;
174890075Sobrien{
174990075Sobrien#ifdef MIPS_DEBUGGING_INFO
175090075Sobrien  current_file = (struct sdb_file *) xmalloc (sizeof *current_file);
175190075Sobrien  current_file->next = NULL;
175290075Sobrien  current_file->name = input_file_name;
175390075Sobrien#endif
175490075Sobrien
175590075Sobrien#ifdef RMS_QUICK_HACK_1
175690075Sobrien  tree t;
175790075Sobrien  for (t = getdecls (); t; t = TREE_CHAIN (t))
175890075Sobrien    if (DECL_NAME (t) && IDENTIFIER_POINTER (DECL_NAME (t)) != 0
175990075Sobrien	&& !strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__vtbl_ptr_type"))
176090075Sobrien      sdbout_symbol (t, 0);
176190075Sobrien#endif
176290075Sobrien
176390075Sobrien#ifdef SDB_ALLOW_FORWARD_REFERENCES
176490075Sobrien  ggc_add_tree_root (&anonymous_types, 1);
176590075Sobrien#endif
176690075Sobrien}
176790075Sobrien
176818334Speter#endif /* SDB_DEBUGGING_INFO */
1769