sdbout.c revision 18334
118334Speter/* Output sdb-format symbol table information from GNU compiler.
218334Speter   Copyright (C) 1988, 1992, 1993, 1994, 1995 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
4718334Speter#include "tree.h"
4818334Speter#include "rtl.h"
4918334Speter#include <stdio.h>
5018334Speter#include "regs.h"
5118334Speter#include "flags.h"
5218334Speter#include "insn-config.h"
5318334Speter#include "reload.h"
5418334Speter
5518334Speter/* Mips systems use the SDB functions to dump out symbols, but
5618334Speter   do not supply usable syms.h include files.  */
5718334Speter#if defined(USG) && !defined(MIPS) && !defined (hpux) && !defined(_WIN32) && !defined(__linux__)
5818334Speter#include <syms.h>
5918334Speter/* Use T_INT if we don't have T_VOID.  */
6018334Speter#ifndef T_VOID
6118334Speter#define T_VOID T_INT
6218334Speter#endif
6318334Speter#else /* not USG, or MIPS */
6418334Speter#include "gsyms.h"
6518334Speter#endif /* not USG, or MIPS */
6618334Speter
6718334Speter/* #include <storclass.h>  used to be this instead of syms.h.  */
6818334Speter
6918334Speter/* 1 if PARM is passed to this function in memory.  */
7018334Speter
7118334Speter#define PARM_PASSED_IN_MEMORY(PARM) \
7218334Speter (GET_CODE (DECL_INCOMING_RTL (PARM)) == MEM)
7318334Speter
7418334Speter/* A C expression for the integer offset value of an automatic variable
7518334Speter   (C_AUTO) having address X (an RTX).  */
7618334Speter#ifndef DEBUGGER_AUTO_OFFSET
7718334Speter#define DEBUGGER_AUTO_OFFSET(X) \
7818334Speter  (GET_CODE (X) == PLUS ? INTVAL (XEXP (X, 1)) : 0)
7918334Speter#endif
8018334Speter
8118334Speter/* A C expression for the integer offset value of an argument (C_ARG)
8218334Speter   having address X (an RTX).  The nominal offset is OFFSET.  */
8318334Speter#ifndef DEBUGGER_ARG_OFFSET
8418334Speter#define DEBUGGER_ARG_OFFSET(OFFSET, X) (OFFSET)
8518334Speter#endif
8618334Speter
8718334Speter/* Line number of beginning of current function, minus one.
8818334Speter   Negative means not in a function or not using sdb.  */
8918334Speter
9018334Speterint sdb_begin_function_line = -1;
9118334Speter
9218334Speter/* Counter to generate unique "names" for nameless struct members.  */
9318334Speter
9418334Speterstatic int unnamed_struct_number = 0;
9518334Speter
9618334Speterextern FILE *asm_out_file;
9718334Speter
9818334Speterextern tree current_function_decl;
9918334Speter
10018334Spetervoid sdbout_init ();
10118334Spetervoid sdbout_symbol ();
10218334Spetervoid sdbout_types();
10318334Speter
10418334Speterstatic void sdbout_typedefs ();
10518334Speterstatic void sdbout_syms ();
10618334Speterstatic void sdbout_one_type ();
10718334Speterstatic void sdbout_queue_anonymous_type ();
10818334Speterstatic void sdbout_dequeue_anonymous_types ();
10918334Speterstatic int plain_type_1 ();
11018334Speter
11118334Speter/* Define the default sizes for various types.  */
11218334Speter
11318334Speter#ifndef CHAR_TYPE_SIZE
11418334Speter#define CHAR_TYPE_SIZE BITS_PER_UNIT
11518334Speter#endif
11618334Speter
11718334Speter#ifndef SHORT_TYPE_SIZE
11818334Speter#define SHORT_TYPE_SIZE (BITS_PER_UNIT * MIN ((UNITS_PER_WORD + 1) / 2, 2))
11918334Speter#endif
12018334Speter
12118334Speter#ifndef INT_TYPE_SIZE
12218334Speter#define INT_TYPE_SIZE BITS_PER_WORD
12318334Speter#endif
12418334Speter
12518334Speter#ifndef LONG_TYPE_SIZE
12618334Speter#define LONG_TYPE_SIZE BITS_PER_WORD
12718334Speter#endif
12818334Speter
12918334Speter#ifndef LONG_LONG_TYPE_SIZE
13018334Speter#define LONG_LONG_TYPE_SIZE (BITS_PER_WORD * 2)
13118334Speter#endif
13218334Speter
13318334Speter#ifndef FLOAT_TYPE_SIZE
13418334Speter#define FLOAT_TYPE_SIZE BITS_PER_WORD
13518334Speter#endif
13618334Speter
13718334Speter#ifndef DOUBLE_TYPE_SIZE
13818334Speter#define DOUBLE_TYPE_SIZE (BITS_PER_WORD * 2)
13918334Speter#endif
14018334Speter
14118334Speter#ifndef LONG_DOUBLE_TYPE_SIZE
14218334Speter#define LONG_DOUBLE_TYPE_SIZE (BITS_PER_WORD * 2)
14318334Speter#endif
14418334Speter
14518334Speter/* Random macros describing parts of SDB data.  */
14618334Speter
14718334Speter/* Put something here if lines get too long */
14818334Speter#define CONTIN
14918334Speter
15018334Speter/* Default value of delimiter is ";".  */
15118334Speter#ifndef SDB_DELIM
15218334Speter#define SDB_DELIM	";"
15318334Speter#endif
15418334Speter
15518334Speter/* Maximum number of dimensions the assembler will allow.  */
15618334Speter#ifndef SDB_MAX_DIM
15718334Speter#define SDB_MAX_DIM 4
15818334Speter#endif
15918334Speter
16018334Speter#ifndef PUT_SDB_SCL
16118334Speter#define PUT_SDB_SCL(a) fprintf(asm_out_file, "\t.scl\t%d%s", (a), SDB_DELIM)
16218334Speter#endif
16318334Speter
16418334Speter#ifndef PUT_SDB_INT_VAL
16518334Speter#define PUT_SDB_INT_VAL(a) fprintf (asm_out_file, "\t.val\t%d%s", (a), SDB_DELIM)
16618334Speter#endif
16718334Speter
16818334Speter#ifndef PUT_SDB_VAL
16918334Speter#define PUT_SDB_VAL(a)				\
17018334Speter( fputs ("\t.val\t", asm_out_file),		\
17118334Speter  output_addr_const (asm_out_file, (a)),	\
17218334Speter  fprintf (asm_out_file, SDB_DELIM))
17318334Speter#endif
17418334Speter
17518334Speter#ifndef PUT_SDB_DEF
17618334Speter#define PUT_SDB_DEF(a)				\
17718334Speterdo { fprintf (asm_out_file, "\t.def\t");	\
17818334Speter     ASM_OUTPUT_LABELREF (asm_out_file, a); 	\
17918334Speter     fprintf (asm_out_file, SDB_DELIM); } while (0)
18018334Speter#endif
18118334Speter
18218334Speter#ifndef PUT_SDB_PLAIN_DEF
18318334Speter#define PUT_SDB_PLAIN_DEF(a) fprintf(asm_out_file,"\t.def\t.%s%s",a, SDB_DELIM)
18418334Speter#endif
18518334Speter
18618334Speter#ifndef PUT_SDB_ENDEF
18718334Speter#define PUT_SDB_ENDEF fputs("\t.endef\n", asm_out_file)
18818334Speter#endif
18918334Speter
19018334Speter#ifndef PUT_SDB_TYPE
19118334Speter#define PUT_SDB_TYPE(a) fprintf(asm_out_file, "\t.type\t0%o%s", a, SDB_DELIM)
19218334Speter#endif
19318334Speter
19418334Speter#ifndef PUT_SDB_SIZE
19518334Speter#define PUT_SDB_SIZE(a) fprintf(asm_out_file, "\t.size\t%d%s", a, SDB_DELIM)
19618334Speter#endif
19718334Speter
19818334Speter#ifndef PUT_SDB_START_DIM
19918334Speter#define PUT_SDB_START_DIM fprintf(asm_out_file, "\t.dim\t")
20018334Speter#endif
20118334Speter
20218334Speter#ifndef PUT_SDB_NEXT_DIM
20318334Speter#define PUT_SDB_NEXT_DIM(a) fprintf(asm_out_file, "%d,", a)
20418334Speter#endif
20518334Speter
20618334Speter#ifndef PUT_SDB_LAST_DIM
20718334Speter#define PUT_SDB_LAST_DIM(a) fprintf(asm_out_file, "%d%s", a, SDB_DELIM)
20818334Speter#endif
20918334Speter
21018334Speter#ifndef PUT_SDB_TAG
21118334Speter#define PUT_SDB_TAG(a)				\
21218334Speterdo { fprintf (asm_out_file, "\t.tag\t");	\
21318334Speter     ASM_OUTPUT_LABELREF (asm_out_file, a);	\
21418334Speter     fprintf (asm_out_file, SDB_DELIM); } while (0)
21518334Speter#endif
21618334Speter
21718334Speter#ifndef PUT_SDB_BLOCK_START
21818334Speter#define PUT_SDB_BLOCK_START(LINE)		\
21918334Speter  fprintf (asm_out_file,			\
22018334Speter	   "\t.def\t.bb%s\t.val\t.%s\t.scl\t100%s\t.line\t%d%s\t.endef\n", \
22118334Speter	   SDB_DELIM, SDB_DELIM, SDB_DELIM, (LINE), SDB_DELIM)
22218334Speter#endif
22318334Speter
22418334Speter#ifndef PUT_SDB_BLOCK_END
22518334Speter#define PUT_SDB_BLOCK_END(LINE)			\
22618334Speter  fprintf (asm_out_file,			\
22718334Speter	   "\t.def\t.eb%s\t.val\t.%s\t.scl\t100%s\t.line\t%d%s\t.endef\n",  \
22818334Speter	   SDB_DELIM, SDB_DELIM, SDB_DELIM, (LINE), SDB_DELIM)
22918334Speter#endif
23018334Speter
23118334Speter#ifndef PUT_SDB_FUNCTION_START
23218334Speter#define PUT_SDB_FUNCTION_START(LINE)		\
23318334Speter  fprintf (asm_out_file,			\
23418334Speter	   "\t.def\t.bf%s\t.val\t.%s\t.scl\t101%s\t.line\t%d%s\t.endef\n", \
23518334Speter	   SDB_DELIM, SDB_DELIM, SDB_DELIM, (LINE), SDB_DELIM)
23618334Speter#endif
23718334Speter
23818334Speter#ifndef PUT_SDB_FUNCTION_END
23918334Speter#define PUT_SDB_FUNCTION_END(LINE)		\
24018334Speter  fprintf (asm_out_file,			\
24118334Speter	   "\t.def\t.ef%s\t.val\t.%s\t.scl\t101%s\t.line\t%d%s\t.endef\n", \
24218334Speter	   SDB_DELIM, SDB_DELIM, SDB_DELIM, (LINE), SDB_DELIM)
24318334Speter#endif
24418334Speter
24518334Speter#ifndef PUT_SDB_EPILOGUE_END
24618334Speter#define PUT_SDB_EPILOGUE_END(NAME)			\
24718334Speterdo { fprintf (asm_out_file, "\t.def\t");		\
24818334Speter     ASM_OUTPUT_LABELREF (asm_out_file, NAME);		\
24918334Speter     fprintf (asm_out_file,				\
25018334Speter	      "%s\t.val\t.%s\t.scl\t-1%s\t.endef\n",	\
25118334Speter	      SDB_DELIM, SDB_DELIM, SDB_DELIM); } while (0)
25218334Speter#endif
25318334Speter
25418334Speter#ifndef SDB_GENERATE_FAKE
25518334Speter#define SDB_GENERATE_FAKE(BUFFER, NUMBER) \
25618334Speter  sprintf ((BUFFER), ".%dfake", (NUMBER));
25718334Speter#endif
25818334Speter
25918334Speter/* Return the sdb tag identifier string for TYPE
26018334Speter   if TYPE has already been defined; otherwise return a null pointer.   */
26118334Speter
26218334Speter#define KNOWN_TYPE_TAG(type)  TYPE_SYMTAB_POINTER (type)
26318334Speter
26418334Speter/* Set the sdb tag identifier string for TYPE to NAME.  */
26518334Speter
26618334Speter#define SET_KNOWN_TYPE_TAG(TYPE, NAME) \
26718334Speter  TYPE_SYMTAB_POINTER (TYPE) = (NAME)
26818334Speter
26918334Speter/* Return the name (a string) of the struct, union or enum tag
27018334Speter   described by the TREE_LIST node LINK.  This is 0 for an anonymous one.  */
27118334Speter
27218334Speter#define TAG_NAME(link) \
27318334Speter  (((link) && TREE_PURPOSE ((link)) \
27418334Speter    && IDENTIFIER_POINTER (TREE_PURPOSE ((link)))) \
27518334Speter   ? IDENTIFIER_POINTER (TREE_PURPOSE ((link))) : (char *) 0)
27618334Speter
27718334Speter/* Ensure we don't output a negative line number.  */
27818334Speter#define MAKE_LINE_SAFE(line)  \
27918334Speter  if (line <= sdb_begin_function_line) line = sdb_begin_function_line + 1
28018334Speter
28118334Speter/* Set up for SDB output at the start of compilation.  */
28218334Speter
28318334Spetervoid
28418334Spetersdbout_init (asm_file, input_file_name, syms)
28518334Speter     FILE *asm_file;
28618334Speter     char *input_file_name;
28718334Speter     tree syms;
28818334Speter{
28918334Speter#ifdef RMS_QUICK_HACK_1
29018334Speter  tree t;
29118334Speter  for (t = syms; t; t = TREE_CHAIN (t))
29218334Speter    if (DECL_NAME (t) && IDENTIFIER_POINTER (DECL_NAME (t)) != 0
29318334Speter	&& !strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__vtbl_ptr_type"))
29418334Speter      sdbout_symbol (t, 0);
29518334Speter#endif
29618334Speter
29718334Speter#if 0 /* Nothing need be output for the predefined types.  */
29818334Speter  /* Get all permanent types that have typedef names,
29918334Speter     and output them all, except for those already output.  */
30018334Speter
30118334Speter  sdbout_typedefs (syms);
30218334Speter#endif
30318334Speter}
30418334Speter
30518334Speter#if 0
30618334Speter
30718334Speter/* return the tag identifier for type
30818334Speter */
30918334Speter
31018334Speterchar *
31118334Spetertag_of_ru_type (type,link)
31218334Speter     tree type,link;
31318334Speter{
31418334Speter  if (TYPE_SYMTAB_ADDRESS (type))
31518334Speter    return TYPE_SYMTAB_ADDRESS (type);
31618334Speter  if (link && TREE_PURPOSE (link)
31718334Speter      && IDENTIFIER_POINTER (TREE_PURPOSE (link)))
31818334Speter    TYPE_SYMTAB_ADDRESS (type) = IDENTIFIER_POINTER (TREE_PURPOSE (link));
31918334Speter  else
32018334Speter    return (char *) TYPE_SYMTAB_ADDRESS (type);
32118334Speter}
32218334Speter#endif
32318334Speter
32418334Speter/* Return a unique string to name an anonymous type.  */
32518334Speter
32618334Speterstatic char *
32718334Spetergen_fake_label ()
32818334Speter{
32918334Speter  char label[10];
33018334Speter  char *labelstr;
33118334Speter  SDB_GENERATE_FAKE (label, unnamed_struct_number);
33218334Speter  unnamed_struct_number++;
33318334Speter  labelstr = (char *) permalloc (strlen (label) + 1);
33418334Speter  strcpy (labelstr, label);
33518334Speter  return labelstr;
33618334Speter}
33718334Speter
33818334Speter/* Return the number which describes TYPE for SDB.
33918334Speter   For pointers, etc., this function is recursive.
34018334Speter   Each record, union or enumeral type must already have had a
34118334Speter   tag number output.  */
34218334Speter
34318334Speter/* The number is given by d6d5d4d3d2d1bbbb
34418334Speter   where bbbb is 4 bit basic type, and di indicate  one of notype,ptr,fn,array.
34518334Speter   Thus, char *foo () has bbbb=T_CHAR
34618334Speter			  d1=D_FCN
34718334Speter			  d2=D_PTR
34818334Speter N_BTMASK=     017       1111     basic type field.
34918334Speter N_TSHIFT=       2                derived type shift
35018334Speter N_BTSHFT=       4                Basic type shift */
35118334Speter
35218334Speter/* Produce the number that describes a pointer, function or array type.
35318334Speter   PREV is the number describing the target, value or element type.
35418334Speter   DT_type describes how to transform that type.  */
35518334Speter#define PUSH_DERIVED_LEVEL(DT_type,PREV)		\
35618334Speter  ((((PREV) & ~(int)N_BTMASK) << (int)N_TSHIFT)		\
35718334Speter   | ((int)DT_type << (int)N_BTSHFT)			\
35818334Speter   | ((PREV) & (int)N_BTMASK))
35918334Speter
36018334Speter/* Number of elements used in sdb_dims.  */
36118334Speterstatic int sdb_n_dims = 0;
36218334Speter
36318334Speter/* Table of array dimensions of current type.  */
36418334Speterstatic int sdb_dims[SDB_MAX_DIM];
36518334Speter
36618334Speter/* Size of outermost array currently being processed.  */
36718334Speterstatic int sdb_type_size = -1;
36818334Speter
36918334Speterstatic int
37018334Speterplain_type (type)
37118334Speter     tree type;
37218334Speter{
37318334Speter  int val = plain_type_1 (type, 0);
37418334Speter
37518334Speter  /* If we have already saved up some array dimensions, print them now.  */
37618334Speter  if (sdb_n_dims > 0)
37718334Speter    {
37818334Speter      int i;
37918334Speter      PUT_SDB_START_DIM;
38018334Speter      for (i = sdb_n_dims - 1; i > 0; i--)
38118334Speter	PUT_SDB_NEXT_DIM (sdb_dims[i]);
38218334Speter      PUT_SDB_LAST_DIM (sdb_dims[0]);
38318334Speter      sdb_n_dims = 0;
38418334Speter
38518334Speter      sdb_type_size = int_size_in_bytes (type);
38618334Speter      /* Don't kill sdb if type is not laid out or has variable size.  */
38718334Speter      if (sdb_type_size < 0)
38818334Speter	sdb_type_size = 0;
38918334Speter    }
39018334Speter  /* If we have computed the size of an array containing this type,
39118334Speter     print it now.  */
39218334Speter  if (sdb_type_size >= 0)
39318334Speter    {
39418334Speter      PUT_SDB_SIZE (sdb_type_size);
39518334Speter      sdb_type_size = -1;
39618334Speter    }
39718334Speter  return val;
39818334Speter}
39918334Speter
40018334Speterstatic int
40118334Spetertemplate_name_p (name)
40218334Speter     tree name;
40318334Speter{
40418334Speter  register char *ptr = IDENTIFIER_POINTER (name);
40518334Speter  while (*ptr && *ptr != '<')
40618334Speter    ptr++;
40718334Speter
40818334Speter  return *ptr != '\0';
40918334Speter}
41018334Speter
41118334Speterstatic void
41218334Spetersdbout_record_type_name (type)
41318334Speter     tree type;
41418334Speter{
41518334Speter  char *name = 0;
41618334Speter  int no_name;
41718334Speter
41818334Speter  if (KNOWN_TYPE_TAG (type))
41918334Speter    return;
42018334Speter
42118334Speter  if (TYPE_NAME (type) != 0)
42218334Speter    {
42318334Speter      tree t = 0;
42418334Speter      /* Find the IDENTIFIER_NODE for the type name.  */
42518334Speter      if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
42618334Speter	t = TYPE_NAME (type);
42718334Speter      else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL)
42818334Speter	{
42918334Speter	  t = DECL_NAME (TYPE_NAME (type));
43018334Speter	  /* The DECL_NAME for templates includes "<>", which breaks
43118334Speter	     most assemblers.  Use its assembler name instead, which
43218334Speter	     has been mangled into being safe.  */
43318334Speter	  if (t && template_name_p (t))
43418334Speter	    t = DECL_ASSEMBLER_NAME (TYPE_NAME (type));
43518334Speter	}
43618334Speter
43718334Speter      /* Now get the name as a string, or invent one.  */
43818334Speter      if (t != NULL_TREE)
43918334Speter	name = IDENTIFIER_POINTER (t);
44018334Speter    }
44118334Speter
44218334Speter  no_name = (name == 0 || *name == 0);
44318334Speter  if (no_name)
44418334Speter    name = gen_fake_label ();
44518334Speter
44618334Speter  SET_KNOWN_TYPE_TAG (type, name);
44718334Speter#ifdef SDB_ALLOW_FORWARD_REFERENCES
44818334Speter  if (no_name)
44918334Speter    sdbout_queue_anonymous_type (type);
45018334Speter#endif
45118334Speter}
45218334Speter
45318334Speter/* Return the .type value for type TYPE.
45418334Speter
45518334Speter   LEVEL indicates how many levels deep we have recursed into the type.
45618334Speter   The SDB debug format can only represent 6 derived levels of types.
45718334Speter   After that, we must output inaccurate debug info.  We deliberately
45818334Speter   stop before the 7th level, so that ADA recursive types will not give an
45918334Speter   infinite loop.  */
46018334Speter
46118334Speterstatic int
46218334Speterplain_type_1 (type, level)
46318334Speter     tree type;
46418334Speter     int level;
46518334Speter{
46618334Speter  if (type == 0)
46718334Speter    type = void_type_node;
46818334Speter  else if (type == error_mark_node)
46918334Speter    type = integer_type_node;
47018334Speter  else
47118334Speter    type = TYPE_MAIN_VARIANT (type);
47218334Speter
47318334Speter  switch (TREE_CODE (type))
47418334Speter    {
47518334Speter    case VOID_TYPE:
47618334Speter      return T_VOID;
47718334Speter    case INTEGER_TYPE:
47818334Speter      {
47918334Speter	int size = int_size_in_bytes (type) * BITS_PER_UNIT;
48018334Speter
48118334Speter	/* Carefully distinguish all the standard types of C,
48218334Speter	   without messing up if the language is not C.
48318334Speter	   Note that we check only for the names that contain spaces;
48418334Speter	   other names might occur by coincidence in other languages.  */
48518334Speter	if (TYPE_NAME (type) != 0
48618334Speter	    && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
48718334Speter	    && DECL_NAME (TYPE_NAME (type)) != 0
48818334Speter	    && TREE_CODE (DECL_NAME (TYPE_NAME (type))) == IDENTIFIER_NODE)
48918334Speter	  {
49018334Speter	    char *name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
49118334Speter
49218334Speter	    if (!strcmp (name, "unsigned char"))
49318334Speter	      return T_UCHAR;
49418334Speter	    if (!strcmp (name, "signed char"))
49518334Speter	      return T_CHAR;
49618334Speter	    if (!strcmp (name, "unsigned int"))
49718334Speter	      return T_UINT;
49818334Speter	    if (!strcmp (name, "short int"))
49918334Speter	      return T_SHORT;
50018334Speter	    if (!strcmp (name, "short unsigned int"))
50118334Speter	      return T_USHORT;
50218334Speter	    if (!strcmp (name, "long int"))
50318334Speter	      return T_LONG;
50418334Speter	    if (!strcmp (name, "long unsigned int"))
50518334Speter	      return T_ULONG;
50618334Speter	  }
50718334Speter
50818334Speter	if (size == CHAR_TYPE_SIZE)
50918334Speter	  return (TREE_UNSIGNED (type) ? T_UCHAR : T_CHAR);
51018334Speter	if (size == SHORT_TYPE_SIZE)
51118334Speter	  return (TREE_UNSIGNED (type) ? T_USHORT : T_SHORT);
51218334Speter	if (size == INT_TYPE_SIZE)
51318334Speter	  return (TREE_UNSIGNED (type) ? T_UINT : T_INT);
51418334Speter	if (size == LONG_TYPE_SIZE)
51518334Speter	  return (TREE_UNSIGNED (type) ? T_ULONG : T_LONG);
51618334Speter	if (size == LONG_LONG_TYPE_SIZE)	/* better than nothing */
51718334Speter	  return (TREE_UNSIGNED (type) ? T_ULONG : T_LONG);
51818334Speter	return 0;
51918334Speter      }
52018334Speter
52118334Speter    case REAL_TYPE:
52218334Speter      {
52318334Speter	int size = int_size_in_bytes (type) * BITS_PER_UNIT;
52418334Speter	if (size == FLOAT_TYPE_SIZE)
52518334Speter	  return T_FLOAT;
52618334Speter	if (size == DOUBLE_TYPE_SIZE)
52718334Speter	  return T_DOUBLE;
52818334Speter	return 0;
52918334Speter      }
53018334Speter
53118334Speter    case ARRAY_TYPE:
53218334Speter      {
53318334Speter	int m;
53418334Speter	if (level >= 6)
53518334Speter	  return T_VOID;
53618334Speter	else
53718334Speter	  m = plain_type_1 (TREE_TYPE (type), level+1);
53818334Speter	if (sdb_n_dims < SDB_MAX_DIM)
53918334Speter	  sdb_dims[sdb_n_dims++]
54018334Speter	    = (TYPE_DOMAIN (type)
54118334Speter	       ? TREE_INT_CST_LOW (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) + 1
54218334Speter	       : 0);
54318334Speter	return PUSH_DERIVED_LEVEL (DT_ARY, m);
54418334Speter      }
54518334Speter
54618334Speter    case RECORD_TYPE:
54718334Speter    case UNION_TYPE:
54818334Speter    case QUAL_UNION_TYPE:
54918334Speter    case ENUMERAL_TYPE:
55018334Speter      {
55118334Speter	char *tag;
55218334Speter#ifdef SDB_ALLOW_FORWARD_REFERENCES
55318334Speter	sdbout_record_type_name (type);
55418334Speter#endif
55518334Speter#ifndef SDB_ALLOW_UNKNOWN_REFERENCES
55618334Speter	if ((TREE_ASM_WRITTEN (type) && KNOWN_TYPE_TAG (type) != 0)
55718334Speter#ifdef SDB_ALLOW_FORWARD_REFERENCES
55818334Speter	    || TYPE_MODE (type) != VOIDmode
55918334Speter#endif
56018334Speter	    )
56118334Speter#endif
56218334Speter	  {
56318334Speter	    /* Output the referenced structure tag name
56418334Speter	       only if the .def has already been finished.
56518334Speter	       At least on 386, the Unix assembler
56618334Speter	       cannot handle forward references to tags.  */
56718334Speter	    /* But the 88100, it requires them, sigh... */
56818334Speter	    /* And the MIPS requires unknown refs as well... */
56918334Speter	    tag = KNOWN_TYPE_TAG (type);
57018334Speter	    PUT_SDB_TAG (tag);
57118334Speter	    /* These 3 lines used to follow the close brace.
57218334Speter	       However, a size of 0 without a tag implies a tag of 0,
57318334Speter	       so if we don't know a tag, we can't mention the size.  */
57418334Speter	    sdb_type_size = int_size_in_bytes (type);
57518334Speter	    if (sdb_type_size < 0)
57618334Speter	      sdb_type_size = 0;
57718334Speter	  }
57818334Speter	return ((TREE_CODE (type) == RECORD_TYPE) ? T_STRUCT
57918334Speter		: (TREE_CODE (type) == UNION_TYPE) ? T_UNION
58018334Speter		: (TREE_CODE (type) == QUAL_UNION_TYPE) ? T_UNION
58118334Speter		: T_ENUM);
58218334Speter      }
58318334Speter    case POINTER_TYPE:
58418334Speter    case REFERENCE_TYPE:
58518334Speter      {
58618334Speter	int m;
58718334Speter	if (level >= 6)
58818334Speter	  return T_VOID;
58918334Speter	else
59018334Speter	  m = plain_type_1 (TREE_TYPE (type), level+1);
59118334Speter	return PUSH_DERIVED_LEVEL (DT_PTR, m);
59218334Speter      }
59318334Speter    case FUNCTION_TYPE:
59418334Speter    case METHOD_TYPE:
59518334Speter      {
59618334Speter	int m;
59718334Speter	if (level >= 6)
59818334Speter	  return T_VOID;
59918334Speter	else
60018334Speter	  m = plain_type_1 (TREE_TYPE (type), level+1);
60118334Speter	return PUSH_DERIVED_LEVEL (DT_FCN, m);
60218334Speter      }
60318334Speter    default:
60418334Speter      return 0;
60518334Speter    }
60618334Speter}
60718334Speter
60818334Speter/* Output the symbols defined in block number DO_BLOCK.
60918334Speter   Set NEXT_BLOCK_NUMBER to 0 before calling.
61018334Speter
61118334Speter   This function works by walking the tree structure of blocks,
61218334Speter   counting blocks until it finds the desired block.  */
61318334Speter
61418334Speterstatic int do_block = 0;
61518334Speter
61618334Speterstatic int next_block_number;
61718334Speter
61818334Speterstatic void
61918334Spetersdbout_block (block)
62018334Speter     register tree block;
62118334Speter{
62218334Speter  while (block)
62318334Speter    {
62418334Speter      /* Ignore blocks never expanded or otherwise marked as real.  */
62518334Speter      if (TREE_USED (block))
62618334Speter	{
62718334Speter	  /* When we reach the specified block, output its symbols.  */
62818334Speter	  if (next_block_number == do_block)
62918334Speter	    {
63018334Speter	      sdbout_syms (BLOCK_VARS (block));
63118334Speter	    }
63218334Speter
63318334Speter	  /* If we are past the specified block, stop the scan.  */
63418334Speter	  if (next_block_number > do_block)
63518334Speter	    return;
63618334Speter
63718334Speter	  next_block_number++;
63818334Speter
63918334Speter	  /* Scan the blocks within this block.  */
64018334Speter	  sdbout_block (BLOCK_SUBBLOCKS (block));
64118334Speter	}
64218334Speter
64318334Speter      block = BLOCK_CHAIN (block);
64418334Speter    }
64518334Speter}
64618334Speter
64718334Speter/* Call sdbout_symbol on each decl in the chain SYMS.  */
64818334Speter
64918334Speterstatic void
65018334Spetersdbout_syms (syms)
65118334Speter     tree syms;
65218334Speter{
65318334Speter  while (syms)
65418334Speter    {
65518334Speter      if (TREE_CODE (syms) != LABEL_DECL)
65618334Speter	sdbout_symbol (syms, 1);
65718334Speter      syms = TREE_CHAIN (syms);
65818334Speter    }
65918334Speter}
66018334Speter
66118334Speter/* Output SDB information for a symbol described by DECL.
66218334Speter   LOCAL is nonzero if the symbol is not file-scope.  */
66318334Speter
66418334Spetervoid
66518334Spetersdbout_symbol (decl, local)
66618334Speter     tree decl;
66718334Speter     int local;
66818334Speter{
66918334Speter  tree type = TREE_TYPE (decl);
67018334Speter  tree context = NULL_TREE;
67118334Speter  rtx value;
67218334Speter  int regno = -1;
67318334Speter  char *name;
67418334Speter
67518334Speter  sdbout_one_type (type);
67618334Speter
67718334Speter#if 0 /* This loses when functions are marked to be ignored,
67818334Speter	 which happens in the C++ front end.  */
67918334Speter  if (DECL_IGNORED_P (decl))
68018334Speter    return;
68118334Speter#endif
68218334Speter
68318334Speter  switch (TREE_CODE (decl))
68418334Speter    {
68518334Speter    case CONST_DECL:
68618334Speter      /* Enum values are defined by defining the enum type.  */
68718334Speter      return;
68818334Speter
68918334Speter    case FUNCTION_DECL:
69018334Speter      /* Don't mention a nested function under its parent.  */
69118334Speter      context = decl_function_context (decl);
69218334Speter      if (context == current_function_decl)
69318334Speter	return;
69418334Speter      if (DECL_EXTERNAL (decl))
69518334Speter	return;
69618334Speter      if (GET_CODE (DECL_RTL (decl)) != MEM
69718334Speter	  || GET_CODE (XEXP (DECL_RTL (decl), 0)) != SYMBOL_REF)
69818334Speter	return;
69918334Speter      PUT_SDB_DEF (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
70018334Speter      PUT_SDB_VAL (XEXP (DECL_RTL (decl), 0));
70118334Speter      PUT_SDB_SCL (TREE_PUBLIC (decl) ? C_EXT : C_STAT);
70218334Speter      break;
70318334Speter
70418334Speter    case TYPE_DECL:
70518334Speter      /* Done with tagged types.  */
70618334Speter      if (DECL_NAME (decl) == 0)
70718334Speter	return;
70818334Speter      if (DECL_IGNORED_P (decl))
70918334Speter	return;
71018334Speter
71118334Speter      /* Output typedef name.  */
71218334Speter      if (template_name_p (DECL_NAME (decl)))
71318334Speter	PUT_SDB_DEF (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
71418334Speter      else
71518334Speter	PUT_SDB_DEF (IDENTIFIER_POINTER (DECL_NAME (decl)));
71618334Speter      PUT_SDB_SCL (C_TPDEF);
71718334Speter      break;
71818334Speter
71918334Speter    case PARM_DECL:
72018334Speter      /* Parm decls go in their own separate chains
72118334Speter	 and are output by sdbout_reg_parms and sdbout_parms.  */
72218334Speter      abort ();
72318334Speter
72418334Speter    case VAR_DECL:
72518334Speter      /* Don't mention a variable that is external.
72618334Speter	 Let the file that defines it describe it.  */
72718334Speter      if (DECL_EXTERNAL (decl))
72818334Speter	return;
72918334Speter
73018334Speter      /* Ignore __FUNCTION__, etc.  */
73118334Speter      if (DECL_IGNORED_P (decl))
73218334Speter	return;
73318334Speter
73418334Speter      /* If there was an error in the declaration, don't dump core
73518334Speter	 if there is no RTL associated with the variable doesn't
73618334Speter	 exist.  */
73718334Speter      if (DECL_RTL (decl) == 0)
73818334Speter	return;
73918334Speter
74018334Speter      DECL_RTL (decl) = eliminate_regs (DECL_RTL (decl), 0, NULL_RTX);
74118334Speter#ifdef LEAF_REG_REMAP
74218334Speter      if (leaf_function)
74318334Speter	leaf_renumber_regs_insn (DECL_RTL (decl));
74418334Speter#endif
74518334Speter      value = DECL_RTL (decl);
74618334Speter
74718334Speter      /* Don't mention a variable at all
74818334Speter	 if it was completely optimized into nothingness.
74918334Speter
75018334Speter	 If DECL was from an inline function, then its rtl
75118334Speter	 is not identically the rtl that was used in this
75218334Speter	 particular compilation.  */
75318334Speter      if (GET_CODE (value) == REG)
75418334Speter	{
75518334Speter	  regno = REGNO (DECL_RTL (decl));
75618334Speter	  if (regno >= FIRST_PSEUDO_REGISTER)
75718334Speter	    return;
75818334Speter	}
75918334Speter      else if (GET_CODE (value) == SUBREG)
76018334Speter	{
76118334Speter	  int offset = 0;
76218334Speter	  while (GET_CODE (value) == SUBREG)
76318334Speter	    {
76418334Speter	      offset += SUBREG_WORD (value);
76518334Speter	      value = SUBREG_REG (value);
76618334Speter	    }
76718334Speter	  if (GET_CODE (value) == REG)
76818334Speter	    {
76918334Speter	      regno = REGNO (value);
77018334Speter	      if (regno >= FIRST_PSEUDO_REGISTER)
77118334Speter		return;
77218334Speter	      regno += offset;
77318334Speter	    }
77418334Speter	  alter_subreg (DECL_RTL (decl));
77518334Speter	  value = DECL_RTL (decl);
77618334Speter	}
77718334Speter      /* Don't output anything if an auto variable
77818334Speter	 gets RTL that is static.
77918334Speter	 GAS version 2.2 can't handle such output.  */
78018334Speter      else if (GET_CODE (value) == MEM && CONSTANT_P (XEXP (value, 0))
78118334Speter	       && ! TREE_STATIC (decl))
78218334Speter	return;
78318334Speter
78418334Speter      /* Emit any structure, union, or enum type that has not been output.
78518334Speter	 This occurs for tag-less structs (et al) used to declare variables
78618334Speter	 within functions.  */
78718334Speter      if (TREE_CODE (type) == ENUMERAL_TYPE
78818334Speter	  || TREE_CODE (type) == RECORD_TYPE
78918334Speter	  || TREE_CODE (type) == UNION_TYPE
79018334Speter	  || TREE_CODE (type) == QUAL_UNION_TYPE)
79118334Speter	{
79218334Speter	  if (TYPE_SIZE (type) != 0		/* not a forward reference */
79318334Speter	      && KNOWN_TYPE_TAG (type) == 0)	/* not yet declared */
79418334Speter	    sdbout_one_type (type);
79518334Speter	}
79618334Speter
79718334Speter      /* Defer SDB information for top-level initialized variables! */
79818334Speter      if (! local
79918334Speter	  && GET_CODE (value) == MEM
80018334Speter	  && DECL_INITIAL (decl))
80118334Speter	return;
80218334Speter
80318334Speter      /* C++ in 2.3 makes nameless symbols.  That will be fixed later.
80418334Speter	 For now, avoid crashing.  */
80518334Speter      if (DECL_NAME (decl) == NULL_TREE)
80618334Speter	return;
80718334Speter
80818334Speter      /* Record the name for, starting a symtab entry.  */
80918334Speter      name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
81018334Speter
81118334Speter      if (GET_CODE (value) == MEM
81218334Speter	  && GET_CODE (XEXP (value, 0)) == SYMBOL_REF)
81318334Speter	{
81418334Speter	  PUT_SDB_DEF (name);
81518334Speter	  if (TREE_PUBLIC (decl))
81618334Speter	    {
81718334Speter	      PUT_SDB_VAL (XEXP (value, 0));
81818334Speter              PUT_SDB_SCL (C_EXT);
81918334Speter	    }
82018334Speter	  else
82118334Speter	    {
82218334Speter	      PUT_SDB_VAL (XEXP (value, 0));
82318334Speter              PUT_SDB_SCL (C_STAT);
82418334Speter	    }
82518334Speter	}
82618334Speter      else if (regno >= 0)
82718334Speter	{
82818334Speter	  PUT_SDB_DEF (name);
82918334Speter	  PUT_SDB_INT_VAL (DBX_REGISTER_NUMBER (regno));
83018334Speter	  PUT_SDB_SCL (C_REG);
83118334Speter	}
83218334Speter      else if (GET_CODE (value) == MEM
83318334Speter	       && (GET_CODE (XEXP (value, 0)) == MEM
83418334Speter		   || (GET_CODE (XEXP (value, 0)) == REG
83518334Speter		       && REGNO (XEXP (value, 0)) != HARD_FRAME_POINTER_REGNUM
83618334Speter		       && REGNO (XEXP (value, 0)) != STACK_POINTER_REGNUM)))
83718334Speter	/* If the value is indirect by memory or by a register
83818334Speter	   that isn't the frame pointer
83918334Speter	   then it means the object is variable-sized and address through
84018334Speter	   that register or stack slot.  COFF has no way to represent this
84118334Speter	   so all we can do is output the variable as a pointer.  */
84218334Speter	{
84318334Speter	  PUT_SDB_DEF (name);
84418334Speter	  if (GET_CODE (XEXP (value, 0)) == REG)
84518334Speter	    {
84618334Speter	      PUT_SDB_INT_VAL (DBX_REGISTER_NUMBER (REGNO (XEXP (value, 0))));
84718334Speter	      PUT_SDB_SCL (C_REG);
84818334Speter	    }
84918334Speter	  else
85018334Speter	    {
85118334Speter	      /* DECL_RTL looks like (MEM (MEM (PLUS (REG...)
85218334Speter		 (CONST_INT...)))).
85318334Speter		 We want the value of that CONST_INT.  */
85418334Speter	      /* Encore compiler hates a newline in a macro arg, it seems.  */
85518334Speter	      PUT_SDB_INT_VAL (DEBUGGER_AUTO_OFFSET
85618334Speter			       (XEXP (XEXP (value, 0), 0)));
85718334Speter	      PUT_SDB_SCL (C_AUTO);
85818334Speter	    }
85918334Speter
86018334Speter	  type = build_pointer_type (TREE_TYPE (decl));
86118334Speter	}
86218334Speter      else if (GET_CODE (value) == MEM
86318334Speter	       && ((GET_CODE (XEXP (value, 0)) == PLUS
86418334Speter		    && GET_CODE (XEXP (XEXP (value, 0), 0)) == REG
86518334Speter		    && GET_CODE (XEXP (XEXP (value, 0), 1)) == CONST_INT)
86618334Speter		   /* This is for variables which are at offset zero from
86718334Speter		      the frame pointer.  This happens on the Alpha.
86818334Speter		      Non-frame pointer registers are excluded above.  */
86918334Speter		   || (GET_CODE (XEXP (value, 0)) == REG)))
87018334Speter	{
87118334Speter	  /* DECL_RTL looks like (MEM (PLUS (REG...) (CONST_INT...)))
87218334Speter	     or (MEM (REG...)).  We want the value of that CONST_INT
87318334Speter	     or zero.  */
87418334Speter	  PUT_SDB_DEF (name);
87518334Speter	  PUT_SDB_INT_VAL (DEBUGGER_AUTO_OFFSET (XEXP (value, 0)));
87618334Speter	  PUT_SDB_SCL (C_AUTO);
87718334Speter	}
87818334Speter      else if (GET_CODE (value) == MEM && GET_CODE (XEXP (value, 0)) == CONST)
87918334Speter	{
88018334Speter	  /* Handle an obscure case which can arise when optimizing and
88118334Speter	     when there are few available registers.  (This is *always*
88218334Speter	     the case for i386/i486 targets).  The DECL_RTL looks like
88318334Speter	     (MEM (CONST ...)) even though this variable is a local `auto'
88418334Speter	     or a local `register' variable.  In effect, what has happened
88518334Speter	     is that the reload pass has seen that all assignments and
88618334Speter	     references for one such a local variable can be replaced by
88718334Speter	     equivalent assignments and references to some static storage
88818334Speter	     variable, thereby avoiding the need for a register.  In such
88918334Speter	     cases we're forced to lie to debuggers and tell them that
89018334Speter	     this variable was itself `static'.  */
89118334Speter	  PUT_SDB_DEF (name);
89218334Speter	  PUT_SDB_VAL (XEXP (XEXP (value, 0), 0));
89318334Speter	  PUT_SDB_SCL (C_STAT);
89418334Speter	}
89518334Speter      else
89618334Speter	{
89718334Speter	  /* It is something we don't know how to represent for SDB.  */
89818334Speter	  return;
89918334Speter	}
90018334Speter      break;
90118334Speter    }
90218334Speter  PUT_SDB_TYPE (plain_type (type));
90318334Speter  PUT_SDB_ENDEF;
90418334Speter}
90518334Speter
90618334Speter/* Output SDB information for a top-level initialized variable
90718334Speter   that has been delayed.  */
90818334Speter
90918334Spetervoid
91018334Spetersdbout_toplevel_data (decl)
91118334Speter     tree decl;
91218334Speter{
91318334Speter  tree type = TREE_TYPE (decl);
91418334Speter
91518334Speter  if (DECL_IGNORED_P (decl))
91618334Speter    return;
91718334Speter
91818334Speter  if (! (TREE_CODE (decl) == VAR_DECL
91918334Speter	 && GET_CODE (DECL_RTL (decl)) == MEM
92018334Speter	 && DECL_INITIAL (decl)))
92118334Speter    abort ();
92218334Speter
92318334Speter  PUT_SDB_DEF (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
92418334Speter  PUT_SDB_VAL (XEXP (DECL_RTL (decl), 0));
92518334Speter  if (TREE_PUBLIC (decl))
92618334Speter    {
92718334Speter      PUT_SDB_SCL (C_EXT);
92818334Speter    }
92918334Speter  else
93018334Speter    {
93118334Speter      PUT_SDB_SCL (C_STAT);
93218334Speter    }
93318334Speter  PUT_SDB_TYPE (plain_type (type));
93418334Speter  PUT_SDB_ENDEF;
93518334Speter}
93618334Speter
93718334Speter#ifdef SDB_ALLOW_FORWARD_REFERENCES
93818334Speter
93918334Speter/* Machinery to record and output anonymous types. */
94018334Speter
94118334Speterstatic tree anonymous_types;
94218334Speter
94318334Speterstatic void
94418334Spetersdbout_queue_anonymous_type (type)
94518334Speter     tree type;
94618334Speter{
94718334Speter  anonymous_types = saveable_tree_cons (NULL_TREE, type, anonymous_types);
94818334Speter}
94918334Speter
95018334Speterstatic void
95118334Spetersdbout_dequeue_anonymous_types ()
95218334Speter{
95318334Speter  register tree types, link;
95418334Speter
95518334Speter  while (anonymous_types)
95618334Speter    {
95718334Speter      types = nreverse (anonymous_types);
95818334Speter      anonymous_types = NULL_TREE;
95918334Speter
96018334Speter      for (link = types; link; link = TREE_CHAIN (link))
96118334Speter	{
96218334Speter	  register tree type = TREE_VALUE (link);
96318334Speter
96418334Speter	  if (type && ! TREE_ASM_WRITTEN (type))
96518334Speter	    sdbout_one_type (type);
96618334Speter	}
96718334Speter    }
96818334Speter}
96918334Speter
97018334Speter#endif
97118334Speter
97218334Speter/* Given a chain of ..._TYPE nodes, all of which have names,
97318334Speter   output definitions of those names, as typedefs.  */
97418334Speter
97518334Spetervoid
97618334Spetersdbout_types (types)
97718334Speter     register tree types;
97818334Speter{
97918334Speter  register tree link;
98018334Speter
98118334Speter  for (link = types; link; link = TREE_CHAIN (link))
98218334Speter    sdbout_one_type (link);
98318334Speter
98418334Speter#ifdef SDB_ALLOW_FORWARD_REFERENCES
98518334Speter  sdbout_dequeue_anonymous_types ();
98618334Speter#endif
98718334Speter}
98818334Speter
98918334Speterstatic void
99018334Spetersdbout_type (type)
99118334Speter     tree type;
99218334Speter{
99318334Speter  if (type == error_mark_node)
99418334Speter    type = integer_type_node;
99518334Speter  PUT_SDB_TYPE (plain_type (type));
99618334Speter}
99718334Speter
99818334Speter/* Output types of the fields of type TYPE, if they are structs.
99918334Speter
100018334Speter   Formerly did not chase through pointer types, since that could be circular.
100118334Speter   They must come before TYPE, since forward refs are not allowed.
100218334Speter   Now james@bigtex.cactus.org says to try them.  */
100318334Speter
100418334Speterstatic void
100518334Spetersdbout_field_types (type)
100618334Speter     tree type;
100718334Speter{
100818334Speter  tree tail;
100918334Speter  for (tail = TYPE_FIELDS (type); tail; tail = TREE_CHAIN (tail))
101018334Speter    if (TREE_CODE (TREE_TYPE (tail)) == POINTER_TYPE)
101118334Speter      sdbout_one_type (TREE_TYPE (TREE_TYPE (tail)));
101218334Speter    else
101318334Speter      sdbout_one_type (TREE_TYPE (tail));
101418334Speter}
101518334Speter
101618334Speter/* Use this to put out the top level defined record and union types
101718334Speter   for later reference.  If this is a struct with a name, then put that
101818334Speter   name out.  Other unnamed structs will have .xxfake labels generated so
101918334Speter   that they may be referred to later.
102018334Speter   The label will be stored in the KNOWN_TYPE_TAG slot of a type.
102118334Speter   It may NOT be called recursively.  */
102218334Speter
102318334Speterstatic void
102418334Spetersdbout_one_type (type)
102518334Speter     tree type;
102618334Speter{
102718334Speter  if (current_function_decl != NULL_TREE
102818334Speter      && DECL_SECTION_NAME (current_function_decl) != NULL_TREE)
102918334Speter    ; /* Don't change section amid function.  */
103018334Speter  else
103118334Speter    text_section ();
103218334Speter
103318334Speter  switch (TREE_CODE (type))
103418334Speter    {
103518334Speter    case RECORD_TYPE:
103618334Speter    case UNION_TYPE:
103718334Speter    case QUAL_UNION_TYPE:
103818334Speter    case ENUMERAL_TYPE:
103918334Speter      type = TYPE_MAIN_VARIANT (type);
104018334Speter      /* Don't output a type twice.  */
104118334Speter      if (TREE_ASM_WRITTEN (type))
104218334Speter	/* James said test TREE_ASM_BEING_WRITTEN here.  */
104318334Speter	return;
104418334Speter
104518334Speter      /* Output nothing if type is not yet defined.  */
104618334Speter      if (TYPE_SIZE (type) == 0)
104718334Speter	return;
104818334Speter
104918334Speter      TREE_ASM_WRITTEN (type) = 1;
105018334Speter#if 1
105118334Speter      /* This is reputed to cause trouble with the following case,
105218334Speter	 but perhaps checking TYPE_SIZE above will fix it.  */
105318334Speter
105418334Speter      /* Here is a test case:
105518334Speter
105618334Speter	struct foo {
105718334Speter	  struct badstr *bbb;
105818334Speter	} forwardref;
105918334Speter
106018334Speter	typedef struct intermediate {
106118334Speter	  int aaaa;
106218334Speter	} intermediate_ref;
106318334Speter
106418334Speter	typedef struct badstr {
106518334Speter	  int ccccc;
106618334Speter	} badtype;   */
106718334Speter
106818334Speter#if 0
106918334Speter      TREE_ASM_BEING_WRITTEN (type) = 1;
107018334Speter#endif
107118334Speter      /* This change, which ought to make better output,
107218334Speter	 used to make the COFF assembler unhappy.
107318334Speter	 Changes involving KNOWN_TYPE_TAG may fix the problem.  */
107418334Speter      /* Before really doing anything, output types we want to refer to.  */
107518334Speter      /* Note that in version 1 the following two lines
107618334Speter	 are not used if forward references are in use.  */
107718334Speter      if (TREE_CODE (type) != ENUMERAL_TYPE)
107818334Speter	sdbout_field_types (type);
107918334Speter#if 0
108018334Speter      TREE_ASM_WRITTEN (type) = 1;
108118334Speter#endif
108218334Speter#endif
108318334Speter
108418334Speter      /* Output a structure type.  */
108518334Speter      {
108618334Speter	int size = int_size_in_bytes (type);
108718334Speter	int member_scl;
108818334Speter	tree tem;
108918334Speter	int i, n_baseclasses = 0;
109018334Speter
109118334Speter	/* Record the type tag, but not in its permanent place just yet.  */
109218334Speter	sdbout_record_type_name (type);
109318334Speter
109418334Speter	PUT_SDB_DEF (KNOWN_TYPE_TAG (type));
109518334Speter
109618334Speter	switch (TREE_CODE (type))
109718334Speter	  {
109818334Speter	  case UNION_TYPE:
109918334Speter	  case QUAL_UNION_TYPE:
110018334Speter	    PUT_SDB_SCL (C_UNTAG);
110118334Speter	    PUT_SDB_TYPE (T_UNION);
110218334Speter	    member_scl = C_MOU;
110318334Speter	    break;
110418334Speter
110518334Speter	  case RECORD_TYPE:
110618334Speter	    PUT_SDB_SCL (C_STRTAG);
110718334Speter	    PUT_SDB_TYPE (T_STRUCT);
110818334Speter	    member_scl = C_MOS;
110918334Speter	    break;
111018334Speter
111118334Speter	  case ENUMERAL_TYPE:
111218334Speter	    PUT_SDB_SCL (C_ENTAG);
111318334Speter	    PUT_SDB_TYPE (T_ENUM);
111418334Speter	    member_scl = C_MOE;
111518334Speter	    break;
111618334Speter	  }
111718334Speter
111818334Speter	PUT_SDB_SIZE (size);
111918334Speter	PUT_SDB_ENDEF;
112018334Speter
112118334Speter	/* Print out the base class information with fields
112218334Speter	   named after the types they hold.  */
112318334Speter	if (TYPE_BINFO (type)
112418334Speter	    && TYPE_BINFO_BASETYPES (type))
112518334Speter	  n_baseclasses = TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (type));
112618334Speter	for (i = 0; i < n_baseclasses; i++)
112718334Speter	  {
112818334Speter	    tree child = TREE_VEC_ELT (BINFO_BASETYPES (TYPE_BINFO (type)), i);
112918334Speter	    tree child_type = BINFO_TYPE (child);
113018334Speter	    tree child_type_name;
113118334Speter	    if (TYPE_NAME (child_type) == 0)
113218334Speter	      continue;
113318334Speter	    if (TREE_CODE (TYPE_NAME (child_type)) == IDENTIFIER_NODE)
113418334Speter	      child_type_name = TYPE_NAME (child_type);
113518334Speter	    else if (TREE_CODE (TYPE_NAME (child_type)) == TYPE_DECL)
113618334Speter	      {
113718334Speter		child_type_name = DECL_NAME (TYPE_NAME (child_type));
113818334Speter		if (child_type_name && template_name_p (child_type_name))
113918334Speter		  child_type_name
114018334Speter		    = DECL_ASSEMBLER_NAME (TYPE_NAME (child_type));
114118334Speter	      }
114218334Speter	    else
114318334Speter	      continue;
114418334Speter
114518334Speter	    CONTIN;
114618334Speter	    PUT_SDB_DEF (IDENTIFIER_POINTER (child_type_name));
114718334Speter	    PUT_SDB_INT_VAL (TREE_INT_CST_LOW (BINFO_OFFSET (child)));
114818334Speter	    PUT_SDB_SCL (member_scl);
114918334Speter	    sdbout_type (BINFO_TYPE (child));
115018334Speter	    PUT_SDB_ENDEF;
115118334Speter	  }
115218334Speter
115318334Speter	/* output the individual fields */
115418334Speter
115518334Speter	if (TREE_CODE (type) == ENUMERAL_TYPE)
115618334Speter	  for (tem = TYPE_FIELDS (type); tem; tem = TREE_CHAIN (tem))
115718334Speter	    {
115818334Speter	      PUT_SDB_DEF (IDENTIFIER_POINTER (TREE_PURPOSE (tem)));
115918334Speter	      PUT_SDB_INT_VAL (TREE_INT_CST_LOW (TREE_VALUE (tem)));
116018334Speter	      PUT_SDB_SCL (C_MOE);
116118334Speter	      PUT_SDB_TYPE (T_MOE);
116218334Speter	      PUT_SDB_ENDEF;
116318334Speter	    }
116418334Speter
116518334Speter	else			/* record or union type */
116618334Speter	  for (tem = TYPE_FIELDS (type); tem; tem = TREE_CHAIN (tem))
116718334Speter	    /* Output the name, type, position (in bits), size (in bits)
116818334Speter	       of each field.  */
116918334Speter
117018334Speter	    /* Omit here the nameless fields that are used to skip bits.
117118334Speter	       Also omit fields with variable size or position.
117218334Speter	       Also omit non FIELD_DECL nodes that GNU C++ may put here.  */
117318334Speter	    if (TREE_CODE (tem) == FIELD_DECL
117418334Speter		&& DECL_NAME (tem) != 0
117518334Speter		&& TREE_CODE (DECL_SIZE (tem)) == INTEGER_CST
117618334Speter		&& TREE_CODE (DECL_FIELD_BITPOS (tem)) == INTEGER_CST)
117718334Speter	      {
117818334Speter		char *name;
117918334Speter
118018334Speter		CONTIN;
118118334Speter		name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (tem));
118218334Speter		PUT_SDB_DEF (name);
118318334Speter		if (DECL_BIT_FIELD_TYPE (tem))
118418334Speter		  {
118518334Speter		    PUT_SDB_INT_VAL (TREE_INT_CST_LOW (DECL_FIELD_BITPOS (tem)));
118618334Speter		    PUT_SDB_SCL (C_FIELD);
118718334Speter		    sdbout_type (DECL_BIT_FIELD_TYPE (tem));
118818334Speter		    PUT_SDB_SIZE (TREE_INT_CST_LOW (DECL_SIZE (tem)));
118918334Speter		  }
119018334Speter		else
119118334Speter		  {
119218334Speter		    PUT_SDB_INT_VAL (TREE_INT_CST_LOW (DECL_FIELD_BITPOS (tem))
119318334Speter				     / BITS_PER_UNIT);
119418334Speter		    PUT_SDB_SCL (member_scl);
119518334Speter		    sdbout_type (TREE_TYPE (tem));
119618334Speter		  }
119718334Speter		PUT_SDB_ENDEF;
119818334Speter	      }
119918334Speter	/* output end of a structure,union, or enumeral definition */
120018334Speter
120118334Speter	PUT_SDB_PLAIN_DEF ("eos");
120218334Speter	PUT_SDB_INT_VAL (size);
120318334Speter	PUT_SDB_SCL (C_EOS);
120418334Speter	PUT_SDB_TAG (KNOWN_TYPE_TAG (type));
120518334Speter	PUT_SDB_SIZE (size);
120618334Speter	PUT_SDB_ENDEF;
120718334Speter	break;
120818334Speter      }
120918334Speter    }
121018334Speter}
121118334Speter
121218334Speter/* The following two functions output definitions of function parameters.
121318334Speter   Each parameter gets a definition locating it in the parameter list.
121418334Speter   Each parameter that is a register variable gets a second definition
121518334Speter   locating it in the register.
121618334Speter
121718334Speter   Printing or argument lists in gdb uses the definitions that
121818334Speter   locate in the parameter list.  But reference to the variable in
121918334Speter   expressions uses preferentially the definition as a register.  */
122018334Speter
122118334Speter/* Output definitions, referring to storage in the parmlist,
122218334Speter   of all the parms in PARMS, which is a chain of PARM_DECL nodes.  */
122318334Speter
122418334Speterstatic void
122518334Spetersdbout_parms (parms)
122618334Speter     tree parms;
122718334Speter{
122818334Speter  for (; parms; parms = TREE_CHAIN (parms))
122918334Speter    if (DECL_NAME (parms))
123018334Speter      {
123118334Speter	int current_sym_value = 0;
123218334Speter	char *name = IDENTIFIER_POINTER (DECL_NAME (parms));
123318334Speter
123418334Speter	if (name == 0 || *name == 0)
123518334Speter	  name = gen_fake_label ();
123618334Speter
123718334Speter	/* Perform any necessary register eliminations on the parameter's rtl,
123818334Speter	   so that the debugging output will be accurate.  */
123918334Speter	DECL_INCOMING_RTL (parms) =
124018334Speter	  eliminate_regs (DECL_INCOMING_RTL (parms), 0, NULL_RTX);
124118334Speter	DECL_RTL (parms) = eliminate_regs (DECL_RTL (parms), 0, NULL_RTX);
124218334Speter
124318334Speter	if (PARM_PASSED_IN_MEMORY (parms))
124418334Speter	  {
124518334Speter	    rtx addr = XEXP (DECL_INCOMING_RTL (parms), 0);
124618334Speter	    tree type;
124718334Speter
124818334Speter	    /* ??? Here we assume that the parm address is indexed
124918334Speter	       off the frame pointer or arg pointer.
125018334Speter	       If that is not true, we produce meaningless results,
125118334Speter	       but do not crash.  */
125218334Speter	    if (GET_CODE (addr) == PLUS
125318334Speter		&& GET_CODE (XEXP (addr, 1)) == CONST_INT)
125418334Speter	      current_sym_value = INTVAL (XEXP (addr, 1));
125518334Speter	    else
125618334Speter	      current_sym_value = 0;
125718334Speter
125818334Speter	    if (GET_CODE (DECL_RTL (parms)) == REG
125918334Speter		&& REGNO (DECL_RTL (parms)) >= 0
126018334Speter		&& REGNO (DECL_RTL (parms)) < FIRST_PSEUDO_REGISTER)
126118334Speter	      type = DECL_ARG_TYPE (parms);
126218334Speter	    else
126318334Speter	      {
126418334Speter		int original_sym_value = current_sym_value;
126518334Speter
126618334Speter		/* This is the case where the parm is passed as an int or
126718334Speter		   double and it is converted to a char, short or float
126818334Speter		   and stored back in the parmlist.  In this case, describe
126918334Speter		   the parm with the variable's declared type, and adjust
127018334Speter		   the address if the least significant bytes (which we are
127118334Speter		   using) are not the first ones.  */
127218334Speter		if (BYTES_BIG_ENDIAN
127318334Speter		    && TREE_TYPE (parms) != DECL_ARG_TYPE (parms))
127418334Speter		  current_sym_value +=
127518334Speter		    (GET_MODE_SIZE (TYPE_MODE (DECL_ARG_TYPE (parms)))
127618334Speter		     - GET_MODE_SIZE (GET_MODE (DECL_RTL (parms))));
127718334Speter
127818334Speter		if (GET_CODE (DECL_RTL (parms)) == MEM
127918334Speter		    && GET_CODE (XEXP (DECL_RTL (parms), 0)) == PLUS
128018334Speter		    && (GET_CODE (XEXP (XEXP (DECL_RTL (parms), 0), 1))
128118334Speter			== CONST_INT)
128218334Speter		    && (INTVAL (XEXP (XEXP (DECL_RTL (parms), 0), 1))
128318334Speter			== current_sym_value))
128418334Speter		  type = TREE_TYPE (parms);
128518334Speter		else
128618334Speter		  {
128718334Speter		    current_sym_value = original_sym_value;
128818334Speter		    type = DECL_ARG_TYPE (parms);
128918334Speter		  }
129018334Speter	      }
129118334Speter
129218334Speter	    PUT_SDB_DEF (name);
129318334Speter	    PUT_SDB_INT_VAL (DEBUGGER_ARG_OFFSET (current_sym_value, addr));
129418334Speter	    PUT_SDB_SCL (C_ARG);
129518334Speter	    PUT_SDB_TYPE (plain_type (type));
129618334Speter	    PUT_SDB_ENDEF;
129718334Speter	  }
129818334Speter	else if (GET_CODE (DECL_RTL (parms)) == REG)
129918334Speter	  {
130018334Speter	    rtx best_rtl;
130118334Speter	    /* Parm passed in registers and lives in registers or nowhere.  */
130218334Speter
130318334Speter	    /* If parm lives in a register, use that register;
130418334Speter	       pretend the parm was passed there.  It would be more consistent
130518334Speter	       to describe the register where the parm was passed,
130618334Speter	       but in practice that register usually holds something else.  */
130718334Speter	    if (REGNO (DECL_RTL (parms)) >= 0
130818334Speter		&& REGNO (DECL_RTL (parms)) < FIRST_PSEUDO_REGISTER)
130918334Speter	      best_rtl = DECL_RTL (parms);
131018334Speter	    /* If the parm lives nowhere,
131118334Speter	       use the register where it was passed.  */
131218334Speter	    else
131318334Speter	      best_rtl = DECL_INCOMING_RTL (parms);
131418334Speter
131518334Speter	    PUT_SDB_DEF (name);
131618334Speter	    PUT_SDB_INT_VAL (DBX_REGISTER_NUMBER (REGNO (best_rtl)));
131718334Speter	    PUT_SDB_SCL (C_REGPARM);
131818334Speter	    PUT_SDB_TYPE (plain_type (TREE_TYPE (parms), 0));
131918334Speter	    PUT_SDB_ENDEF;
132018334Speter	  }
132118334Speter	else if (GET_CODE (DECL_RTL (parms)) == MEM
132218334Speter		 && XEXP (DECL_RTL (parms), 0) != const0_rtx)
132318334Speter	  {
132418334Speter	    /* Parm was passed in registers but lives on the stack.  */
132518334Speter
132618334Speter	    /* DECL_RTL looks like (MEM (PLUS (REG...) (CONST_INT...))),
132718334Speter	       in which case we want the value of that CONST_INT,
132818334Speter	       or (MEM (REG ...)) or (MEM (MEM ...)),
132918334Speter	       in which case we use a value of zero.  */
133018334Speter	    if (GET_CODE (XEXP (DECL_RTL (parms), 0)) == REG
133118334Speter		|| GET_CODE (XEXP (DECL_RTL (parms), 0)) == MEM)
133218334Speter	      current_sym_value = 0;
133318334Speter	    else
133418334Speter	      current_sym_value = INTVAL (XEXP (XEXP (DECL_RTL (parms), 0), 1));
133518334Speter
133618334Speter	    /* Again, this assumes the offset is based on the arg pointer.  */
133718334Speter	    PUT_SDB_DEF (name);
133818334Speter	    PUT_SDB_INT_VAL (DEBUGGER_ARG_OFFSET (current_sym_value,
133918334Speter						  XEXP (DECL_RTL (parms), 0)));
134018334Speter	    PUT_SDB_SCL (C_ARG);
134118334Speter	    PUT_SDB_TYPE (plain_type (TREE_TYPE (parms), 0));
134218334Speter	    PUT_SDB_ENDEF;
134318334Speter	  }
134418334Speter      }
134518334Speter}
134618334Speter
134718334Speter/* Output definitions for the places where parms live during the function,
134818334Speter   when different from where they were passed, when the parms were passed
134918334Speter   in memory.
135018334Speter
135118334Speter   It is not useful to do this for parms passed in registers
135218334Speter   that live during the function in different registers, because it is
135318334Speter   impossible to look in the passed register for the passed value,
135418334Speter   so we use the within-the-function register to begin with.
135518334Speter
135618334Speter   PARMS is a chain of PARM_DECL nodes.  */
135718334Speter
135818334Speterstatic void
135918334Spetersdbout_reg_parms (parms)
136018334Speter     tree parms;
136118334Speter{
136218334Speter  for (; parms; parms = TREE_CHAIN (parms))
136318334Speter    if (DECL_NAME (parms))
136418334Speter      {
136518334Speter	char *name = IDENTIFIER_POINTER (DECL_NAME (parms));
136618334Speter
136718334Speter	/* Report parms that live in registers during the function
136818334Speter	   but were passed in memory.  */
136918334Speter	if (GET_CODE (DECL_RTL (parms)) == REG
137018334Speter	    && REGNO (DECL_RTL (parms)) >= 0
137118334Speter	    && REGNO (DECL_RTL (parms)) < FIRST_PSEUDO_REGISTER
137218334Speter	    && PARM_PASSED_IN_MEMORY (parms))
137318334Speter	  {
137418334Speter	    if (name == 0 || *name == 0)
137518334Speter	      name = gen_fake_label ();
137618334Speter	    PUT_SDB_DEF (name);
137718334Speter	    PUT_SDB_INT_VAL (DBX_REGISTER_NUMBER (REGNO (DECL_RTL (parms))));
137818334Speter	    PUT_SDB_SCL (C_REG);
137918334Speter	    PUT_SDB_TYPE (plain_type (TREE_TYPE (parms), 0));
138018334Speter	    PUT_SDB_ENDEF;
138118334Speter	  }
138218334Speter	/* Report parms that live in memory but not where they were passed.  */
138318334Speter	else if (GET_CODE (DECL_RTL (parms)) == MEM
138418334Speter		 && GET_CODE (XEXP (DECL_RTL (parms), 0)) == PLUS
138518334Speter		 && GET_CODE (XEXP (XEXP (DECL_RTL (parms), 0), 1)) == CONST_INT
138618334Speter		 && PARM_PASSED_IN_MEMORY (parms)
138718334Speter		 && ! rtx_equal_p (DECL_RTL (parms), DECL_INCOMING_RTL (parms)))
138818334Speter	  {
138918334Speter#if 0 /* ??? It is not clear yet what should replace this.  */
139018334Speter	    int offset = DECL_OFFSET (parms) / BITS_PER_UNIT;
139118334Speter	    /* A parm declared char is really passed as an int,
139218334Speter	       so it occupies the least significant bytes.
139318334Speter	       On a big-endian machine those are not the low-numbered ones.  */
139418334Speter	    if (BYTES_BIG_ENDIAN
139518334Speter		&& offset != -1
139618334Speter		&& TREE_TYPE (parms) != DECL_ARG_TYPE (parms))
139718334Speter	      offset += (GET_MODE_SIZE (TYPE_MODE (DECL_ARG_TYPE (parms)))
139818334Speter			 - GET_MODE_SIZE (GET_MODE (DECL_RTL (parms))));
139918334Speter	    if (INTVAL (XEXP (XEXP (DECL_RTL (parms), 0), 1)) != offset) {...}
140018334Speter#endif
140118334Speter	      {
140218334Speter		if (name == 0 || *name == 0)
140318334Speter		  name = gen_fake_label ();
140418334Speter		PUT_SDB_DEF (name);
140518334Speter		PUT_SDB_INT_VAL (DEBUGGER_AUTO_OFFSET
140618334Speter				 (XEXP (DECL_RTL (parms), 0)));
140718334Speter		PUT_SDB_SCL (C_AUTO);
140818334Speter		PUT_SDB_TYPE (plain_type (TREE_TYPE (parms)));
140918334Speter		PUT_SDB_ENDEF;
141018334Speter	      }
141118334Speter	  }
141218334Speter      }
141318334Speter}
141418334Speter
141518334Speter/* Describe the beginning of an internal block within a function.
141618334Speter   Also output descriptions of variables defined in this block.
141718334Speter
141818334Speter   N is the number of the block, by order of beginning, counting from 1,
141918334Speter   and not counting the outermost (function top-level) block.
142018334Speter   The blocks match the BLOCKs in DECL_INITIAL (current_function_decl),
142118334Speter   if the count starts at 0 for the outermost one.  */
142218334Speter
142318334Spetervoid
142418334Spetersdbout_begin_block (file, line, n)
142518334Speter     FILE *file;
142618334Speter     int line;
142718334Speter     int n;
142818334Speter{
142918334Speter  tree decl = current_function_decl;
143018334Speter  MAKE_LINE_SAFE (line);
143118334Speter
143218334Speter  /* The SCO compiler does not emit a separate block for the function level
143318334Speter     scope, so we avoid it here also.  However, mips ECOFF compilers do emit
143418334Speter     a separate block, so we retain it when MIPS_DEBUGGING_INFO is defined.  */
143518334Speter#ifndef MIPS_DEBUGGING_INFO
143618334Speter  if (n != 1)
143718334Speter#endif
143818334Speter    PUT_SDB_BLOCK_START (line - sdb_begin_function_line);
143918334Speter
144018334Speter  if (n == 1)
144118334Speter    {
144218334Speter      /* Include the outermost BLOCK's variables in block 1.  */
144318334Speter      next_block_number = 0;
144418334Speter      do_block = 0;
144518334Speter      sdbout_block (DECL_INITIAL (decl));
144618334Speter    }
144718334Speter  /* If -g1, suppress all the internal symbols of functions
144818334Speter     except for arguments.  */
144918334Speter  if (debug_info_level != DINFO_LEVEL_TERSE)
145018334Speter    {
145118334Speter      next_block_number = 0;
145218334Speter      do_block = n;
145318334Speter      sdbout_block (DECL_INITIAL (decl));
145418334Speter    }
145518334Speter
145618334Speter#ifdef SDB_ALLOW_FORWARD_REFERENCES
145718334Speter  sdbout_dequeue_anonymous_types ();
145818334Speter#endif
145918334Speter}
146018334Speter
146118334Speter/* Describe the end line-number of an internal block within a function.  */
146218334Speter
146318334Spetervoid
146418334Spetersdbout_end_block (file, line, n)
146518334Speter     FILE *file;
146618334Speter     int line;
146718334Speter     int n;
146818334Speter{
146918334Speter  MAKE_LINE_SAFE (line);
147018334Speter
147118334Speter  /* The SCO compiler does not emit a separate block for the function level
147218334Speter     scope, so we avoid it here also.  However, mips ECOFF compilers do emit
147318334Speter     a separate block, so we retain it when MIPS_DEBUGGING_INFO is defined.  */
147418334Speter#ifndef MIPS_DEBUGGING_INFO
147518334Speter  if (n != 1)
147618334Speter#endif
147718334Speter  PUT_SDB_BLOCK_END (line - sdb_begin_function_line);
147818334Speter}
147918334Speter
148018334Speter/* Output sdb info for the current function name.
148118334Speter   Called from assemble_start_function.  */
148218334Speter
148318334Spetervoid
148418334Spetersdbout_mark_begin_function ()
148518334Speter{
148618334Speter  sdbout_symbol (current_function_decl, 0);
148718334Speter}
148818334Speter
148918334Speter/* Called at beginning of function body (after prologue).
149018334Speter   Record the function's starting line number, so we can output
149118334Speter   relative line numbers for the other lines.
149218334Speter   Describe beginning of outermost block.
149318334Speter   Also describe the parameter list.  */
149418334Speter
149518334Spetervoid
149618334Spetersdbout_begin_function (line)
149718334Speter     int line;
149818334Speter{
149918334Speter  sdb_begin_function_line = line - 1;
150018334Speter  PUT_SDB_FUNCTION_START (line);
150118334Speter  sdbout_parms (DECL_ARGUMENTS (current_function_decl));
150218334Speter  sdbout_reg_parms (DECL_ARGUMENTS (current_function_decl));
150318334Speter}
150418334Speter
150518334Speter/* Called at end of function (before epilogue).
150618334Speter   Describe end of outermost block.  */
150718334Speter
150818334Spetervoid
150918334Spetersdbout_end_function (line)
151018334Speter     int line;
151118334Speter{
151218334Speter#ifdef SDB_ALLOW_FORWARD_REFERENCES
151318334Speter  sdbout_dequeue_anonymous_types ();
151418334Speter#endif
151518334Speter
151618334Speter  MAKE_LINE_SAFE (line);
151718334Speter  PUT_SDB_FUNCTION_END (line - sdb_begin_function_line);
151818334Speter
151918334Speter  /* Indicate we are between functions, for line-number output.  */
152018334Speter  sdb_begin_function_line = -1;
152118334Speter}
152218334Speter
152318334Speter/* Output sdb info for the absolute end of a function.
152418334Speter   Called after the epilogue is output.  */
152518334Speter
152618334Spetervoid
152718334Spetersdbout_end_epilogue ()
152818334Speter{
152918334Speter  char *name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl));
153018334Speter  PUT_SDB_EPILOGUE_END (name);
153118334Speter}
153218334Speter
153318334Speter/* Output sdb info for the given label.  Called only if LABEL_NAME (insn)
153418334Speter   is present.  */
153518334Speter
153618334Spetervoid
153718334Spetersdbout_label (insn)
153818334Speter     register rtx insn;
153918334Speter{
154018334Speter  PUT_SDB_DEF (LABEL_NAME (insn));
154118334Speter  PUT_SDB_VAL (insn);
154218334Speter  PUT_SDB_SCL (C_LABEL);
154318334Speter  PUT_SDB_TYPE (T_NULL);
154418334Speter  PUT_SDB_ENDEF;
154518334Speter}
154618334Speter
154718334Speter#endif /* SDB_DEBUGGING_INFO */
1548