sdbout.c revision 117395
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"
45117395Skan#include "system.h"
46117395Skan#include "debug.h"
47117395Skan#include "tree.h"
48117395Skan#include "ggc.h"
4918334Speter
50117395Skanstatic GTY(()) tree anonymous_types;
51117395Skan
5218334Speter#ifdef SDB_DEBUGGING_INFO
5318334Speter
5418334Speter#include "rtl.h"
5518334Speter#include "regs.h"
5618334Speter#include "flags.h"
5718334Speter#include "insn-config.h"
5818334Speter#include "reload.h"
5950397Sobrien#include "output.h"
6050397Sobrien#include "toplev.h"
6190075Sobrien#include "tm_p.h"
6218334Speter#include "gsyms.h"
63117395Skan#include "langhooks.h"
6418334Speter
6518334Speter/* 1 if PARM is passed to this function in memory.  */
6618334Speter
6718334Speter#define PARM_PASSED_IN_MEMORY(PARM) \
6818334Speter (GET_CODE (DECL_INCOMING_RTL (PARM)) == MEM)
6918334Speter
7018334Speter/* A C expression for the integer offset value of an automatic variable
7118334Speter   (C_AUTO) having address X (an RTX).  */
7218334Speter#ifndef DEBUGGER_AUTO_OFFSET
7318334Speter#define DEBUGGER_AUTO_OFFSET(X) \
7418334Speter  (GET_CODE (X) == PLUS ? INTVAL (XEXP (X, 1)) : 0)
7518334Speter#endif
7618334Speter
7718334Speter/* A C expression for the integer offset value of an argument (C_ARG)
7818334Speter   having address X (an RTX).  The nominal offset is OFFSET.  */
7918334Speter#ifndef DEBUGGER_ARG_OFFSET
8018334Speter#define DEBUGGER_ARG_OFFSET(OFFSET, X) (OFFSET)
8118334Speter#endif
8218334Speter
8318334Speter/* Line number of beginning of current function, minus one.
8418334Speter   Negative means not in a function or not using sdb.  */
8518334Speter
8618334Speterint sdb_begin_function_line = -1;
8718334Speter
8818334Speter/* Counter to generate unique "names" for nameless struct members.  */
8918334Speter
9018334Speterstatic int unnamed_struct_number = 0;
9118334Speter
9218334Speterextern FILE *asm_out_file;
9318334Speter
9418334Speterextern tree current_function_decl;
9518334Speter
9650397Sobrien#include "sdbout.h"
9718334Speter
9890075Sobrienstatic void sdbout_init			PARAMS ((const char *));
9990075Sobrienstatic void sdbout_finish		PARAMS ((const char *));
10090075Sobrienstatic void sdbout_start_source_file	PARAMS ((unsigned int, const char *));
10190075Sobrienstatic void sdbout_end_source_file	PARAMS ((unsigned int));
10290075Sobrienstatic void sdbout_begin_block		PARAMS ((unsigned int, unsigned int));
10390075Sobrienstatic void sdbout_end_block		PARAMS ((unsigned int, unsigned int));
10490075Sobrienstatic void sdbout_source_line		PARAMS ((unsigned int, const char *));
105117395Skanstatic void sdbout_end_epilogue		PARAMS ((unsigned int, const char *));
10690075Sobrienstatic void sdbout_global_decl		PARAMS ((tree));
10790075Sobrien#ifndef MIPS_DEBUGGING_INFO
10890075Sobrienstatic void sdbout_begin_prologue	PARAMS ((unsigned int, const char *));
10918334Speter#endif
110117395Skanstatic void sdbout_end_prologue		PARAMS ((unsigned int, const char *));
11190075Sobrienstatic void sdbout_begin_function	PARAMS ((tree));
11290075Sobrienstatic void sdbout_end_function		PARAMS ((unsigned int));
11390075Sobrienstatic void sdbout_toplevel_data	PARAMS ((tree));
11490075Sobrienstatic void sdbout_label		PARAMS ((rtx));
11590075Sobrienstatic char *gen_fake_label		PARAMS ((void));
11690075Sobrienstatic int plain_type			PARAMS ((tree));
11790075Sobrienstatic int template_name_p		PARAMS ((tree));
11890075Sobrienstatic void sdbout_record_type_name	PARAMS ((tree));
11990075Sobrienstatic int plain_type_1			PARAMS ((tree, int));
12090075Sobrienstatic void sdbout_block		PARAMS ((tree));
12190075Sobrienstatic void sdbout_syms			PARAMS ((tree));
12290075Sobrien#ifdef SDB_ALLOW_FORWARD_REFERENCES
12390075Sobrienstatic void sdbout_queue_anonymous_type	PARAMS ((tree));
12490075Sobrienstatic void sdbout_dequeue_anonymous_types PARAMS ((void));
12518334Speter#endif
12690075Sobrienstatic void sdbout_type			PARAMS ((tree));
12790075Sobrienstatic void sdbout_field_types		PARAMS ((tree));
12890075Sobrienstatic void sdbout_one_type		PARAMS ((tree));
12990075Sobrienstatic void sdbout_parms		PARAMS ((tree));
13090075Sobrienstatic void sdbout_reg_parms		PARAMS ((tree));
13190075Sobrienstatic void sdbout_global_decl		PARAMS ((tree));
13218334Speter
13318334Speter/* Random macros describing parts of SDB data.  */
13418334Speter
13518334Speter/* Put something here if lines get too long */
13618334Speter#define CONTIN
13718334Speter
13818334Speter/* Default value of delimiter is ";".  */
13918334Speter#ifndef SDB_DELIM
14018334Speter#define SDB_DELIM	";"
14118334Speter#endif
14218334Speter
14318334Speter/* Maximum number of dimensions the assembler will allow.  */
14418334Speter#ifndef SDB_MAX_DIM
14518334Speter#define SDB_MAX_DIM 4
14618334Speter#endif
14718334Speter
14818334Speter#ifndef PUT_SDB_SCL
14918334Speter#define PUT_SDB_SCL(a) fprintf(asm_out_file, "\t.scl\t%d%s", (a), SDB_DELIM)
15018334Speter#endif
15118334Speter
15218334Speter#ifndef PUT_SDB_INT_VAL
15350397Sobrien#define PUT_SDB_INT_VAL(a) \
15450397Sobrien do {									\
15550397Sobrien   fputs ("\t.val\t", asm_out_file);		       			\
15690075Sobrien   fprintf (asm_out_file, HOST_WIDE_INT_PRINT_DEC, (HOST_WIDE_INT) (a)); \
15750397Sobrien   fprintf (asm_out_file, "%s", SDB_DELIM);				\
15850397Sobrien } while (0)
15950397Sobrien
16018334Speter#endif
16118334Speter
16218334Speter#ifndef PUT_SDB_VAL
16318334Speter#define PUT_SDB_VAL(a)				\
16418334Speter( fputs ("\t.val\t", asm_out_file),		\
16518334Speter  output_addr_const (asm_out_file, (a)),	\
16618334Speter  fprintf (asm_out_file, SDB_DELIM))
16718334Speter#endif
16818334Speter
16918334Speter#ifndef PUT_SDB_DEF
17018334Speter#define PUT_SDB_DEF(a)				\
17118334Speterdo { fprintf (asm_out_file, "\t.def\t");	\
17290075Sobrien     assemble_name (asm_out_file, a); 	\
17318334Speter     fprintf (asm_out_file, SDB_DELIM); } while (0)
17418334Speter#endif
17518334Speter
17618334Speter#ifndef PUT_SDB_PLAIN_DEF
17718334Speter#define PUT_SDB_PLAIN_DEF(a) fprintf(asm_out_file,"\t.def\t.%s%s",a, SDB_DELIM)
17818334Speter#endif
17918334Speter
18018334Speter#ifndef PUT_SDB_ENDEF
18118334Speter#define PUT_SDB_ENDEF fputs("\t.endef\n", asm_out_file)
18218334Speter#endif
18318334Speter
18418334Speter#ifndef PUT_SDB_TYPE
18518334Speter#define PUT_SDB_TYPE(a) fprintf(asm_out_file, "\t.type\t0%o%s", a, SDB_DELIM)
18618334Speter#endif
18718334Speter
18818334Speter#ifndef PUT_SDB_SIZE
18950397Sobrien#define PUT_SDB_SIZE(a) \
19050397Sobrien do {									\
19150397Sobrien   fputs ("\t.size\t", asm_out_file);					\
19290075Sobrien   fprintf (asm_out_file, HOST_WIDE_INT_PRINT_DEC, (HOST_WIDE_INT) (a)); \
19350397Sobrien   fprintf (asm_out_file, "%s", SDB_DELIM);				\
19450397Sobrien } while(0)
19518334Speter#endif
19618334Speter
19718334Speter#ifndef PUT_SDB_START_DIM
19818334Speter#define PUT_SDB_START_DIM fprintf(asm_out_file, "\t.dim\t")
19918334Speter#endif
20018334Speter
20118334Speter#ifndef PUT_SDB_NEXT_DIM
20218334Speter#define PUT_SDB_NEXT_DIM(a) fprintf(asm_out_file, "%d,", a)
20318334Speter#endif
20418334Speter
20518334Speter#ifndef PUT_SDB_LAST_DIM
20618334Speter#define PUT_SDB_LAST_DIM(a) fprintf(asm_out_file, "%d%s", a, SDB_DELIM)
20718334Speter#endif
20818334Speter
20918334Speter#ifndef PUT_SDB_TAG
21018334Speter#define PUT_SDB_TAG(a)				\
21118334Speterdo { fprintf (asm_out_file, "\t.tag\t");	\
21290075Sobrien     assemble_name (asm_out_file, a);	\
21318334Speter     fprintf (asm_out_file, SDB_DELIM); } while (0)
21418334Speter#endif
21518334Speter
21618334Speter#ifndef PUT_SDB_BLOCK_START
21718334Speter#define PUT_SDB_BLOCK_START(LINE)		\
21818334Speter  fprintf (asm_out_file,			\
21918334Speter	   "\t.def\t.bb%s\t.val\t.%s\t.scl\t100%s\t.line\t%d%s\t.endef\n", \
22018334Speter	   SDB_DELIM, SDB_DELIM, SDB_DELIM, (LINE), SDB_DELIM)
22118334Speter#endif
22218334Speter
22318334Speter#ifndef PUT_SDB_BLOCK_END
22418334Speter#define PUT_SDB_BLOCK_END(LINE)			\
22518334Speter  fprintf (asm_out_file,			\
22618334Speter	   "\t.def\t.eb%s\t.val\t.%s\t.scl\t100%s\t.line\t%d%s\t.endef\n",  \
22718334Speter	   SDB_DELIM, SDB_DELIM, SDB_DELIM, (LINE), SDB_DELIM)
22818334Speter#endif
22918334Speter
23018334Speter#ifndef PUT_SDB_FUNCTION_START
23118334Speter#define PUT_SDB_FUNCTION_START(LINE)		\
23218334Speter  fprintf (asm_out_file,			\
23318334Speter	   "\t.def\t.bf%s\t.val\t.%s\t.scl\t101%s\t.line\t%d%s\t.endef\n", \
23418334Speter	   SDB_DELIM, SDB_DELIM, SDB_DELIM, (LINE), SDB_DELIM)
23518334Speter#endif
23618334Speter
23718334Speter#ifndef PUT_SDB_FUNCTION_END
23818334Speter#define PUT_SDB_FUNCTION_END(LINE)		\
23918334Speter  fprintf (asm_out_file,			\
24018334Speter	   "\t.def\t.ef%s\t.val\t.%s\t.scl\t101%s\t.line\t%d%s\t.endef\n", \
24118334Speter	   SDB_DELIM, SDB_DELIM, SDB_DELIM, (LINE), SDB_DELIM)
24218334Speter#endif
24318334Speter
24418334Speter#ifndef SDB_GENERATE_FAKE
24518334Speter#define SDB_GENERATE_FAKE(BUFFER, NUMBER) \
24618334Speter  sprintf ((BUFFER), ".%dfake", (NUMBER));
24718334Speter#endif
24818334Speter
24918334Speter/* Return the sdb tag identifier string for TYPE
25090075Sobrien   if TYPE has already been defined; otherwise return a null pointer.  */
25118334Speter
25218334Speter#define KNOWN_TYPE_TAG(type)  TYPE_SYMTAB_POINTER (type)
25318334Speter
25418334Speter/* Set the sdb tag identifier string for TYPE to NAME.  */
25518334Speter
25618334Speter#define SET_KNOWN_TYPE_TAG(TYPE, NAME) \
25718334Speter  TYPE_SYMTAB_POINTER (TYPE) = (NAME)
25818334Speter
25918334Speter/* Return the name (a string) of the struct, union or enum tag
26018334Speter   described by the TREE_LIST node LINK.  This is 0 for an anonymous one.  */
26118334Speter
26218334Speter#define TAG_NAME(link) \
26318334Speter  (((link) && TREE_PURPOSE ((link)) \
26418334Speter    && IDENTIFIER_POINTER (TREE_PURPOSE ((link)))) \
26518334Speter   ? IDENTIFIER_POINTER (TREE_PURPOSE ((link))) : (char *) 0)
26618334Speter
26718334Speter/* Ensure we don't output a negative line number.  */
26818334Speter#define MAKE_LINE_SAFE(line)  \
26990075Sobrien  if ((int) line <= sdb_begin_function_line) \
27090075Sobrien    line = sdb_begin_function_line + 1
27150397Sobrien
27250397Sobrien/* Perform linker optimization of merging header file definitions together
27350397Sobrien   for targets with MIPS_DEBUGGING_INFO defined.  This won't work without a
27450397Sobrien   post 960826 version of GAS.  Nothing breaks with earlier versions of GAS,
27550397Sobrien   the optimization just won't be done.  The native assembler already has the
27650397Sobrien   necessary support.  */
27750397Sobrien
27850397Sobrien#ifdef MIPS_DEBUGGING_INFO
27950397Sobrien
28050397Sobrien#ifndef PUT_SDB_SRC_FILE
28150397Sobrien#define PUT_SDB_SRC_FILE(FILENAME) \
28250397Sobrienoutput_file_directive (asm_out_file, (FILENAME))
28350397Sobrien#endif
28450397Sobrien
28550397Sobrien/* ECOFF linkers have an optimization that does the same kind of thing as
28650397Sobrien   N_BINCL/E_INCL in stabs: eliminate duplicate debug information in the
28750397Sobrien   executable.  To achieve this, GCC must output a .file for each file
28850397Sobrien   name change.  */
28950397Sobrien
29050397Sobrien/* This is a stack of input files.  */
29150397Sobrien
29250397Sobrienstruct sdb_file
29350397Sobrien{
29450397Sobrien  struct sdb_file *next;
29590075Sobrien  const char *name;
29650397Sobrien};
29750397Sobrien
29850397Sobrien/* This is the top of the stack.  */
29950397Sobrien
30050397Sobrienstatic struct sdb_file *current_file;
30150397Sobrien
30250397Sobrien#endif /* MIPS_DEBUGGING_INFO */
30318334Speter
30490075Sobrien/* The debug hooks structure.  */
305117395Skanconst struct gcc_debug_hooks sdb_debug_hooks =
30618334Speter{
30790075Sobrien  sdbout_init,			/* init */
30890075Sobrien  sdbout_finish,		/* finish */
30990075Sobrien  debug_nothing_int_charstar,	/* define */
31090075Sobrien  debug_nothing_int_charstar,	/* undef */
31190075Sobrien  sdbout_start_source_file,	/* start_source_file */
31290075Sobrien  sdbout_end_source_file,	/* end_source_file */
31390075Sobrien  sdbout_begin_block,		/* begin_block */
31490075Sobrien  sdbout_end_block,		/* end_block */
31590075Sobrien  debug_true_tree,		/* ignore_block */
31690075Sobrien  sdbout_source_line,		/* source_line */
31750397Sobrien#ifdef MIPS_DEBUGGING_INFO
31890075Sobrien  /* Defer on MIPS systems so that parameter descriptions follow
31990075Sobrien     function entry.  */
32090075Sobrien  debug_nothing_int_charstar,	/* begin_prologue */
32190075Sobrien  sdbout_end_prologue,		/* end_prologue */
32290075Sobrien#else
32390075Sobrien  sdbout_begin_prologue,	/* begin_prologue */
324117395Skan  debug_nothing_int_charstar,	/* end_prologue */
32550397Sobrien#endif
32690075Sobrien  sdbout_end_epilogue,		/* end_epilogue */
32790075Sobrien  sdbout_begin_function,	/* begin_function */
32890075Sobrien  sdbout_end_function,		/* end_function */
32990075Sobrien  debug_nothing_tree,		/* function_decl */
33090075Sobrien  sdbout_global_decl,		/* global_decl */
33190075Sobrien  debug_nothing_tree,		/* deferred_inline_function */
33290075Sobrien  debug_nothing_tree,		/* outlining_inline_function */
33390075Sobrien  sdbout_label
33490075Sobrien};
33590075Sobrien
33618334Speter#if 0
33718334Speter
33818334Speter/* return the tag identifier for type
33918334Speter */
34018334Speter
34118334Speterchar *
34218334Spetertag_of_ru_type (type,link)
34318334Speter     tree type,link;
34418334Speter{
34518334Speter  if (TYPE_SYMTAB_ADDRESS (type))
34618334Speter    return TYPE_SYMTAB_ADDRESS (type);
34718334Speter  if (link && TREE_PURPOSE (link)
34818334Speter      && IDENTIFIER_POINTER (TREE_PURPOSE (link)))
34918334Speter    TYPE_SYMTAB_ADDRESS (type) = IDENTIFIER_POINTER (TREE_PURPOSE (link));
35018334Speter  else
35118334Speter    return (char *) TYPE_SYMTAB_ADDRESS (type);
35218334Speter}
35318334Speter#endif
35418334Speter
35518334Speter/* Return a unique string to name an anonymous type.  */
35618334Speter
35718334Speterstatic char *
35818334Spetergen_fake_label ()
35918334Speter{
36018334Speter  char label[10];
36118334Speter  char *labelstr;
36218334Speter  SDB_GENERATE_FAKE (label, unnamed_struct_number);
36318334Speter  unnamed_struct_number++;
364117395Skan  labelstr = xstrdup (label);
36518334Speter  return labelstr;
36618334Speter}
36718334Speter
36818334Speter/* Return the number which describes TYPE for SDB.
36918334Speter   For pointers, etc., this function is recursive.
37018334Speter   Each record, union or enumeral type must already have had a
37118334Speter   tag number output.  */
37218334Speter
37318334Speter/* The number is given by d6d5d4d3d2d1bbbb
37418334Speter   where bbbb is 4 bit basic type, and di indicate  one of notype,ptr,fn,array.
37518334Speter   Thus, char *foo () has bbbb=T_CHAR
37618334Speter			  d1=D_FCN
37718334Speter			  d2=D_PTR
37818334Speter N_BTMASK=     017       1111     basic type field.
37918334Speter N_TSHIFT=       2                derived type shift
38018334Speter N_BTSHFT=       4                Basic type shift */
38118334Speter
38218334Speter/* Produce the number that describes a pointer, function or array type.
38318334Speter   PREV is the number describing the target, value or element type.
38418334Speter   DT_type describes how to transform that type.  */
38518334Speter#define PUSH_DERIVED_LEVEL(DT_type,PREV)		\
38690075Sobrien  ((((PREV) & ~(int) N_BTMASK) << (int) N_TSHIFT)		\
38790075Sobrien   | ((int) DT_type << (int) N_BTSHFT)			\
38890075Sobrien   | ((PREV) & (int) N_BTMASK))
38918334Speter
39018334Speter/* Number of elements used in sdb_dims.  */
39118334Speterstatic int sdb_n_dims = 0;
39218334Speter
39318334Speter/* Table of array dimensions of current type.  */
39418334Speterstatic int sdb_dims[SDB_MAX_DIM];
39518334Speter
39618334Speter/* Size of outermost array currently being processed.  */
39718334Speterstatic int sdb_type_size = -1;
39818334Speter
39918334Speterstatic int
40018334Speterplain_type (type)
40118334Speter     tree type;
40218334Speter{
40318334Speter  int val = plain_type_1 (type, 0);
40418334Speter
40518334Speter  /* If we have already saved up some array dimensions, print them now.  */
40618334Speter  if (sdb_n_dims > 0)
40718334Speter    {
40818334Speter      int i;
40918334Speter      PUT_SDB_START_DIM;
41018334Speter      for (i = sdb_n_dims - 1; i > 0; i--)
41118334Speter	PUT_SDB_NEXT_DIM (sdb_dims[i]);
41218334Speter      PUT_SDB_LAST_DIM (sdb_dims[0]);
41318334Speter      sdb_n_dims = 0;
41418334Speter
41518334Speter      sdb_type_size = int_size_in_bytes (type);
41618334Speter      /* Don't kill sdb if type is not laid out or has variable size.  */
41718334Speter      if (sdb_type_size < 0)
41818334Speter	sdb_type_size = 0;
41918334Speter    }
42018334Speter  /* If we have computed the size of an array containing this type,
42118334Speter     print it now.  */
42218334Speter  if (sdb_type_size >= 0)
42318334Speter    {
42418334Speter      PUT_SDB_SIZE (sdb_type_size);
42518334Speter      sdb_type_size = -1;
42618334Speter    }
42718334Speter  return val;
42818334Speter}
42918334Speter
43018334Speterstatic int
43118334Spetertemplate_name_p (name)
43218334Speter     tree name;
43318334Speter{
43490075Sobrien  const char *ptr = IDENTIFIER_POINTER (name);
43518334Speter  while (*ptr && *ptr != '<')
43618334Speter    ptr++;
43718334Speter
43818334Speter  return *ptr != '\0';
43918334Speter}
44018334Speter
44118334Speterstatic void
44218334Spetersdbout_record_type_name (type)
44318334Speter     tree type;
44418334Speter{
44590075Sobrien  const char *name = 0;
44618334Speter  int no_name;
44718334Speter
44818334Speter  if (KNOWN_TYPE_TAG (type))
44918334Speter    return;
45018334Speter
45118334Speter  if (TYPE_NAME (type) != 0)
45218334Speter    {
45318334Speter      tree t = 0;
45490075Sobrien
45518334Speter      /* Find the IDENTIFIER_NODE for the type name.  */
45618334Speter      if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
45718334Speter	t = TYPE_NAME (type);
45818334Speter      else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL)
45918334Speter	{
46018334Speter	  t = DECL_NAME (TYPE_NAME (type));
46118334Speter	  /* The DECL_NAME for templates includes "<>", which breaks
46218334Speter	     most assemblers.  Use its assembler name instead, which
46318334Speter	     has been mangled into being safe.  */
46418334Speter	  if (t && template_name_p (t))
46518334Speter	    t = DECL_ASSEMBLER_NAME (TYPE_NAME (type));
46618334Speter	}
46718334Speter
46818334Speter      /* Now get the name as a string, or invent one.  */
46918334Speter      if (t != NULL_TREE)
47018334Speter	name = IDENTIFIER_POINTER (t);
47118334Speter    }
47218334Speter
47318334Speter  no_name = (name == 0 || *name == 0);
47418334Speter  if (no_name)
47518334Speter    name = gen_fake_label ();
47618334Speter
47718334Speter  SET_KNOWN_TYPE_TAG (type, name);
47818334Speter#ifdef SDB_ALLOW_FORWARD_REFERENCES
47918334Speter  if (no_name)
48018334Speter    sdbout_queue_anonymous_type (type);
48118334Speter#endif
48218334Speter}
48318334Speter
48418334Speter/* Return the .type value for type TYPE.
48518334Speter
48618334Speter   LEVEL indicates how many levels deep we have recursed into the type.
48718334Speter   The SDB debug format can only represent 6 derived levels of types.
48818334Speter   After that, we must output inaccurate debug info.  We deliberately
48918334Speter   stop before the 7th level, so that ADA recursive types will not give an
49018334Speter   infinite loop.  */
49118334Speter
49218334Speterstatic int
49318334Speterplain_type_1 (type, level)
49418334Speter     tree type;
49518334Speter     int level;
49618334Speter{
49718334Speter  if (type == 0)
49818334Speter    type = void_type_node;
49918334Speter  else if (type == error_mark_node)
50018334Speter    type = integer_type_node;
50118334Speter  else
50218334Speter    type = TYPE_MAIN_VARIANT (type);
50318334Speter
50418334Speter  switch (TREE_CODE (type))
50518334Speter    {
50618334Speter    case VOID_TYPE:
50718334Speter      return T_VOID;
50852284Sobrien    case BOOLEAN_TYPE:
50918334Speter    case INTEGER_TYPE:
51018334Speter      {
51118334Speter	int size = int_size_in_bytes (type) * BITS_PER_UNIT;
51218334Speter
51318334Speter	/* Carefully distinguish all the standard types of C,
51418334Speter	   without messing up if the language is not C.
51518334Speter	   Note that we check only for the names that contain spaces;
51618334Speter	   other names might occur by coincidence in other languages.  */
51718334Speter	if (TYPE_NAME (type) != 0
51818334Speter	    && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
51918334Speter	    && DECL_NAME (TYPE_NAME (type)) != 0
52018334Speter	    && TREE_CODE (DECL_NAME (TYPE_NAME (type))) == IDENTIFIER_NODE)
52118334Speter	  {
52290075Sobrien	    const char *const name
52390075Sobrien	      = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
52418334Speter
52550397Sobrien	    if (!strcmp (name, "char"))
52650397Sobrien	      return T_CHAR;
52718334Speter	    if (!strcmp (name, "unsigned char"))
52818334Speter	      return T_UCHAR;
52918334Speter	    if (!strcmp (name, "signed char"))
53018334Speter	      return T_CHAR;
53150397Sobrien	    if (!strcmp (name, "int"))
53250397Sobrien	      return T_INT;
53318334Speter	    if (!strcmp (name, "unsigned int"))
53418334Speter	      return T_UINT;
53518334Speter	    if (!strcmp (name, "short int"))
53618334Speter	      return T_SHORT;
53718334Speter	    if (!strcmp (name, "short unsigned int"))
53818334Speter	      return T_USHORT;
53918334Speter	    if (!strcmp (name, "long int"))
54018334Speter	      return T_LONG;
54118334Speter	    if (!strcmp (name, "long unsigned int"))
54218334Speter	      return T_ULONG;
54318334Speter	  }
54418334Speter
54550397Sobrien	if (size == INT_TYPE_SIZE)
54650397Sobrien	  return (TREE_UNSIGNED (type) ? T_UINT : T_INT);
54718334Speter	if (size == CHAR_TYPE_SIZE)
54818334Speter	  return (TREE_UNSIGNED (type) ? T_UCHAR : T_CHAR);
54918334Speter	if (size == SHORT_TYPE_SIZE)
55018334Speter	  return (TREE_UNSIGNED (type) ? T_USHORT : T_SHORT);
55118334Speter	if (size == LONG_TYPE_SIZE)
55218334Speter	  return (TREE_UNSIGNED (type) ? T_ULONG : T_LONG);
55318334Speter	if (size == LONG_LONG_TYPE_SIZE)	/* better than nothing */
55418334Speter	  return (TREE_UNSIGNED (type) ? T_ULONG : T_LONG);
55518334Speter	return 0;
55618334Speter      }
55718334Speter
55818334Speter    case REAL_TYPE:
55918334Speter      {
56050397Sobrien	int precision = TYPE_PRECISION (type);
56150397Sobrien	if (precision == FLOAT_TYPE_SIZE)
56218334Speter	  return T_FLOAT;
56350397Sobrien	if (precision == DOUBLE_TYPE_SIZE)
56418334Speter	  return T_DOUBLE;
56550397Sobrien#ifdef EXTENDED_SDB_BASIC_TYPES
56650397Sobrien	if (precision == LONG_DOUBLE_TYPE_SIZE)
56750397Sobrien	  return T_LNGDBL;
56850397Sobrien#else
56950397Sobrien	if (precision == LONG_DOUBLE_TYPE_SIZE)
57050397Sobrien	  return T_DOUBLE;	/* better than nothing */
57150397Sobrien#endif
57218334Speter	return 0;
57318334Speter      }
57418334Speter
57518334Speter    case ARRAY_TYPE:
57618334Speter      {
57718334Speter	int m;
57818334Speter	if (level >= 6)
57918334Speter	  return T_VOID;
58018334Speter	else
58118334Speter	  m = plain_type_1 (TREE_TYPE (type), level+1);
58218334Speter	if (sdb_n_dims < SDB_MAX_DIM)
58318334Speter	  sdb_dims[sdb_n_dims++]
58418334Speter	    = (TYPE_DOMAIN (type)
58590075Sobrien	       && TYPE_MIN_VALUE (TYPE_DOMAIN (type)) != 0
58690075Sobrien	       && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) != 0
58790075Sobrien	       && host_integerp (TYPE_MAX_VALUE (TYPE_DOMAIN (type)), 0)
58890075Sobrien	       && host_integerp (TYPE_MIN_VALUE (TYPE_DOMAIN (type)), 0)
58990075Sobrien	       ? (tree_low_cst (TYPE_MAX_VALUE (TYPE_DOMAIN (type)), 0)
59090075Sobrien		  - tree_low_cst (TYPE_MIN_VALUE (TYPE_DOMAIN (type)), 0) + 1)
59118334Speter	       : 0);
59290075Sobrien
59318334Speter	return PUSH_DERIVED_LEVEL (DT_ARY, m);
59418334Speter      }
59518334Speter
59618334Speter    case RECORD_TYPE:
59718334Speter    case UNION_TYPE:
59818334Speter    case QUAL_UNION_TYPE:
59918334Speter    case ENUMERAL_TYPE:
60018334Speter      {
60118334Speter	char *tag;
60218334Speter#ifdef SDB_ALLOW_FORWARD_REFERENCES
60318334Speter	sdbout_record_type_name (type);
60418334Speter#endif
60518334Speter#ifndef SDB_ALLOW_UNKNOWN_REFERENCES
60618334Speter	if ((TREE_ASM_WRITTEN (type) && KNOWN_TYPE_TAG (type) != 0)
60718334Speter#ifdef SDB_ALLOW_FORWARD_REFERENCES
60818334Speter	    || TYPE_MODE (type) != VOIDmode
60918334Speter#endif
61018334Speter	    )
61118334Speter#endif
61218334Speter	  {
61318334Speter	    /* Output the referenced structure tag name
61418334Speter	       only if the .def has already been finished.
61518334Speter	       At least on 386, the Unix assembler
61618334Speter	       cannot handle forward references to tags.  */
61750397Sobrien	    /* But the 88100, it requires them, sigh...  */
61850397Sobrien	    /* And the MIPS requires unknown refs as well...  */
61918334Speter	    tag = KNOWN_TYPE_TAG (type);
62018334Speter	    PUT_SDB_TAG (tag);
62118334Speter	    /* These 3 lines used to follow the close brace.
62218334Speter	       However, a size of 0 without a tag implies a tag of 0,
62318334Speter	       so if we don't know a tag, we can't mention the size.  */
62418334Speter	    sdb_type_size = int_size_in_bytes (type);
62518334Speter	    if (sdb_type_size < 0)
62618334Speter	      sdb_type_size = 0;
62718334Speter	  }
62818334Speter	return ((TREE_CODE (type) == RECORD_TYPE) ? T_STRUCT
62918334Speter		: (TREE_CODE (type) == UNION_TYPE) ? T_UNION
63018334Speter		: (TREE_CODE (type) == QUAL_UNION_TYPE) ? T_UNION
63118334Speter		: T_ENUM);
63218334Speter      }
63318334Speter    case POINTER_TYPE:
63418334Speter    case REFERENCE_TYPE:
63518334Speter      {
63618334Speter	int m;
63718334Speter	if (level >= 6)
63818334Speter	  return T_VOID;
63918334Speter	else
64018334Speter	  m = plain_type_1 (TREE_TYPE (type), level+1);
64118334Speter	return PUSH_DERIVED_LEVEL (DT_PTR, m);
64218334Speter      }
64318334Speter    case FUNCTION_TYPE:
64418334Speter    case METHOD_TYPE:
64518334Speter      {
64618334Speter	int m;
64718334Speter	if (level >= 6)
64818334Speter	  return T_VOID;
64918334Speter	else
65018334Speter	  m = plain_type_1 (TREE_TYPE (type), level+1);
65118334Speter	return PUSH_DERIVED_LEVEL (DT_FCN, m);
65218334Speter      }
65318334Speter    default:
65418334Speter      return 0;
65518334Speter    }
65618334Speter}
65718334Speter
65818334Speter/* Output the symbols defined in block number DO_BLOCK.
65918334Speter
66018334Speter   This function works by walking the tree structure of blocks,
66118334Speter   counting blocks until it finds the desired block.  */
66218334Speter
66318334Speterstatic int do_block = 0;
66418334Speter
66518334Speterstatic void
66618334Spetersdbout_block (block)
66790075Sobrien     tree block;
66818334Speter{
66918334Speter  while (block)
67018334Speter    {
67118334Speter      /* Ignore blocks never expanded or otherwise marked as real.  */
67218334Speter      if (TREE_USED (block))
67318334Speter	{
67418334Speter	  /* When we reach the specified block, output its symbols.  */
67590075Sobrien	  if (BLOCK_NUMBER (block) == do_block)
67690075Sobrien	    sdbout_syms (BLOCK_VARS (block));
67718334Speter
67818334Speter	  /* If we are past the specified block, stop the scan.  */
67990075Sobrien	  if (BLOCK_NUMBER (block) > do_block)
68018334Speter	    return;
68118334Speter
68218334Speter	  /* Scan the blocks within this block.  */
68318334Speter	  sdbout_block (BLOCK_SUBBLOCKS (block));
68418334Speter	}
68518334Speter
68618334Speter      block = BLOCK_CHAIN (block);
68718334Speter    }
68818334Speter}
68918334Speter
69018334Speter/* Call sdbout_symbol on each decl in the chain SYMS.  */
69118334Speter
69218334Speterstatic void
69318334Spetersdbout_syms (syms)
69418334Speter     tree syms;
69518334Speter{
69618334Speter  while (syms)
69718334Speter    {
69818334Speter      if (TREE_CODE (syms) != LABEL_DECL)
69918334Speter	sdbout_symbol (syms, 1);
70018334Speter      syms = TREE_CHAIN (syms);
70118334Speter    }
70218334Speter}
70318334Speter
70418334Speter/* Output SDB information for a symbol described by DECL.
70518334Speter   LOCAL is nonzero if the symbol is not file-scope.  */
70618334Speter
70718334Spetervoid
70818334Spetersdbout_symbol (decl, local)
70918334Speter     tree decl;
71018334Speter     int local;
71118334Speter{
71218334Speter  tree type = TREE_TYPE (decl);
71318334Speter  tree context = NULL_TREE;
71418334Speter  rtx value;
71518334Speter  int regno = -1;
71690075Sobrien  const char *name;
71718334Speter
71818334Speter  sdbout_one_type (type);
71918334Speter
72018334Speter#if 0 /* This loses when functions are marked to be ignored,
72118334Speter	 which happens in the C++ front end.  */
72218334Speter  if (DECL_IGNORED_P (decl))
72318334Speter    return;
72418334Speter#endif
72518334Speter
72618334Speter  switch (TREE_CODE (decl))
72718334Speter    {
72818334Speter    case CONST_DECL:
72918334Speter      /* Enum values are defined by defining the enum type.  */
73018334Speter      return;
73118334Speter
73218334Speter    case FUNCTION_DECL:
73318334Speter      /* Don't mention a nested function under its parent.  */
73418334Speter      context = decl_function_context (decl);
73518334Speter      if (context == current_function_decl)
73618334Speter	return;
73750397Sobrien      /* Check DECL_INITIAL to distinguish declarations from definitions.
73850397Sobrien	 Don't output debug info here for declarations; they will have
73950397Sobrien	 a DECL_INITIAL value of 0.  */
74050397Sobrien      if (! DECL_INITIAL (decl))
74118334Speter	return;
74218334Speter      if (GET_CODE (DECL_RTL (decl)) != MEM
74318334Speter	  || GET_CODE (XEXP (DECL_RTL (decl), 0)) != SYMBOL_REF)
74418334Speter	return;
74518334Speter      PUT_SDB_DEF (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
74618334Speter      PUT_SDB_VAL (XEXP (DECL_RTL (decl), 0));
74718334Speter      PUT_SDB_SCL (TREE_PUBLIC (decl) ? C_EXT : C_STAT);
74818334Speter      break;
74918334Speter
75018334Speter    case TYPE_DECL:
75118334Speter      /* Done with tagged types.  */
75218334Speter      if (DECL_NAME (decl) == 0)
75318334Speter	return;
75418334Speter      if (DECL_IGNORED_P (decl))
75518334Speter	return;
75618334Speter
75718334Speter      /* Output typedef name.  */
75818334Speter      if (template_name_p (DECL_NAME (decl)))
75918334Speter	PUT_SDB_DEF (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
76018334Speter      else
76118334Speter	PUT_SDB_DEF (IDENTIFIER_POINTER (DECL_NAME (decl)));
76218334Speter      PUT_SDB_SCL (C_TPDEF);
76318334Speter      break;
76418334Speter
76518334Speter    case PARM_DECL:
76618334Speter      /* Parm decls go in their own separate chains
76718334Speter	 and are output by sdbout_reg_parms and sdbout_parms.  */
76818334Speter      abort ();
76918334Speter
77018334Speter    case VAR_DECL:
77118334Speter      /* Don't mention a variable that is external.
77218334Speter	 Let the file that defines it describe it.  */
77318334Speter      if (DECL_EXTERNAL (decl))
77418334Speter	return;
77518334Speter
77618334Speter      /* Ignore __FUNCTION__, etc.  */
77718334Speter      if (DECL_IGNORED_P (decl))
77818334Speter	return;
77918334Speter
78018334Speter      /* If there was an error in the declaration, don't dump core
78118334Speter	 if there is no RTL associated with the variable doesn't
78218334Speter	 exist.  */
78390075Sobrien      if (!DECL_RTL_SET_P (decl))
78418334Speter	return;
78518334Speter
786117395Skan      SET_DECL_RTL (decl,
78790075Sobrien		    eliminate_regs (DECL_RTL (decl), 0, NULL_RTX));
78818334Speter#ifdef LEAF_REG_REMAP
78952284Sobrien      if (current_function_uses_only_leaf_regs)
79018334Speter	leaf_renumber_regs_insn (DECL_RTL (decl));
79118334Speter#endif
79218334Speter      value = DECL_RTL (decl);
79318334Speter
79418334Speter      /* Don't mention a variable at all
79518334Speter	 if it was completely optimized into nothingness.
79618334Speter
79718334Speter	 If DECL was from an inline function, then its rtl
79818334Speter	 is not identically the rtl that was used in this
79918334Speter	 particular compilation.  */
80018334Speter      if (GET_CODE (value) == REG)
80118334Speter	{
80290075Sobrien	  regno = REGNO (value);
80318334Speter	  if (regno >= FIRST_PSEUDO_REGISTER)
80418334Speter	    return;
80518334Speter	}
80618334Speter      else if (GET_CODE (value) == SUBREG)
80718334Speter	{
80818334Speter	  while (GET_CODE (value) == SUBREG)
80990075Sobrien	    value = SUBREG_REG (value);
81018334Speter	  if (GET_CODE (value) == REG)
81118334Speter	    {
81290075Sobrien	      if (REGNO (value) >= FIRST_PSEUDO_REGISTER)
81318334Speter		return;
81418334Speter	    }
81590075Sobrien	  regno = REGNO (alter_subreg (&value));
81690075Sobrien	  SET_DECL_RTL (decl, value);
81718334Speter	}
81818334Speter      /* Don't output anything if an auto variable
81918334Speter	 gets RTL that is static.
82018334Speter	 GAS version 2.2 can't handle such output.  */
82118334Speter      else if (GET_CODE (value) == MEM && CONSTANT_P (XEXP (value, 0))
82218334Speter	       && ! TREE_STATIC (decl))
82318334Speter	return;
82418334Speter
82518334Speter      /* Emit any structure, union, or enum type that has not been output.
82618334Speter	 This occurs for tag-less structs (et al) used to declare variables
82718334Speter	 within functions.  */
82818334Speter      if (TREE_CODE (type) == ENUMERAL_TYPE
82918334Speter	  || TREE_CODE (type) == RECORD_TYPE
83018334Speter	  || TREE_CODE (type) == UNION_TYPE
83118334Speter	  || TREE_CODE (type) == QUAL_UNION_TYPE)
83218334Speter	{
83390075Sobrien	  if (COMPLETE_TYPE_P (type)		/* not a forward reference */
83418334Speter	      && KNOWN_TYPE_TAG (type) == 0)	/* not yet declared */
83518334Speter	    sdbout_one_type (type);
83618334Speter	}
83718334Speter
83818334Speter      /* Defer SDB information for top-level initialized variables! */
83918334Speter      if (! local
84018334Speter	  && GET_CODE (value) == MEM
84118334Speter	  && DECL_INITIAL (decl))
84218334Speter	return;
84318334Speter
84418334Speter      /* C++ in 2.3 makes nameless symbols.  That will be fixed later.
84518334Speter	 For now, avoid crashing.  */
84618334Speter      if (DECL_NAME (decl) == NULL_TREE)
84718334Speter	return;
84818334Speter
84918334Speter      /* Record the name for, starting a symtab entry.  */
85090075Sobrien      if (local)
85190075Sobrien	name = IDENTIFIER_POINTER (DECL_NAME (decl));
85290075Sobrien      else
85390075Sobrien	name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
85418334Speter
85518334Speter      if (GET_CODE (value) == MEM
85618334Speter	  && GET_CODE (XEXP (value, 0)) == SYMBOL_REF)
85718334Speter	{
85818334Speter	  PUT_SDB_DEF (name);
85918334Speter	  if (TREE_PUBLIC (decl))
86018334Speter	    {
86118334Speter	      PUT_SDB_VAL (XEXP (value, 0));
862117395Skan	      PUT_SDB_SCL (C_EXT);
86318334Speter	    }
86418334Speter	  else
86518334Speter	    {
86618334Speter	      PUT_SDB_VAL (XEXP (value, 0));
867117395Skan	      PUT_SDB_SCL (C_STAT);
86818334Speter	    }
86918334Speter	}
87018334Speter      else if (regno >= 0)
87118334Speter	{
87218334Speter	  PUT_SDB_DEF (name);
87318334Speter	  PUT_SDB_INT_VAL (DBX_REGISTER_NUMBER (regno));
87418334Speter	  PUT_SDB_SCL (C_REG);
87518334Speter	}
87618334Speter      else if (GET_CODE (value) == MEM
87718334Speter	       && (GET_CODE (XEXP (value, 0)) == MEM
87818334Speter		   || (GET_CODE (XEXP (value, 0)) == REG
87918334Speter		       && REGNO (XEXP (value, 0)) != HARD_FRAME_POINTER_REGNUM
88018334Speter		       && REGNO (XEXP (value, 0)) != STACK_POINTER_REGNUM)))
88118334Speter	/* If the value is indirect by memory or by a register
88218334Speter	   that isn't the frame pointer
88318334Speter	   then it means the object is variable-sized and address through
88418334Speter	   that register or stack slot.  COFF has no way to represent this
88518334Speter	   so all we can do is output the variable as a pointer.  */
88618334Speter	{
88718334Speter	  PUT_SDB_DEF (name);
88818334Speter	  if (GET_CODE (XEXP (value, 0)) == REG)
88918334Speter	    {
89018334Speter	      PUT_SDB_INT_VAL (DBX_REGISTER_NUMBER (REGNO (XEXP (value, 0))));
89118334Speter	      PUT_SDB_SCL (C_REG);
89218334Speter	    }
89318334Speter	  else
89418334Speter	    {
89518334Speter	      /* DECL_RTL looks like (MEM (MEM (PLUS (REG...)
89618334Speter		 (CONST_INT...)))).
89718334Speter		 We want the value of that CONST_INT.  */
89818334Speter	      /* Encore compiler hates a newline in a macro arg, it seems.  */
89918334Speter	      PUT_SDB_INT_VAL (DEBUGGER_AUTO_OFFSET
90018334Speter			       (XEXP (XEXP (value, 0), 0)));
90118334Speter	      PUT_SDB_SCL (C_AUTO);
90218334Speter	    }
90318334Speter
90452284Sobrien	  /* Effectively do build_pointer_type, but don't cache this type,
90552284Sobrien	     since it might be temporary whereas the type it points to
90652284Sobrien	     might have been saved for inlining.  */
90752284Sobrien	  /* Don't use REFERENCE_TYPE because dbx can't handle that.  */
90852284Sobrien	  type = make_node (POINTER_TYPE);
90952284Sobrien	  TREE_TYPE (type) = TREE_TYPE (decl);
91018334Speter	}
91118334Speter      else if (GET_CODE (value) == MEM
91218334Speter	       && ((GET_CODE (XEXP (value, 0)) == PLUS
91318334Speter		    && GET_CODE (XEXP (XEXP (value, 0), 0)) == REG
91418334Speter		    && GET_CODE (XEXP (XEXP (value, 0), 1)) == CONST_INT)
91518334Speter		   /* This is for variables which are at offset zero from
91618334Speter		      the frame pointer.  This happens on the Alpha.
91718334Speter		      Non-frame pointer registers are excluded above.  */
91818334Speter		   || (GET_CODE (XEXP (value, 0)) == REG)))
91918334Speter	{
92018334Speter	  /* DECL_RTL looks like (MEM (PLUS (REG...) (CONST_INT...)))
92118334Speter	     or (MEM (REG...)).  We want the value of that CONST_INT
92218334Speter	     or zero.  */
92318334Speter	  PUT_SDB_DEF (name);
92418334Speter	  PUT_SDB_INT_VAL (DEBUGGER_AUTO_OFFSET (XEXP (value, 0)));
92518334Speter	  PUT_SDB_SCL (C_AUTO);
92618334Speter	}
92718334Speter      else
92818334Speter	{
92918334Speter	  /* It is something we don't know how to represent for SDB.  */
93018334Speter	  return;
93118334Speter	}
93218334Speter      break;
93350397Sobrien
93450397Sobrien    default:
93550397Sobrien      break;
93618334Speter    }
93718334Speter  PUT_SDB_TYPE (plain_type (type));
93818334Speter  PUT_SDB_ENDEF;
93918334Speter}
94018334Speter
94118334Speter/* Output SDB information for a top-level initialized variable
94218334Speter   that has been delayed.  */
94318334Speter
94490075Sobrienstatic void
94518334Spetersdbout_toplevel_data (decl)
94618334Speter     tree decl;
94718334Speter{
94818334Speter  tree type = TREE_TYPE (decl);
94918334Speter
95018334Speter  if (DECL_IGNORED_P (decl))
95118334Speter    return;
95218334Speter
95318334Speter  if (! (TREE_CODE (decl) == VAR_DECL
95418334Speter	 && GET_CODE (DECL_RTL (decl)) == MEM
95518334Speter	 && DECL_INITIAL (decl)))
95618334Speter    abort ();
95718334Speter
95818334Speter  PUT_SDB_DEF (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
95918334Speter  PUT_SDB_VAL (XEXP (DECL_RTL (decl), 0));
96018334Speter  if (TREE_PUBLIC (decl))
96118334Speter    {
96218334Speter      PUT_SDB_SCL (C_EXT);
96318334Speter    }
96418334Speter  else
96518334Speter    {
96618334Speter      PUT_SDB_SCL (C_STAT);
96718334Speter    }
96818334Speter  PUT_SDB_TYPE (plain_type (type));
96918334Speter  PUT_SDB_ENDEF;
97018334Speter}
97118334Speter
97218334Speter#ifdef SDB_ALLOW_FORWARD_REFERENCES
97318334Speter
97450397Sobrien/* Machinery to record and output anonymous types.  */
97518334Speter
97618334Speterstatic void
97718334Spetersdbout_queue_anonymous_type (type)
97818334Speter     tree type;
97918334Speter{
98090075Sobrien  anonymous_types = tree_cons (NULL_TREE, type, anonymous_types);
98118334Speter}
98218334Speter
98318334Speterstatic void
98418334Spetersdbout_dequeue_anonymous_types ()
98518334Speter{
98690075Sobrien  tree types, link;
98718334Speter
98818334Speter  while (anonymous_types)
98918334Speter    {
99018334Speter      types = nreverse (anonymous_types);
99118334Speter      anonymous_types = NULL_TREE;
99218334Speter
99318334Speter      for (link = types; link; link = TREE_CHAIN (link))
99418334Speter	{
99590075Sobrien	  tree type = TREE_VALUE (link);
99618334Speter
99718334Speter	  if (type && ! TREE_ASM_WRITTEN (type))
99818334Speter	    sdbout_one_type (type);
99918334Speter	}
100018334Speter    }
100118334Speter}
100218334Speter
100318334Speter#endif
100418334Speter
100518334Speter/* Given a chain of ..._TYPE nodes, all of which have names,
100618334Speter   output definitions of those names, as typedefs.  */
100718334Speter
100818334Spetervoid
100918334Spetersdbout_types (types)
101090075Sobrien     tree types;
101118334Speter{
101290075Sobrien  tree link;
101318334Speter
101418334Speter  for (link = types; link; link = TREE_CHAIN (link))
101518334Speter    sdbout_one_type (link);
101618334Speter
101718334Speter#ifdef SDB_ALLOW_FORWARD_REFERENCES
101818334Speter  sdbout_dequeue_anonymous_types ();
101918334Speter#endif
102018334Speter}
102118334Speter
102218334Speterstatic void
102318334Spetersdbout_type (type)
102418334Speter     tree type;
102518334Speter{
102618334Speter  if (type == error_mark_node)
102718334Speter    type = integer_type_node;
102818334Speter  PUT_SDB_TYPE (plain_type (type));
102918334Speter}
103018334Speter
103118334Speter/* Output types of the fields of type TYPE, if they are structs.
103218334Speter
103318334Speter   Formerly did not chase through pointer types, since that could be circular.
103418334Speter   They must come before TYPE, since forward refs are not allowed.
103518334Speter   Now james@bigtex.cactus.org says to try them.  */
103618334Speter
103718334Speterstatic void
103818334Spetersdbout_field_types (type)
103918334Speter     tree type;
104018334Speter{
104118334Speter  tree tail;
104250397Sobrien
104318334Speter  for (tail = TYPE_FIELDS (type); tail; tail = TREE_CHAIN (tail))
104490075Sobrien    /* This condition should match the one for emitting the actual
104590075Sobrien       members below.  */
104652284Sobrien    if (TREE_CODE (tail) == FIELD_DECL
104790075Sobrien	&& DECL_NAME (tail)
104890075Sobrien	&& DECL_SIZE (tail)
104990075Sobrien	&& host_integerp (DECL_SIZE (tail), 1)
105090075Sobrien	&& host_integerp (bit_position (tail), 0))
105152284Sobrien      {
105252284Sobrien	if (POINTER_TYPE_P (TREE_TYPE (tail)))
105352284Sobrien	  sdbout_one_type (TREE_TYPE (TREE_TYPE (tail)));
105452284Sobrien	else
105552284Sobrien	  sdbout_one_type (TREE_TYPE (tail));
105652284Sobrien      }
105718334Speter}
105818334Speter
105918334Speter/* Use this to put out the top level defined record and union types
106018334Speter   for later reference.  If this is a struct with a name, then put that
106118334Speter   name out.  Other unnamed structs will have .xxfake labels generated so
106218334Speter   that they may be referred to later.
106318334Speter   The label will be stored in the KNOWN_TYPE_TAG slot of a type.
106418334Speter   It may NOT be called recursively.  */
106518334Speter
106618334Speterstatic void
106718334Spetersdbout_one_type (type)
106818334Speter     tree type;
106918334Speter{
107018334Speter  if (current_function_decl != NULL_TREE
107118334Speter      && DECL_SECTION_NAME (current_function_decl) != NULL_TREE)
107218334Speter    ; /* Don't change section amid function.  */
107318334Speter  else
107418334Speter    text_section ();
107518334Speter
107618334Speter  switch (TREE_CODE (type))
107718334Speter    {
107818334Speter    case RECORD_TYPE:
107918334Speter    case UNION_TYPE:
108018334Speter    case QUAL_UNION_TYPE:
108118334Speter    case ENUMERAL_TYPE:
108218334Speter      type = TYPE_MAIN_VARIANT (type);
108318334Speter      /* Don't output a type twice.  */
108418334Speter      if (TREE_ASM_WRITTEN (type))
108518334Speter	/* James said test TREE_ASM_BEING_WRITTEN here.  */
108618334Speter	return;
108718334Speter
108818334Speter      /* Output nothing if type is not yet defined.  */
108990075Sobrien      if (!COMPLETE_TYPE_P (type))
109018334Speter	return;
109118334Speter
109218334Speter      TREE_ASM_WRITTEN (type) = 1;
109318334Speter#if 1
109418334Speter      /* This is reputed to cause trouble with the following case,
109518334Speter	 but perhaps checking TYPE_SIZE above will fix it.  */
109618334Speter
109718334Speter      /* Here is a test case:
109818334Speter
109918334Speter	struct foo {
110018334Speter	  struct badstr *bbb;
110118334Speter	} forwardref;
110218334Speter
110318334Speter	typedef struct intermediate {
110418334Speter	  int aaaa;
110518334Speter	} intermediate_ref;
110618334Speter
110718334Speter	typedef struct badstr {
110818334Speter	  int ccccc;
110918334Speter	} badtype;   */
111018334Speter
111118334Speter#if 0
111218334Speter      TREE_ASM_BEING_WRITTEN (type) = 1;
111318334Speter#endif
111418334Speter      /* This change, which ought to make better output,
111518334Speter	 used to make the COFF assembler unhappy.
111618334Speter	 Changes involving KNOWN_TYPE_TAG may fix the problem.  */
111718334Speter      /* Before really doing anything, output types we want to refer to.  */
111818334Speter      /* Note that in version 1 the following two lines
111918334Speter	 are not used if forward references are in use.  */
112018334Speter      if (TREE_CODE (type) != ENUMERAL_TYPE)
112118334Speter	sdbout_field_types (type);
112218334Speter#if 0
112318334Speter      TREE_ASM_WRITTEN (type) = 1;
112418334Speter#endif
112518334Speter#endif
112618334Speter
112718334Speter      /* Output a structure type.  */
112818334Speter      {
112918334Speter	int size = int_size_in_bytes (type);
113090075Sobrien	int member_scl = 0;
113118334Speter	tree tem;
113218334Speter	int i, n_baseclasses = 0;
113318334Speter
113418334Speter	/* Record the type tag, but not in its permanent place just yet.  */
113518334Speter	sdbout_record_type_name (type);
113618334Speter
113718334Speter	PUT_SDB_DEF (KNOWN_TYPE_TAG (type));
113818334Speter
113918334Speter	switch (TREE_CODE (type))
114018334Speter	  {
114118334Speter	  case UNION_TYPE:
114218334Speter	  case QUAL_UNION_TYPE:
114318334Speter	    PUT_SDB_SCL (C_UNTAG);
114418334Speter	    PUT_SDB_TYPE (T_UNION);
114518334Speter	    member_scl = C_MOU;
114618334Speter	    break;
114718334Speter
114818334Speter	  case RECORD_TYPE:
114918334Speter	    PUT_SDB_SCL (C_STRTAG);
115018334Speter	    PUT_SDB_TYPE (T_STRUCT);
115118334Speter	    member_scl = C_MOS;
115218334Speter	    break;
115318334Speter
115418334Speter	  case ENUMERAL_TYPE:
115518334Speter	    PUT_SDB_SCL (C_ENTAG);
115618334Speter	    PUT_SDB_TYPE (T_ENUM);
115718334Speter	    member_scl = C_MOE;
115818334Speter	    break;
115950397Sobrien
116050397Sobrien	  default:
116150397Sobrien	    break;
116218334Speter	  }
116318334Speter
116418334Speter	PUT_SDB_SIZE (size);
116518334Speter	PUT_SDB_ENDEF;
116618334Speter
116718334Speter	/* Print out the base class information with fields
116818334Speter	   named after the types they hold.  */
116990075Sobrien	/* This is only relevant to aggregate types.  TYPE_BINFO is used
117052284Sobrien	   for other purposes in an ENUMERAL_TYPE, so we must exclude that
117152284Sobrien	   case.  */
117252284Sobrien	if (TREE_CODE (type) != ENUMERAL_TYPE)
117318334Speter	  {
117452284Sobrien	    if (TYPE_BINFO (type)
117552284Sobrien		&& TYPE_BINFO_BASETYPES (type))
117652284Sobrien	      n_baseclasses = TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (type));
117752284Sobrien	    for (i = 0; i < n_baseclasses; i++)
117818334Speter	      {
117952284Sobrien		tree child = TREE_VEC_ELT (BINFO_BASETYPES (TYPE_BINFO (type)),
118052284Sobrien					   i);
118152284Sobrien		tree child_type = BINFO_TYPE (child);
118252284Sobrien		tree child_type_name;
118352284Sobrien		if (TYPE_NAME (child_type) == 0)
118452284Sobrien		  continue;
118552284Sobrien		if (TREE_CODE (TYPE_NAME (child_type)) == IDENTIFIER_NODE)
118652284Sobrien		  child_type_name = TYPE_NAME (child_type);
118752284Sobrien		else if (TREE_CODE (TYPE_NAME (child_type)) == TYPE_DECL)
118852284Sobrien		  {
118952284Sobrien		    child_type_name = DECL_NAME (TYPE_NAME (child_type));
119052284Sobrien		    if (child_type_name && template_name_p (child_type_name))
119152284Sobrien		      child_type_name
119252284Sobrien			= DECL_ASSEMBLER_NAME (TYPE_NAME (child_type));
119352284Sobrien		  }
119452284Sobrien		else
119552284Sobrien		  continue;
119652284Sobrien
119752284Sobrien		CONTIN;
119852284Sobrien		PUT_SDB_DEF (IDENTIFIER_POINTER (child_type_name));
119990075Sobrien		PUT_SDB_INT_VAL (tree_low_cst (BINFO_OFFSET (child), 0));
120052284Sobrien		PUT_SDB_SCL (member_scl);
120152284Sobrien		sdbout_type (BINFO_TYPE (child));
120252284Sobrien		PUT_SDB_ENDEF;
120318334Speter	      }
120418334Speter	  }
120518334Speter
120618334Speter	/* output the individual fields */
120718334Speter
120818334Speter	if (TREE_CODE (type) == ENUMERAL_TYPE)
120990075Sobrien	  {
121090075Sobrien	    for (tem = TYPE_FIELDS (type); tem; tem = TREE_CHAIN (tem))
121190075Sobrien	      if (host_integerp (TREE_VALUE (tem), 0))
121290075Sobrien		{
121390075Sobrien		  PUT_SDB_DEF (IDENTIFIER_POINTER (TREE_PURPOSE (tem)));
121490075Sobrien		  PUT_SDB_INT_VAL (tree_low_cst (TREE_VALUE (tem), 0));
121590075Sobrien		  PUT_SDB_SCL (C_MOE);
121690075Sobrien		  PUT_SDB_TYPE (T_MOE);
121790075Sobrien		  PUT_SDB_ENDEF;
121890075Sobrien		}
121990075Sobrien	  }
122018334Speter	else			/* record or union type */
122118334Speter	  for (tem = TYPE_FIELDS (type); tem; tem = TREE_CHAIN (tem))
122218334Speter	    /* Output the name, type, position (in bits), size (in bits)
122318334Speter	       of each field.  */
122418334Speter
122518334Speter	    /* Omit here the nameless fields that are used to skip bits.
122618334Speter	       Also omit fields with variable size or position.
122718334Speter	       Also omit non FIELD_DECL nodes that GNU C++ may put here.  */
122818334Speter	    if (TREE_CODE (tem) == FIELD_DECL
122990075Sobrien		&& DECL_NAME (tem)
123090075Sobrien		&& DECL_SIZE (tem)
123190075Sobrien		&& host_integerp (DECL_SIZE (tem), 1)
123290075Sobrien		&& host_integerp (bit_position (tem), 0))
123318334Speter	      {
123490075Sobrien		const char *name;
123518334Speter
123618334Speter		CONTIN;
123790075Sobrien		name = IDENTIFIER_POINTER (DECL_NAME (tem));
123818334Speter		PUT_SDB_DEF (name);
123918334Speter		if (DECL_BIT_FIELD_TYPE (tem))
124018334Speter		  {
124190075Sobrien		    PUT_SDB_INT_VAL (int_bit_position (tem));
124218334Speter		    PUT_SDB_SCL (C_FIELD);
124318334Speter		    sdbout_type (DECL_BIT_FIELD_TYPE (tem));
124490075Sobrien		    PUT_SDB_SIZE (tree_low_cst (DECL_SIZE (tem), 1));
124518334Speter		  }
124618334Speter		else
124718334Speter		  {
124890075Sobrien		    PUT_SDB_INT_VAL (int_bit_position (tem) / BITS_PER_UNIT);
124918334Speter		    PUT_SDB_SCL (member_scl);
125018334Speter		    sdbout_type (TREE_TYPE (tem));
125118334Speter		  }
125218334Speter		PUT_SDB_ENDEF;
125318334Speter	      }
125418334Speter	/* output end of a structure,union, or enumeral definition */
125518334Speter
125618334Speter	PUT_SDB_PLAIN_DEF ("eos");
125718334Speter	PUT_SDB_INT_VAL (size);
125818334Speter	PUT_SDB_SCL (C_EOS);
125918334Speter	PUT_SDB_TAG (KNOWN_TYPE_TAG (type));
126018334Speter	PUT_SDB_SIZE (size);
126118334Speter	PUT_SDB_ENDEF;
126218334Speter	break;
126350397Sobrien
126450397Sobrien      default:
126550397Sobrien	break;
126618334Speter      }
126718334Speter    }
126818334Speter}
126918334Speter
127018334Speter/* The following two functions output definitions of function parameters.
127118334Speter   Each parameter gets a definition locating it in the parameter list.
127218334Speter   Each parameter that is a register variable gets a second definition
127318334Speter   locating it in the register.
127418334Speter
127518334Speter   Printing or argument lists in gdb uses the definitions that
127618334Speter   locate in the parameter list.  But reference to the variable in
127718334Speter   expressions uses preferentially the definition as a register.  */
127818334Speter
127918334Speter/* Output definitions, referring to storage in the parmlist,
128018334Speter   of all the parms in PARMS, which is a chain of PARM_DECL nodes.  */
128118334Speter
128218334Speterstatic void
128318334Spetersdbout_parms (parms)
128418334Speter     tree parms;
128518334Speter{
128618334Speter  for (; parms; parms = TREE_CHAIN (parms))
128718334Speter    if (DECL_NAME (parms))
128818334Speter      {
128918334Speter	int current_sym_value = 0;
129090075Sobrien	const char *name = IDENTIFIER_POINTER (DECL_NAME (parms));
129118334Speter
129218334Speter	if (name == 0 || *name == 0)
129318334Speter	  name = gen_fake_label ();
129418334Speter
129518334Speter	/* Perform any necessary register eliminations on the parameter's rtl,
129618334Speter	   so that the debugging output will be accurate.  */
129750397Sobrien	DECL_INCOMING_RTL (parms)
129850397Sobrien	  = eliminate_regs (DECL_INCOMING_RTL (parms), 0, NULL_RTX);
129990075Sobrien	SET_DECL_RTL (parms,
130090075Sobrien		      eliminate_regs (DECL_RTL (parms), 0, NULL_RTX));
130118334Speter
130218334Speter	if (PARM_PASSED_IN_MEMORY (parms))
130318334Speter	  {
130418334Speter	    rtx addr = XEXP (DECL_INCOMING_RTL (parms), 0);
130518334Speter	    tree type;
130618334Speter
130718334Speter	    /* ??? Here we assume that the parm address is indexed
130818334Speter	       off the frame pointer or arg pointer.
130918334Speter	       If that is not true, we produce meaningless results,
131018334Speter	       but do not crash.  */
131118334Speter	    if (GET_CODE (addr) == PLUS
131218334Speter		&& GET_CODE (XEXP (addr, 1)) == CONST_INT)
131318334Speter	      current_sym_value = INTVAL (XEXP (addr, 1));
131418334Speter	    else
131518334Speter	      current_sym_value = 0;
131618334Speter
131718334Speter	    if (GET_CODE (DECL_RTL (parms)) == REG
131818334Speter		&& REGNO (DECL_RTL (parms)) < FIRST_PSEUDO_REGISTER)
131918334Speter	      type = DECL_ARG_TYPE (parms);
132018334Speter	    else
132118334Speter	      {
132218334Speter		int original_sym_value = current_sym_value;
132318334Speter
132418334Speter		/* This is the case where the parm is passed as an int or
132518334Speter		   double and it is converted to a char, short or float
132618334Speter		   and stored back in the parmlist.  In this case, describe
132718334Speter		   the parm with the variable's declared type, and adjust
132818334Speter		   the address if the least significant bytes (which we are
132918334Speter		   using) are not the first ones.  */
133018334Speter		if (BYTES_BIG_ENDIAN
133118334Speter		    && TREE_TYPE (parms) != DECL_ARG_TYPE (parms))
133218334Speter		  current_sym_value +=
133318334Speter		    (GET_MODE_SIZE (TYPE_MODE (DECL_ARG_TYPE (parms)))
133418334Speter		     - GET_MODE_SIZE (GET_MODE (DECL_RTL (parms))));
133518334Speter
133618334Speter		if (GET_CODE (DECL_RTL (parms)) == MEM
133718334Speter		    && GET_CODE (XEXP (DECL_RTL (parms), 0)) == PLUS
133818334Speter		    && (GET_CODE (XEXP (XEXP (DECL_RTL (parms), 0), 1))
133918334Speter			== CONST_INT)
134018334Speter		    && (INTVAL (XEXP (XEXP (DECL_RTL (parms), 0), 1))
134118334Speter			== current_sym_value))
134218334Speter		  type = TREE_TYPE (parms);
134318334Speter		else
134418334Speter		  {
134518334Speter		    current_sym_value = original_sym_value;
134618334Speter		    type = DECL_ARG_TYPE (parms);
134718334Speter		  }
134818334Speter	      }
134918334Speter
135018334Speter	    PUT_SDB_DEF (name);
135118334Speter	    PUT_SDB_INT_VAL (DEBUGGER_ARG_OFFSET (current_sym_value, addr));
135218334Speter	    PUT_SDB_SCL (C_ARG);
135318334Speter	    PUT_SDB_TYPE (plain_type (type));
135418334Speter	    PUT_SDB_ENDEF;
135518334Speter	  }
135618334Speter	else if (GET_CODE (DECL_RTL (parms)) == REG)
135718334Speter	  {
135818334Speter	    rtx best_rtl;
135918334Speter	    /* Parm passed in registers and lives in registers or nowhere.  */
136018334Speter
136118334Speter	    /* If parm lives in a register, use that register;
136218334Speter	       pretend the parm was passed there.  It would be more consistent
136318334Speter	       to describe the register where the parm was passed,
136418334Speter	       but in practice that register usually holds something else.  */
136590075Sobrien	    if (REGNO (DECL_RTL (parms)) < FIRST_PSEUDO_REGISTER)
136618334Speter	      best_rtl = DECL_RTL (parms);
136718334Speter	    /* If the parm lives nowhere,
136818334Speter	       use the register where it was passed.  */
136918334Speter	    else
137018334Speter	      best_rtl = DECL_INCOMING_RTL (parms);
137118334Speter
137218334Speter	    PUT_SDB_DEF (name);
137318334Speter	    PUT_SDB_INT_VAL (DBX_REGISTER_NUMBER (REGNO (best_rtl)));
137418334Speter	    PUT_SDB_SCL (C_REGPARM);
137550397Sobrien	    PUT_SDB_TYPE (plain_type (TREE_TYPE (parms)));
137618334Speter	    PUT_SDB_ENDEF;
137718334Speter	  }
137818334Speter	else if (GET_CODE (DECL_RTL (parms)) == MEM
137918334Speter		 && XEXP (DECL_RTL (parms), 0) != const0_rtx)
138018334Speter	  {
138118334Speter	    /* Parm was passed in registers but lives on the stack.  */
138218334Speter
138318334Speter	    /* DECL_RTL looks like (MEM (PLUS (REG...) (CONST_INT...))),
138418334Speter	       in which case we want the value of that CONST_INT,
138518334Speter	       or (MEM (REG ...)) or (MEM (MEM ...)),
138618334Speter	       in which case we use a value of zero.  */
138718334Speter	    if (GET_CODE (XEXP (DECL_RTL (parms), 0)) == REG
138818334Speter		|| GET_CODE (XEXP (DECL_RTL (parms), 0)) == MEM)
138918334Speter	      current_sym_value = 0;
139018334Speter	    else
139118334Speter	      current_sym_value = INTVAL (XEXP (XEXP (DECL_RTL (parms), 0), 1));
139218334Speter
139318334Speter	    /* Again, this assumes the offset is based on the arg pointer.  */
139418334Speter	    PUT_SDB_DEF (name);
139518334Speter	    PUT_SDB_INT_VAL (DEBUGGER_ARG_OFFSET (current_sym_value,
139618334Speter						  XEXP (DECL_RTL (parms), 0)));
139718334Speter	    PUT_SDB_SCL (C_ARG);
139850397Sobrien	    PUT_SDB_TYPE (plain_type (TREE_TYPE (parms)));
139918334Speter	    PUT_SDB_ENDEF;
140018334Speter	  }
140118334Speter      }
140218334Speter}
140318334Speter
140418334Speter/* Output definitions for the places where parms live during the function,
140518334Speter   when different from where they were passed, when the parms were passed
140618334Speter   in memory.
140718334Speter
140818334Speter   It is not useful to do this for parms passed in registers
140918334Speter   that live during the function in different registers, because it is
141018334Speter   impossible to look in the passed register for the passed value,
141118334Speter   so we use the within-the-function register to begin with.
141218334Speter
141318334Speter   PARMS is a chain of PARM_DECL nodes.  */
141418334Speter
141518334Speterstatic void
141618334Spetersdbout_reg_parms (parms)
141718334Speter     tree parms;
141818334Speter{
141918334Speter  for (; parms; parms = TREE_CHAIN (parms))
142018334Speter    if (DECL_NAME (parms))
142118334Speter      {
142290075Sobrien	const char *name = IDENTIFIER_POINTER (DECL_NAME (parms));
142318334Speter
142418334Speter	/* Report parms that live in registers during the function
142518334Speter	   but were passed in memory.  */
142618334Speter	if (GET_CODE (DECL_RTL (parms)) == REG
142718334Speter	    && REGNO (DECL_RTL (parms)) < FIRST_PSEUDO_REGISTER
142818334Speter	    && PARM_PASSED_IN_MEMORY (parms))
142918334Speter	  {
143018334Speter	    if (name == 0 || *name == 0)
143118334Speter	      name = gen_fake_label ();
143218334Speter	    PUT_SDB_DEF (name);
143318334Speter	    PUT_SDB_INT_VAL (DBX_REGISTER_NUMBER (REGNO (DECL_RTL (parms))));
143418334Speter	    PUT_SDB_SCL (C_REG);
143550397Sobrien	    PUT_SDB_TYPE (plain_type (TREE_TYPE (parms)));
143618334Speter	    PUT_SDB_ENDEF;
143718334Speter	  }
143818334Speter	/* Report parms that live in memory but not where they were passed.  */
143918334Speter	else if (GET_CODE (DECL_RTL (parms)) == MEM
144018334Speter		 && GET_CODE (XEXP (DECL_RTL (parms), 0)) == PLUS
144118334Speter		 && GET_CODE (XEXP (XEXP (DECL_RTL (parms), 0), 1)) == CONST_INT
144218334Speter		 && PARM_PASSED_IN_MEMORY (parms)
144318334Speter		 && ! rtx_equal_p (DECL_RTL (parms), DECL_INCOMING_RTL (parms)))
144418334Speter	  {
144518334Speter#if 0 /* ??? It is not clear yet what should replace this.  */
144618334Speter	    int offset = DECL_OFFSET (parms) / BITS_PER_UNIT;
144718334Speter	    /* A parm declared char is really passed as an int,
144818334Speter	       so it occupies the least significant bytes.
144918334Speter	       On a big-endian machine those are not the low-numbered ones.  */
145018334Speter	    if (BYTES_BIG_ENDIAN
145118334Speter		&& offset != -1
145218334Speter		&& TREE_TYPE (parms) != DECL_ARG_TYPE (parms))
145318334Speter	      offset += (GET_MODE_SIZE (TYPE_MODE (DECL_ARG_TYPE (parms)))
145418334Speter			 - GET_MODE_SIZE (GET_MODE (DECL_RTL (parms))));
145518334Speter	    if (INTVAL (XEXP (XEXP (DECL_RTL (parms), 0), 1)) != offset) {...}
145618334Speter#endif
145718334Speter	      {
145818334Speter		if (name == 0 || *name == 0)
145918334Speter		  name = gen_fake_label ();
146018334Speter		PUT_SDB_DEF (name);
146118334Speter		PUT_SDB_INT_VAL (DEBUGGER_AUTO_OFFSET
146218334Speter				 (XEXP (DECL_RTL (parms), 0)));
146318334Speter		PUT_SDB_SCL (C_AUTO);
146418334Speter		PUT_SDB_TYPE (plain_type (TREE_TYPE (parms)));
146518334Speter		PUT_SDB_ENDEF;
146618334Speter	      }
146718334Speter	  }
146818334Speter      }
146918334Speter}
147018334Speter
147190075Sobrien/* Output debug information for a global DECL.  Called from toplev.c
147290075Sobrien   after compilation proper has finished.  */
147390075Sobrien
147490075Sobrienstatic void
147590075Sobriensdbout_global_decl (decl)
147690075Sobrien     tree decl;
147790075Sobrien{
147890075Sobrien  if (TREE_CODE (decl) == VAR_DECL
147990075Sobrien      && !DECL_EXTERNAL (decl)
148090075Sobrien      && DECL_RTL_SET_P (decl))
148190075Sobrien    {
148290075Sobrien      /* The COFF linker can move initialized global vars to the end.
148390075Sobrien	 And that can screw up the symbol ordering.  Defer those for
148490075Sobrien	 sdbout_finish ().  */
148590075Sobrien      if (!DECL_INITIAL (decl) || !TREE_PUBLIC (decl))
148690075Sobrien	sdbout_symbol (decl, 0);
148790075Sobrien
148890075Sobrien      /* Output COFF information for non-global file-scope initialized
148990075Sobrien	 variables.  */
149090075Sobrien      if (DECL_INITIAL (decl) && GET_CODE (DECL_RTL (decl)) == MEM)
149190075Sobrien	sdbout_toplevel_data (decl);
149290075Sobrien    }
149390075Sobrien}
149490075Sobrien
149590075Sobrien/* Output initialized global vars at the end, in the order of
149690075Sobrien   definition.  See comment in sdbout_global_decl.  */
149790075Sobrien
149890075Sobrienstatic void
149990075Sobriensdbout_finish (main_filename)
150090075Sobrien     const char *main_filename ATTRIBUTE_UNUSED;
150190075Sobrien{
1502117395Skan  tree decl = (*lang_hooks.decls.getdecls) ();
150390075Sobrien  unsigned int len = list_length (decl);
150490075Sobrien  tree *vec = (tree *) xmalloc (sizeof (tree) * len);
150590075Sobrien  unsigned int i;
150690075Sobrien
150790075Sobrien  /* Process the decls in reverse order--earliest first.  Put them
150890075Sobrien     into VEC from back to front, then take out from front.  */
150990075Sobrien
151090075Sobrien  for (i = 0; i < len; i++, decl = TREE_CHAIN (decl))
151190075Sobrien    vec[len - i - 1] = decl;
151290075Sobrien
151390075Sobrien  for (i = 0; i < len; i++)
151490075Sobrien    {
151590075Sobrien      decl = vec[i];
151690075Sobrien      if (TREE_CODE (decl) == VAR_DECL
151790075Sobrien	  && ! DECL_EXTERNAL (decl)
151890075Sobrien	  && DECL_INITIAL (decl)
151990075Sobrien	  && TREE_PUBLIC (decl)
152090075Sobrien	  && DECL_RTL_SET_P (decl))
152190075Sobrien	sdbout_symbol (decl, 0);
152290075Sobrien    }
152390075Sobrien
152490075Sobrien  free (vec);
152590075Sobrien}
152690075Sobrien
152718334Speter/* Describe the beginning of an internal block within a function.
152818334Speter   Also output descriptions of variables defined in this block.
152918334Speter
153018334Speter   N is the number of the block, by order of beginning, counting from 1,
153118334Speter   and not counting the outermost (function top-level) block.
153218334Speter   The blocks match the BLOCKs in DECL_INITIAL (current_function_decl),
153318334Speter   if the count starts at 0 for the outermost one.  */
153418334Speter
153590075Sobrienstatic void
153690075Sobriensdbout_begin_block (line, n)
153790075Sobrien     unsigned int line;
153890075Sobrien     unsigned int n;
153918334Speter{
154018334Speter  tree decl = current_function_decl;
154118334Speter  MAKE_LINE_SAFE (line);
154218334Speter
154318334Speter  /* The SCO compiler does not emit a separate block for the function level
154418334Speter     scope, so we avoid it here also.  However, mips ECOFF compilers do emit
154518334Speter     a separate block, so we retain it when MIPS_DEBUGGING_INFO is defined.  */
154618334Speter#ifndef MIPS_DEBUGGING_INFO
154718334Speter  if (n != 1)
154818334Speter#endif
154918334Speter    PUT_SDB_BLOCK_START (line - sdb_begin_function_line);
155018334Speter
155118334Speter  if (n == 1)
155218334Speter    {
155318334Speter      /* Include the outermost BLOCK's variables in block 1.  */
155490075Sobrien      do_block = BLOCK_NUMBER (DECL_INITIAL (decl));
155518334Speter      sdbout_block (DECL_INITIAL (decl));
155618334Speter    }
155718334Speter  /* If -g1, suppress all the internal symbols of functions
155818334Speter     except for arguments.  */
155918334Speter  if (debug_info_level != DINFO_LEVEL_TERSE)
156018334Speter    {
156118334Speter      do_block = n;
156218334Speter      sdbout_block (DECL_INITIAL (decl));
156318334Speter    }
156418334Speter
156518334Speter#ifdef SDB_ALLOW_FORWARD_REFERENCES
156618334Speter  sdbout_dequeue_anonymous_types ();
156718334Speter#endif
156818334Speter}
156918334Speter
157018334Speter/* Describe the end line-number of an internal block within a function.  */
157118334Speter
157290075Sobrienstatic void
157390075Sobriensdbout_end_block (line, n)
157490075Sobrien     unsigned int line;
157590075Sobrien     unsigned int n ATTRIBUTE_UNUSED;
157618334Speter{
157718334Speter  MAKE_LINE_SAFE (line);
157818334Speter
157918334Speter  /* The SCO compiler does not emit a separate block for the function level
158018334Speter     scope, so we avoid it here also.  However, mips ECOFF compilers do emit
158118334Speter     a separate block, so we retain it when MIPS_DEBUGGING_INFO is defined.  */
158218334Speter#ifndef MIPS_DEBUGGING_INFO
158318334Speter  if (n != 1)
158418334Speter#endif
158518334Speter  PUT_SDB_BLOCK_END (line - sdb_begin_function_line);
158618334Speter}
158718334Speter
158890075Sobrienstatic void
158990075Sobriensdbout_source_line (line, filename)
159090075Sobrien     unsigned int line;
159190075Sobrien     const char *filename ATTRIBUTE_UNUSED;
159290075Sobrien{
159390075Sobrien  /* COFF relative line numbers must be positive.  */
159490075Sobrien  if ((int) line > sdb_begin_function_line)
159590075Sobrien    {
159690075Sobrien#ifdef ASM_OUTPUT_SOURCE_LINE
159790075Sobrien      ASM_OUTPUT_SOURCE_LINE (asm_out_file, line);
159890075Sobrien#else
159990075Sobrien      fprintf (asm_out_file, "\t.ln\t%d\n",
160090075Sobrien	       ((sdb_begin_function_line > -1)
160190075Sobrien		? line - sdb_begin_function_line : 1));
160290075Sobrien#endif
160390075Sobrien    }
160490075Sobrien}
160590075Sobrien
160618334Speter/* Output sdb info for the current function name.
160718334Speter   Called from assemble_start_function.  */
160818334Speter
160990075Sobrienstatic void
161090075Sobriensdbout_begin_function (decl)
161190075Sobrien     tree decl ATTRIBUTE_UNUSED;
161218334Speter{
161318334Speter  sdbout_symbol (current_function_decl, 0);
161418334Speter}
161518334Speter
161690075Sobrien/* Called at beginning of function body (before or after prologue,
161790075Sobrien   depending on MIPS_DEBUGGING_INFO).  Record the function's starting
161890075Sobrien   line number, so we can output relative line numbers for the other
161990075Sobrien   lines.  Describe beginning of outermost block.  Also describe the
162090075Sobrien   parameter list.  */
162118334Speter
162290075Sobrien#ifndef MIPS_DEBUGGING_INFO
162390075Sobrienstatic void
162490075Sobriensdbout_begin_prologue (line, file)
162590075Sobrien     unsigned int line;
162690075Sobrien     const char *file ATTRIBUTE_UNUSED;
162718334Speter{
1628117395Skan  sdbout_end_prologue (line, file);
162990075Sobrien}
163090075Sobrien#endif
163190075Sobrien
163290075Sobrienstatic void
1633117395Skansdbout_end_prologue (line, file)
163490075Sobrien     unsigned int line;
1635117395Skan     const char *file ATTRIBUTE_UNUSED;
163690075Sobrien{
163718334Speter  sdb_begin_function_line = line - 1;
163818334Speter  PUT_SDB_FUNCTION_START (line);
163918334Speter  sdbout_parms (DECL_ARGUMENTS (current_function_decl));
164018334Speter  sdbout_reg_parms (DECL_ARGUMENTS (current_function_decl));
164118334Speter}
164218334Speter
164318334Speter/* Called at end of function (before epilogue).
164418334Speter   Describe end of outermost block.  */
164518334Speter
164690075Sobrienstatic void
164718334Spetersdbout_end_function (line)
164890075Sobrien     unsigned int line;
164918334Speter{
165018334Speter#ifdef SDB_ALLOW_FORWARD_REFERENCES
165118334Speter  sdbout_dequeue_anonymous_types ();
165218334Speter#endif
165318334Speter
165418334Speter  MAKE_LINE_SAFE (line);
165518334Speter  PUT_SDB_FUNCTION_END (line - sdb_begin_function_line);
165618334Speter
165718334Speter  /* Indicate we are between functions, for line-number output.  */
165818334Speter  sdb_begin_function_line = -1;
165918334Speter}
166018334Speter
166118334Speter/* Output sdb info for the absolute end of a function.
166218334Speter   Called after the epilogue is output.  */
166318334Speter
166490075Sobrienstatic void
1665117395Skansdbout_end_epilogue (line, file)
1666117395Skan     unsigned int line ATTRIBUTE_UNUSED;
1667117395Skan     const char *file ATTRIBUTE_UNUSED;
166818334Speter{
166990075Sobrien  const char *const name ATTRIBUTE_UNUSED
167090075Sobrien    = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl));
167190075Sobrien
167290075Sobrien#ifdef PUT_SDB_EPILOGUE_END
167318334Speter  PUT_SDB_EPILOGUE_END (name);
167490075Sobrien#else
167590075Sobrien  fprintf (asm_out_file, "\t.def\t");
167690075Sobrien  assemble_name (asm_out_file, name);
167790075Sobrien  fprintf (asm_out_file, "%s\t.val\t.%s\t.scl\t-1%s\t.endef\n",
167890075Sobrien	   SDB_DELIM, SDB_DELIM, SDB_DELIM);
167990075Sobrien#endif
168018334Speter}
168118334Speter
168218334Speter/* Output sdb info for the given label.  Called only if LABEL_NAME (insn)
168318334Speter   is present.  */
168418334Speter
168590075Sobrienstatic void
168618334Spetersdbout_label (insn)
168790075Sobrien     rtx insn;
168818334Speter{
168918334Speter  PUT_SDB_DEF (LABEL_NAME (insn));
169018334Speter  PUT_SDB_VAL (insn);
169118334Speter  PUT_SDB_SCL (C_LABEL);
169218334Speter  PUT_SDB_TYPE (T_NULL);
169318334Speter  PUT_SDB_ENDEF;
169418334Speter}
169518334Speter
169650397Sobrien/* Change to reading from a new source file.  */
169750397Sobrien
169890075Sobrienstatic void
169990075Sobriensdbout_start_source_file (line, filename)
170090075Sobrien     unsigned int line ATTRIBUTE_UNUSED;
170190075Sobrien     const char *filename ATTRIBUTE_UNUSED;
170250397Sobrien{
170350397Sobrien#ifdef MIPS_DEBUGGING_INFO
170450397Sobrien  struct sdb_file *n = (struct sdb_file *) xmalloc (sizeof *n);
170550397Sobrien
170650397Sobrien  n->next = current_file;
170750397Sobrien  n->name = filename;
170850397Sobrien  current_file = n;
170950397Sobrien  PUT_SDB_SRC_FILE (filename);
171050397Sobrien#endif
171150397Sobrien}
171250397Sobrien
171350397Sobrien/* Revert to reading a previous source file.  */
171450397Sobrien
171590075Sobrienstatic void
171690075Sobriensdbout_end_source_file (line)
171790075Sobrien     unsigned int line ATTRIBUTE_UNUSED;
171850397Sobrien{
171950397Sobrien#ifdef MIPS_DEBUGGING_INFO
172050397Sobrien  struct sdb_file *next;
172150397Sobrien
172250397Sobrien  next = current_file->next;
172350397Sobrien  free (current_file);
172450397Sobrien  current_file = next;
172550397Sobrien  PUT_SDB_SRC_FILE (current_file->name);
172650397Sobrien#endif
172750397Sobrien}
172850397Sobrien
172990075Sobrien/* Set up for SDB output at the start of compilation.  */
173090075Sobrien
173190075Sobrienstatic void
173290075Sobriensdbout_init (input_file_name)
173390075Sobrien     const char *input_file_name ATTRIBUTE_UNUSED;
173490075Sobrien{
173590075Sobrien#ifdef MIPS_DEBUGGING_INFO
173690075Sobrien  current_file = (struct sdb_file *) xmalloc (sizeof *current_file);
173790075Sobrien  current_file->next = NULL;
173890075Sobrien  current_file->name = input_file_name;
173990075Sobrien#endif
174090075Sobrien
174190075Sobrien#ifdef RMS_QUICK_HACK_1
174290075Sobrien  tree t;
1743117395Skan  for (t = (*lang_hooks.decls.getdecls) (); t; t = TREE_CHAIN (t))
174490075Sobrien    if (DECL_NAME (t) && IDENTIFIER_POINTER (DECL_NAME (t)) != 0
174590075Sobrien	&& !strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__vtbl_ptr_type"))
174690075Sobrien      sdbout_symbol (t, 0);
174790075Sobrien#endif
174890075Sobrien}
174990075Sobrien
1750117395Skan#else  /* SDB_DEBUGGING_INFO */
1751117395Skan
1752117395Skan/* This should never be used, but its address is needed for comparisons.  */
1753117395Skanconst struct gcc_debug_hooks sdb_debug_hooks;
1754117395Skan
175518334Speter#endif /* SDB_DEBUGGING_INFO */
1756117395Skan
1757117395Skan#include "gt-sdbout.h"
1758