sdbout.c
来自「GCC编译器源代码」· C语言 代码 · 共 1,635 行 · 第 1/4 页
C
1,635 行
static intplain_type (type) tree type;{ int val = plain_type_1 (type, 0); /* 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 inttemplate_name_p (name) tree name;{ register char *ptr = IDENTIFIER_POINTER (name); while (*ptr && *ptr != '<') ptr++; return *ptr != '\0';}static voidsdbout_record_type_name (type) tree type;{ char *name = 0; int no_name; 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)); /* The DECL_NAME for templates includes "<>", which breaks most assemblers. Use its assembler name instead, which has been mangled into being safe. */ if (t && template_name_p (t)) t = DECL_ASSEMBLER_NAME (TYPE_NAME (type)); } /* Now get the name as a string, or invent one. */ if (t != NULL_TREE) name = IDENTIFIER_POINTER (t); } no_name = (name == 0 || *name == 0); if (no_name) name = gen_fake_label (); SET_KNOWN_TYPE_TAG (type, name);#ifdef SDB_ALLOW_FORWARD_REFERENCES if (no_name) sdbout_queue_anonymous_type (type);#endif}/* Return the .type value for type TYPE. LEVEL indicates how many levels deep we have recursed into the type. The SDB debug format can only represent 6 derived levels of types. After that, we must output inaccurate debug info. We deliberately stop before the 7th level, so that ADA recursive types will not give an infinite loop. */static intplain_type_1 (type, level) tree type; int level;{ if (type == 0) type = void_type_node; else if (type == error_mark_node) type = integer_type_node; else type = TYPE_MAIN_VARIANT (type); switch (TREE_CODE (type)) { case VOID_TYPE: return T_VOID; case INTEGER_TYPE: { int size = int_size_in_bytes (type) * BITS_PER_UNIT; /* Carefully distinguish all the standard types of C, without messing up if the language is not C. Note that we check only for the names that contain spaces; other names might occur by coincidence in other languages. */ if (TYPE_NAME (type) != 0 && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL && DECL_NAME (TYPE_NAME (type)) != 0 && TREE_CODE (DECL_NAME (TYPE_NAME (type))) == IDENTIFIER_NODE) { char *name = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type))); if (!strcmp (name, "char")) return T_CHAR; if (!strcmp (name, "unsigned char")) return T_UCHAR; if (!strcmp (name, "signed char")) return T_CHAR; if (!strcmp (name, "int")) return T_INT; if (!strcmp (name, "unsigned int")) return T_UINT; if (!strcmp (name, "short int")) return T_SHORT; if (!strcmp (name, "short unsigned int")) return T_USHORT; if (!strcmp (name, "long int")) return T_LONG; if (!strcmp (name, "long unsigned int")) return T_ULONG; } if (size == INT_TYPE_SIZE) return (TREE_UNSIGNED (type) ? T_UINT : T_INT); if (size == CHAR_TYPE_SIZE) return (TREE_UNSIGNED (type) ? T_UCHAR : T_CHAR); if (size == SHORT_TYPE_SIZE) return (TREE_UNSIGNED (type) ? T_USHORT : T_SHORT); if (size == LONG_TYPE_SIZE) return (TREE_UNSIGNED (type) ? T_ULONG : T_LONG); if (size == LONG_LONG_TYPE_SIZE) /* better than nothing */ return (TREE_UNSIGNED (type) ? T_ULONG : T_LONG); return 0; } case REAL_TYPE: { int precision = TYPE_PRECISION (type); if (precision == FLOAT_TYPE_SIZE) return T_FLOAT; if (precision == DOUBLE_TYPE_SIZE) return T_DOUBLE;#ifdef EXTENDED_SDB_BASIC_TYPES if (precision == LONG_DOUBLE_TYPE_SIZE) return T_LNGDBL;#endif return 0; } case ARRAY_TYPE: { int m; if (level >= 6) return T_VOID; else m = plain_type_1 (TREE_TYPE (type), level+1); if (sdb_n_dims < SDB_MAX_DIM) sdb_dims[sdb_n_dims++] = (TYPE_DOMAIN (type) && TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) == INTEGER_CST && TREE_CODE (TYPE_MIN_VALUE (TYPE_DOMAIN (type))) == INTEGER_CST ? (TREE_INT_CST_LOW (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) - TREE_INT_CST_LOW (TYPE_MIN_VALUE (TYPE_DOMAIN (type))) + 1) : 0); return PUSH_DERIVED_LEVEL (DT_ARY, m); } case RECORD_TYPE: case UNION_TYPE: case QUAL_UNION_TYPE: case ENUMERAL_TYPE: { char *tag;#ifdef SDB_ALLOW_FORWARD_REFERENCES sdbout_record_type_name (type);#endif#ifndef SDB_ALLOW_UNKNOWN_REFERENCES if ((TREE_ASM_WRITTEN (type) && KNOWN_TYPE_TAG (type) != 0)#ifdef SDB_ALLOW_FORWARD_REFERENCES || TYPE_MODE (type) != VOIDmode#endif )#endif { /* Output the referenced structure tag name only if the .def has already been finished. At least on 386, the Unix assembler cannot handle forward references to tags. */ /* But the 88100, it requires them, sigh... */ /* And the MIPS requires unknown refs as well... */ tag = KNOWN_TYPE_TAG (type); PUT_SDB_TAG (tag); /* These 3 lines used to follow the close brace. However, a size of 0 without a tag implies a tag of 0, so if we don't know a tag, we can't mention the size. */ 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 : (TREE_CODE (type) == QUAL_UNION_TYPE) ? T_UNION : T_ENUM); } case POINTER_TYPE: case REFERENCE_TYPE: { int m; if (level >= 6) return T_VOID; else m = plain_type_1 (TREE_TYPE (type), level+1); return PUSH_DERIVED_LEVEL (DT_PTR, m); } case FUNCTION_TYPE: case METHOD_TYPE: { int m; if (level >= 6) return T_VOID; else m = plain_type_1 (TREE_TYPE (type), level+1); 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 of blocks, counting blocks until it finds the desired block. */static int do_block = 0;static int next_block_number;static voidsdbout_block (block) register tree block;{ while (block) { /* Ignore blocks never expanded or otherwise marked as real. */ if (TREE_USED (block)) { /* When we reach the specified block, output its symbols. */ if (next_block_number == do_block) { sdbout_syms (BLOCK_VARS (block)); } /* 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 (BLOCK_SUBBLOCKS (block)); } block = BLOCK_CHAIN (block); }}/* Call sdbout_symbol on each decl in the chain SYMS. */static voidsdbout_syms (syms) tree syms;{ while (syms) { if (TREE_CODE (syms) != LABEL_DECL) sdbout_symbol (syms, 1); syms = TREE_CHAIN (syms); }}/* Output SDB information for a symbol described by DECL. LOCAL is nonzero if the symbol is not file-scope. */voidsdbout_symbol (decl, local) tree decl; int local;{ tree type = TREE_TYPE (decl); tree context = NULL_TREE; rtx value; int regno = -1; char *name; sdbout_one_type (type);#if 0 /* This loses when functions are marked to be ignored, which happens in the C++ front end. */ if (DECL_IGNORED_P (decl)) return;#endif switch (TREE_CODE (decl)) { case CONST_DECL: /* Enum values are defined by defining the enum type. */ return; case FUNCTION_DECL: /* Don't mention a nested function under its parent. */ context = decl_function_context (decl); if (context == current_function_decl) return; /* Check DECL_INITIAL to distinguish declarations from definitions. Don't output debug info here for declarations; they will have a DECL_INITIAL value of 0. */ if (! DECL_INITIAL (decl)) return; if (GET_CODE (DECL_RTL (decl)) != MEM || GET_CODE (XEXP (DECL_RTL (decl), 0)) != SYMBOL_REF) return; PUT_SDB_DEF (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))); PUT_SDB_VAL (XEXP (DECL_RTL (decl), 0)); PUT_SDB_SCL (TREE_PUBLIC (decl) ? C_EXT : C_STAT); break; case TYPE_DECL: /* Done with tagged types. */ if (DECL_NAME (decl) == 0) return; if (DECL_IGNORED_P (decl)) return; /* Output typedef name. */ if (template_name_p (DECL_NAME (decl))) PUT_SDB_DEF (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))); else PUT_SDB_DEF (IDENTIFIER_POINTER (DECL_NAME (decl))); PUT_SDB_SCL (C_TPDEF); break; case PARM_DECL: /* Parm decls go in their own separate chains and are output by sdbout_reg_parms and sdbout_parms. */ abort (); case VAR_DECL: /* Don't mention a variable that is external. Let the file that defines it describe it. */ if (DECL_EXTERNAL (decl)) return; /* Ignore __FUNCTION__, etc. */ if (DECL_IGNORED_P (decl)) return; /* If there was an error in the declaration, don't dump core if there is no RTL associated with the variable doesn't exist. */ if (DECL_RTL (decl) == 0) return; DECL_RTL (decl) = eliminate_regs (DECL_RTL (decl), 0, NULL_RTX, 0);#ifdef LEAF_REG_REMAP if (leaf_function) leaf_renumber_regs_insn (DECL_RTL (decl));#endif value = DECL_RTL (decl); /* Don't mention a variable at all if it was completely optimized into nothingness. If DECL was from an inline function, then its rtl is not identically the rtl that was used in this particular compilation. */ if (GET_CODE (value) == REG) { regno = REGNO (DECL_RTL (decl)); if (regno >= FIRST_PSEUDO_REGISTER) return; } else if (GET_CODE (value) == SUBREG) { int offset = 0; while (GET_CODE (value) == SUBREG)
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?