sdbout.c revision 52284
118334Speter/* Output sdb-format symbol table information from GNU compiler.
250397Sobrien   Copyright (C) 1988, 92-97, 1998 Free Software Foundation, Inc.
318334Speter
418334SpeterThis file is part of GNU CC.
518334Speter
618334SpeterGNU CC is free software; you can redistribute it and/or modify
718334Speterit under the terms of the GNU General Public License as published by
818334Speterthe Free Software Foundation; either version 2, or (at your option)
918334Speterany later version.
1018334Speter
1118334SpeterGNU CC is distributed in the hope that it will be useful,
1218334Speterbut WITHOUT ANY WARRANTY; without even the implied warranty of
1318334SpeterMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1418334SpeterGNU General Public License for more details.
1518334Speter
1618334SpeterYou should have received a copy of the GNU General Public License
1718334Speteralong with GNU CC; see the file COPYING.  If not, write to
1818334Speterthe Free Software Foundation, 59 Temple Place - Suite 330,
1918334SpeterBoston, MA 02111-1307, USA.  */
2018334Speter
2118334Speter/*  mike@tredysvr.Tredydev.Unisys.COM says:
2218334SpeterI modified the struct.c example and have a nm of a .o resulting from the
2318334SpeterAT&T C compiler.  From the example below I would conclude the following:
2418334Speter
2518334Speter1. All .defs from structures are emitted as scanned.  The example below
2618334Speter   clearly shows the symbol table entries for BoxRec2 are after the first
2718334Speter   function.
2818334Speter
2918334Speter2. All functions and their locals (including statics) are emitted as scanned.
3018334Speter
3118334Speter3. All nested unnamed union and structure .defs must be emitted before
3218334Speter   the structure in which they are nested.  The AT&T assembler is a
3318334Speter   one pass beast as far as symbolics are concerned.
3418334Speter
3518334Speter4. All structure .defs are emitted before the typedefs that refer to them.
3618334Speter
3718334Speter5. All top level static and external variable definitions are moved to the
3818334Speter   end of file with all top level statics occurring first before externs.
3918334Speter
4018334Speter6. All undefined references are at the end of the file.
4118334Speter*/
4218334Speter
4318334Speter#include "config.h"
4418334Speter
4518334Speter#ifdef SDB_DEBUGGING_INFO
4618334Speter
4750397Sobrien#include "system.h"
4818334Speter#include "tree.h"
4918334Speter#include "rtl.h"
5018334Speter#include "regs.h"
5150397Sobrien#include "defaults.h"
5218334Speter#include "flags.h"
5318334Speter#include "insn-config.h"
5418334Speter#include "reload.h"
5550397Sobrien#include "output.h"
5650397Sobrien#include "toplev.h"
5718334Speter
5850397Sobrien/* Mips systems use the SDB functions to dump out symbols, but do not
5950397Sobrien   supply usable syms.h include files.  Which syms.h file to use is a
6050397Sobrien   target parameter so don't use the native one if we're cross compiling.  */
6150397Sobrien
6252284Sobrien#if defined(USG) && !defined(MIPS) && !defined (hpux) && !defined(_WIN32) && !defined(__linux__) && !defined(__INTERIX) && !defined(CROSS_COMPILE)
6318334Speter#include <syms.h>
6418334Speter/* Use T_INT if we don't have T_VOID.  */
6518334Speter#ifndef T_VOID
6618334Speter#define T_VOID T_INT
6718334Speter#endif
6850397Sobrien#else
6918334Speter#include "gsyms.h"
7050397Sobrien#endif
7118334Speter
7218334Speter/* #include <storclass.h>  used to be this instead of syms.h.  */
7318334Speter
7418334Speter/* 1 if PARM is passed to this function in memory.  */
7518334Speter
7618334Speter#define PARM_PASSED_IN_MEMORY(PARM) \
7718334Speter (GET_CODE (DECL_INCOMING_RTL (PARM)) == MEM)
7818334Speter
7918334Speter/* A C expression for the integer offset value of an automatic variable
8018334Speter   (C_AUTO) having address X (an RTX).  */
8118334Speter#ifndef DEBUGGER_AUTO_OFFSET
8218334Speter#define DEBUGGER_AUTO_OFFSET(X) \
8318334Speter  (GET_CODE (X) == PLUS ? INTVAL (XEXP (X, 1)) : 0)
8418334Speter#endif
8518334Speter
8618334Speter/* A C expression for the integer offset value of an argument (C_ARG)
8718334Speter   having address X (an RTX).  The nominal offset is OFFSET.  */
8818334Speter#ifndef DEBUGGER_ARG_OFFSET
8918334Speter#define DEBUGGER_ARG_OFFSET(OFFSET, X) (OFFSET)
9018334Speter#endif
9118334Speter
9218334Speter/* Line number of beginning of current function, minus one.
9318334Speter   Negative means not in a function or not using sdb.  */
9418334Speter
9518334Speterint sdb_begin_function_line = -1;
9618334Speter
9718334Speter/* Counter to generate unique "names" for nameless struct members.  */
9818334Speter
9918334Speterstatic int unnamed_struct_number = 0;
10018334Speter
10118334Speterextern FILE *asm_out_file;
10218334Speter
10318334Speterextern tree current_function_decl;
10418334Speter
10550397Sobrien#include "sdbout.h"
10618334Speter
10750397Sobrienstatic char *gen_fake_label		PROTO((void));
10850397Sobrienstatic int plain_type			PROTO((tree));
10950397Sobrienstatic int template_name_p		PROTO((tree));
11050397Sobrienstatic void sdbout_record_type_name	PROTO((tree));
11150397Sobrienstatic int plain_type_1			PROTO((tree, int));
11250397Sobrienstatic void sdbout_block		PROTO((tree));
11350397Sobrienstatic void sdbout_syms			PROTO((tree));
11450397Sobrienstatic void sdbout_queue_anonymous_type	PROTO((tree));
11550397Sobrienstatic void sdbout_dequeue_anonymous_types PROTO((void));
11650397Sobrienstatic void sdbout_type			PROTO((tree));
11750397Sobrienstatic void sdbout_field_types		PROTO((tree));
11850397Sobrienstatic void sdbout_one_type		PROTO((tree));
11950397Sobrienstatic void sdbout_parms		PROTO((tree));
12050397Sobrienstatic void sdbout_reg_parms		PROTO((tree));
12118334Speter
12218334Speter/* Define the default sizes for various types.  */
12318334Speter
12418334Speter#ifndef CHAR_TYPE_SIZE
12518334Speter#define CHAR_TYPE_SIZE BITS_PER_UNIT
12618334Speter#endif
12718334Speter
12818334Speter#ifndef SHORT_TYPE_SIZE
12918334Speter#define SHORT_TYPE_SIZE (BITS_PER_UNIT * MIN ((UNITS_PER_WORD + 1) / 2, 2))
13018334Speter#endif
13118334Speter
13218334Speter#ifndef INT_TYPE_SIZE
13318334Speter#define INT_TYPE_SIZE BITS_PER_WORD
13418334Speter#endif
13518334Speter
13618334Speter#ifndef LONG_TYPE_SIZE
13718334Speter#define LONG_TYPE_SIZE BITS_PER_WORD
13818334Speter#endif
13918334Speter
14018334Speter#ifndef LONG_LONG_TYPE_SIZE
14118334Speter#define LONG_LONG_TYPE_SIZE (BITS_PER_WORD * 2)
14218334Speter#endif
14318334Speter
14418334Speter#ifndef FLOAT_TYPE_SIZE
14518334Speter#define FLOAT_TYPE_SIZE BITS_PER_WORD
14618334Speter#endif
14718334Speter
14818334Speter#ifndef DOUBLE_TYPE_SIZE
14918334Speter#define DOUBLE_TYPE_SIZE (BITS_PER_WORD * 2)
15018334Speter#endif
15118334Speter
15218334Speter#ifndef LONG_DOUBLE_TYPE_SIZE
15318334Speter#define LONG_DOUBLE_TYPE_SIZE (BITS_PER_WORD * 2)
15418334Speter#endif
15518334Speter
15618334Speter/* Random macros describing parts of SDB data.  */
15718334Speter
15818334Speter/* Put something here if lines get too long */
15918334Speter#define CONTIN
16018334Speter
16118334Speter/* Default value of delimiter is ";".  */
16218334Speter#ifndef SDB_DELIM
16318334Speter#define SDB_DELIM	";"
16418334Speter#endif
16518334Speter
16618334Speter/* Maximum number of dimensions the assembler will allow.  */
16718334Speter#ifndef SDB_MAX_DIM
16818334Speter#define SDB_MAX_DIM 4
16918334Speter#endif
17018334Speter
17118334Speter#ifndef PUT_SDB_SCL
17218334Speter#define PUT_SDB_SCL(a) fprintf(asm_out_file, "\t.scl\t%d%s", (a), SDB_DELIM)
17318334Speter#endif
17418334Speter
17518334Speter#ifndef PUT_SDB_INT_VAL
17650397Sobrien#define PUT_SDB_INT_VAL(a) \
17750397Sobrien do {									\
17850397Sobrien   fputs ("\t.val\t", asm_out_file);		       			\
17950397Sobrien   fprintf (asm_out_file, HOST_WIDE_INT_PRINT_DEC, (HOST_WIDE_INT)(a));	\
18050397Sobrien   fprintf (asm_out_file, "%s", SDB_DELIM);				\
18150397Sobrien } while (0)
18250397Sobrien
18318334Speter#endif
18418334Speter
18518334Speter#ifndef PUT_SDB_VAL
18618334Speter#define PUT_SDB_VAL(a)				\
18718334Speter( fputs ("\t.val\t", asm_out_file),		\
18818334Speter  output_addr_const (asm_out_file, (a)),	\
18918334Speter  fprintf (asm_out_file, SDB_DELIM))
19018334Speter#endif
19118334Speter
19218334Speter#ifndef PUT_SDB_DEF
19318334Speter#define PUT_SDB_DEF(a)				\
19418334Speterdo { fprintf (asm_out_file, "\t.def\t");	\
19518334Speter     ASM_OUTPUT_LABELREF (asm_out_file, a); 	\
19618334Speter     fprintf (asm_out_file, SDB_DELIM); } while (0)
19718334Speter#endif
19818334Speter
19918334Speter#ifndef PUT_SDB_PLAIN_DEF
20018334Speter#define PUT_SDB_PLAIN_DEF(a) fprintf(asm_out_file,"\t.def\t.%s%s",a, SDB_DELIM)
20118334Speter#endif
20218334Speter
20318334Speter#ifndef PUT_SDB_ENDEF
20418334Speter#define PUT_SDB_ENDEF fputs("\t.endef\n", asm_out_file)
20518334Speter#endif
20618334Speter
20718334Speter#ifndef PUT_SDB_TYPE
20818334Speter#define PUT_SDB_TYPE(a) fprintf(asm_out_file, "\t.type\t0%o%s", a, SDB_DELIM)
20918334Speter#endif
21018334Speter
21118334Speter#ifndef PUT_SDB_SIZE
21250397Sobrien#define PUT_SDB_SIZE(a) \
21350397Sobrien do {									\
21450397Sobrien   fputs ("\t.size\t", asm_out_file);					\
21550397Sobrien   fprintf (asm_out_file, HOST_WIDE_INT_PRINT_DEC, (HOST_WIDE_INT)(a));	\
21650397Sobrien   fprintf (asm_out_file, "%s", SDB_DELIM);				\
21750397Sobrien } while(0)
21818334Speter#endif
21918334Speter
22018334Speter#ifndef PUT_SDB_START_DIM
22118334Speter#define PUT_SDB_START_DIM fprintf(asm_out_file, "\t.dim\t")
22218334Speter#endif
22318334Speter
22418334Speter#ifndef PUT_SDB_NEXT_DIM
22518334Speter#define PUT_SDB_NEXT_DIM(a) fprintf(asm_out_file, "%d,", a)
22618334Speter#endif
22718334Speter
22818334Speter#ifndef PUT_SDB_LAST_DIM
22918334Speter#define PUT_SDB_LAST_DIM(a) fprintf(asm_out_file, "%d%s", a, SDB_DELIM)
23018334Speter#endif
23118334Speter
23218334Speter#ifndef PUT_SDB_TAG
23318334Speter#define PUT_SDB_TAG(a)				\
23418334Speterdo { fprintf (asm_out_file, "\t.tag\t");	\
23518334Speter     ASM_OUTPUT_LABELREF (asm_out_file, a);	\
23618334Speter     fprintf (asm_out_file, SDB_DELIM); } while (0)
23718334Speter#endif
23818334Speter
23918334Speter#ifndef PUT_SDB_BLOCK_START
24018334Speter#define PUT_SDB_BLOCK_START(LINE)		\
24118334Speter  fprintf (asm_out_file,			\
24218334Speter	   "\t.def\t.bb%s\t.val\t.%s\t.scl\t100%s\t.line\t%d%s\t.endef\n", \
24318334Speter	   SDB_DELIM, SDB_DELIM, SDB_DELIM, (LINE), SDB_DELIM)
24418334Speter#endif
24518334Speter
24618334Speter#ifndef PUT_SDB_BLOCK_END
24718334Speter#define PUT_SDB_BLOCK_END(LINE)			\
24818334Speter  fprintf (asm_out_file,			\
24918334Speter	   "\t.def\t.eb%s\t.val\t.%s\t.scl\t100%s\t.line\t%d%s\t.endef\n",  \
25018334Speter	   SDB_DELIM, SDB_DELIM, SDB_DELIM, (LINE), SDB_DELIM)
25118334Speter#endif
25218334Speter
25318334Speter#ifndef PUT_SDB_FUNCTION_START
25418334Speter#define PUT_SDB_FUNCTION_START(LINE)		\
25518334Speter  fprintf (asm_out_file,			\
25618334Speter	   "\t.def\t.bf%s\t.val\t.%s\t.scl\t101%s\t.line\t%d%s\t.endef\n", \
25718334Speter	   SDB_DELIM, SDB_DELIM, SDB_DELIM, (LINE), SDB_DELIM)
25818334Speter#endif
25918334Speter
26018334Speter#ifndef PUT_SDB_FUNCTION_END
26118334Speter#define PUT_SDB_FUNCTION_END(LINE)		\
26218334Speter  fprintf (asm_out_file,			\
26318334Speter	   "\t.def\t.ef%s\t.val\t.%s\t.scl\t101%s\t.line\t%d%s\t.endef\n", \
26418334Speter	   SDB_DELIM, SDB_DELIM, SDB_DELIM, (LINE), SDB_DELIM)
26518334Speter#endif
26618334Speter
26718334Speter#ifndef PUT_SDB_EPILOGUE_END
26818334Speter#define PUT_SDB_EPILOGUE_END(NAME)			\
26918334Speterdo { fprintf (asm_out_file, "\t.def\t");		\
27018334Speter     ASM_OUTPUT_LABELREF (asm_out_file, NAME);		\
27118334Speter     fprintf (asm_out_file,				\
27218334Speter	      "%s\t.val\t.%s\t.scl\t-1%s\t.endef\n",	\
27318334Speter	      SDB_DELIM, SDB_DELIM, SDB_DELIM); } while (0)
27418334Speter#endif
27518334Speter
27618334Speter#ifndef SDB_GENERATE_FAKE
27718334Speter#define SDB_GENERATE_FAKE(BUFFER, NUMBER) \
27818334Speter  sprintf ((BUFFER), ".%dfake", (NUMBER));
27918334Speter#endif
28018334Speter
28118334Speter/* Return the sdb tag identifier string for TYPE
28218334Speter   if TYPE has already been defined; otherwise return a null pointer.   */
28318334Speter
28418334Speter#define KNOWN_TYPE_TAG(type)  TYPE_SYMTAB_POINTER (type)
28518334Speter
28618334Speter/* Set the sdb tag identifier string for TYPE to NAME.  */
28718334Speter
28818334Speter#define SET_KNOWN_TYPE_TAG(TYPE, NAME) \
28918334Speter  TYPE_SYMTAB_POINTER (TYPE) = (NAME)
29018334Speter
29118334Speter/* Return the name (a string) of the struct, union or enum tag
29218334Speter   described by the TREE_LIST node LINK.  This is 0 for an anonymous one.  */
29318334Speter
29418334Speter#define TAG_NAME(link) \
29518334Speter  (((link) && TREE_PURPOSE ((link)) \
29618334Speter    && IDENTIFIER_POINTER (TREE_PURPOSE ((link)))) \
29718334Speter   ? IDENTIFIER_POINTER (TREE_PURPOSE ((link))) : (char *) 0)
29818334Speter
29918334Speter/* Ensure we don't output a negative line number.  */
30018334Speter#define MAKE_LINE_SAFE(line)  \
30118334Speter  if (line <= sdb_begin_function_line) line = sdb_begin_function_line + 1
30250397Sobrien
30350397Sobrien/* Perform linker optimization of merging header file definitions together
30450397Sobrien   for targets with MIPS_DEBUGGING_INFO defined.  This won't work without a
30550397Sobrien   post 960826 version of GAS.  Nothing breaks with earlier versions of GAS,
30650397Sobrien   the optimization just won't be done.  The native assembler already has the
30750397Sobrien   necessary support.  */
30850397Sobrien
30950397Sobrien#ifdef MIPS_DEBUGGING_INFO
31050397Sobrien
31150397Sobrien#ifndef PUT_SDB_SRC_FILE
31250397Sobrien#define PUT_SDB_SRC_FILE(FILENAME) \
31350397Sobrienoutput_file_directive (asm_out_file, (FILENAME))
31450397Sobrien#endif
31550397Sobrien
31650397Sobrien/* ECOFF linkers have an optimization that does the same kind of thing as
31750397Sobrien   N_BINCL/E_INCL in stabs: eliminate duplicate debug information in the
31850397Sobrien   executable.  To achieve this, GCC must output a .file for each file
31950397Sobrien   name change.  */
32050397Sobrien
32150397Sobrien/* This is a stack of input files.  */
32250397Sobrien
32350397Sobrienstruct sdb_file
32450397Sobrien{
32550397Sobrien  struct sdb_file *next;
32650397Sobrien  char *name;
32750397Sobrien};
32850397Sobrien
32950397Sobrien/* This is the top of the stack.  */
33050397Sobrien
33150397Sobrienstatic struct sdb_file *current_file;
33250397Sobrien
33350397Sobrien#endif /* MIPS_DEBUGGING_INFO */
33418334Speter
33518334Speter/* Set up for SDB output at the start of compilation.  */
33618334Speter
33718334Spetervoid
33818334Spetersdbout_init (asm_file, input_file_name, syms)
33918334Speter     FILE *asm_file;
34018334Speter     char *input_file_name;
34152284Sobrien     tree syms ATTRIBUTE_UNUSED;
34218334Speter{
34350397Sobrien#ifdef MIPS_DEBUGGING_INFO
34450397Sobrien  current_file = (struct sdb_file *) xmalloc (sizeof *current_file);
34550397Sobrien  current_file->next = NULL;
34650397Sobrien  current_file->name = input_file_name;
34750397Sobrien#endif
34850397Sobrien
34918334Speter#ifdef RMS_QUICK_HACK_1
35018334Speter  tree t;
35118334Speter  for (t = syms; t; t = TREE_CHAIN (t))
35218334Speter    if (DECL_NAME (t) && IDENTIFIER_POINTER (DECL_NAME (t)) != 0
35318334Speter	&& !strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__vtbl_ptr_type"))
35418334Speter      sdbout_symbol (t, 0);
35518334Speter#endif
35618334Speter}
35718334Speter
35818334Speter#if 0
35918334Speter
36018334Speter/* return the tag identifier for type
36118334Speter */
36218334Speter
36318334Speterchar *
36418334Spetertag_of_ru_type (type,link)
36518334Speter     tree type,link;
36618334Speter{
36718334Speter  if (TYPE_SYMTAB_ADDRESS (type))
36818334Speter    return TYPE_SYMTAB_ADDRESS (type);
36918334Speter  if (link && TREE_PURPOSE (link)
37018334Speter      && IDENTIFIER_POINTER (TREE_PURPOSE (link)))
37118334Speter    TYPE_SYMTAB_ADDRESS (type) = IDENTIFIER_POINTER (TREE_PURPOSE (link));
37218334Speter  else
37318334Speter    return (char *) TYPE_SYMTAB_ADDRESS (type);
37418334Speter}
37518334Speter#endif
37618334Speter
37718334Speter/* Return a unique string to name an anonymous type.  */
37818334Speter
37918334Speterstatic char *
38018334Spetergen_fake_label ()
38118334Speter{
38218334Speter  char label[10];
38318334Speter  char *labelstr;
38418334Speter  SDB_GENERATE_FAKE (label, unnamed_struct_number);
38518334Speter  unnamed_struct_number++;
38618334Speter  labelstr = (char *) permalloc (strlen (label) + 1);
38718334Speter  strcpy (labelstr, label);
38818334Speter  return labelstr;
38918334Speter}
39018334Speter
39118334Speter/* Return the number which describes TYPE for SDB.
39218334Speter   For pointers, etc., this function is recursive.
39318334Speter   Each record, union or enumeral type must already have had a
39418334Speter   tag number output.  */
39518334Speter
39618334Speter/* The number is given by d6d5d4d3d2d1bbbb
39718334Speter   where bbbb is 4 bit basic type, and di indicate  one of notype,ptr,fn,array.
39818334Speter   Thus, char *foo () has bbbb=T_CHAR
39918334Speter			  d1=D_FCN
40018334Speter			  d2=D_PTR
40118334Speter N_BTMASK=     017       1111     basic type field.
40218334Speter N_TSHIFT=       2                derived type shift
40318334Speter N_BTSHFT=       4                Basic type shift */
40418334Speter
40518334Speter/* Produce the number that describes a pointer, function or array type.
40618334Speter   PREV is the number describing the target, value or element type.
40718334Speter   DT_type describes how to transform that type.  */
40818334Speter#define PUSH_DERIVED_LEVEL(DT_type,PREV)		\
40918334Speter  ((((PREV) & ~(int)N_BTMASK) << (int)N_TSHIFT)		\
41018334Speter   | ((int)DT_type << (int)N_BTSHFT)			\
41118334Speter   | ((PREV) & (int)N_BTMASK))
41218334Speter
41318334Speter/* Number of elements used in sdb_dims.  */
41418334Speterstatic int sdb_n_dims = 0;
41518334Speter
41618334Speter/* Table of array dimensions of current type.  */
41718334Speterstatic int sdb_dims[SDB_MAX_DIM];
41818334Speter
41918334Speter/* Size of outermost array currently being processed.  */
42018334Speterstatic int sdb_type_size = -1;
42118334Speter
42218334Speterstatic int
42318334Speterplain_type (type)
42418334Speter     tree type;
42518334Speter{
42618334Speter  int val = plain_type_1 (type, 0);
42718334Speter
42818334Speter  /* If we have already saved up some array dimensions, print them now.  */
42918334Speter  if (sdb_n_dims > 0)
43018334Speter    {
43118334Speter      int i;
43218334Speter      PUT_SDB_START_DIM;
43318334Speter      for (i = sdb_n_dims - 1; i > 0; i--)
43418334Speter	PUT_SDB_NEXT_DIM (sdb_dims[i]);
43518334Speter      PUT_SDB_LAST_DIM (sdb_dims[0]);
43618334Speter      sdb_n_dims = 0;
43718334Speter
43818334Speter      sdb_type_size = int_size_in_bytes (type);
43918334Speter      /* Don't kill sdb if type is not laid out or has variable size.  */
44018334Speter      if (sdb_type_size < 0)
44118334Speter	sdb_type_size = 0;
44218334Speter    }
44318334Speter  /* If we have computed the size of an array containing this type,
44418334Speter     print it now.  */
44518334Speter  if (sdb_type_size >= 0)
44618334Speter    {
44718334Speter      PUT_SDB_SIZE (sdb_type_size);
44818334Speter      sdb_type_size = -1;
44918334Speter    }
45018334Speter  return val;
45118334Speter}
45218334Speter
45318334Speterstatic int
45418334Spetertemplate_name_p (name)
45518334Speter     tree name;
45618334Speter{
45718334Speter  register char *ptr = IDENTIFIER_POINTER (name);
45818334Speter  while (*ptr && *ptr != '<')
45918334Speter    ptr++;
46018334Speter
46118334Speter  return *ptr != '\0';
46218334Speter}
46318334Speter
46418334Speterstatic void
46518334Spetersdbout_record_type_name (type)
46618334Speter     tree type;
46718334Speter{
46818334Speter  char *name = 0;
46918334Speter  int no_name;
47018334Speter
47118334Speter  if (KNOWN_TYPE_TAG (type))
47218334Speter    return;
47318334Speter
47418334Speter  if (TYPE_NAME (type) != 0)
47518334Speter    {
47618334Speter      tree t = 0;
47718334Speter      /* Find the IDENTIFIER_NODE for the type name.  */
47818334Speter      if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
47918334Speter	t = TYPE_NAME (type);
48018334Speter      else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL)
48118334Speter	{
48218334Speter	  t = DECL_NAME (TYPE_NAME (type));
48318334Speter	  /* The DECL_NAME for templates includes "<>", which breaks
48418334Speter	     most assemblers.  Use its assembler name instead, which
48518334Speter	     has been mangled into being safe.  */
48618334Speter	  if (t && template_name_p (t))
48718334Speter	    t = DECL_ASSEMBLER_NAME (TYPE_NAME (type));
48818334Speter	}
48918334Speter
49018334Speter      /* Now get the name as a string, or invent one.  */
49118334Speter      if (t != NULL_TREE)
49218334Speter	name = IDENTIFIER_POINTER (t);
49318334Speter    }
49418334Speter
49518334Speter  no_name = (name == 0 || *name == 0);
49618334Speter  if (no_name)
49718334Speter    name = gen_fake_label ();
49818334Speter
49918334Speter  SET_KNOWN_TYPE_TAG (type, name);
50018334Speter#ifdef SDB_ALLOW_FORWARD_REFERENCES
50118334Speter  if (no_name)
50218334Speter    sdbout_queue_anonymous_type (type);
50318334Speter#endif
50418334Speter}
50518334Speter
50618334Speter/* Return the .type value for type TYPE.
50718334Speter
50818334Speter   LEVEL indicates how many levels deep we have recursed into the type.
50918334Speter   The SDB debug format can only represent 6 derived levels of types.
51018334Speter   After that, we must output inaccurate debug info.  We deliberately
51118334Speter   stop before the 7th level, so that ADA recursive types will not give an
51218334Speter   infinite loop.  */
51318334Speter
51418334Speterstatic int
51518334Speterplain_type_1 (type, level)
51618334Speter     tree type;
51718334Speter     int level;
51818334Speter{
51918334Speter  if (type == 0)
52018334Speter    type = void_type_node;
52118334Speter  else if (type == error_mark_node)
52218334Speter    type = integer_type_node;
52318334Speter  else
52418334Speter    type = TYPE_MAIN_VARIANT (type);
52518334Speter
52618334Speter  switch (TREE_CODE (type))
52718334Speter    {
52818334Speter    case VOID_TYPE:
52918334Speter      return T_VOID;
53052284Sobrien    case BOOLEAN_TYPE:
53118334Speter    case INTEGER_TYPE:
53218334Speter      {
53318334Speter	int size = int_size_in_bytes (type) * BITS_PER_UNIT;
53418334Speter
53518334Speter	/* Carefully distinguish all the standard types of C,
53618334Speter	   without messing up if the language is not C.
53718334Speter	   Note that we check only for the names that contain spaces;
53818334Speter	   other names might occur by coincidence in other languages.  */
53918334Speter	if (TYPE_NAME (type) != 0
54018334Speter	    && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
54118334Speter	    && DECL_NAME (TYPE_NAME (type)) != 0
54218334Speter	    && TREE_CODE (DECL_NAME (TYPE_NAME (type))) == IDENTIFIER_NODE)
54318334Speter	  {
54418334Speter	    char *name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
54518334Speter
54650397Sobrien	    if (!strcmp (name, "char"))
54750397Sobrien	      return T_CHAR;
54818334Speter	    if (!strcmp (name, "unsigned char"))
54918334Speter	      return T_UCHAR;
55018334Speter	    if (!strcmp (name, "signed char"))
55118334Speter	      return T_CHAR;
55250397Sobrien	    if (!strcmp (name, "int"))
55350397Sobrien	      return T_INT;
55418334Speter	    if (!strcmp (name, "unsigned int"))
55518334Speter	      return T_UINT;
55618334Speter	    if (!strcmp (name, "short int"))
55718334Speter	      return T_SHORT;
55818334Speter	    if (!strcmp (name, "short unsigned int"))
55918334Speter	      return T_USHORT;
56018334Speter	    if (!strcmp (name, "long int"))
56118334Speter	      return T_LONG;
56218334Speter	    if (!strcmp (name, "long unsigned int"))
56318334Speter	      return T_ULONG;
56418334Speter	  }
56518334Speter
56650397Sobrien	if (size == INT_TYPE_SIZE)
56750397Sobrien	  return (TREE_UNSIGNED (type) ? T_UINT : T_INT);
56818334Speter	if (size == CHAR_TYPE_SIZE)
56918334Speter	  return (TREE_UNSIGNED (type) ? T_UCHAR : T_CHAR);
57018334Speter	if (size == SHORT_TYPE_SIZE)
57118334Speter	  return (TREE_UNSIGNED (type) ? T_USHORT : T_SHORT);
57218334Speter	if (size == LONG_TYPE_SIZE)
57318334Speter	  return (TREE_UNSIGNED (type) ? T_ULONG : T_LONG);
57418334Speter	if (size == LONG_LONG_TYPE_SIZE)	/* better than nothing */
57518334Speter	  return (TREE_UNSIGNED (type) ? T_ULONG : T_LONG);
57618334Speter	return 0;
57718334Speter      }
57818334Speter
57918334Speter    case REAL_TYPE:
58018334Speter      {
58150397Sobrien	int precision = TYPE_PRECISION (type);
58250397Sobrien	if (precision == FLOAT_TYPE_SIZE)
58318334Speter	  return T_FLOAT;
58450397Sobrien	if (precision == DOUBLE_TYPE_SIZE)
58518334Speter	  return T_DOUBLE;
58650397Sobrien#ifdef EXTENDED_SDB_BASIC_TYPES
58750397Sobrien	if (precision == LONG_DOUBLE_TYPE_SIZE)
58850397Sobrien	  return T_LNGDBL;
58950397Sobrien#else
59050397Sobrien	if (precision == LONG_DOUBLE_TYPE_SIZE)
59150397Sobrien	  return T_DOUBLE;	/* better than nothing */
59250397Sobrien#endif
59318334Speter	return 0;
59418334Speter      }
59518334Speter
59618334Speter    case ARRAY_TYPE:
59718334Speter      {
59818334Speter	int m;
59918334Speter	if (level >= 6)
60018334Speter	  return T_VOID;
60118334Speter	else
60218334Speter	  m = plain_type_1 (TREE_TYPE (type), level+1);
60318334Speter	if (sdb_n_dims < SDB_MAX_DIM)
60418334Speter	  sdb_dims[sdb_n_dims++]
60518334Speter	    = (TYPE_DOMAIN (type)
60650397Sobrien	       && TYPE_MAX_VALUE (TYPE_DOMAIN (type))
60750397Sobrien	       && TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) == INTEGER_CST
60850397Sobrien	       && TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (type))) == INTEGER_CST
60950397Sobrien	       ? (TREE_INT_CST_LOW (TYPE_MAX_VALUE (TYPE_DOMAIN (type)))
61050397Sobrien		  - TREE_INT_CST_LOW (TYPE_MIN_VALUE (TYPE_DOMAIN (type))) + 1)
61118334Speter	       : 0);
61218334Speter	return PUSH_DERIVED_LEVEL (DT_ARY, m);
61318334Speter      }
61418334Speter
61518334Speter    case RECORD_TYPE:
61618334Speter    case UNION_TYPE:
61718334Speter    case QUAL_UNION_TYPE:
61818334Speter    case ENUMERAL_TYPE:
61918334Speter      {
62018334Speter	char *tag;
62118334Speter#ifdef SDB_ALLOW_FORWARD_REFERENCES
62218334Speter	sdbout_record_type_name (type);
62318334Speter#endif
62418334Speter#ifndef SDB_ALLOW_UNKNOWN_REFERENCES
62518334Speter	if ((TREE_ASM_WRITTEN (type) && KNOWN_TYPE_TAG (type) != 0)
62618334Speter#ifdef SDB_ALLOW_FORWARD_REFERENCES
62718334Speter	    || TYPE_MODE (type) != VOIDmode
62818334Speter#endif
62918334Speter	    )
63018334Speter#endif
63118334Speter	  {
63218334Speter	    /* Output the referenced structure tag name
63318334Speter	       only if the .def has already been finished.
63418334Speter	       At least on 386, the Unix assembler
63518334Speter	       cannot handle forward references to tags.  */
63650397Sobrien	    /* But the 88100, it requires them, sigh...  */
63750397Sobrien	    /* And the MIPS requires unknown refs as well...  */
63818334Speter	    tag = KNOWN_TYPE_TAG (type);
63918334Speter	    PUT_SDB_TAG (tag);
64018334Speter	    /* These 3 lines used to follow the close brace.
64118334Speter	       However, a size of 0 without a tag implies a tag of 0,
64218334Speter	       so if we don't know a tag, we can't mention the size.  */
64318334Speter	    sdb_type_size = int_size_in_bytes (type);
64418334Speter	    if (sdb_type_size < 0)
64518334Speter	      sdb_type_size = 0;
64618334Speter	  }
64718334Speter	return ((TREE_CODE (type) == RECORD_TYPE) ? T_STRUCT
64818334Speter		: (TREE_CODE (type) == UNION_TYPE) ? T_UNION
64918334Speter		: (TREE_CODE (type) == QUAL_UNION_TYPE) ? T_UNION
65018334Speter		: T_ENUM);
65118334Speter      }
65218334Speter    case POINTER_TYPE:
65318334Speter    case REFERENCE_TYPE:
65418334Speter      {
65518334Speter	int m;
65618334Speter	if (level >= 6)
65718334Speter	  return T_VOID;
65818334Speter	else
65918334Speter	  m = plain_type_1 (TREE_TYPE (type), level+1);
66018334Speter	return PUSH_DERIVED_LEVEL (DT_PTR, m);
66118334Speter      }
66218334Speter    case FUNCTION_TYPE:
66318334Speter    case METHOD_TYPE:
66418334Speter      {
66518334Speter	int m;
66618334Speter	if (level >= 6)
66718334Speter	  return T_VOID;
66818334Speter	else
66918334Speter	  m = plain_type_1 (TREE_TYPE (type), level+1);
67018334Speter	return PUSH_DERIVED_LEVEL (DT_FCN, m);
67118334Speter      }
67218334Speter    default:
67318334Speter      return 0;
67418334Speter    }
67518334Speter}
67618334Speter
67718334Speter/* Output the symbols defined in block number DO_BLOCK.
67818334Speter   Set NEXT_BLOCK_NUMBER to 0 before calling.
67918334Speter
68018334Speter   This function works by walking the tree structure of blocks,
68118334Speter   counting blocks until it finds the desired block.  */
68218334Speter
68318334Speterstatic int do_block = 0;
68418334Speter
68518334Speterstatic int next_block_number;
68618334Speter
68718334Speterstatic void
68818334Spetersdbout_block (block)
68918334Speter     register tree block;
69018334Speter{
69118334Speter  while (block)
69218334Speter    {
69318334Speter      /* Ignore blocks never expanded or otherwise marked as real.  */
69418334Speter      if (TREE_USED (block))
69518334Speter	{
69618334Speter	  /* When we reach the specified block, output its symbols.  */
69718334Speter	  if (next_block_number == do_block)
69818334Speter	    {
69918334Speter	      sdbout_syms (BLOCK_VARS (block));
70018334Speter	    }
70118334Speter
70218334Speter	  /* If we are past the specified block, stop the scan.  */
70318334Speter	  if (next_block_number > do_block)
70418334Speter	    return;
70518334Speter
70618334Speter	  next_block_number++;
70718334Speter
70818334Speter	  /* Scan the blocks within this block.  */
70918334Speter	  sdbout_block (BLOCK_SUBBLOCKS (block));
71018334Speter	}
71118334Speter
71218334Speter      block = BLOCK_CHAIN (block);
71318334Speter    }
71418334Speter}
71518334Speter
71618334Speter/* Call sdbout_symbol on each decl in the chain SYMS.  */
71718334Speter
71818334Speterstatic void
71918334Spetersdbout_syms (syms)
72018334Speter     tree syms;
72118334Speter{
72218334Speter  while (syms)
72318334Speter    {
72418334Speter      if (TREE_CODE (syms) != LABEL_DECL)
72518334Speter	sdbout_symbol (syms, 1);
72618334Speter      syms = TREE_CHAIN (syms);
72718334Speter    }
72818334Speter}
72918334Speter
73018334Speter/* Output SDB information for a symbol described by DECL.
73118334Speter   LOCAL is nonzero if the symbol is not file-scope.  */
73218334Speter
73318334Spetervoid
73418334Spetersdbout_symbol (decl, local)
73518334Speter     tree decl;
73618334Speter     int local;
73718334Speter{
73818334Speter  tree type = TREE_TYPE (decl);
73918334Speter  tree context = NULL_TREE;
74018334Speter  rtx value;
74118334Speter  int regno = -1;
74218334Speter  char *name;
74318334Speter
74418334Speter  sdbout_one_type (type);
74518334Speter
74618334Speter#if 0 /* This loses when functions are marked to be ignored,
74718334Speter	 which happens in the C++ front end.  */
74818334Speter  if (DECL_IGNORED_P (decl))
74918334Speter    return;
75018334Speter#endif
75118334Speter
75218334Speter  switch (TREE_CODE (decl))
75318334Speter    {
75418334Speter    case CONST_DECL:
75518334Speter      /* Enum values are defined by defining the enum type.  */
75618334Speter      return;
75718334Speter
75818334Speter    case FUNCTION_DECL:
75918334Speter      /* Don't mention a nested function under its parent.  */
76018334Speter      context = decl_function_context (decl);
76118334Speter      if (context == current_function_decl)
76218334Speter	return;
76350397Sobrien      /* Check DECL_INITIAL to distinguish declarations from definitions.
76450397Sobrien	 Don't output debug info here for declarations; they will have
76550397Sobrien	 a DECL_INITIAL value of 0.  */
76650397Sobrien      if (! DECL_INITIAL (decl))
76718334Speter	return;
76818334Speter      if (GET_CODE (DECL_RTL (decl)) != MEM
76918334Speter	  || GET_CODE (XEXP (DECL_RTL (decl), 0)) != SYMBOL_REF)
77018334Speter	return;
77118334Speter      PUT_SDB_DEF (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
77218334Speter      PUT_SDB_VAL (XEXP (DECL_RTL (decl), 0));
77318334Speter      PUT_SDB_SCL (TREE_PUBLIC (decl) ? C_EXT : C_STAT);
77418334Speter      break;
77518334Speter
77618334Speter    case TYPE_DECL:
77718334Speter      /* Done with tagged types.  */
77818334Speter      if (DECL_NAME (decl) == 0)
77918334Speter	return;
78018334Speter      if (DECL_IGNORED_P (decl))
78118334Speter	return;
78218334Speter
78318334Speter      /* Output typedef name.  */
78418334Speter      if (template_name_p (DECL_NAME (decl)))
78518334Speter	PUT_SDB_DEF (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
78618334Speter      else
78718334Speter	PUT_SDB_DEF (IDENTIFIER_POINTER (DECL_NAME (decl)));
78818334Speter      PUT_SDB_SCL (C_TPDEF);
78918334Speter      break;
79018334Speter
79118334Speter    case PARM_DECL:
79218334Speter      /* Parm decls go in their own separate chains
79318334Speter	 and are output by sdbout_reg_parms and sdbout_parms.  */
79418334Speter      abort ();
79518334Speter
79618334Speter    case VAR_DECL:
79718334Speter      /* Don't mention a variable that is external.
79818334Speter	 Let the file that defines it describe it.  */
79918334Speter      if (DECL_EXTERNAL (decl))
80018334Speter	return;
80118334Speter
80218334Speter      /* Ignore __FUNCTION__, etc.  */
80318334Speter      if (DECL_IGNORED_P (decl))
80418334Speter	return;
80518334Speter
80618334Speter      /* If there was an error in the declaration, don't dump core
80718334Speter	 if there is no RTL associated with the variable doesn't
80818334Speter	 exist.  */
80918334Speter      if (DECL_RTL (decl) == 0)
81018334Speter	return;
81118334Speter
81218334Speter      DECL_RTL (decl) = eliminate_regs (DECL_RTL (decl), 0, NULL_RTX);
81318334Speter#ifdef LEAF_REG_REMAP
81452284Sobrien      if (current_function_uses_only_leaf_regs)
81518334Speter	leaf_renumber_regs_insn (DECL_RTL (decl));
81618334Speter#endif
81718334Speter      value = DECL_RTL (decl);
81818334Speter
81918334Speter      /* Don't mention a variable at all
82018334Speter	 if it was completely optimized into nothingness.
82118334Speter
82218334Speter	 If DECL was from an inline function, then its rtl
82318334Speter	 is not identically the rtl that was used in this
82418334Speter	 particular compilation.  */
82518334Speter      if (GET_CODE (value) == REG)
82618334Speter	{
82718334Speter	  regno = REGNO (DECL_RTL (decl));
82818334Speter	  if (regno >= FIRST_PSEUDO_REGISTER)
82918334Speter	    return;
83018334Speter	}
83118334Speter      else if (GET_CODE (value) == SUBREG)
83218334Speter	{
83318334Speter	  int offset = 0;
83418334Speter	  while (GET_CODE (value) == SUBREG)
83518334Speter	    {
83618334Speter	      offset += SUBREG_WORD (value);
83718334Speter	      value = SUBREG_REG (value);
83818334Speter	    }
83918334Speter	  if (GET_CODE (value) == REG)
84018334Speter	    {
84118334Speter	      regno = REGNO (value);
84218334Speter	      if (regno >= FIRST_PSEUDO_REGISTER)
84318334Speter		return;
84418334Speter	      regno += offset;
84518334Speter	    }
84618334Speter	  alter_subreg (DECL_RTL (decl));
84718334Speter	  value = DECL_RTL (decl);
84818334Speter	}
84918334Speter      /* Don't output anything if an auto variable
85018334Speter	 gets RTL that is static.
85118334Speter	 GAS version 2.2 can't handle such output.  */
85218334Speter      else if (GET_CODE (value) == MEM && CONSTANT_P (XEXP (value, 0))
85318334Speter	       && ! TREE_STATIC (decl))
85418334Speter	return;
85518334Speter
85618334Speter      /* Emit any structure, union, or enum type that has not been output.
85718334Speter	 This occurs for tag-less structs (et al) used to declare variables
85818334Speter	 within functions.  */
85918334Speter      if (TREE_CODE (type) == ENUMERAL_TYPE
86018334Speter	  || TREE_CODE (type) == RECORD_TYPE
86118334Speter	  || TREE_CODE (type) == UNION_TYPE
86218334Speter	  || TREE_CODE (type) == QUAL_UNION_TYPE)
86318334Speter	{
86418334Speter	  if (TYPE_SIZE (type) != 0		/* not a forward reference */
86518334Speter	      && KNOWN_TYPE_TAG (type) == 0)	/* not yet declared */
86618334Speter	    sdbout_one_type (type);
86718334Speter	}
86818334Speter
86918334Speter      /* Defer SDB information for top-level initialized variables! */
87018334Speter      if (! local
87118334Speter	  && GET_CODE (value) == MEM
87218334Speter	  && DECL_INITIAL (decl))
87318334Speter	return;
87418334Speter
87518334Speter      /* C++ in 2.3 makes nameless symbols.  That will be fixed later.
87618334Speter	 For now, avoid crashing.  */
87718334Speter      if (DECL_NAME (decl) == NULL_TREE)
87818334Speter	return;
87918334Speter
88018334Speter      /* Record the name for, starting a symtab entry.  */
88118334Speter      name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
88218334Speter
88318334Speter      if (GET_CODE (value) == MEM
88418334Speter	  && GET_CODE (XEXP (value, 0)) == SYMBOL_REF)
88518334Speter	{
88618334Speter	  PUT_SDB_DEF (name);
88718334Speter	  if (TREE_PUBLIC (decl))
88818334Speter	    {
88918334Speter	      PUT_SDB_VAL (XEXP (value, 0));
89018334Speter              PUT_SDB_SCL (C_EXT);
89118334Speter	    }
89218334Speter	  else
89318334Speter	    {
89418334Speter	      PUT_SDB_VAL (XEXP (value, 0));
89518334Speter              PUT_SDB_SCL (C_STAT);
89618334Speter	    }
89718334Speter	}
89818334Speter      else if (regno >= 0)
89918334Speter	{
90018334Speter	  PUT_SDB_DEF (name);
90118334Speter	  PUT_SDB_INT_VAL (DBX_REGISTER_NUMBER (regno));
90218334Speter	  PUT_SDB_SCL (C_REG);
90318334Speter	}
90418334Speter      else if (GET_CODE (value) == MEM
90518334Speter	       && (GET_CODE (XEXP (value, 0)) == MEM
90618334Speter		   || (GET_CODE (XEXP (value, 0)) == REG
90718334Speter		       && REGNO (XEXP (value, 0)) != HARD_FRAME_POINTER_REGNUM
90818334Speter		       && REGNO (XEXP (value, 0)) != STACK_POINTER_REGNUM)))
90918334Speter	/* If the value is indirect by memory or by a register
91018334Speter	   that isn't the frame pointer
91118334Speter	   then it means the object is variable-sized and address through
91218334Speter	   that register or stack slot.  COFF has no way to represent this
91318334Speter	   so all we can do is output the variable as a pointer.  */
91418334Speter	{
91518334Speter	  PUT_SDB_DEF (name);
91618334Speter	  if (GET_CODE (XEXP (value, 0)) == REG)
91718334Speter	    {
91818334Speter	      PUT_SDB_INT_VAL (DBX_REGISTER_NUMBER (REGNO (XEXP (value, 0))));
91918334Speter	      PUT_SDB_SCL (C_REG);
92018334Speter	    }
92118334Speter	  else
92218334Speter	    {
92318334Speter	      /* DECL_RTL looks like (MEM (MEM (PLUS (REG...)
92418334Speter		 (CONST_INT...)))).
92518334Speter		 We want the value of that CONST_INT.  */
92618334Speter	      /* Encore compiler hates a newline in a macro arg, it seems.  */
92718334Speter	      PUT_SDB_INT_VAL (DEBUGGER_AUTO_OFFSET
92818334Speter			       (XEXP (XEXP (value, 0), 0)));
92918334Speter	      PUT_SDB_SCL (C_AUTO);
93018334Speter	    }
93118334Speter
93252284Sobrien	  /* Effectively do build_pointer_type, but don't cache this type,
93352284Sobrien	     since it might be temporary whereas the type it points to
93452284Sobrien	     might have been saved for inlining.  */
93552284Sobrien	  /* Don't use REFERENCE_TYPE because dbx can't handle that.  */
93652284Sobrien	  type = make_node (POINTER_TYPE);
93752284Sobrien	  TREE_TYPE (type) = TREE_TYPE (decl);
93818334Speter	}
93918334Speter      else if (GET_CODE (value) == MEM
94018334Speter	       && ((GET_CODE (XEXP (value, 0)) == PLUS
94118334Speter		    && GET_CODE (XEXP (XEXP (value, 0), 0)) == REG
94218334Speter		    && GET_CODE (XEXP (XEXP (value, 0), 1)) == CONST_INT)
94318334Speter		   /* This is for variables which are at offset zero from
94418334Speter		      the frame pointer.  This happens on the Alpha.
94518334Speter		      Non-frame pointer registers are excluded above.  */
94618334Speter		   || (GET_CODE (XEXP (value, 0)) == REG)))
94718334Speter	{
94818334Speter	  /* DECL_RTL looks like (MEM (PLUS (REG...) (CONST_INT...)))
94918334Speter	     or (MEM (REG...)).  We want the value of that CONST_INT
95018334Speter	     or zero.  */
95118334Speter	  PUT_SDB_DEF (name);
95218334Speter	  PUT_SDB_INT_VAL (DEBUGGER_AUTO_OFFSET (XEXP (value, 0)));
95318334Speter	  PUT_SDB_SCL (C_AUTO);
95418334Speter	}
95518334Speter      else if (GET_CODE (value) == MEM && GET_CODE (XEXP (value, 0)) == CONST)
95618334Speter	{
95718334Speter	  /* Handle an obscure case which can arise when optimizing and
95818334Speter	     when there are few available registers.  (This is *always*
95918334Speter	     the case for i386/i486 targets).  The DECL_RTL looks like
96018334Speter	     (MEM (CONST ...)) even though this variable is a local `auto'
96118334Speter	     or a local `register' variable.  In effect, what has happened
96218334Speter	     is that the reload pass has seen that all assignments and
96318334Speter	     references for one such a local variable can be replaced by
96418334Speter	     equivalent assignments and references to some static storage
96518334Speter	     variable, thereby avoiding the need for a register.  In such
96618334Speter	     cases we're forced to lie to debuggers and tell them that
96718334Speter	     this variable was itself `static'.  */
96818334Speter	  PUT_SDB_DEF (name);
96918334Speter	  PUT_SDB_VAL (XEXP (XEXP (value, 0), 0));
97018334Speter	  PUT_SDB_SCL (C_STAT);
97118334Speter	}
97218334Speter      else
97318334Speter	{
97418334Speter	  /* It is something we don't know how to represent for SDB.  */
97518334Speter	  return;
97618334Speter	}
97718334Speter      break;
97850397Sobrien
97950397Sobrien    default:
98050397Sobrien      break;
98118334Speter    }
98218334Speter  PUT_SDB_TYPE (plain_type (type));
98318334Speter  PUT_SDB_ENDEF;
98418334Speter}
98518334Speter
98618334Speter/* Output SDB information for a top-level initialized variable
98718334Speter   that has been delayed.  */
98818334Speter
98918334Spetervoid
99018334Spetersdbout_toplevel_data (decl)
99118334Speter     tree decl;
99218334Speter{
99318334Speter  tree type = TREE_TYPE (decl);
99418334Speter
99518334Speter  if (DECL_IGNORED_P (decl))
99618334Speter    return;
99718334Speter
99818334Speter  if (! (TREE_CODE (decl) == VAR_DECL
99918334Speter	 && GET_CODE (DECL_RTL (decl)) == MEM
100018334Speter	 && DECL_INITIAL (decl)))
100118334Speter    abort ();
100218334Speter
100318334Speter  PUT_SDB_DEF (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
100418334Speter  PUT_SDB_VAL (XEXP (DECL_RTL (decl), 0));
100518334Speter  if (TREE_PUBLIC (decl))
100618334Speter    {
100718334Speter      PUT_SDB_SCL (C_EXT);
100818334Speter    }
100918334Speter  else
101018334Speter    {
101118334Speter      PUT_SDB_SCL (C_STAT);
101218334Speter    }
101318334Speter  PUT_SDB_TYPE (plain_type (type));
101418334Speter  PUT_SDB_ENDEF;
101518334Speter}
101618334Speter
101718334Speter#ifdef SDB_ALLOW_FORWARD_REFERENCES
101818334Speter
101950397Sobrien/* Machinery to record and output anonymous types.  */
102018334Speter
102118334Speterstatic tree anonymous_types;
102218334Speter
102318334Speterstatic void
102418334Spetersdbout_queue_anonymous_type (type)
102518334Speter     tree type;
102618334Speter{
102718334Speter  anonymous_types = saveable_tree_cons (NULL_TREE, type, anonymous_types);
102818334Speter}
102918334Speter
103018334Speterstatic void
103118334Spetersdbout_dequeue_anonymous_types ()
103218334Speter{
103318334Speter  register tree types, link;
103418334Speter
103518334Speter  while (anonymous_types)
103618334Speter    {
103718334Speter      types = nreverse (anonymous_types);
103818334Speter      anonymous_types = NULL_TREE;
103918334Speter
104018334Speter      for (link = types; link; link = TREE_CHAIN (link))
104118334Speter	{
104218334Speter	  register tree type = TREE_VALUE (link);
104318334Speter
104418334Speter	  if (type && ! TREE_ASM_WRITTEN (type))
104518334Speter	    sdbout_one_type (type);
104618334Speter	}
104718334Speter    }
104818334Speter}
104918334Speter
105018334Speter#endif
105118334Speter
105218334Speter/* Given a chain of ..._TYPE nodes, all of which have names,
105318334Speter   output definitions of those names, as typedefs.  */
105418334Speter
105518334Spetervoid
105618334Spetersdbout_types (types)
105718334Speter     register tree types;
105818334Speter{
105918334Speter  register tree link;
106018334Speter
106118334Speter  for (link = types; link; link = TREE_CHAIN (link))
106218334Speter    sdbout_one_type (link);
106318334Speter
106418334Speter#ifdef SDB_ALLOW_FORWARD_REFERENCES
106518334Speter  sdbout_dequeue_anonymous_types ();
106618334Speter#endif
106718334Speter}
106818334Speter
106918334Speterstatic void
107018334Spetersdbout_type (type)
107118334Speter     tree type;
107218334Speter{
107318334Speter  if (type == error_mark_node)
107418334Speter    type = integer_type_node;
107518334Speter  PUT_SDB_TYPE (plain_type (type));
107618334Speter}
107718334Speter
107818334Speter/* Output types of the fields of type TYPE, if they are structs.
107918334Speter
108018334Speter   Formerly did not chase through pointer types, since that could be circular.
108118334Speter   They must come before TYPE, since forward refs are not allowed.
108218334Speter   Now james@bigtex.cactus.org says to try them.  */
108318334Speter
108418334Speterstatic void
108518334Spetersdbout_field_types (type)
108618334Speter     tree type;
108718334Speter{
108818334Speter  tree tail;
108950397Sobrien
109018334Speter  for (tail = TYPE_FIELDS (type); tail; tail = TREE_CHAIN (tail))
109152284Sobrien    /* This condition should match the one for emitting the actual members
109252284Sobrien       below.  */
109352284Sobrien    if (TREE_CODE (tail) == FIELD_DECL
109452284Sobrien	&& DECL_NAME (tail) != 0
109552284Sobrien	&& TREE_CODE (DECL_SIZE (tail)) == INTEGER_CST
109652284Sobrien	&& TREE_CODE (DECL_FIELD_BITPOS (tail)) == INTEGER_CST)
109752284Sobrien      {
109852284Sobrien	if (POINTER_TYPE_P (TREE_TYPE (tail)))
109952284Sobrien	  sdbout_one_type (TREE_TYPE (TREE_TYPE (tail)));
110052284Sobrien	else
110152284Sobrien	  sdbout_one_type (TREE_TYPE (tail));
110252284Sobrien      }
110318334Speter}
110418334Speter
110518334Speter/* Use this to put out the top level defined record and union types
110618334Speter   for later reference.  If this is a struct with a name, then put that
110718334Speter   name out.  Other unnamed structs will have .xxfake labels generated so
110818334Speter   that they may be referred to later.
110918334Speter   The label will be stored in the KNOWN_TYPE_TAG slot of a type.
111018334Speter   It may NOT be called recursively.  */
111118334Speter
111218334Speterstatic void
111318334Spetersdbout_one_type (type)
111418334Speter     tree type;
111518334Speter{
111618334Speter  if (current_function_decl != NULL_TREE
111718334Speter      && DECL_SECTION_NAME (current_function_decl) != NULL_TREE)
111818334Speter    ; /* Don't change section amid function.  */
111918334Speter  else
112018334Speter    text_section ();
112118334Speter
112218334Speter  switch (TREE_CODE (type))
112318334Speter    {
112418334Speter    case RECORD_TYPE:
112518334Speter    case UNION_TYPE:
112618334Speter    case QUAL_UNION_TYPE:
112718334Speter    case ENUMERAL_TYPE:
112818334Speter      type = TYPE_MAIN_VARIANT (type);
112918334Speter      /* Don't output a type twice.  */
113018334Speter      if (TREE_ASM_WRITTEN (type))
113118334Speter	/* James said test TREE_ASM_BEING_WRITTEN here.  */
113218334Speter	return;
113318334Speter
113418334Speter      /* Output nothing if type is not yet defined.  */
113518334Speter      if (TYPE_SIZE (type) == 0)
113618334Speter	return;
113718334Speter
113818334Speter      TREE_ASM_WRITTEN (type) = 1;
113918334Speter#if 1
114018334Speter      /* This is reputed to cause trouble with the following case,
114118334Speter	 but perhaps checking TYPE_SIZE above will fix it.  */
114218334Speter
114318334Speter      /* Here is a test case:
114418334Speter
114518334Speter	struct foo {
114618334Speter	  struct badstr *bbb;
114718334Speter	} forwardref;
114818334Speter
114918334Speter	typedef struct intermediate {
115018334Speter	  int aaaa;
115118334Speter	} intermediate_ref;
115218334Speter
115318334Speter	typedef struct badstr {
115418334Speter	  int ccccc;
115518334Speter	} badtype;   */
115618334Speter
115718334Speter#if 0
115818334Speter      TREE_ASM_BEING_WRITTEN (type) = 1;
115918334Speter#endif
116018334Speter      /* This change, which ought to make better output,
116118334Speter	 used to make the COFF assembler unhappy.
116218334Speter	 Changes involving KNOWN_TYPE_TAG may fix the problem.  */
116318334Speter      /* Before really doing anything, output types we want to refer to.  */
116418334Speter      /* Note that in version 1 the following two lines
116518334Speter	 are not used if forward references are in use.  */
116618334Speter      if (TREE_CODE (type) != ENUMERAL_TYPE)
116718334Speter	sdbout_field_types (type);
116818334Speter#if 0
116918334Speter      TREE_ASM_WRITTEN (type) = 1;
117018334Speter#endif
117118334Speter#endif
117218334Speter
117318334Speter      /* Output a structure type.  */
117418334Speter      {
117518334Speter	int size = int_size_in_bytes (type);
117618334Speter	int member_scl;
117718334Speter	tree tem;
117818334Speter	int i, n_baseclasses = 0;
117918334Speter
118018334Speter	/* Record the type tag, but not in its permanent place just yet.  */
118118334Speter	sdbout_record_type_name (type);
118218334Speter
118318334Speter	PUT_SDB_DEF (KNOWN_TYPE_TAG (type));
118418334Speter
118518334Speter	switch (TREE_CODE (type))
118618334Speter	  {
118718334Speter	  case UNION_TYPE:
118818334Speter	  case QUAL_UNION_TYPE:
118918334Speter	    PUT_SDB_SCL (C_UNTAG);
119018334Speter	    PUT_SDB_TYPE (T_UNION);
119118334Speter	    member_scl = C_MOU;
119218334Speter	    break;
119318334Speter
119418334Speter	  case RECORD_TYPE:
119518334Speter	    PUT_SDB_SCL (C_STRTAG);
119618334Speter	    PUT_SDB_TYPE (T_STRUCT);
119718334Speter	    member_scl = C_MOS;
119818334Speter	    break;
119918334Speter
120018334Speter	  case ENUMERAL_TYPE:
120118334Speter	    PUT_SDB_SCL (C_ENTAG);
120218334Speter	    PUT_SDB_TYPE (T_ENUM);
120318334Speter	    member_scl = C_MOE;
120418334Speter	    break;
120550397Sobrien
120650397Sobrien	  default:
120750397Sobrien	    break;
120818334Speter	  }
120918334Speter
121018334Speter	PUT_SDB_SIZE (size);
121118334Speter	PUT_SDB_ENDEF;
121218334Speter
121318334Speter	/* Print out the base class information with fields
121418334Speter	   named after the types they hold.  */
121552284Sobrien	/* This is only relevent to aggregate types.  TYPE_BINFO is used
121652284Sobrien	   for other purposes in an ENUMERAL_TYPE, so we must exclude that
121752284Sobrien	   case.  */
121852284Sobrien	if (TREE_CODE (type) != ENUMERAL_TYPE)
121918334Speter	  {
122052284Sobrien	    if (TYPE_BINFO (type)
122152284Sobrien		&& TYPE_BINFO_BASETYPES (type))
122252284Sobrien	      n_baseclasses = TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (type));
122352284Sobrien	    for (i = 0; i < n_baseclasses; i++)
122418334Speter	      {
122552284Sobrien		tree child = TREE_VEC_ELT (BINFO_BASETYPES (TYPE_BINFO (type)),
122652284Sobrien					   i);
122752284Sobrien		tree child_type = BINFO_TYPE (child);
122852284Sobrien		tree child_type_name;
122952284Sobrien		if (TYPE_NAME (child_type) == 0)
123052284Sobrien		  continue;
123152284Sobrien		if (TREE_CODE (TYPE_NAME (child_type)) == IDENTIFIER_NODE)
123252284Sobrien		  child_type_name = TYPE_NAME (child_type);
123352284Sobrien		else if (TREE_CODE (TYPE_NAME (child_type)) == TYPE_DECL)
123452284Sobrien		  {
123552284Sobrien		    child_type_name = DECL_NAME (TYPE_NAME (child_type));
123652284Sobrien		    if (child_type_name && template_name_p (child_type_name))
123752284Sobrien		      child_type_name
123852284Sobrien			= DECL_ASSEMBLER_NAME (TYPE_NAME (child_type));
123952284Sobrien		  }
124052284Sobrien		else
124152284Sobrien		  continue;
124252284Sobrien
124352284Sobrien		CONTIN;
124452284Sobrien		PUT_SDB_DEF (IDENTIFIER_POINTER (child_type_name));
124552284Sobrien		PUT_SDB_INT_VAL (TREE_INT_CST_LOW (BINFO_OFFSET (child)));
124652284Sobrien		PUT_SDB_SCL (member_scl);
124752284Sobrien		sdbout_type (BINFO_TYPE (child));
124852284Sobrien		PUT_SDB_ENDEF;
124918334Speter	      }
125018334Speter	  }
125118334Speter
125218334Speter	/* output the individual fields */
125318334Speter
125418334Speter	if (TREE_CODE (type) == ENUMERAL_TYPE)
125518334Speter	  for (tem = TYPE_FIELDS (type); tem; tem = TREE_CHAIN (tem))
125618334Speter	    {
125718334Speter	      PUT_SDB_DEF (IDENTIFIER_POINTER (TREE_PURPOSE (tem)));
125818334Speter	      PUT_SDB_INT_VAL (TREE_INT_CST_LOW (TREE_VALUE (tem)));
125918334Speter	      PUT_SDB_SCL (C_MOE);
126018334Speter	      PUT_SDB_TYPE (T_MOE);
126118334Speter	      PUT_SDB_ENDEF;
126218334Speter	    }
126318334Speter
126418334Speter	else			/* record or union type */
126518334Speter	  for (tem = TYPE_FIELDS (type); tem; tem = TREE_CHAIN (tem))
126618334Speter	    /* Output the name, type, position (in bits), size (in bits)
126718334Speter	       of each field.  */
126818334Speter
126918334Speter	    /* Omit here the nameless fields that are used to skip bits.
127018334Speter	       Also omit fields with variable size or position.
127118334Speter	       Also omit non FIELD_DECL nodes that GNU C++ may put here.  */
127218334Speter	    if (TREE_CODE (tem) == FIELD_DECL
127318334Speter		&& DECL_NAME (tem) != 0
127418334Speter		&& TREE_CODE (DECL_SIZE (tem)) == INTEGER_CST
127518334Speter		&& TREE_CODE (DECL_FIELD_BITPOS (tem)) == INTEGER_CST)
127618334Speter	      {
127718334Speter		char *name;
127818334Speter
127918334Speter		CONTIN;
128018334Speter		name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (tem));
128118334Speter		PUT_SDB_DEF (name);
128218334Speter		if (DECL_BIT_FIELD_TYPE (tem))
128318334Speter		  {
128418334Speter		    PUT_SDB_INT_VAL (TREE_INT_CST_LOW (DECL_FIELD_BITPOS (tem)));
128518334Speter		    PUT_SDB_SCL (C_FIELD);
128618334Speter		    sdbout_type (DECL_BIT_FIELD_TYPE (tem));
128718334Speter		    PUT_SDB_SIZE (TREE_INT_CST_LOW (DECL_SIZE (tem)));
128818334Speter		  }
128918334Speter		else
129018334Speter		  {
129118334Speter		    PUT_SDB_INT_VAL (TREE_INT_CST_LOW (DECL_FIELD_BITPOS (tem))
129218334Speter				     / BITS_PER_UNIT);
129318334Speter		    PUT_SDB_SCL (member_scl);
129418334Speter		    sdbout_type (TREE_TYPE (tem));
129518334Speter		  }
129618334Speter		PUT_SDB_ENDEF;
129718334Speter	      }
129818334Speter	/* output end of a structure,union, or enumeral definition */
129918334Speter
130018334Speter	PUT_SDB_PLAIN_DEF ("eos");
130118334Speter	PUT_SDB_INT_VAL (size);
130218334Speter	PUT_SDB_SCL (C_EOS);
130318334Speter	PUT_SDB_TAG (KNOWN_TYPE_TAG (type));
130418334Speter	PUT_SDB_SIZE (size);
130518334Speter	PUT_SDB_ENDEF;
130618334Speter	break;
130750397Sobrien
130850397Sobrien      default:
130950397Sobrien	break;
131018334Speter      }
131118334Speter    }
131218334Speter}
131318334Speter
131418334Speter/* The following two functions output definitions of function parameters.
131518334Speter   Each parameter gets a definition locating it in the parameter list.
131618334Speter   Each parameter that is a register variable gets a second definition
131718334Speter   locating it in the register.
131818334Speter
131918334Speter   Printing or argument lists in gdb uses the definitions that
132018334Speter   locate in the parameter list.  But reference to the variable in
132118334Speter   expressions uses preferentially the definition as a register.  */
132218334Speter
132318334Speter/* Output definitions, referring to storage in the parmlist,
132418334Speter   of all the parms in PARMS, which is a chain of PARM_DECL nodes.  */
132518334Speter
132618334Speterstatic void
132718334Spetersdbout_parms (parms)
132818334Speter     tree parms;
132918334Speter{
133018334Speter  for (; parms; parms = TREE_CHAIN (parms))
133118334Speter    if (DECL_NAME (parms))
133218334Speter      {
133318334Speter	int current_sym_value = 0;
133418334Speter	char *name = IDENTIFIER_POINTER (DECL_NAME (parms));
133518334Speter
133618334Speter	if (name == 0 || *name == 0)
133718334Speter	  name = gen_fake_label ();
133818334Speter
133918334Speter	/* Perform any necessary register eliminations on the parameter's rtl,
134018334Speter	   so that the debugging output will be accurate.  */
134150397Sobrien	DECL_INCOMING_RTL (parms)
134250397Sobrien	  = eliminate_regs (DECL_INCOMING_RTL (parms), 0, NULL_RTX);
134318334Speter	DECL_RTL (parms) = eliminate_regs (DECL_RTL (parms), 0, NULL_RTX);
134418334Speter
134518334Speter	if (PARM_PASSED_IN_MEMORY (parms))
134618334Speter	  {
134718334Speter	    rtx addr = XEXP (DECL_INCOMING_RTL (parms), 0);
134818334Speter	    tree type;
134918334Speter
135018334Speter	    /* ??? Here we assume that the parm address is indexed
135118334Speter	       off the frame pointer or arg pointer.
135218334Speter	       If that is not true, we produce meaningless results,
135318334Speter	       but do not crash.  */
135418334Speter	    if (GET_CODE (addr) == PLUS
135518334Speter		&& GET_CODE (XEXP (addr, 1)) == CONST_INT)
135618334Speter	      current_sym_value = INTVAL (XEXP (addr, 1));
135718334Speter	    else
135818334Speter	      current_sym_value = 0;
135918334Speter
136018334Speter	    if (GET_CODE (DECL_RTL (parms)) == REG
136118334Speter		&& REGNO (DECL_RTL (parms)) >= 0
136218334Speter		&& REGNO (DECL_RTL (parms)) < FIRST_PSEUDO_REGISTER)
136318334Speter	      type = DECL_ARG_TYPE (parms);
136418334Speter	    else
136518334Speter	      {
136618334Speter		int original_sym_value = current_sym_value;
136718334Speter
136818334Speter		/* This is the case where the parm is passed as an int or
136918334Speter		   double and it is converted to a char, short or float
137018334Speter		   and stored back in the parmlist.  In this case, describe
137118334Speter		   the parm with the variable's declared type, and adjust
137218334Speter		   the address if the least significant bytes (which we are
137318334Speter		   using) are not the first ones.  */
137418334Speter		if (BYTES_BIG_ENDIAN
137518334Speter		    && TREE_TYPE (parms) != DECL_ARG_TYPE (parms))
137618334Speter		  current_sym_value +=
137718334Speter		    (GET_MODE_SIZE (TYPE_MODE (DECL_ARG_TYPE (parms)))
137818334Speter		     - GET_MODE_SIZE (GET_MODE (DECL_RTL (parms))));
137918334Speter
138018334Speter		if (GET_CODE (DECL_RTL (parms)) == MEM
138118334Speter		    && GET_CODE (XEXP (DECL_RTL (parms), 0)) == PLUS
138218334Speter		    && (GET_CODE (XEXP (XEXP (DECL_RTL (parms), 0), 1))
138318334Speter			== CONST_INT)
138418334Speter		    && (INTVAL (XEXP (XEXP (DECL_RTL (parms), 0), 1))
138518334Speter			== current_sym_value))
138618334Speter		  type = TREE_TYPE (parms);
138718334Speter		else
138818334Speter		  {
138918334Speter		    current_sym_value = original_sym_value;
139018334Speter		    type = DECL_ARG_TYPE (parms);
139118334Speter		  }
139218334Speter	      }
139318334Speter
139418334Speter	    PUT_SDB_DEF (name);
139518334Speter	    PUT_SDB_INT_VAL (DEBUGGER_ARG_OFFSET (current_sym_value, addr));
139618334Speter	    PUT_SDB_SCL (C_ARG);
139718334Speter	    PUT_SDB_TYPE (plain_type (type));
139818334Speter	    PUT_SDB_ENDEF;
139918334Speter	  }
140018334Speter	else if (GET_CODE (DECL_RTL (parms)) == REG)
140118334Speter	  {
140218334Speter	    rtx best_rtl;
140318334Speter	    /* Parm passed in registers and lives in registers or nowhere.  */
140418334Speter
140518334Speter	    /* If parm lives in a register, use that register;
140618334Speter	       pretend the parm was passed there.  It would be more consistent
140718334Speter	       to describe the register where the parm was passed,
140818334Speter	       but in practice that register usually holds something else.  */
140918334Speter	    if (REGNO (DECL_RTL (parms)) >= 0
141018334Speter		&& REGNO (DECL_RTL (parms)) < FIRST_PSEUDO_REGISTER)
141118334Speter	      best_rtl = DECL_RTL (parms);
141218334Speter	    /* If the parm lives nowhere,
141318334Speter	       use the register where it was passed.  */
141418334Speter	    else
141518334Speter	      best_rtl = DECL_INCOMING_RTL (parms);
141618334Speter
141718334Speter	    PUT_SDB_DEF (name);
141818334Speter	    PUT_SDB_INT_VAL (DBX_REGISTER_NUMBER (REGNO (best_rtl)));
141918334Speter	    PUT_SDB_SCL (C_REGPARM);
142050397Sobrien	    PUT_SDB_TYPE (plain_type (TREE_TYPE (parms)));
142118334Speter	    PUT_SDB_ENDEF;
142218334Speter	  }
142318334Speter	else if (GET_CODE (DECL_RTL (parms)) == MEM
142418334Speter		 && XEXP (DECL_RTL (parms), 0) != const0_rtx)
142518334Speter	  {
142618334Speter	    /* Parm was passed in registers but lives on the stack.  */
142718334Speter
142818334Speter	    /* DECL_RTL looks like (MEM (PLUS (REG...) (CONST_INT...))),
142918334Speter	       in which case we want the value of that CONST_INT,
143018334Speter	       or (MEM (REG ...)) or (MEM (MEM ...)),
143118334Speter	       in which case we use a value of zero.  */
143218334Speter	    if (GET_CODE (XEXP (DECL_RTL (parms), 0)) == REG
143318334Speter		|| GET_CODE (XEXP (DECL_RTL (parms), 0)) == MEM)
143418334Speter	      current_sym_value = 0;
143518334Speter	    else
143618334Speter	      current_sym_value = INTVAL (XEXP (XEXP (DECL_RTL (parms), 0), 1));
143718334Speter
143818334Speter	    /* Again, this assumes the offset is based on the arg pointer.  */
143918334Speter	    PUT_SDB_DEF (name);
144018334Speter	    PUT_SDB_INT_VAL (DEBUGGER_ARG_OFFSET (current_sym_value,
144118334Speter						  XEXP (DECL_RTL (parms), 0)));
144218334Speter	    PUT_SDB_SCL (C_ARG);
144350397Sobrien	    PUT_SDB_TYPE (plain_type (TREE_TYPE (parms)));
144418334Speter	    PUT_SDB_ENDEF;
144518334Speter	  }
144618334Speter      }
144718334Speter}
144818334Speter
144918334Speter/* Output definitions for the places where parms live during the function,
145018334Speter   when different from where they were passed, when the parms were passed
145118334Speter   in memory.
145218334Speter
145318334Speter   It is not useful to do this for parms passed in registers
145418334Speter   that live during the function in different registers, because it is
145518334Speter   impossible to look in the passed register for the passed value,
145618334Speter   so we use the within-the-function register to begin with.
145718334Speter
145818334Speter   PARMS is a chain of PARM_DECL nodes.  */
145918334Speter
146018334Speterstatic void
146118334Spetersdbout_reg_parms (parms)
146218334Speter     tree parms;
146318334Speter{
146418334Speter  for (; parms; parms = TREE_CHAIN (parms))
146518334Speter    if (DECL_NAME (parms))
146618334Speter      {
146718334Speter	char *name = IDENTIFIER_POINTER (DECL_NAME (parms));
146818334Speter
146918334Speter	/* Report parms that live in registers during the function
147018334Speter	   but were passed in memory.  */
147118334Speter	if (GET_CODE (DECL_RTL (parms)) == REG
147218334Speter	    && REGNO (DECL_RTL (parms)) >= 0
147318334Speter	    && REGNO (DECL_RTL (parms)) < FIRST_PSEUDO_REGISTER
147418334Speter	    && PARM_PASSED_IN_MEMORY (parms))
147518334Speter	  {
147618334Speter	    if (name == 0 || *name == 0)
147718334Speter	      name = gen_fake_label ();
147818334Speter	    PUT_SDB_DEF (name);
147918334Speter	    PUT_SDB_INT_VAL (DBX_REGISTER_NUMBER (REGNO (DECL_RTL (parms))));
148018334Speter	    PUT_SDB_SCL (C_REG);
148150397Sobrien	    PUT_SDB_TYPE (plain_type (TREE_TYPE (parms)));
148218334Speter	    PUT_SDB_ENDEF;
148318334Speter	  }
148418334Speter	/* Report parms that live in memory but not where they were passed.  */
148518334Speter	else if (GET_CODE (DECL_RTL (parms)) == MEM
148618334Speter		 && GET_CODE (XEXP (DECL_RTL (parms), 0)) == PLUS
148718334Speter		 && GET_CODE (XEXP (XEXP (DECL_RTL (parms), 0), 1)) == CONST_INT
148818334Speter		 && PARM_PASSED_IN_MEMORY (parms)
148918334Speter		 && ! rtx_equal_p (DECL_RTL (parms), DECL_INCOMING_RTL (parms)))
149018334Speter	  {
149118334Speter#if 0 /* ??? It is not clear yet what should replace this.  */
149218334Speter	    int offset = DECL_OFFSET (parms) / BITS_PER_UNIT;
149318334Speter	    /* A parm declared char is really passed as an int,
149418334Speter	       so it occupies the least significant bytes.
149518334Speter	       On a big-endian machine those are not the low-numbered ones.  */
149618334Speter	    if (BYTES_BIG_ENDIAN
149718334Speter		&& offset != -1
149818334Speter		&& TREE_TYPE (parms) != DECL_ARG_TYPE (parms))
149918334Speter	      offset += (GET_MODE_SIZE (TYPE_MODE (DECL_ARG_TYPE (parms)))
150018334Speter			 - GET_MODE_SIZE (GET_MODE (DECL_RTL (parms))));
150118334Speter	    if (INTVAL (XEXP (XEXP (DECL_RTL (parms), 0), 1)) != offset) {...}
150218334Speter#endif
150318334Speter	      {
150418334Speter		if (name == 0 || *name == 0)
150518334Speter		  name = gen_fake_label ();
150618334Speter		PUT_SDB_DEF (name);
150718334Speter		PUT_SDB_INT_VAL (DEBUGGER_AUTO_OFFSET
150818334Speter				 (XEXP (DECL_RTL (parms), 0)));
150918334Speter		PUT_SDB_SCL (C_AUTO);
151018334Speter		PUT_SDB_TYPE (plain_type (TREE_TYPE (parms)));
151118334Speter		PUT_SDB_ENDEF;
151218334Speter	      }
151318334Speter	  }
151418334Speter      }
151518334Speter}
151618334Speter
151718334Speter/* Describe the beginning of an internal block within a function.
151818334Speter   Also output descriptions of variables defined in this block.
151918334Speter
152018334Speter   N is the number of the block, by order of beginning, counting from 1,
152118334Speter   and not counting the outermost (function top-level) block.
152218334Speter   The blocks match the BLOCKs in DECL_INITIAL (current_function_decl),
152318334Speter   if the count starts at 0 for the outermost one.  */
152418334Speter
152518334Spetervoid
152618334Spetersdbout_begin_block (file, line, n)
152718334Speter     FILE *file;
152818334Speter     int line;
152918334Speter     int n;
153018334Speter{
153118334Speter  tree decl = current_function_decl;
153218334Speter  MAKE_LINE_SAFE (line);
153318334Speter
153418334Speter  /* The SCO compiler does not emit a separate block for the function level
153518334Speter     scope, so we avoid it here also.  However, mips ECOFF compilers do emit
153618334Speter     a separate block, so we retain it when MIPS_DEBUGGING_INFO is defined.  */
153718334Speter#ifndef MIPS_DEBUGGING_INFO
153818334Speter  if (n != 1)
153918334Speter#endif
154018334Speter    PUT_SDB_BLOCK_START (line - sdb_begin_function_line);
154118334Speter
154218334Speter  if (n == 1)
154318334Speter    {
154418334Speter      /* Include the outermost BLOCK's variables in block 1.  */
154518334Speter      next_block_number = 0;
154618334Speter      do_block = 0;
154718334Speter      sdbout_block (DECL_INITIAL (decl));
154818334Speter    }
154918334Speter  /* If -g1, suppress all the internal symbols of functions
155018334Speter     except for arguments.  */
155118334Speter  if (debug_info_level != DINFO_LEVEL_TERSE)
155218334Speter    {
155318334Speter      next_block_number = 0;
155418334Speter      do_block = n;
155518334Speter      sdbout_block (DECL_INITIAL (decl));
155618334Speter    }
155718334Speter
155818334Speter#ifdef SDB_ALLOW_FORWARD_REFERENCES
155918334Speter  sdbout_dequeue_anonymous_types ();
156018334Speter#endif
156118334Speter}
156218334Speter
156318334Speter/* Describe the end line-number of an internal block within a function.  */
156418334Speter
156518334Spetervoid
156618334Spetersdbout_end_block (file, line, n)
156718334Speter     FILE *file;
156818334Speter     int line;
156952284Sobrien     int n ATTRIBUTE_UNUSED;
157018334Speter{
157118334Speter  MAKE_LINE_SAFE (line);
157218334Speter
157318334Speter  /* The SCO compiler does not emit a separate block for the function level
157418334Speter     scope, so we avoid it here also.  However, mips ECOFF compilers do emit
157518334Speter     a separate block, so we retain it when MIPS_DEBUGGING_INFO is defined.  */
157618334Speter#ifndef MIPS_DEBUGGING_INFO
157718334Speter  if (n != 1)
157818334Speter#endif
157918334Speter  PUT_SDB_BLOCK_END (line - sdb_begin_function_line);
158018334Speter}
158118334Speter
158218334Speter/* Output sdb info for the current function name.
158318334Speter   Called from assemble_start_function.  */
158418334Speter
158518334Spetervoid
158618334Spetersdbout_mark_begin_function ()
158718334Speter{
158818334Speter  sdbout_symbol (current_function_decl, 0);
158918334Speter}
159018334Speter
159118334Speter/* Called at beginning of function body (after prologue).
159218334Speter   Record the function's starting line number, so we can output
159318334Speter   relative line numbers for the other lines.
159418334Speter   Describe beginning of outermost block.
159518334Speter   Also describe the parameter list.  */
159618334Speter
159718334Spetervoid
159818334Spetersdbout_begin_function (line)
159918334Speter     int line;
160018334Speter{
160118334Speter  sdb_begin_function_line = line - 1;
160218334Speter  PUT_SDB_FUNCTION_START (line);
160318334Speter  sdbout_parms (DECL_ARGUMENTS (current_function_decl));
160418334Speter  sdbout_reg_parms (DECL_ARGUMENTS (current_function_decl));
160518334Speter}
160618334Speter
160718334Speter/* Called at end of function (before epilogue).
160818334Speter   Describe end of outermost block.  */
160918334Speter
161018334Spetervoid
161118334Spetersdbout_end_function (line)
161218334Speter     int line;
161318334Speter{
161418334Speter#ifdef SDB_ALLOW_FORWARD_REFERENCES
161518334Speter  sdbout_dequeue_anonymous_types ();
161618334Speter#endif
161718334Speter
161818334Speter  MAKE_LINE_SAFE (line);
161918334Speter  PUT_SDB_FUNCTION_END (line - sdb_begin_function_line);
162018334Speter
162118334Speter  /* Indicate we are between functions, for line-number output.  */
162218334Speter  sdb_begin_function_line = -1;
162318334Speter}
162418334Speter
162518334Speter/* Output sdb info for the absolute end of a function.
162618334Speter   Called after the epilogue is output.  */
162718334Speter
162818334Spetervoid
162918334Spetersdbout_end_epilogue ()
163018334Speter{
163118334Speter  char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl));
163218334Speter  PUT_SDB_EPILOGUE_END (name);
163318334Speter}
163418334Speter
163518334Speter/* Output sdb info for the given label.  Called only if LABEL_NAME (insn)
163618334Speter   is present.  */
163718334Speter
163818334Spetervoid
163918334Spetersdbout_label (insn)
164018334Speter     register rtx insn;
164118334Speter{
164218334Speter  PUT_SDB_DEF (LABEL_NAME (insn));
164318334Speter  PUT_SDB_VAL (insn);
164418334Speter  PUT_SDB_SCL (C_LABEL);
164518334Speter  PUT_SDB_TYPE (T_NULL);
164618334Speter  PUT_SDB_ENDEF;
164718334Speter}
164818334Speter
164950397Sobrien/* Change to reading from a new source file.  */
165050397Sobrien
165150397Sobrienvoid
165250397Sobriensdbout_start_new_source_file (filename)
165350397Sobrien     char *filename;
165450397Sobrien{
165550397Sobrien#ifdef MIPS_DEBUGGING_INFO
165650397Sobrien  struct sdb_file *n = (struct sdb_file *) xmalloc (sizeof *n);
165750397Sobrien
165850397Sobrien  n->next = current_file;
165950397Sobrien  n->name = filename;
166050397Sobrien  current_file = n;
166150397Sobrien  PUT_SDB_SRC_FILE (filename);
166250397Sobrien#endif
166350397Sobrien}
166450397Sobrien
166550397Sobrien/* Revert to reading a previous source file.  */
166650397Sobrien
166750397Sobrienvoid
166850397Sobriensdbout_resume_previous_source_file ()
166950397Sobrien{
167050397Sobrien#ifdef MIPS_DEBUGGING_INFO
167150397Sobrien  struct sdb_file *next;
167250397Sobrien
167350397Sobrien  next = current_file->next;
167450397Sobrien  free (current_file);
167550397Sobrien  current_file = next;
167650397Sobrien  PUT_SDB_SRC_FILE (current_file->name);
167750397Sobrien#endif
167850397Sobrien}
167950397Sobrien
168018334Speter#endif /* SDB_DEBUGGING_INFO */
1681