📄 sdbout.c
字号:
/* Output sdb-format symbol table information from GNU compiler. Copyright (C) 1988 Free Software Foundation, Inc.This file is part of GNU CC.GNU CC is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 1, or (at your option)any later version.GNU CC is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with GNU CC; see the file COPYING. If not, write tothe Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */#define SDB_NO_FORWARD_REFS#include "config.h"#ifdef SDB_DEBUGGING_INFO#include "tree.h"#include "rtl.h"#include <stdio.h>#if defined(USG) && !defined(MIPS_DEBUGGING_INFO)#include <syms.h>/* #include <storclass.h> used to be this instead of syms.h. */#else/* For cross compilation, use the portable defintions from the COFF documentation. */#define C_EFCN -1#define C_NULL 0#define C_AUTO 1#define C_EXT 2#define C_STAT 3#define C_REG 4#define C_EXTDEF 5#define C_LABEL 6#define C_ULABEL 7#define C_MOS 8#define C_ARG 9#define C_STRTAG 10#define C_MOU 11#define C_UNTAG 12#define C_TPDEF 13#define C_USTATIC 14#define C_ENTAG 15#define C_MOE 16#define C_REGPARM 17#define C_FIELD 18#define C_BLOCK 100#define C_FCN 101#define C_EOS 102#define C_FILE 103#define C_LINE 104#define C_ALIAS 105#define C_HIDDEN 106#define T_NULL 0#define T_ARG 1#define T_CHAR 2#define T_SHORT 3#define T_INT 4#define T_LONG 5#define T_FLOAT 6#define T_DOUBLE 7#define T_STRUCT 8#define T_UNION 9#define T_ENUM 10#define T_MOE 11#define T_UCHAR 12#define T_USHORT 13#define T_UINT 14#define T_ULONG 15#define DT_NON 0#define DT_PTR 1#define DT_FCN 2#define DT_ARY 3#define N_BTMASK 017#define N_TMASK 060#define N_TMASK1 0300#define N_TMASK2 0360#define N_BTSHFT 4#define N_TSHIFT 2#endif/* Line number of beginning of current function, minus one. Negative means not in a function or not using sdb. */int sdb_begin_function_line = -1;/* Counter to generate unique "names" for nameless struct members. */static int unnamed_struct_number = 0;extern FILE *asm_out_file;extern tree current_function_decl;void sdbout_init ();void sdbout_symbol ();void sdbout_tags();void sdbout_types();static void sdbout_syms ();static void sdbout_one_type ();static int plain_type_1 ();/* Random macros describing parts of SDB data. *//* Put something here if lines get too long */#define CONTIN/* Maximum number of dimensions the assembler will allow. */#ifndef SDB_MAX_DIM#define SDB_MAX_DIM 4#endif#ifndef PUT_SDB_SCL#define PUT_SDB_SCL(a) fprintf(asm_out_file, "\t.scl\t%d;", (a))#endif#ifndef PUT_SDB_INT_VAL#define PUT_SDB_INT_VAL(a) fprintf (asm_out_file, "\t.val\t%d;", (a))#endif#ifndef PUT_SDB_VAL#define PUT_SDB_VAL(a) \( fputs ("\t.val\t", asm_out_file), \ output_addr_const (asm_out_file, (a)), \ fputc (';', asm_out_file))#endif#ifndef PUT_SDB_DEF#define PUT_SDB_DEF(a) \do { fprintf (asm_out_file, "\t.def\t"); \ ASM_OUTPUT_LABELREF (asm_out_file, a); \ fprintf (asm_out_file, ";"); } while (0)#endif#ifndef PUT_SDB_PLAIN_DEF#define PUT_SDB_PLAIN_DEF(a) fprintf(asm_out_file,"\t.def\t.%s;",a)#endif#ifndef PUT_SDB_ENDEF#define PUT_SDB_ENDEF fputs("\t.endef\n", asm_out_file)#endif#ifndef PUT_SDB_TYPE#define PUT_SDB_TYPE(a) fprintf(asm_out_file, "\t.type\t0%o;", a)#endif#ifndef PUT_SDB_SIZE#define PUT_SDB_SIZE(a) fprintf(asm_out_file, "\t.size\t%d;", a)#endif#ifndef PUT_SDB_START_DIM#define PUT_SDB_START_DIM fprintf(asm_out_file, "\t.dim\t")#endif#ifndef PUT_SDB_NEXT_DIM#define PUT_SDB_NEXT_DIM(a) fprintf(asm_out_file, "%d,", a)#endif#ifndef PUT_SDB_LAST_DIM#define PUT_SDB_LAST_DIM(a) fprintf(asm_out_file, "%d;", a)#endif#ifndef PUT_SDB_TAG#define PUT_SDB_TAG(a) \do { fprintf (asm_out_file, "\t.tag\t"); \ ASM_OUTPUT_LABELREF (asm_out_file, a); \ fprintf (asm_out_file, ";"); } while (0)#endif#ifndef PUT_SDB_BLOCK_START#define PUT_SDB_BLOCK_START(LINE) \ fprintf (asm_out_file, \ "\t.def\t.bb;\t.val\t.;\t.scl\t100;\t.line\t%d;\t.endef\n", \ (LINE))#endif#ifndef PUT_SDB_BLOCK_END#define PUT_SDB_BLOCK_END(LINE) \ fprintf (asm_out_file, \ "\t.def\t.eb;.val\t.;\t.scl\t100;\t.line\t%d;\t.endef\n", \ (LINE))#endif#ifndef PUT_SDB_FUNCTION_START#define PUT_SDB_FUNCTION_START(LINE) \ fprintf (asm_out_file, \ "\t.def\t.bf;\t.val\t.;\t.scl\t101;\t.line\t%d;\t.endef\n", \ (LINE))#endif#ifndef PUT_SDB_FUNCTION_END#define PUT_SDB_FUNCTION_END(LINE) \ fprintf (asm_out_file, \ "\t.def\t.ef;\t.val\t.;\t.scl\t101;\t.line\t%d;\t.endef\n", \ (LINE))#endif#ifndef PUT_SDB_EPILOGUE_END#define PUT_SDB_EPILOGUE_END(NAME) \ fprintf (asm_out_file, \ "\t.def\t%s;\t.val\t.;\t.scl\t-1;\t.endef\n", \ (NAME))#endif#ifndef SDB_GENERATE_FAKE#define SDB_GENERATE_FAKE(BUFFER, NUMBER) \ sprintf ((BUFFER), ".%dfake", (NUMBER));#endif/* Return the sdb tag identifier string for TYPE if TYPE has already been defined; otherwise return a null pointer. */ #define KNOWN_TYPE_TAG(type) (char *)(TYPE_SYMTAB_ADDRESS (type))/* Set the sdb tag identifier string for TYPE to NAME. */#define SET_KNOWN_TYPE_TAG(TYPE, NAME) \ (TYPE_SYMTAB_ADDRESS (TYPE) = (int)(NAME))/* Return the name (a string) of the struct, union or enum tag described by the TREE_LIST node LINK. This is 0 for an anonymous one. */#define TAG_NAME(link) \ (((link) && TREE_PURPOSE ((link)) \ && IDENTIFIER_POINTER (TREE_PURPOSE ((link)))) \ ? IDENTIFIER_POINTER (TREE_PURPOSE ((link))) : (char *) 0)/* Ensure we don't output a negative line number. */#define MAKE_LINE_SAFE(line) \ if (line <= sdb_begin_function_line) line = sdb_begin_function_line + 1/* Tell the assembler the source file name. On systems that use SDB, this is done whether or not -g, so it is called by ASM_FILE_START. ASM_FILE is the assembler code output file, INPUT_NAME is the name of the main input file. */voidsdbout_filename (asm_file, input_name) FILE *asm_file; char *input_name;{ int len = strlen (input_name); char *na = input_name + len; /* NA gets INPUT_NAME sans directory names. */ while (na > input_name) { if (na[-1] == '/') break; na--; }#ifdef ASM_OUTPUT_SOURCE_FILENAME ASM_OUTPUT_SOURCE_FILENAME (asm_file, na);#else fprintf (asm_file, "\t.file\t\"%s\"\n", na);#endif}/* Set up for SDB output at the start of compilation. */voidsdbout_init (){ /* Output all the initial permanent types. */ sdbout_types (nreverse (get_permanent_types ()));}#if 0/* return the tag identifier for type */{char *tag_of_ru_type (type,link) tree type,link;{ if (TYPE_SYMTAB_ADDRESS (type)) return (char *)TYPE_SYMTAB_ADDRESS (type); if (link && TREE_PURPOSE (link) && IDENTIFIER_POINTER (TREE_PURPOSE (link))) TYPE_SYMTAB_ADDRESS (type) = (int)IDENTIFIER_POINTER (TREE_PURPOSE (link)); else return (char *) TYPE_SYMTAB_ADDRESS (type);}#endif/* Return a unique string to name an anonymous type. */static char *gen_fake_label (){ char label[10]; char *labelstr; SDB_GENERATE_FAKE (label, unnamed_struct_number); unnamed_struct_number++; labelstr = (char *) permalloc (strlen (label) + 1); strcpy (labelstr, label); return labelstr;}/* Return the number which describes TYPE for SDB. For pointers, etc., this function is recursive. Each record, union or enumeral type must already have had a tag number output. *//* The number is given by d6d5d4d3d2d1bbbb where bbbb is 4 bit basic type, and di indicate one of notype,ptr,fn,array. Thus, char *foo () has bbbb=T_CHAR d1=D_FCN d2=D_PTR N_BTMASK= 017 1111 basic type field. N_TSHIFT= 2 derived type shift N_BTSHFT= 4 Basic type shift *//* Produce the number that describes a pointer, function or array type. PREV is the number describing the target, value or element type. DT_type describes how to transform that type. */#define PUSH_DERIVED_LEVEL(DT_type,PREV) \ ((((PREV)&~N_BTMASK)<<N_TSHIFT)|(DT_type<<N_BTSHFT)|(PREV&N_BTMASK))/* Number of elements used in sdb_dims. */static int sdb_n_dims = 0;/* Table of array dimensions of current type. */static int sdb_dims[SDB_MAX_DIM];/* Size of outermost array currently being processed. */static int sdb_type_size = -1;static intplain_type (type) tree type;{ int val = plain_type_1 (type); /* If we have already saved up some array dimensions, print them now. */ if (sdb_n_dims > 0) { int i; PUT_SDB_START_DIM; for (i = sdb_n_dims - 1; i > 0; i--) PUT_SDB_NEXT_DIM (sdb_dims[i]); PUT_SDB_LAST_DIM (sdb_dims[0]); sdb_n_dims = 0; sdb_type_size = int_size_in_bytes (type); /* Don't kill sdb if type is not laid out or has variable size. */ if (sdb_type_size < 0) sdb_type_size = 0; } /* If we have computed the size of an array containing this type, print it now. */ if (sdb_type_size >= 0) { PUT_SDB_SIZE (sdb_type_size); sdb_type_size = -1; } return val;}static voidsdbout_record_type_name (type) tree type;{ char *name = 0; if (KNOWN_TYPE_TAG (type)) return; if (TYPE_NAME (type) != 0) { tree t = 0; /* Find the IDENTIFIER_NODE for the type name. */ if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE) { t = TYPE_NAME (type); } else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL) { t = DECL_NAME (TYPE_NAME (type)); } /* Now get the name as a string, or invent one. */ if (t != 0) name = IDENTIFIER_POINTER (t); } if (name == 0) name = gen_fake_label (); SET_KNOWN_TYPE_TAG (type, name);}static intplain_type_1 (type) tree type;{ if (type == 0) type = void_type_node; if (type == error_mark_node) type = integer_type_node; type = TYPE_MAIN_VARIANT (type); switch (TREE_CODE (type)) { case VOID_TYPE: return T_INT; case INTEGER_TYPE: switch (int_size_in_bytes (type)) { case 4: return (TREE_UNSIGNED (type) ? T_UINT : T_INT); case 1: return (TREE_UNSIGNED (type) ? T_UCHAR : T_CHAR); case 2: return (TREE_UNSIGNED (type) ? T_USHORT : T_SHORT); default: return 0; } case REAL_TYPE: switch (int_size_in_bytes (type)) { case 4: return T_FLOAT; default: return T_DOUBLE; } case ARRAY_TYPE: { int m; m = plain_type_1 (TREE_TYPE (type)); if (sdb_n_dims < SDB_MAX_DIM) sdb_dims[sdb_n_dims++] = (TYPE_DOMAIN (type) ? TREE_INT_CST_LOW (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) + 1 : 0); return PUSH_DERIVED_LEVEL (DT_ARY, m); } case RECORD_TYPE: case UNION_TYPE: case ENUMERAL_TYPE: { char *tag;#ifndef SDB_NO_FORWARD_REFS /* Taken out because this sets KNOWN_TYPE_TAG. If we don't want forward references, this is clearly not needed. */ sdbout_record_type_name (type);#endif if (TREE_ASM_WRITTEN (type)#ifdef SDB_NO_FORWARD_REFS && KNOWN_TYPE_TAG (type)#endif ) { /* Output the referenced structure tag name only if the .def has already been output. At least on 386, the Unix assembler cannot handle forward references to tags. */ tag = KNOWN_TYPE_TAG (type); PUT_SDB_TAG (tag); } sdb_type_size = int_size_in_bytes (type); if (sdb_type_size < 0) sdb_type_size = 0; return ((TREE_CODE (type) == RECORD_TYPE) ? T_STRUCT : (TREE_CODE (type) == UNION_TYPE) ? T_UNION : T_ENUM); } case POINTER_TYPE: case REFERENCE_TYPE: { int m = plain_type_1 (TREE_TYPE (type)); return PUSH_DERIVED_LEVEL (DT_PTR, m); } case FUNCTION_TYPE: case METHOD_TYPE: { int m = plain_type_1 (TREE_TYPE (type)); return PUSH_DERIVED_LEVEL (DT_FCN, m); } default: return 0; }}/* Output the symbols defined in block number DO_BLOCK. Set NEXT_BLOCK_NUMBER to 0 before calling. This function works by walking the tree structure, counting blocks, until it finds the desired block. */static int do_block = 0;static int next_block_number;static voidsdbout_block (stmt) register tree stmt;{ while (stmt) { switch (TREE_CODE (stmt)) { case COMPOUND_STMT: case LOOP_STMT: sdbout_block (STMT_BODY (stmt)); break; case IF_STMT: sdbout_block (STMT_THEN (stmt)); sdbout_block (STMT_ELSE (stmt)); break; case LET_STMT: /* Ignore LET_STMTs for blocks never really used to make RTL. */ if (! TREE_USED (stmt)) break; /* When we reach the specified block, output its symbols. */ if (next_block_number == do_block) { sdbout_tags (STMT_TYPE_TAGS (stmt)); sdbout_syms (STMT_VARS (stmt)); } /* If we are past the specified block, stop the scan. */ if (next_block_number > do_block) return; next_block_number++; /* Scan the blocks within this block. */ sdbout_block (STMT_SUBBLOCKS (stmt)); } stmt = TREE_CHAIN (stmt);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -