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