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