sdbout.c revision 90075
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" 4518334Speter 4618334Speter#ifdef SDB_DEBUGGING_INFO 4718334Speter 4850397Sobrien#include "system.h" 4918334Speter#include "tree.h" 5018334Speter#include "rtl.h" 5118334Speter#include "regs.h" 5218334Speter#include "flags.h" 5318334Speter#include "insn-config.h" 5418334Speter#include "reload.h" 5550397Sobrien#include "output.h" 5650397Sobrien#include "toplev.h" 5790075Sobrien#include "ggc.h" 5890075Sobrien#include "tm_p.h" 5918334Speter#include "gsyms.h" 6090075Sobrien#include "debug.h" 6118334Speter 6218334Speter/* 1 if PARM is passed to this function in memory. */ 6318334Speter 6418334Speter#define PARM_PASSED_IN_MEMORY(PARM) \ 6518334Speter (GET_CODE (DECL_INCOMING_RTL (PARM)) == MEM) 6618334Speter 6718334Speter/* A C expression for the integer offset value of an automatic variable 6818334Speter (C_AUTO) having address X (an RTX). */ 6918334Speter#ifndef DEBUGGER_AUTO_OFFSET 7018334Speter#define DEBUGGER_AUTO_OFFSET(X) \ 7118334Speter (GET_CODE (X) == PLUS ? INTVAL (XEXP (X, 1)) : 0) 7218334Speter#endif 7318334Speter 7418334Speter/* A C expression for the integer offset value of an argument (C_ARG) 7518334Speter having address X (an RTX). The nominal offset is OFFSET. */ 7618334Speter#ifndef DEBUGGER_ARG_OFFSET 7718334Speter#define DEBUGGER_ARG_OFFSET(OFFSET, X) (OFFSET) 7818334Speter#endif 7918334Speter 8018334Speter/* Line number of beginning of current function, minus one. 8118334Speter Negative means not in a function or not using sdb. */ 8218334Speter 8318334Speterint sdb_begin_function_line = -1; 8418334Speter 8518334Speter/* Counter to generate unique "names" for nameless struct members. */ 8618334Speter 8718334Speterstatic int unnamed_struct_number = 0; 8818334Speter 8918334Speterextern FILE *asm_out_file; 9018334Speter 9118334Speterextern tree current_function_decl; 9218334Speter 9350397Sobrien#include "sdbout.h" 9418334Speter 9590075Sobrienstatic void sdbout_init PARAMS ((const char *)); 9690075Sobrienstatic void sdbout_finish PARAMS ((const char *)); 9790075Sobrienstatic void sdbout_start_source_file PARAMS ((unsigned int, const char *)); 9890075Sobrienstatic void sdbout_end_source_file PARAMS ((unsigned int)); 9990075Sobrienstatic void sdbout_begin_block PARAMS ((unsigned int, unsigned int)); 10090075Sobrienstatic void sdbout_end_block PARAMS ((unsigned int, unsigned int)); 10190075Sobrienstatic void sdbout_source_line PARAMS ((unsigned int, const char *)); 10290075Sobrienstatic void sdbout_end_epilogue PARAMS ((void)); 10390075Sobrienstatic void sdbout_global_decl PARAMS ((tree)); 10490075Sobrien#ifndef MIPS_DEBUGGING_INFO 10590075Sobrienstatic void sdbout_begin_prologue PARAMS ((unsigned int, const char *)); 10618334Speter#endif 10790075Sobrienstatic void sdbout_end_prologue PARAMS ((unsigned int)); 10890075Sobrienstatic void sdbout_begin_function PARAMS ((tree)); 10990075Sobrienstatic void sdbout_end_function PARAMS ((unsigned int)); 11090075Sobrienstatic void sdbout_toplevel_data PARAMS ((tree)); 11190075Sobrienstatic void sdbout_label PARAMS ((rtx)); 11290075Sobrienstatic char *gen_fake_label PARAMS ((void)); 11390075Sobrienstatic int plain_type PARAMS ((tree)); 11490075Sobrienstatic int template_name_p PARAMS ((tree)); 11590075Sobrienstatic void sdbout_record_type_name PARAMS ((tree)); 11690075Sobrienstatic int plain_type_1 PARAMS ((tree, int)); 11790075Sobrienstatic void sdbout_block PARAMS ((tree)); 11890075Sobrienstatic void sdbout_syms PARAMS ((tree)); 11990075Sobrien#ifdef SDB_ALLOW_FORWARD_REFERENCES 12090075Sobrienstatic void sdbout_queue_anonymous_type PARAMS ((tree)); 12190075Sobrienstatic void sdbout_dequeue_anonymous_types PARAMS ((void)); 12218334Speter#endif 12390075Sobrienstatic void sdbout_type PARAMS ((tree)); 12490075Sobrienstatic void sdbout_field_types PARAMS ((tree)); 12590075Sobrienstatic void sdbout_one_type PARAMS ((tree)); 12690075Sobrienstatic void sdbout_parms PARAMS ((tree)); 12790075Sobrienstatic void sdbout_reg_parms PARAMS ((tree)); 12890075Sobrienstatic void sdbout_global_decl PARAMS ((tree)); 12918334Speter 13018334Speter/* Random macros describing parts of SDB data. */ 13118334Speter 13218334Speter/* Put something here if lines get too long */ 13318334Speter#define CONTIN 13418334Speter 13518334Speter/* Default value of delimiter is ";". */ 13618334Speter#ifndef SDB_DELIM 13718334Speter#define SDB_DELIM ";" 13818334Speter#endif 13918334Speter 14018334Speter/* Maximum number of dimensions the assembler will allow. */ 14118334Speter#ifndef SDB_MAX_DIM 14218334Speter#define SDB_MAX_DIM 4 14318334Speter#endif 14418334Speter 14518334Speter#ifndef PUT_SDB_SCL 14618334Speter#define PUT_SDB_SCL(a) fprintf(asm_out_file, "\t.scl\t%d%s", (a), SDB_DELIM) 14718334Speter#endif 14818334Speter 14918334Speter#ifndef PUT_SDB_INT_VAL 15050397Sobrien#define PUT_SDB_INT_VAL(a) \ 15150397Sobrien do { \ 15250397Sobrien fputs ("\t.val\t", asm_out_file); \ 15390075Sobrien fprintf (asm_out_file, HOST_WIDE_INT_PRINT_DEC, (HOST_WIDE_INT) (a)); \ 15450397Sobrien fprintf (asm_out_file, "%s", SDB_DELIM); \ 15550397Sobrien } while (0) 15650397Sobrien 15718334Speter#endif 15818334Speter 15918334Speter#ifndef PUT_SDB_VAL 16018334Speter#define PUT_SDB_VAL(a) \ 16118334Speter( fputs ("\t.val\t", asm_out_file), \ 16218334Speter output_addr_const (asm_out_file, (a)), \ 16318334Speter fprintf (asm_out_file, SDB_DELIM)) 16418334Speter#endif 16518334Speter 16618334Speter#ifndef PUT_SDB_DEF 16718334Speter#define PUT_SDB_DEF(a) \ 16818334Speterdo { fprintf (asm_out_file, "\t.def\t"); \ 16990075Sobrien assemble_name (asm_out_file, a); \ 17018334Speter fprintf (asm_out_file, SDB_DELIM); } while (0) 17118334Speter#endif 17218334Speter 17318334Speter#ifndef PUT_SDB_PLAIN_DEF 17418334Speter#define PUT_SDB_PLAIN_DEF(a) fprintf(asm_out_file,"\t.def\t.%s%s",a, SDB_DELIM) 17518334Speter#endif 17618334Speter 17718334Speter#ifndef PUT_SDB_ENDEF 17818334Speter#define PUT_SDB_ENDEF fputs("\t.endef\n", asm_out_file) 17918334Speter#endif 18018334Speter 18118334Speter#ifndef PUT_SDB_TYPE 18218334Speter#define PUT_SDB_TYPE(a) fprintf(asm_out_file, "\t.type\t0%o%s", a, SDB_DELIM) 18318334Speter#endif 18418334Speter 18518334Speter#ifndef PUT_SDB_SIZE 18650397Sobrien#define PUT_SDB_SIZE(a) \ 18750397Sobrien do { \ 18850397Sobrien fputs ("\t.size\t", asm_out_file); \ 18990075Sobrien fprintf (asm_out_file, HOST_WIDE_INT_PRINT_DEC, (HOST_WIDE_INT) (a)); \ 19050397Sobrien fprintf (asm_out_file, "%s", SDB_DELIM); \ 19150397Sobrien } while(0) 19218334Speter#endif 19318334Speter 19418334Speter#ifndef PUT_SDB_START_DIM 19518334Speter#define PUT_SDB_START_DIM fprintf(asm_out_file, "\t.dim\t") 19618334Speter#endif 19718334Speter 19818334Speter#ifndef PUT_SDB_NEXT_DIM 19918334Speter#define PUT_SDB_NEXT_DIM(a) fprintf(asm_out_file, "%d,", a) 20018334Speter#endif 20118334Speter 20218334Speter#ifndef PUT_SDB_LAST_DIM 20318334Speter#define PUT_SDB_LAST_DIM(a) fprintf(asm_out_file, "%d%s", a, SDB_DELIM) 20418334Speter#endif 20518334Speter 20618334Speter#ifndef PUT_SDB_TAG 20718334Speter#define PUT_SDB_TAG(a) \ 20818334Speterdo { fprintf (asm_out_file, "\t.tag\t"); \ 20990075Sobrien assemble_name (asm_out_file, a); \ 21018334Speter fprintf (asm_out_file, SDB_DELIM); } while (0) 21118334Speter#endif 21218334Speter 21318334Speter#ifndef PUT_SDB_BLOCK_START 21418334Speter#define PUT_SDB_BLOCK_START(LINE) \ 21518334Speter fprintf (asm_out_file, \ 21618334Speter "\t.def\t.bb%s\t.val\t.%s\t.scl\t100%s\t.line\t%d%s\t.endef\n", \ 21718334Speter SDB_DELIM, SDB_DELIM, SDB_DELIM, (LINE), SDB_DELIM) 21818334Speter#endif 21918334Speter 22018334Speter#ifndef PUT_SDB_BLOCK_END 22118334Speter#define PUT_SDB_BLOCK_END(LINE) \ 22218334Speter fprintf (asm_out_file, \ 22318334Speter "\t.def\t.eb%s\t.val\t.%s\t.scl\t100%s\t.line\t%d%s\t.endef\n", \ 22418334Speter SDB_DELIM, SDB_DELIM, SDB_DELIM, (LINE), SDB_DELIM) 22518334Speter#endif 22618334Speter 22718334Speter#ifndef PUT_SDB_FUNCTION_START 22818334Speter#define PUT_SDB_FUNCTION_START(LINE) \ 22918334Speter fprintf (asm_out_file, \ 23018334Speter "\t.def\t.bf%s\t.val\t.%s\t.scl\t101%s\t.line\t%d%s\t.endef\n", \ 23118334Speter SDB_DELIM, SDB_DELIM, SDB_DELIM, (LINE), SDB_DELIM) 23218334Speter#endif 23318334Speter 23418334Speter#ifndef PUT_SDB_FUNCTION_END 23518334Speter#define PUT_SDB_FUNCTION_END(LINE) \ 23618334Speter fprintf (asm_out_file, \ 23718334Speter "\t.def\t.ef%s\t.val\t.%s\t.scl\t101%s\t.line\t%d%s\t.endef\n", \ 23818334Speter SDB_DELIM, SDB_DELIM, SDB_DELIM, (LINE), SDB_DELIM) 23918334Speter#endif 24018334Speter 24118334Speter#ifndef SDB_GENERATE_FAKE 24218334Speter#define SDB_GENERATE_FAKE(BUFFER, NUMBER) \ 24318334Speter sprintf ((BUFFER), ".%dfake", (NUMBER)); 24418334Speter#endif 24518334Speter 24618334Speter/* Return the sdb tag identifier string for TYPE 24790075Sobrien if TYPE has already been defined; otherwise return a null pointer. */ 24818334Speter 24918334Speter#define KNOWN_TYPE_TAG(type) TYPE_SYMTAB_POINTER (type) 25018334Speter 25118334Speter/* Set the sdb tag identifier string for TYPE to NAME. */ 25218334Speter 25318334Speter#define SET_KNOWN_TYPE_TAG(TYPE, NAME) \ 25418334Speter TYPE_SYMTAB_POINTER (TYPE) = (NAME) 25518334Speter 25618334Speter/* Return the name (a string) of the struct, union or enum tag 25718334Speter described by the TREE_LIST node LINK. This is 0 for an anonymous one. */ 25818334Speter 25918334Speter#define TAG_NAME(link) \ 26018334Speter (((link) && TREE_PURPOSE ((link)) \ 26118334Speter && IDENTIFIER_POINTER (TREE_PURPOSE ((link)))) \ 26218334Speter ? IDENTIFIER_POINTER (TREE_PURPOSE ((link))) : (char *) 0) 26318334Speter 26418334Speter/* Ensure we don't output a negative line number. */ 26518334Speter#define MAKE_LINE_SAFE(line) \ 26690075Sobrien if ((int) line <= sdb_begin_function_line) \ 26790075Sobrien line = sdb_begin_function_line + 1 26850397Sobrien 26950397Sobrien/* Perform linker optimization of merging header file definitions together 27050397Sobrien for targets with MIPS_DEBUGGING_INFO defined. This won't work without a 27150397Sobrien post 960826 version of GAS. Nothing breaks with earlier versions of GAS, 27250397Sobrien the optimization just won't be done. The native assembler already has the 27350397Sobrien necessary support. */ 27450397Sobrien 27550397Sobrien#ifdef MIPS_DEBUGGING_INFO 27650397Sobrien 27750397Sobrien#ifndef PUT_SDB_SRC_FILE 27850397Sobrien#define PUT_SDB_SRC_FILE(FILENAME) \ 27950397Sobrienoutput_file_directive (asm_out_file, (FILENAME)) 28050397Sobrien#endif 28150397Sobrien 28250397Sobrien/* ECOFF linkers have an optimization that does the same kind of thing as 28350397Sobrien N_BINCL/E_INCL in stabs: eliminate duplicate debug information in the 28450397Sobrien executable. To achieve this, GCC must output a .file for each file 28550397Sobrien name change. */ 28650397Sobrien 28750397Sobrien/* This is a stack of input files. */ 28850397Sobrien 28950397Sobrienstruct sdb_file 29050397Sobrien{ 29150397Sobrien struct sdb_file *next; 29290075Sobrien const char *name; 29350397Sobrien}; 29450397Sobrien 29550397Sobrien/* This is the top of the stack. */ 29650397Sobrien 29750397Sobrienstatic struct sdb_file *current_file; 29850397Sobrien 29950397Sobrien#endif /* MIPS_DEBUGGING_INFO */ 30018334Speter 30190075Sobrien/* The debug hooks structure. */ 30290075Sobrienstruct gcc_debug_hooks sdb_debug_hooks = 30318334Speter{ 30490075Sobrien sdbout_init, /* init */ 30590075Sobrien sdbout_finish, /* finish */ 30690075Sobrien debug_nothing_int_charstar, /* define */ 30790075Sobrien debug_nothing_int_charstar, /* undef */ 30890075Sobrien sdbout_start_source_file, /* start_source_file */ 30990075Sobrien sdbout_end_source_file, /* end_source_file */ 31090075Sobrien sdbout_begin_block, /* begin_block */ 31190075Sobrien sdbout_end_block, /* end_block */ 31290075Sobrien debug_true_tree, /* ignore_block */ 31390075Sobrien sdbout_source_line, /* source_line */ 31450397Sobrien#ifdef MIPS_DEBUGGING_INFO 31590075Sobrien /* Defer on MIPS systems so that parameter descriptions follow 31690075Sobrien function entry. */ 31790075Sobrien debug_nothing_int_charstar, /* begin_prologue */ 31890075Sobrien sdbout_end_prologue, /* end_prologue */ 31990075Sobrien#else 32090075Sobrien sdbout_begin_prologue, /* begin_prologue */ 32190075Sobrien debug_nothing_int, /* end_prologue */ 32250397Sobrien#endif 32390075Sobrien sdbout_end_epilogue, /* end_epilogue */ 32490075Sobrien sdbout_begin_function, /* begin_function */ 32590075Sobrien sdbout_end_function, /* end_function */ 32690075Sobrien debug_nothing_tree, /* function_decl */ 32790075Sobrien sdbout_global_decl, /* global_decl */ 32890075Sobrien debug_nothing_tree, /* deferred_inline_function */ 32990075Sobrien debug_nothing_tree, /* outlining_inline_function */ 33090075Sobrien sdbout_label 33190075Sobrien}; 33290075Sobrien 33318334Speter#if 0 33418334Speter 33518334Speter/* return the tag identifier for type 33618334Speter */ 33718334Speter 33818334Speterchar * 33918334Spetertag_of_ru_type (type,link) 34018334Speter tree type,link; 34118334Speter{ 34218334Speter if (TYPE_SYMTAB_ADDRESS (type)) 34318334Speter return TYPE_SYMTAB_ADDRESS (type); 34418334Speter if (link && TREE_PURPOSE (link) 34518334Speter && IDENTIFIER_POINTER (TREE_PURPOSE (link))) 34618334Speter TYPE_SYMTAB_ADDRESS (type) = IDENTIFIER_POINTER (TREE_PURPOSE (link)); 34718334Speter else 34818334Speter return (char *) TYPE_SYMTAB_ADDRESS (type); 34918334Speter} 35018334Speter#endif 35118334Speter 35218334Speter/* Return a unique string to name an anonymous type. */ 35318334Speter 35418334Speterstatic char * 35518334Spetergen_fake_label () 35618334Speter{ 35718334Speter char label[10]; 35818334Speter char *labelstr; 35918334Speter SDB_GENERATE_FAKE (label, unnamed_struct_number); 36018334Speter unnamed_struct_number++; 36118334Speter labelstr = (char *) permalloc (strlen (label) + 1); 36218334Speter strcpy (labelstr, label); 36318334Speter return labelstr; 36418334Speter} 36518334Speter 36618334Speter/* Return the number which describes TYPE for SDB. 36718334Speter For pointers, etc., this function is recursive. 36818334Speter Each record, union or enumeral type must already have had a 36918334Speter tag number output. */ 37018334Speter 37118334Speter/* The number is given by d6d5d4d3d2d1bbbb 37218334Speter where bbbb is 4 bit basic type, and di indicate one of notype,ptr,fn,array. 37318334Speter Thus, char *foo () has bbbb=T_CHAR 37418334Speter d1=D_FCN 37518334Speter d2=D_PTR 37618334Speter N_BTMASK= 017 1111 basic type field. 37718334Speter N_TSHIFT= 2 derived type shift 37818334Speter N_BTSHFT= 4 Basic type shift */ 37918334Speter 38018334Speter/* Produce the number that describes a pointer, function or array type. 38118334Speter PREV is the number describing the target, value or element type. 38218334Speter DT_type describes how to transform that type. */ 38318334Speter#define PUSH_DERIVED_LEVEL(DT_type,PREV) \ 38490075Sobrien ((((PREV) & ~(int) N_BTMASK) << (int) N_TSHIFT) \ 38590075Sobrien | ((int) DT_type << (int) N_BTSHFT) \ 38690075Sobrien | ((PREV) & (int) N_BTMASK)) 38718334Speter 38818334Speter/* Number of elements used in sdb_dims. */ 38918334Speterstatic int sdb_n_dims = 0; 39018334Speter 39118334Speter/* Table of array dimensions of current type. */ 39218334Speterstatic int sdb_dims[SDB_MAX_DIM]; 39318334Speter 39418334Speter/* Size of outermost array currently being processed. */ 39518334Speterstatic int sdb_type_size = -1; 39618334Speter 39718334Speterstatic int 39818334Speterplain_type (type) 39918334Speter tree type; 40018334Speter{ 40118334Speter int val = plain_type_1 (type, 0); 40218334Speter 40318334Speter /* If we have already saved up some array dimensions, print them now. */ 40418334Speter if (sdb_n_dims > 0) 40518334Speter { 40618334Speter int i; 40718334Speter PUT_SDB_START_DIM; 40818334Speter for (i = sdb_n_dims - 1; i > 0; i--) 40918334Speter PUT_SDB_NEXT_DIM (sdb_dims[i]); 41018334Speter PUT_SDB_LAST_DIM (sdb_dims[0]); 41118334Speter sdb_n_dims = 0; 41218334Speter 41318334Speter sdb_type_size = int_size_in_bytes (type); 41418334Speter /* Don't kill sdb if type is not laid out or has variable size. */ 41518334Speter if (sdb_type_size < 0) 41618334Speter sdb_type_size = 0; 41718334Speter } 41818334Speter /* If we have computed the size of an array containing this type, 41918334Speter print it now. */ 42018334Speter if (sdb_type_size >= 0) 42118334Speter { 42218334Speter PUT_SDB_SIZE (sdb_type_size); 42318334Speter sdb_type_size = -1; 42418334Speter } 42518334Speter return val; 42618334Speter} 42718334Speter 42818334Speterstatic int 42918334Spetertemplate_name_p (name) 43018334Speter tree name; 43118334Speter{ 43290075Sobrien const char *ptr = IDENTIFIER_POINTER (name); 43318334Speter while (*ptr && *ptr != '<') 43418334Speter ptr++; 43518334Speter 43618334Speter return *ptr != '\0'; 43718334Speter} 43818334Speter 43918334Speterstatic void 44018334Spetersdbout_record_type_name (type) 44118334Speter tree type; 44218334Speter{ 44390075Sobrien const char *name = 0; 44418334Speter int no_name; 44518334Speter 44618334Speter if (KNOWN_TYPE_TAG (type)) 44718334Speter return; 44818334Speter 44918334Speter if (TYPE_NAME (type) != 0) 45018334Speter { 45118334Speter tree t = 0; 45290075Sobrien 45318334Speter /* Find the IDENTIFIER_NODE for the type name. */ 45418334Speter if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE) 45518334Speter t = TYPE_NAME (type); 45618334Speter else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL) 45718334Speter { 45818334Speter t = DECL_NAME (TYPE_NAME (type)); 45918334Speter /* The DECL_NAME for templates includes "<>", which breaks 46018334Speter most assemblers. Use its assembler name instead, which 46118334Speter has been mangled into being safe. */ 46218334Speter if (t && template_name_p (t)) 46318334Speter t = DECL_ASSEMBLER_NAME (TYPE_NAME (type)); 46418334Speter } 46518334Speter 46618334Speter /* Now get the name as a string, or invent one. */ 46718334Speter if (t != NULL_TREE) 46818334Speter name = IDENTIFIER_POINTER (t); 46918334Speter } 47018334Speter 47118334Speter no_name = (name == 0 || *name == 0); 47218334Speter if (no_name) 47318334Speter name = gen_fake_label (); 47418334Speter 47518334Speter SET_KNOWN_TYPE_TAG (type, name); 47618334Speter#ifdef SDB_ALLOW_FORWARD_REFERENCES 47718334Speter if (no_name) 47818334Speter sdbout_queue_anonymous_type (type); 47918334Speter#endif 48018334Speter} 48118334Speter 48218334Speter/* Return the .type value for type TYPE. 48318334Speter 48418334Speter LEVEL indicates how many levels deep we have recursed into the type. 48518334Speter The SDB debug format can only represent 6 derived levels of types. 48618334Speter After that, we must output inaccurate debug info. We deliberately 48718334Speter stop before the 7th level, so that ADA recursive types will not give an 48818334Speter infinite loop. */ 48918334Speter 49018334Speterstatic int 49118334Speterplain_type_1 (type, level) 49218334Speter tree type; 49318334Speter int level; 49418334Speter{ 49518334Speter if (type == 0) 49618334Speter type = void_type_node; 49718334Speter else if (type == error_mark_node) 49818334Speter type = integer_type_node; 49918334Speter else 50018334Speter type = TYPE_MAIN_VARIANT (type); 50118334Speter 50218334Speter switch (TREE_CODE (type)) 50318334Speter { 50418334Speter case VOID_TYPE: 50518334Speter return T_VOID; 50652284Sobrien case BOOLEAN_TYPE: 50718334Speter case INTEGER_TYPE: 50818334Speter { 50918334Speter int size = int_size_in_bytes (type) * BITS_PER_UNIT; 51018334Speter 51118334Speter /* Carefully distinguish all the standard types of C, 51218334Speter without messing up if the language is not C. 51318334Speter Note that we check only for the names that contain spaces; 51418334Speter other names might occur by coincidence in other languages. */ 51518334Speter if (TYPE_NAME (type) != 0 51618334Speter && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL 51718334Speter && DECL_NAME (TYPE_NAME (type)) != 0 51818334Speter && TREE_CODE (DECL_NAME (TYPE_NAME (type))) == IDENTIFIER_NODE) 51918334Speter { 52090075Sobrien const char *const name 52190075Sobrien = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))); 52218334Speter 52350397Sobrien if (!strcmp (name, "char")) 52450397Sobrien return T_CHAR; 52518334Speter if (!strcmp (name, "unsigned char")) 52618334Speter return T_UCHAR; 52718334Speter if (!strcmp (name, "signed char")) 52818334Speter return T_CHAR; 52950397Sobrien if (!strcmp (name, "int")) 53050397Sobrien return T_INT; 53118334Speter if (!strcmp (name, "unsigned int")) 53218334Speter return T_UINT; 53318334Speter if (!strcmp (name, "short int")) 53418334Speter return T_SHORT; 53518334Speter if (!strcmp (name, "short unsigned int")) 53618334Speter return T_USHORT; 53718334Speter if (!strcmp (name, "long int")) 53818334Speter return T_LONG; 53918334Speter if (!strcmp (name, "long unsigned int")) 54018334Speter return T_ULONG; 54118334Speter } 54218334Speter 54350397Sobrien if (size == INT_TYPE_SIZE) 54450397Sobrien return (TREE_UNSIGNED (type) ? T_UINT : T_INT); 54518334Speter if (size == CHAR_TYPE_SIZE) 54618334Speter return (TREE_UNSIGNED (type) ? T_UCHAR : T_CHAR); 54718334Speter if (size == SHORT_TYPE_SIZE) 54818334Speter return (TREE_UNSIGNED (type) ? T_USHORT : T_SHORT); 54918334Speter if (size == LONG_TYPE_SIZE) 55018334Speter return (TREE_UNSIGNED (type) ? T_ULONG : T_LONG); 55118334Speter if (size == LONG_LONG_TYPE_SIZE) /* better than nothing */ 55218334Speter return (TREE_UNSIGNED (type) ? T_ULONG : T_LONG); 55318334Speter return 0; 55418334Speter } 55518334Speter 55618334Speter case REAL_TYPE: 55718334Speter { 55850397Sobrien int precision = TYPE_PRECISION (type); 55950397Sobrien if (precision == FLOAT_TYPE_SIZE) 56018334Speter return T_FLOAT; 56150397Sobrien if (precision == DOUBLE_TYPE_SIZE) 56218334Speter return T_DOUBLE; 56350397Sobrien#ifdef EXTENDED_SDB_BASIC_TYPES 56450397Sobrien if (precision == LONG_DOUBLE_TYPE_SIZE) 56550397Sobrien return T_LNGDBL; 56650397Sobrien#else 56750397Sobrien if (precision == LONG_DOUBLE_TYPE_SIZE) 56850397Sobrien return T_DOUBLE; /* better than nothing */ 56950397Sobrien#endif 57018334Speter return 0; 57118334Speter } 57218334Speter 57318334Speter case ARRAY_TYPE: 57418334Speter { 57518334Speter int m; 57618334Speter if (level >= 6) 57718334Speter return T_VOID; 57818334Speter else 57918334Speter m = plain_type_1 (TREE_TYPE (type), level+1); 58018334Speter if (sdb_n_dims < SDB_MAX_DIM) 58118334Speter sdb_dims[sdb_n_dims++] 58218334Speter = (TYPE_DOMAIN (type) 58390075Sobrien && TYPE_MIN_VALUE (TYPE_DOMAIN (type)) != 0 58490075Sobrien && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) != 0 58590075Sobrien && host_integerp (TYPE_MAX_VALUE (TYPE_DOMAIN (type)), 0) 58690075Sobrien && host_integerp (TYPE_MIN_VALUE (TYPE_DOMAIN (type)), 0) 58790075Sobrien ? (tree_low_cst (TYPE_MAX_VALUE (TYPE_DOMAIN (type)), 0) 58890075Sobrien - tree_low_cst (TYPE_MIN_VALUE (TYPE_DOMAIN (type)), 0) + 1) 58918334Speter : 0); 59090075Sobrien 59118334Speter return PUSH_DERIVED_LEVEL (DT_ARY, m); 59218334Speter } 59318334Speter 59418334Speter case RECORD_TYPE: 59518334Speter case UNION_TYPE: 59618334Speter case QUAL_UNION_TYPE: 59718334Speter case ENUMERAL_TYPE: 59818334Speter { 59918334Speter char *tag; 60018334Speter#ifdef SDB_ALLOW_FORWARD_REFERENCES 60118334Speter sdbout_record_type_name (type); 60218334Speter#endif 60318334Speter#ifndef SDB_ALLOW_UNKNOWN_REFERENCES 60418334Speter if ((TREE_ASM_WRITTEN (type) && KNOWN_TYPE_TAG (type) != 0) 60518334Speter#ifdef SDB_ALLOW_FORWARD_REFERENCES 60618334Speter || TYPE_MODE (type) != VOIDmode 60718334Speter#endif 60818334Speter ) 60918334Speter#endif 61018334Speter { 61118334Speter /* Output the referenced structure tag name 61218334Speter only if the .def has already been finished. 61318334Speter At least on 386, the Unix assembler 61418334Speter cannot handle forward references to tags. */ 61550397Sobrien /* But the 88100, it requires them, sigh... */ 61650397Sobrien /* And the MIPS requires unknown refs as well... */ 61718334Speter tag = KNOWN_TYPE_TAG (type); 61818334Speter PUT_SDB_TAG (tag); 61918334Speter /* These 3 lines used to follow the close brace. 62018334Speter However, a size of 0 without a tag implies a tag of 0, 62118334Speter so if we don't know a tag, we can't mention the size. */ 62218334Speter sdb_type_size = int_size_in_bytes (type); 62318334Speter if (sdb_type_size < 0) 62418334Speter sdb_type_size = 0; 62518334Speter } 62618334Speter return ((TREE_CODE (type) == RECORD_TYPE) ? T_STRUCT 62718334Speter : (TREE_CODE (type) == UNION_TYPE) ? T_UNION 62818334Speter : (TREE_CODE (type) == QUAL_UNION_TYPE) ? T_UNION 62918334Speter : T_ENUM); 63018334Speter } 63118334Speter case POINTER_TYPE: 63218334Speter case REFERENCE_TYPE: 63318334Speter { 63418334Speter int m; 63518334Speter if (level >= 6) 63618334Speter return T_VOID; 63718334Speter else 63818334Speter m = plain_type_1 (TREE_TYPE (type), level+1); 63918334Speter return PUSH_DERIVED_LEVEL (DT_PTR, m); 64018334Speter } 64118334Speter case FUNCTION_TYPE: 64218334Speter case METHOD_TYPE: 64318334Speter { 64418334Speter int m; 64518334Speter if (level >= 6) 64618334Speter return T_VOID; 64718334Speter else 64818334Speter m = plain_type_1 (TREE_TYPE (type), level+1); 64918334Speter return PUSH_DERIVED_LEVEL (DT_FCN, m); 65018334Speter } 65118334Speter default: 65218334Speter return 0; 65318334Speter } 65418334Speter} 65518334Speter 65618334Speter/* Output the symbols defined in block number DO_BLOCK. 65718334Speter 65818334Speter This function works by walking the tree structure of blocks, 65918334Speter counting blocks until it finds the desired block. */ 66018334Speter 66118334Speterstatic int do_block = 0; 66218334Speter 66318334Speterstatic void 66418334Spetersdbout_block (block) 66590075Sobrien tree block; 66618334Speter{ 66718334Speter while (block) 66818334Speter { 66918334Speter /* Ignore blocks never expanded or otherwise marked as real. */ 67018334Speter if (TREE_USED (block)) 67118334Speter { 67218334Speter /* When we reach the specified block, output its symbols. */ 67390075Sobrien if (BLOCK_NUMBER (block) == do_block) 67490075Sobrien sdbout_syms (BLOCK_VARS (block)); 67518334Speter 67618334Speter /* If we are past the specified block, stop the scan. */ 67790075Sobrien if (BLOCK_NUMBER (block) > do_block) 67818334Speter return; 67918334Speter 68018334Speter /* Scan the blocks within this block. */ 68118334Speter sdbout_block (BLOCK_SUBBLOCKS (block)); 68218334Speter } 68318334Speter 68418334Speter block = BLOCK_CHAIN (block); 68518334Speter } 68618334Speter} 68718334Speter 68818334Speter/* Call sdbout_symbol on each decl in the chain SYMS. */ 68918334Speter 69018334Speterstatic void 69118334Spetersdbout_syms (syms) 69218334Speter tree syms; 69318334Speter{ 69418334Speter while (syms) 69518334Speter { 69618334Speter if (TREE_CODE (syms) != LABEL_DECL) 69718334Speter sdbout_symbol (syms, 1); 69818334Speter syms = TREE_CHAIN (syms); 69918334Speter } 70018334Speter} 70118334Speter 70218334Speter/* Output SDB information for a symbol described by DECL. 70318334Speter LOCAL is nonzero if the symbol is not file-scope. */ 70418334Speter 70518334Spetervoid 70618334Spetersdbout_symbol (decl, local) 70718334Speter tree decl; 70818334Speter int local; 70918334Speter{ 71018334Speter tree type = TREE_TYPE (decl); 71118334Speter tree context = NULL_TREE; 71218334Speter rtx value; 71318334Speter int regno = -1; 71490075Sobrien const char *name; 71518334Speter 71618334Speter sdbout_one_type (type); 71718334Speter 71818334Speter#if 0 /* This loses when functions are marked to be ignored, 71918334Speter which happens in the C++ front end. */ 72018334Speter if (DECL_IGNORED_P (decl)) 72118334Speter return; 72218334Speter#endif 72318334Speter 72418334Speter switch (TREE_CODE (decl)) 72518334Speter { 72618334Speter case CONST_DECL: 72718334Speter /* Enum values are defined by defining the enum type. */ 72818334Speter return; 72918334Speter 73018334Speter case FUNCTION_DECL: 73118334Speter /* Don't mention a nested function under its parent. */ 73218334Speter context = decl_function_context (decl); 73318334Speter if (context == current_function_decl) 73418334Speter return; 73550397Sobrien /* Check DECL_INITIAL to distinguish declarations from definitions. 73650397Sobrien Don't output debug info here for declarations; they will have 73750397Sobrien a DECL_INITIAL value of 0. */ 73850397Sobrien if (! DECL_INITIAL (decl)) 73918334Speter return; 74018334Speter if (GET_CODE (DECL_RTL (decl)) != MEM 74118334Speter || GET_CODE (XEXP (DECL_RTL (decl), 0)) != SYMBOL_REF) 74218334Speter return; 74318334Speter PUT_SDB_DEF (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))); 74418334Speter PUT_SDB_VAL (XEXP (DECL_RTL (decl), 0)); 74518334Speter PUT_SDB_SCL (TREE_PUBLIC (decl) ? C_EXT : C_STAT); 74618334Speter break; 74718334Speter 74818334Speter case TYPE_DECL: 74918334Speter /* Done with tagged types. */ 75018334Speter if (DECL_NAME (decl) == 0) 75118334Speter return; 75218334Speter if (DECL_IGNORED_P (decl)) 75318334Speter return; 75418334Speter 75518334Speter /* Output typedef name. */ 75618334Speter if (template_name_p (DECL_NAME (decl))) 75718334Speter PUT_SDB_DEF (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))); 75818334Speter else 75918334Speter PUT_SDB_DEF (IDENTIFIER_POINTER (DECL_NAME (decl))); 76018334Speter PUT_SDB_SCL (C_TPDEF); 76118334Speter break; 76218334Speter 76318334Speter case PARM_DECL: 76418334Speter /* Parm decls go in their own separate chains 76518334Speter and are output by sdbout_reg_parms and sdbout_parms. */ 76618334Speter abort (); 76718334Speter 76818334Speter case VAR_DECL: 76918334Speter /* Don't mention a variable that is external. 77018334Speter Let the file that defines it describe it. */ 77118334Speter if (DECL_EXTERNAL (decl)) 77218334Speter return; 77318334Speter 77418334Speter /* Ignore __FUNCTION__, etc. */ 77518334Speter if (DECL_IGNORED_P (decl)) 77618334Speter return; 77718334Speter 77818334Speter /* If there was an error in the declaration, don't dump core 77918334Speter if there is no RTL associated with the variable doesn't 78018334Speter exist. */ 78190075Sobrien if (!DECL_RTL_SET_P (decl)) 78218334Speter return; 78318334Speter 78490075Sobrien SET_DECL_RTL (decl, 78590075Sobrien eliminate_regs (DECL_RTL (decl), 0, NULL_RTX)); 78618334Speter#ifdef LEAF_REG_REMAP 78752284Sobrien if (current_function_uses_only_leaf_regs) 78818334Speter leaf_renumber_regs_insn (DECL_RTL (decl)); 78918334Speter#endif 79018334Speter value = DECL_RTL (decl); 79118334Speter 79218334Speter /* Don't mention a variable at all 79318334Speter if it was completely optimized into nothingness. 79418334Speter 79518334Speter If DECL was from an inline function, then its rtl 79618334Speter is not identically the rtl that was used in this 79718334Speter particular compilation. */ 79818334Speter if (GET_CODE (value) == REG) 79918334Speter { 80090075Sobrien regno = REGNO (value); 80118334Speter if (regno >= FIRST_PSEUDO_REGISTER) 80218334Speter return; 80318334Speter } 80418334Speter else if (GET_CODE (value) == SUBREG) 80518334Speter { 80618334Speter while (GET_CODE (value) == SUBREG) 80790075Sobrien value = SUBREG_REG (value); 80818334Speter if (GET_CODE (value) == REG) 80918334Speter { 81090075Sobrien if (REGNO (value) >= FIRST_PSEUDO_REGISTER) 81118334Speter return; 81218334Speter } 81390075Sobrien regno = REGNO (alter_subreg (&value)); 81490075Sobrien SET_DECL_RTL (decl, value); 81518334Speter } 81618334Speter /* Don't output anything if an auto variable 81718334Speter gets RTL that is static. 81818334Speter GAS version 2.2 can't handle such output. */ 81918334Speter else if (GET_CODE (value) == MEM && CONSTANT_P (XEXP (value, 0)) 82018334Speter && ! TREE_STATIC (decl)) 82118334Speter return; 82218334Speter 82318334Speter /* Emit any structure, union, or enum type that has not been output. 82418334Speter This occurs for tag-less structs (et al) used to declare variables 82518334Speter within functions. */ 82618334Speter if (TREE_CODE (type) == ENUMERAL_TYPE 82718334Speter || TREE_CODE (type) == RECORD_TYPE 82818334Speter || TREE_CODE (type) == UNION_TYPE 82918334Speter || TREE_CODE (type) == QUAL_UNION_TYPE) 83018334Speter { 83190075Sobrien if (COMPLETE_TYPE_P (type) /* not a forward reference */ 83218334Speter && KNOWN_TYPE_TAG (type) == 0) /* not yet declared */ 83318334Speter sdbout_one_type (type); 83418334Speter } 83518334Speter 83618334Speter /* Defer SDB information for top-level initialized variables! */ 83718334Speter if (! local 83818334Speter && GET_CODE (value) == MEM 83918334Speter && DECL_INITIAL (decl)) 84018334Speter return; 84118334Speter 84218334Speter /* C++ in 2.3 makes nameless symbols. That will be fixed later. 84318334Speter For now, avoid crashing. */ 84418334Speter if (DECL_NAME (decl) == NULL_TREE) 84518334Speter return; 84618334Speter 84718334Speter /* Record the name for, starting a symtab entry. */ 84890075Sobrien if (local) 84990075Sobrien name = IDENTIFIER_POINTER (DECL_NAME (decl)); 85090075Sobrien else 85190075Sobrien name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); 85218334Speter 85318334Speter if (GET_CODE (value) == MEM 85418334Speter && GET_CODE (XEXP (value, 0)) == SYMBOL_REF) 85518334Speter { 85618334Speter PUT_SDB_DEF (name); 85718334Speter if (TREE_PUBLIC (decl)) 85818334Speter { 85918334Speter PUT_SDB_VAL (XEXP (value, 0)); 86018334Speter PUT_SDB_SCL (C_EXT); 86118334Speter } 86218334Speter else 86318334Speter { 86418334Speter PUT_SDB_VAL (XEXP (value, 0)); 86518334Speter PUT_SDB_SCL (C_STAT); 86618334Speter } 86718334Speter } 86818334Speter else if (regno >= 0) 86918334Speter { 87018334Speter PUT_SDB_DEF (name); 87118334Speter PUT_SDB_INT_VAL (DBX_REGISTER_NUMBER (regno)); 87218334Speter PUT_SDB_SCL (C_REG); 87318334Speter } 87418334Speter else if (GET_CODE (value) == MEM 87518334Speter && (GET_CODE (XEXP (value, 0)) == MEM 87618334Speter || (GET_CODE (XEXP (value, 0)) == REG 87718334Speter && REGNO (XEXP (value, 0)) != HARD_FRAME_POINTER_REGNUM 87818334Speter && REGNO (XEXP (value, 0)) != STACK_POINTER_REGNUM))) 87918334Speter /* If the value is indirect by memory or by a register 88018334Speter that isn't the frame pointer 88118334Speter then it means the object is variable-sized and address through 88218334Speter that register or stack slot. COFF has no way to represent this 88318334Speter so all we can do is output the variable as a pointer. */ 88418334Speter { 88518334Speter PUT_SDB_DEF (name); 88618334Speter if (GET_CODE (XEXP (value, 0)) == REG) 88718334Speter { 88818334Speter PUT_SDB_INT_VAL (DBX_REGISTER_NUMBER (REGNO (XEXP (value, 0)))); 88918334Speter PUT_SDB_SCL (C_REG); 89018334Speter } 89118334Speter else 89218334Speter { 89318334Speter /* DECL_RTL looks like (MEM (MEM (PLUS (REG...) 89418334Speter (CONST_INT...)))). 89518334Speter We want the value of that CONST_INT. */ 89618334Speter /* Encore compiler hates a newline in a macro arg, it seems. */ 89718334Speter PUT_SDB_INT_VAL (DEBUGGER_AUTO_OFFSET 89818334Speter (XEXP (XEXP (value, 0), 0))); 89918334Speter PUT_SDB_SCL (C_AUTO); 90018334Speter } 90118334Speter 90252284Sobrien /* Effectively do build_pointer_type, but don't cache this type, 90352284Sobrien since it might be temporary whereas the type it points to 90452284Sobrien might have been saved for inlining. */ 90552284Sobrien /* Don't use REFERENCE_TYPE because dbx can't handle that. */ 90652284Sobrien type = make_node (POINTER_TYPE); 90752284Sobrien TREE_TYPE (type) = TREE_TYPE (decl); 90818334Speter } 90918334Speter else if (GET_CODE (value) == MEM 91018334Speter && ((GET_CODE (XEXP (value, 0)) == PLUS 91118334Speter && GET_CODE (XEXP (XEXP (value, 0), 0)) == REG 91218334Speter && GET_CODE (XEXP (XEXP (value, 0), 1)) == CONST_INT) 91318334Speter /* This is for variables which are at offset zero from 91418334Speter the frame pointer. This happens on the Alpha. 91518334Speter Non-frame pointer registers are excluded above. */ 91618334Speter || (GET_CODE (XEXP (value, 0)) == REG))) 91718334Speter { 91818334Speter /* DECL_RTL looks like (MEM (PLUS (REG...) (CONST_INT...))) 91918334Speter or (MEM (REG...)). We want the value of that CONST_INT 92018334Speter or zero. */ 92118334Speter PUT_SDB_DEF (name); 92218334Speter PUT_SDB_INT_VAL (DEBUGGER_AUTO_OFFSET (XEXP (value, 0))); 92318334Speter PUT_SDB_SCL (C_AUTO); 92418334Speter } 92518334Speter else if (GET_CODE (value) == MEM && GET_CODE (XEXP (value, 0)) == CONST) 92618334Speter { 92718334Speter /* Handle an obscure case which can arise when optimizing and 92818334Speter when there are few available registers. (This is *always* 92918334Speter the case for i386/i486 targets). The DECL_RTL looks like 93018334Speter (MEM (CONST ...)) even though this variable is a local `auto' 93118334Speter or a local `register' variable. In effect, what has happened 93218334Speter is that the reload pass has seen that all assignments and 93318334Speter references for one such a local variable can be replaced by 93418334Speter equivalent assignments and references to some static storage 93518334Speter variable, thereby avoiding the need for a register. In such 93618334Speter cases we're forced to lie to debuggers and tell them that 93718334Speter this variable was itself `static'. */ 93818334Speter PUT_SDB_DEF (name); 93918334Speter PUT_SDB_VAL (XEXP (XEXP (value, 0), 0)); 94018334Speter PUT_SDB_SCL (C_STAT); 94118334Speter } 94218334Speter else 94318334Speter { 94418334Speter /* It is something we don't know how to represent for SDB. */ 94518334Speter return; 94618334Speter } 94718334Speter break; 94850397Sobrien 94950397Sobrien default: 95050397Sobrien break; 95118334Speter } 95218334Speter PUT_SDB_TYPE (plain_type (type)); 95318334Speter PUT_SDB_ENDEF; 95418334Speter} 95518334Speter 95618334Speter/* Output SDB information for a top-level initialized variable 95718334Speter that has been delayed. */ 95818334Speter 95990075Sobrienstatic void 96018334Spetersdbout_toplevel_data (decl) 96118334Speter tree decl; 96218334Speter{ 96318334Speter tree type = TREE_TYPE (decl); 96418334Speter 96518334Speter if (DECL_IGNORED_P (decl)) 96618334Speter return; 96718334Speter 96818334Speter if (! (TREE_CODE (decl) == VAR_DECL 96918334Speter && GET_CODE (DECL_RTL (decl)) == MEM 97018334Speter && DECL_INITIAL (decl))) 97118334Speter abort (); 97218334Speter 97318334Speter PUT_SDB_DEF (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))); 97418334Speter PUT_SDB_VAL (XEXP (DECL_RTL (decl), 0)); 97518334Speter if (TREE_PUBLIC (decl)) 97618334Speter { 97718334Speter PUT_SDB_SCL (C_EXT); 97818334Speter } 97918334Speter else 98018334Speter { 98118334Speter PUT_SDB_SCL (C_STAT); 98218334Speter } 98318334Speter PUT_SDB_TYPE (plain_type (type)); 98418334Speter PUT_SDB_ENDEF; 98518334Speter} 98618334Speter 98718334Speter#ifdef SDB_ALLOW_FORWARD_REFERENCES 98818334Speter 98950397Sobrien/* Machinery to record and output anonymous types. */ 99018334Speter 99118334Speterstatic tree anonymous_types; 99218334Speter 99318334Speterstatic void 99418334Spetersdbout_queue_anonymous_type (type) 99518334Speter tree type; 99618334Speter{ 99790075Sobrien anonymous_types = tree_cons (NULL_TREE, type, anonymous_types); 99818334Speter} 99918334Speter 100018334Speterstatic void 100118334Spetersdbout_dequeue_anonymous_types () 100218334Speter{ 100390075Sobrien tree types, link; 100418334Speter 100518334Speter while (anonymous_types) 100618334Speter { 100718334Speter types = nreverse (anonymous_types); 100818334Speter anonymous_types = NULL_TREE; 100918334Speter 101018334Speter for (link = types; link; link = TREE_CHAIN (link)) 101118334Speter { 101290075Sobrien tree type = TREE_VALUE (link); 101318334Speter 101418334Speter if (type && ! TREE_ASM_WRITTEN (type)) 101518334Speter sdbout_one_type (type); 101618334Speter } 101718334Speter } 101818334Speter} 101918334Speter 102018334Speter#endif 102118334Speter 102218334Speter/* Given a chain of ..._TYPE nodes, all of which have names, 102318334Speter output definitions of those names, as typedefs. */ 102418334Speter 102518334Spetervoid 102618334Spetersdbout_types (types) 102790075Sobrien tree types; 102818334Speter{ 102990075Sobrien tree link; 103018334Speter 103118334Speter for (link = types; link; link = TREE_CHAIN (link)) 103218334Speter sdbout_one_type (link); 103318334Speter 103418334Speter#ifdef SDB_ALLOW_FORWARD_REFERENCES 103518334Speter sdbout_dequeue_anonymous_types (); 103618334Speter#endif 103718334Speter} 103818334Speter 103918334Speterstatic void 104018334Spetersdbout_type (type) 104118334Speter tree type; 104218334Speter{ 104318334Speter if (type == error_mark_node) 104418334Speter type = integer_type_node; 104518334Speter PUT_SDB_TYPE (plain_type (type)); 104618334Speter} 104718334Speter 104818334Speter/* Output types of the fields of type TYPE, if they are structs. 104918334Speter 105018334Speter Formerly did not chase through pointer types, since that could be circular. 105118334Speter They must come before TYPE, since forward refs are not allowed. 105218334Speter Now james@bigtex.cactus.org says to try them. */ 105318334Speter 105418334Speterstatic void 105518334Spetersdbout_field_types (type) 105618334Speter tree type; 105718334Speter{ 105818334Speter tree tail; 105950397Sobrien 106018334Speter for (tail = TYPE_FIELDS (type); tail; tail = TREE_CHAIN (tail)) 106190075Sobrien /* This condition should match the one for emitting the actual 106290075Sobrien members below. */ 106352284Sobrien if (TREE_CODE (tail) == FIELD_DECL 106490075Sobrien && DECL_NAME (tail) 106590075Sobrien && DECL_SIZE (tail) 106690075Sobrien && host_integerp (DECL_SIZE (tail), 1) 106790075Sobrien && host_integerp (bit_position (tail), 0)) 106852284Sobrien { 106952284Sobrien if (POINTER_TYPE_P (TREE_TYPE (tail))) 107052284Sobrien sdbout_one_type (TREE_TYPE (TREE_TYPE (tail))); 107152284Sobrien else 107252284Sobrien sdbout_one_type (TREE_TYPE (tail)); 107352284Sobrien } 107418334Speter} 107518334Speter 107618334Speter/* Use this to put out the top level defined record and union types 107718334Speter for later reference. If this is a struct with a name, then put that 107818334Speter name out. Other unnamed structs will have .xxfake labels generated so 107918334Speter that they may be referred to later. 108018334Speter The label will be stored in the KNOWN_TYPE_TAG slot of a type. 108118334Speter It may NOT be called recursively. */ 108218334Speter 108318334Speterstatic void 108418334Spetersdbout_one_type (type) 108518334Speter tree type; 108618334Speter{ 108718334Speter if (current_function_decl != NULL_TREE 108818334Speter && DECL_SECTION_NAME (current_function_decl) != NULL_TREE) 108918334Speter ; /* Don't change section amid function. */ 109018334Speter else 109118334Speter text_section (); 109218334Speter 109318334Speter switch (TREE_CODE (type)) 109418334Speter { 109518334Speter case RECORD_TYPE: 109618334Speter case UNION_TYPE: 109718334Speter case QUAL_UNION_TYPE: 109818334Speter case ENUMERAL_TYPE: 109918334Speter type = TYPE_MAIN_VARIANT (type); 110018334Speter /* Don't output a type twice. */ 110118334Speter if (TREE_ASM_WRITTEN (type)) 110218334Speter /* James said test TREE_ASM_BEING_WRITTEN here. */ 110318334Speter return; 110418334Speter 110518334Speter /* Output nothing if type is not yet defined. */ 110690075Sobrien if (!COMPLETE_TYPE_P (type)) 110718334Speter return; 110818334Speter 110918334Speter TREE_ASM_WRITTEN (type) = 1; 111018334Speter#if 1 111118334Speter /* This is reputed to cause trouble with the following case, 111218334Speter but perhaps checking TYPE_SIZE above will fix it. */ 111318334Speter 111418334Speter /* Here is a test case: 111518334Speter 111618334Speter struct foo { 111718334Speter struct badstr *bbb; 111818334Speter } forwardref; 111918334Speter 112018334Speter typedef struct intermediate { 112118334Speter int aaaa; 112218334Speter } intermediate_ref; 112318334Speter 112418334Speter typedef struct badstr { 112518334Speter int ccccc; 112618334Speter } badtype; */ 112718334Speter 112818334Speter#if 0 112918334Speter TREE_ASM_BEING_WRITTEN (type) = 1; 113018334Speter#endif 113118334Speter /* This change, which ought to make better output, 113218334Speter used to make the COFF assembler unhappy. 113318334Speter Changes involving KNOWN_TYPE_TAG may fix the problem. */ 113418334Speter /* Before really doing anything, output types we want to refer to. */ 113518334Speter /* Note that in version 1 the following two lines 113618334Speter are not used if forward references are in use. */ 113718334Speter if (TREE_CODE (type) != ENUMERAL_TYPE) 113818334Speter sdbout_field_types (type); 113918334Speter#if 0 114018334Speter TREE_ASM_WRITTEN (type) = 1; 114118334Speter#endif 114218334Speter#endif 114318334Speter 114418334Speter /* Output a structure type. */ 114518334Speter { 114618334Speter int size = int_size_in_bytes (type); 114790075Sobrien int member_scl = 0; 114818334Speter tree tem; 114918334Speter int i, n_baseclasses = 0; 115018334Speter 115118334Speter /* Record the type tag, but not in its permanent place just yet. */ 115218334Speter sdbout_record_type_name (type); 115318334Speter 115418334Speter PUT_SDB_DEF (KNOWN_TYPE_TAG (type)); 115518334Speter 115618334Speter switch (TREE_CODE (type)) 115718334Speter { 115818334Speter case UNION_TYPE: 115918334Speter case QUAL_UNION_TYPE: 116018334Speter PUT_SDB_SCL (C_UNTAG); 116118334Speter PUT_SDB_TYPE (T_UNION); 116218334Speter member_scl = C_MOU; 116318334Speter break; 116418334Speter 116518334Speter case RECORD_TYPE: 116618334Speter PUT_SDB_SCL (C_STRTAG); 116718334Speter PUT_SDB_TYPE (T_STRUCT); 116818334Speter member_scl = C_MOS; 116918334Speter break; 117018334Speter 117118334Speter case ENUMERAL_TYPE: 117218334Speter PUT_SDB_SCL (C_ENTAG); 117318334Speter PUT_SDB_TYPE (T_ENUM); 117418334Speter member_scl = C_MOE; 117518334Speter break; 117650397Sobrien 117750397Sobrien default: 117850397Sobrien break; 117918334Speter } 118018334Speter 118118334Speter PUT_SDB_SIZE (size); 118218334Speter PUT_SDB_ENDEF; 118318334Speter 118418334Speter /* Print out the base class information with fields 118518334Speter named after the types they hold. */ 118690075Sobrien /* This is only relevant to aggregate types. TYPE_BINFO is used 118752284Sobrien for other purposes in an ENUMERAL_TYPE, so we must exclude that 118852284Sobrien case. */ 118952284Sobrien if (TREE_CODE (type) != ENUMERAL_TYPE) 119018334Speter { 119152284Sobrien if (TYPE_BINFO (type) 119252284Sobrien && TYPE_BINFO_BASETYPES (type)) 119352284Sobrien n_baseclasses = TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (type)); 119452284Sobrien for (i = 0; i < n_baseclasses; i++) 119518334Speter { 119652284Sobrien tree child = TREE_VEC_ELT (BINFO_BASETYPES (TYPE_BINFO (type)), 119752284Sobrien i); 119852284Sobrien tree child_type = BINFO_TYPE (child); 119952284Sobrien tree child_type_name; 120052284Sobrien if (TYPE_NAME (child_type) == 0) 120152284Sobrien continue; 120252284Sobrien if (TREE_CODE (TYPE_NAME (child_type)) == IDENTIFIER_NODE) 120352284Sobrien child_type_name = TYPE_NAME (child_type); 120452284Sobrien else if (TREE_CODE (TYPE_NAME (child_type)) == TYPE_DECL) 120552284Sobrien { 120652284Sobrien child_type_name = DECL_NAME (TYPE_NAME (child_type)); 120752284Sobrien if (child_type_name && template_name_p (child_type_name)) 120852284Sobrien child_type_name 120952284Sobrien = DECL_ASSEMBLER_NAME (TYPE_NAME (child_type)); 121052284Sobrien } 121152284Sobrien else 121252284Sobrien continue; 121352284Sobrien 121452284Sobrien CONTIN; 121552284Sobrien PUT_SDB_DEF (IDENTIFIER_POINTER (child_type_name)); 121690075Sobrien PUT_SDB_INT_VAL (tree_low_cst (BINFO_OFFSET (child), 0)); 121752284Sobrien PUT_SDB_SCL (member_scl); 121852284Sobrien sdbout_type (BINFO_TYPE (child)); 121952284Sobrien PUT_SDB_ENDEF; 122018334Speter } 122118334Speter } 122218334Speter 122318334Speter /* output the individual fields */ 122418334Speter 122518334Speter if (TREE_CODE (type) == ENUMERAL_TYPE) 122690075Sobrien { 122790075Sobrien for (tem = TYPE_FIELDS (type); tem; tem = TREE_CHAIN (tem)) 122890075Sobrien if (host_integerp (TREE_VALUE (tem), 0)) 122990075Sobrien { 123090075Sobrien PUT_SDB_DEF (IDENTIFIER_POINTER (TREE_PURPOSE (tem))); 123190075Sobrien PUT_SDB_INT_VAL (tree_low_cst (TREE_VALUE (tem), 0)); 123290075Sobrien PUT_SDB_SCL (C_MOE); 123390075Sobrien PUT_SDB_TYPE (T_MOE); 123490075Sobrien PUT_SDB_ENDEF; 123590075Sobrien } 123690075Sobrien } 123718334Speter else /* record or union type */ 123818334Speter for (tem = TYPE_FIELDS (type); tem; tem = TREE_CHAIN (tem)) 123918334Speter /* Output the name, type, position (in bits), size (in bits) 124018334Speter of each field. */ 124118334Speter 124218334Speter /* Omit here the nameless fields that are used to skip bits. 124318334Speter Also omit fields with variable size or position. 124418334Speter Also omit non FIELD_DECL nodes that GNU C++ may put here. */ 124518334Speter if (TREE_CODE (tem) == FIELD_DECL 124690075Sobrien && DECL_NAME (tem) 124790075Sobrien && DECL_SIZE (tem) 124890075Sobrien && host_integerp (DECL_SIZE (tem), 1) 124990075Sobrien && host_integerp (bit_position (tem), 0)) 125018334Speter { 125190075Sobrien const char *name; 125218334Speter 125318334Speter CONTIN; 125490075Sobrien name = IDENTIFIER_POINTER (DECL_NAME (tem)); 125518334Speter PUT_SDB_DEF (name); 125618334Speter if (DECL_BIT_FIELD_TYPE (tem)) 125718334Speter { 125890075Sobrien PUT_SDB_INT_VAL (int_bit_position (tem)); 125918334Speter PUT_SDB_SCL (C_FIELD); 126018334Speter sdbout_type (DECL_BIT_FIELD_TYPE (tem)); 126190075Sobrien PUT_SDB_SIZE (tree_low_cst (DECL_SIZE (tem), 1)); 126218334Speter } 126318334Speter else 126418334Speter { 126590075Sobrien PUT_SDB_INT_VAL (int_bit_position (tem) / BITS_PER_UNIT); 126618334Speter PUT_SDB_SCL (member_scl); 126718334Speter sdbout_type (TREE_TYPE (tem)); 126818334Speter } 126918334Speter PUT_SDB_ENDEF; 127018334Speter } 127118334Speter /* output end of a structure,union, or enumeral definition */ 127218334Speter 127318334Speter PUT_SDB_PLAIN_DEF ("eos"); 127418334Speter PUT_SDB_INT_VAL (size); 127518334Speter PUT_SDB_SCL (C_EOS); 127618334Speter PUT_SDB_TAG (KNOWN_TYPE_TAG (type)); 127718334Speter PUT_SDB_SIZE (size); 127818334Speter PUT_SDB_ENDEF; 127918334Speter break; 128050397Sobrien 128150397Sobrien default: 128250397Sobrien break; 128318334Speter } 128418334Speter } 128518334Speter} 128618334Speter 128718334Speter/* The following two functions output definitions of function parameters. 128818334Speter Each parameter gets a definition locating it in the parameter list. 128918334Speter Each parameter that is a register variable gets a second definition 129018334Speter locating it in the register. 129118334Speter 129218334Speter Printing or argument lists in gdb uses the definitions that 129318334Speter locate in the parameter list. But reference to the variable in 129418334Speter expressions uses preferentially the definition as a register. */ 129518334Speter 129618334Speter/* Output definitions, referring to storage in the parmlist, 129718334Speter of all the parms in PARMS, which is a chain of PARM_DECL nodes. */ 129818334Speter 129918334Speterstatic void 130018334Spetersdbout_parms (parms) 130118334Speter tree parms; 130218334Speter{ 130318334Speter for (; parms; parms = TREE_CHAIN (parms)) 130418334Speter if (DECL_NAME (parms)) 130518334Speter { 130618334Speter int current_sym_value = 0; 130790075Sobrien const char *name = IDENTIFIER_POINTER (DECL_NAME (parms)); 130818334Speter 130918334Speter if (name == 0 || *name == 0) 131018334Speter name = gen_fake_label (); 131118334Speter 131218334Speter /* Perform any necessary register eliminations on the parameter's rtl, 131318334Speter so that the debugging output will be accurate. */ 131450397Sobrien DECL_INCOMING_RTL (parms) 131550397Sobrien = eliminate_regs (DECL_INCOMING_RTL (parms), 0, NULL_RTX); 131690075Sobrien SET_DECL_RTL (parms, 131790075Sobrien eliminate_regs (DECL_RTL (parms), 0, NULL_RTX)); 131818334Speter 131918334Speter if (PARM_PASSED_IN_MEMORY (parms)) 132018334Speter { 132118334Speter rtx addr = XEXP (DECL_INCOMING_RTL (parms), 0); 132218334Speter tree type; 132318334Speter 132418334Speter /* ??? Here we assume that the parm address is indexed 132518334Speter off the frame pointer or arg pointer. 132618334Speter If that is not true, we produce meaningless results, 132718334Speter but do not crash. */ 132818334Speter if (GET_CODE (addr) == PLUS 132918334Speter && GET_CODE (XEXP (addr, 1)) == CONST_INT) 133018334Speter current_sym_value = INTVAL (XEXP (addr, 1)); 133118334Speter else 133218334Speter current_sym_value = 0; 133318334Speter 133418334Speter if (GET_CODE (DECL_RTL (parms)) == REG 133518334Speter && REGNO (DECL_RTL (parms)) < FIRST_PSEUDO_REGISTER) 133618334Speter type = DECL_ARG_TYPE (parms); 133718334Speter else 133818334Speter { 133918334Speter int original_sym_value = current_sym_value; 134018334Speter 134118334Speter /* This is the case where the parm is passed as an int or 134218334Speter double and it is converted to a char, short or float 134318334Speter and stored back in the parmlist. In this case, describe 134418334Speter the parm with the variable's declared type, and adjust 134518334Speter the address if the least significant bytes (which we are 134618334Speter using) are not the first ones. */ 134718334Speter if (BYTES_BIG_ENDIAN 134818334Speter && TREE_TYPE (parms) != DECL_ARG_TYPE (parms)) 134918334Speter current_sym_value += 135018334Speter (GET_MODE_SIZE (TYPE_MODE (DECL_ARG_TYPE (parms))) 135118334Speter - GET_MODE_SIZE (GET_MODE (DECL_RTL (parms)))); 135218334Speter 135318334Speter if (GET_CODE (DECL_RTL (parms)) == MEM 135418334Speter && GET_CODE (XEXP (DECL_RTL (parms), 0)) == PLUS 135518334Speter && (GET_CODE (XEXP (XEXP (DECL_RTL (parms), 0), 1)) 135618334Speter == CONST_INT) 135718334Speter && (INTVAL (XEXP (XEXP (DECL_RTL (parms), 0), 1)) 135818334Speter == current_sym_value)) 135918334Speter type = TREE_TYPE (parms); 136018334Speter else 136118334Speter { 136218334Speter current_sym_value = original_sym_value; 136318334Speter type = DECL_ARG_TYPE (parms); 136418334Speter } 136518334Speter } 136618334Speter 136718334Speter PUT_SDB_DEF (name); 136818334Speter PUT_SDB_INT_VAL (DEBUGGER_ARG_OFFSET (current_sym_value, addr)); 136918334Speter PUT_SDB_SCL (C_ARG); 137018334Speter PUT_SDB_TYPE (plain_type (type)); 137118334Speter PUT_SDB_ENDEF; 137218334Speter } 137318334Speter else if (GET_CODE (DECL_RTL (parms)) == REG) 137418334Speter { 137518334Speter rtx best_rtl; 137618334Speter /* Parm passed in registers and lives in registers or nowhere. */ 137718334Speter 137818334Speter /* If parm lives in a register, use that register; 137918334Speter pretend the parm was passed there. It would be more consistent 138018334Speter to describe the register where the parm was passed, 138118334Speter but in practice that register usually holds something else. */ 138290075Sobrien if (REGNO (DECL_RTL (parms)) < FIRST_PSEUDO_REGISTER) 138318334Speter best_rtl = DECL_RTL (parms); 138418334Speter /* If the parm lives nowhere, 138518334Speter use the register where it was passed. */ 138618334Speter else 138718334Speter best_rtl = DECL_INCOMING_RTL (parms); 138818334Speter 138918334Speter PUT_SDB_DEF (name); 139018334Speter PUT_SDB_INT_VAL (DBX_REGISTER_NUMBER (REGNO (best_rtl))); 139118334Speter PUT_SDB_SCL (C_REGPARM); 139250397Sobrien PUT_SDB_TYPE (plain_type (TREE_TYPE (parms))); 139318334Speter PUT_SDB_ENDEF; 139418334Speter } 139518334Speter else if (GET_CODE (DECL_RTL (parms)) == MEM 139618334Speter && XEXP (DECL_RTL (parms), 0) != const0_rtx) 139718334Speter { 139818334Speter /* Parm was passed in registers but lives on the stack. */ 139918334Speter 140018334Speter /* DECL_RTL looks like (MEM (PLUS (REG...) (CONST_INT...))), 140118334Speter in which case we want the value of that CONST_INT, 140218334Speter or (MEM (REG ...)) or (MEM (MEM ...)), 140318334Speter in which case we use a value of zero. */ 140418334Speter if (GET_CODE (XEXP (DECL_RTL (parms), 0)) == REG 140518334Speter || GET_CODE (XEXP (DECL_RTL (parms), 0)) == MEM) 140618334Speter current_sym_value = 0; 140718334Speter else 140818334Speter current_sym_value = INTVAL (XEXP (XEXP (DECL_RTL (parms), 0), 1)); 140918334Speter 141018334Speter /* Again, this assumes the offset is based on the arg pointer. */ 141118334Speter PUT_SDB_DEF (name); 141218334Speter PUT_SDB_INT_VAL (DEBUGGER_ARG_OFFSET (current_sym_value, 141318334Speter XEXP (DECL_RTL (parms), 0))); 141418334Speter PUT_SDB_SCL (C_ARG); 141550397Sobrien PUT_SDB_TYPE (plain_type (TREE_TYPE (parms))); 141618334Speter PUT_SDB_ENDEF; 141718334Speter } 141818334Speter } 141918334Speter} 142018334Speter 142118334Speter/* Output definitions for the places where parms live during the function, 142218334Speter when different from where they were passed, when the parms were passed 142318334Speter in memory. 142418334Speter 142518334Speter It is not useful to do this for parms passed in registers 142618334Speter that live during the function in different registers, because it is 142718334Speter impossible to look in the passed register for the passed value, 142818334Speter so we use the within-the-function register to begin with. 142918334Speter 143018334Speter PARMS is a chain of PARM_DECL nodes. */ 143118334Speter 143218334Speterstatic void 143318334Spetersdbout_reg_parms (parms) 143418334Speter tree parms; 143518334Speter{ 143618334Speter for (; parms; parms = TREE_CHAIN (parms)) 143718334Speter if (DECL_NAME (parms)) 143818334Speter { 143990075Sobrien const char *name = IDENTIFIER_POINTER (DECL_NAME (parms)); 144018334Speter 144118334Speter /* Report parms that live in registers during the function 144218334Speter but were passed in memory. */ 144318334Speter if (GET_CODE (DECL_RTL (parms)) == REG 144418334Speter && REGNO (DECL_RTL (parms)) < FIRST_PSEUDO_REGISTER 144518334Speter && PARM_PASSED_IN_MEMORY (parms)) 144618334Speter { 144718334Speter if (name == 0 || *name == 0) 144818334Speter name = gen_fake_label (); 144918334Speter PUT_SDB_DEF (name); 145018334Speter PUT_SDB_INT_VAL (DBX_REGISTER_NUMBER (REGNO (DECL_RTL (parms)))); 145118334Speter PUT_SDB_SCL (C_REG); 145250397Sobrien PUT_SDB_TYPE (plain_type (TREE_TYPE (parms))); 145318334Speter PUT_SDB_ENDEF; 145418334Speter } 145518334Speter /* Report parms that live in memory but not where they were passed. */ 145618334Speter else if (GET_CODE (DECL_RTL (parms)) == MEM 145718334Speter && GET_CODE (XEXP (DECL_RTL (parms), 0)) == PLUS 145818334Speter && GET_CODE (XEXP (XEXP (DECL_RTL (parms), 0), 1)) == CONST_INT 145918334Speter && PARM_PASSED_IN_MEMORY (parms) 146018334Speter && ! rtx_equal_p (DECL_RTL (parms), DECL_INCOMING_RTL (parms))) 146118334Speter { 146218334Speter#if 0 /* ??? It is not clear yet what should replace this. */ 146318334Speter int offset = DECL_OFFSET (parms) / BITS_PER_UNIT; 146418334Speter /* A parm declared char is really passed as an int, 146518334Speter so it occupies the least significant bytes. 146618334Speter On a big-endian machine those are not the low-numbered ones. */ 146718334Speter if (BYTES_BIG_ENDIAN 146818334Speter && offset != -1 146918334Speter && TREE_TYPE (parms) != DECL_ARG_TYPE (parms)) 147018334Speter offset += (GET_MODE_SIZE (TYPE_MODE (DECL_ARG_TYPE (parms))) 147118334Speter - GET_MODE_SIZE (GET_MODE (DECL_RTL (parms)))); 147218334Speter if (INTVAL (XEXP (XEXP (DECL_RTL (parms), 0), 1)) != offset) {...} 147318334Speter#endif 147418334Speter { 147518334Speter if (name == 0 || *name == 0) 147618334Speter name = gen_fake_label (); 147718334Speter PUT_SDB_DEF (name); 147818334Speter PUT_SDB_INT_VAL (DEBUGGER_AUTO_OFFSET 147918334Speter (XEXP (DECL_RTL (parms), 0))); 148018334Speter PUT_SDB_SCL (C_AUTO); 148118334Speter PUT_SDB_TYPE (plain_type (TREE_TYPE (parms))); 148218334Speter PUT_SDB_ENDEF; 148318334Speter } 148418334Speter } 148518334Speter } 148618334Speter} 148718334Speter 148890075Sobrien/* Output debug information for a global DECL. Called from toplev.c 148990075Sobrien after compilation proper has finished. */ 149090075Sobrien 149190075Sobrienstatic void 149290075Sobriensdbout_global_decl (decl) 149390075Sobrien tree decl; 149490075Sobrien{ 149590075Sobrien if (TREE_CODE (decl) == VAR_DECL 149690075Sobrien && !DECL_EXTERNAL (decl) 149790075Sobrien && DECL_RTL_SET_P (decl)) 149890075Sobrien { 149990075Sobrien /* The COFF linker can move initialized global vars to the end. 150090075Sobrien And that can screw up the symbol ordering. Defer those for 150190075Sobrien sdbout_finish (). */ 150290075Sobrien if (!DECL_INITIAL (decl) || !TREE_PUBLIC (decl)) 150390075Sobrien sdbout_symbol (decl, 0); 150490075Sobrien 150590075Sobrien /* Output COFF information for non-global file-scope initialized 150690075Sobrien variables. */ 150790075Sobrien if (DECL_INITIAL (decl) && GET_CODE (DECL_RTL (decl)) == MEM) 150890075Sobrien sdbout_toplevel_data (decl); 150990075Sobrien } 151090075Sobrien} 151190075Sobrien 151290075Sobrien/* Output initialized global vars at the end, in the order of 151390075Sobrien definition. See comment in sdbout_global_decl. */ 151490075Sobrien 151590075Sobrienstatic void 151690075Sobriensdbout_finish (main_filename) 151790075Sobrien const char *main_filename ATTRIBUTE_UNUSED; 151890075Sobrien{ 151990075Sobrien tree decl = getdecls (); 152090075Sobrien unsigned int len = list_length (decl); 152190075Sobrien tree *vec = (tree *) xmalloc (sizeof (tree) * len); 152290075Sobrien unsigned int i; 152390075Sobrien 152490075Sobrien /* Process the decls in reverse order--earliest first. Put them 152590075Sobrien into VEC from back to front, then take out from front. */ 152690075Sobrien 152790075Sobrien for (i = 0; i < len; i++, decl = TREE_CHAIN (decl)) 152890075Sobrien vec[len - i - 1] = decl; 152990075Sobrien 153090075Sobrien for (i = 0; i < len; i++) 153190075Sobrien { 153290075Sobrien decl = vec[i]; 153390075Sobrien if (TREE_CODE (decl) == VAR_DECL 153490075Sobrien && ! DECL_EXTERNAL (decl) 153590075Sobrien && DECL_INITIAL (decl) 153690075Sobrien && TREE_PUBLIC (decl) 153790075Sobrien && DECL_RTL_SET_P (decl)) 153890075Sobrien sdbout_symbol (decl, 0); 153990075Sobrien } 154090075Sobrien 154190075Sobrien free (vec); 154290075Sobrien} 154390075Sobrien 154418334Speter/* Describe the beginning of an internal block within a function. 154518334Speter Also output descriptions of variables defined in this block. 154618334Speter 154718334Speter N is the number of the block, by order of beginning, counting from 1, 154818334Speter and not counting the outermost (function top-level) block. 154918334Speter The blocks match the BLOCKs in DECL_INITIAL (current_function_decl), 155018334Speter if the count starts at 0 for the outermost one. */ 155118334Speter 155290075Sobrienstatic void 155390075Sobriensdbout_begin_block (line, n) 155490075Sobrien unsigned int line; 155590075Sobrien unsigned int n; 155618334Speter{ 155718334Speter tree decl = current_function_decl; 155818334Speter MAKE_LINE_SAFE (line); 155918334Speter 156018334Speter /* The SCO compiler does not emit a separate block for the function level 156118334Speter scope, so we avoid it here also. However, mips ECOFF compilers do emit 156218334Speter a separate block, so we retain it when MIPS_DEBUGGING_INFO is defined. */ 156318334Speter#ifndef MIPS_DEBUGGING_INFO 156418334Speter if (n != 1) 156518334Speter#endif 156618334Speter PUT_SDB_BLOCK_START (line - sdb_begin_function_line); 156718334Speter 156818334Speter if (n == 1) 156918334Speter { 157018334Speter /* Include the outermost BLOCK's variables in block 1. */ 157190075Sobrien do_block = BLOCK_NUMBER (DECL_INITIAL (decl)); 157218334Speter sdbout_block (DECL_INITIAL (decl)); 157318334Speter } 157418334Speter /* If -g1, suppress all the internal symbols of functions 157518334Speter except for arguments. */ 157618334Speter if (debug_info_level != DINFO_LEVEL_TERSE) 157718334Speter { 157818334Speter do_block = n; 157918334Speter sdbout_block (DECL_INITIAL (decl)); 158018334Speter } 158118334Speter 158218334Speter#ifdef SDB_ALLOW_FORWARD_REFERENCES 158318334Speter sdbout_dequeue_anonymous_types (); 158418334Speter#endif 158518334Speter} 158618334Speter 158718334Speter/* Describe the end line-number of an internal block within a function. */ 158818334Speter 158990075Sobrienstatic void 159090075Sobriensdbout_end_block (line, n) 159190075Sobrien unsigned int line; 159290075Sobrien unsigned int n ATTRIBUTE_UNUSED; 159318334Speter{ 159418334Speter MAKE_LINE_SAFE (line); 159518334Speter 159618334Speter /* The SCO compiler does not emit a separate block for the function level 159718334Speter scope, so we avoid it here also. However, mips ECOFF compilers do emit 159818334Speter a separate block, so we retain it when MIPS_DEBUGGING_INFO is defined. */ 159918334Speter#ifndef MIPS_DEBUGGING_INFO 160018334Speter if (n != 1) 160118334Speter#endif 160218334Speter PUT_SDB_BLOCK_END (line - sdb_begin_function_line); 160318334Speter} 160418334Speter 160590075Sobrienstatic void 160690075Sobriensdbout_source_line (line, filename) 160790075Sobrien unsigned int line; 160890075Sobrien const char *filename ATTRIBUTE_UNUSED; 160990075Sobrien{ 161090075Sobrien /* COFF relative line numbers must be positive. */ 161190075Sobrien if ((int) line > sdb_begin_function_line) 161290075Sobrien { 161390075Sobrien#ifdef ASM_OUTPUT_SOURCE_LINE 161490075Sobrien ASM_OUTPUT_SOURCE_LINE (asm_out_file, line); 161590075Sobrien#else 161690075Sobrien fprintf (asm_out_file, "\t.ln\t%d\n", 161790075Sobrien ((sdb_begin_function_line > -1) 161890075Sobrien ? line - sdb_begin_function_line : 1)); 161990075Sobrien#endif 162090075Sobrien } 162190075Sobrien} 162290075Sobrien 162318334Speter/* Output sdb info for the current function name. 162418334Speter Called from assemble_start_function. */ 162518334Speter 162690075Sobrienstatic void 162790075Sobriensdbout_begin_function (decl) 162890075Sobrien tree decl ATTRIBUTE_UNUSED; 162918334Speter{ 163018334Speter sdbout_symbol (current_function_decl, 0); 163118334Speter} 163218334Speter 163390075Sobrien/* Called at beginning of function body (before or after prologue, 163490075Sobrien depending on MIPS_DEBUGGING_INFO). Record the function's starting 163590075Sobrien line number, so we can output relative line numbers for the other 163690075Sobrien lines. Describe beginning of outermost block. Also describe the 163790075Sobrien parameter list. */ 163818334Speter 163990075Sobrien#ifndef MIPS_DEBUGGING_INFO 164090075Sobrienstatic void 164190075Sobriensdbout_begin_prologue (line, file) 164290075Sobrien unsigned int line; 164390075Sobrien const char *file ATTRIBUTE_UNUSED; 164418334Speter{ 164590075Sobrien sdbout_end_prologue (line); 164690075Sobrien} 164790075Sobrien#endif 164890075Sobrien 164990075Sobrienstatic void 165090075Sobriensdbout_end_prologue (line) 165190075Sobrien unsigned int line; 165290075Sobrien{ 165318334Speter sdb_begin_function_line = line - 1; 165418334Speter PUT_SDB_FUNCTION_START (line); 165518334Speter sdbout_parms (DECL_ARGUMENTS (current_function_decl)); 165618334Speter sdbout_reg_parms (DECL_ARGUMENTS (current_function_decl)); 165718334Speter} 165818334Speter 165918334Speter/* Called at end of function (before epilogue). 166018334Speter Describe end of outermost block. */ 166118334Speter 166290075Sobrienstatic void 166318334Spetersdbout_end_function (line) 166490075Sobrien unsigned int line; 166518334Speter{ 166618334Speter#ifdef SDB_ALLOW_FORWARD_REFERENCES 166718334Speter sdbout_dequeue_anonymous_types (); 166818334Speter#endif 166918334Speter 167018334Speter MAKE_LINE_SAFE (line); 167118334Speter PUT_SDB_FUNCTION_END (line - sdb_begin_function_line); 167218334Speter 167318334Speter /* Indicate we are between functions, for line-number output. */ 167418334Speter sdb_begin_function_line = -1; 167518334Speter} 167618334Speter 167718334Speter/* Output sdb info for the absolute end of a function. 167818334Speter Called after the epilogue is output. */ 167918334Speter 168090075Sobrienstatic void 168118334Spetersdbout_end_epilogue () 168218334Speter{ 168390075Sobrien const char *const name ATTRIBUTE_UNUSED 168490075Sobrien = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (current_function_decl)); 168590075Sobrien 168690075Sobrien#ifdef PUT_SDB_EPILOGUE_END 168718334Speter PUT_SDB_EPILOGUE_END (name); 168890075Sobrien#else 168990075Sobrien fprintf (asm_out_file, "\t.def\t"); 169090075Sobrien assemble_name (asm_out_file, name); 169190075Sobrien fprintf (asm_out_file, "%s\t.val\t.%s\t.scl\t-1%s\t.endef\n", 169290075Sobrien SDB_DELIM, SDB_DELIM, SDB_DELIM); 169390075Sobrien#endif 169418334Speter} 169518334Speter 169618334Speter/* Output sdb info for the given label. Called only if LABEL_NAME (insn) 169718334Speter is present. */ 169818334Speter 169990075Sobrienstatic void 170018334Spetersdbout_label (insn) 170190075Sobrien rtx insn; 170218334Speter{ 170318334Speter PUT_SDB_DEF (LABEL_NAME (insn)); 170418334Speter PUT_SDB_VAL (insn); 170518334Speter PUT_SDB_SCL (C_LABEL); 170618334Speter PUT_SDB_TYPE (T_NULL); 170718334Speter PUT_SDB_ENDEF; 170818334Speter} 170918334Speter 171050397Sobrien/* Change to reading from a new source file. */ 171150397Sobrien 171290075Sobrienstatic void 171390075Sobriensdbout_start_source_file (line, filename) 171490075Sobrien unsigned int line ATTRIBUTE_UNUSED; 171590075Sobrien const char *filename ATTRIBUTE_UNUSED; 171650397Sobrien{ 171750397Sobrien#ifdef MIPS_DEBUGGING_INFO 171850397Sobrien struct sdb_file *n = (struct sdb_file *) xmalloc (sizeof *n); 171950397Sobrien 172050397Sobrien n->next = current_file; 172150397Sobrien n->name = filename; 172250397Sobrien current_file = n; 172350397Sobrien PUT_SDB_SRC_FILE (filename); 172450397Sobrien#endif 172550397Sobrien} 172650397Sobrien 172750397Sobrien/* Revert to reading a previous source file. */ 172850397Sobrien 172990075Sobrienstatic void 173090075Sobriensdbout_end_source_file (line) 173190075Sobrien unsigned int line ATTRIBUTE_UNUSED; 173250397Sobrien{ 173350397Sobrien#ifdef MIPS_DEBUGGING_INFO 173450397Sobrien struct sdb_file *next; 173550397Sobrien 173650397Sobrien next = current_file->next; 173750397Sobrien free (current_file); 173850397Sobrien current_file = next; 173950397Sobrien PUT_SDB_SRC_FILE (current_file->name); 174050397Sobrien#endif 174150397Sobrien} 174250397Sobrien 174390075Sobrien/* Set up for SDB output at the start of compilation. */ 174490075Sobrien 174590075Sobrienstatic void 174690075Sobriensdbout_init (input_file_name) 174790075Sobrien const char *input_file_name ATTRIBUTE_UNUSED; 174890075Sobrien{ 174990075Sobrien#ifdef MIPS_DEBUGGING_INFO 175090075Sobrien current_file = (struct sdb_file *) xmalloc (sizeof *current_file); 175190075Sobrien current_file->next = NULL; 175290075Sobrien current_file->name = input_file_name; 175390075Sobrien#endif 175490075Sobrien 175590075Sobrien#ifdef RMS_QUICK_HACK_1 175690075Sobrien tree t; 175790075Sobrien for (t = getdecls (); t; t = TREE_CHAIN (t)) 175890075Sobrien if (DECL_NAME (t) && IDENTIFIER_POINTER (DECL_NAME (t)) != 0 175990075Sobrien && !strcmp (IDENTIFIER_POINTER (DECL_NAME (t)), "__vtbl_ptr_type")) 176090075Sobrien sdbout_symbol (t, 0); 176190075Sobrien#endif 176290075Sobrien 176390075Sobrien#ifdef SDB_ALLOW_FORWARD_REFERENCES 176490075Sobrien ggc_add_tree_root (&anonymous_types, 1); 176590075Sobrien#endif 176690075Sobrien} 176790075Sobrien 176818334Speter#endif /* SDB_DEBUGGING_INFO */ 1769