dbxout.c
来自「GCC编译器源代码」· C语言 代码 · 共 2,183 行 · 第 1/5 页
C
2,183 行
int_size_in_bytes (type)); if (use_gnu_debug_info_extensions) { if (n_baseclasses) { have_used_extensions = 1; fprintf (asmfile, "!%d,", n_baseclasses); CHARS (8); } } for (i = 0; i < n_baseclasses; i++) { tree child = TREE_VEC_ELT (BINFO_BASETYPES (TYPE_BINFO (type)), i); if (use_gnu_debug_info_extensions) { have_used_extensions = 1; putc (TREE_VIA_VIRTUAL (child) ? '1' : '0', asmfile); putc (TREE_VIA_PUBLIC (child) ? '2' : '0', asmfile); fprintf (asmfile, "%d,", TREE_INT_CST_LOW (BINFO_OFFSET (child)) * BITS_PER_UNIT); CHARS (15); dbxout_type (BINFO_TYPE (child), 0, 0); putc (';', asmfile); } else { /* Print out the base class information with fields which have the same names at the types they hold. */ dbxout_type_name (BINFO_TYPE (child)); putc (':', asmfile); dbxout_type (BINFO_TYPE (child), full, 0); fprintf (asmfile, ",%d,%d;", TREE_INT_CST_LOW (BINFO_OFFSET (child)) * BITS_PER_UNIT, TREE_INT_CST_LOW (DECL_SIZE (TYPE_NAME (BINFO_TYPE (child)))) * BITS_PER_UNIT); CHARS (20); } } } CHARS (11); /* Write out the field declarations. */ dbxout_type_fields (type); if (use_gnu_debug_info_extensions && TYPE_METHODS (type) != NULL_TREE) { have_used_extensions = 1; dbxout_type_methods (type); } putc (';', asmfile); if (use_gnu_debug_info_extensions && TREE_CODE (type) == RECORD_TYPE /* Avoid the ~ if we don't really need it--it confuses dbx. */ && TYPE_VFIELD (type)) { have_used_extensions = 1; /* Tell GDB+ that it may keep reading. */ putc ('~', asmfile); /* We need to write out info about what field this class uses as its "main" vtable pointer field, because if this field is inherited from a base class, GDB cannot necessarily figure out which field it's using in time. */ if (TYPE_VFIELD (type)) { putc ('%', asmfile); dbxout_type (DECL_FCONTEXT (TYPE_VFIELD (type)), 0, 0); } putc (';', asmfile); CHARS (3); } break; case ENUMERAL_TYPE: /* We must use the same test here as we use in the DBX_NO_XREFS case above. We simplify it a bit since an enum will never have a variable size. */ if ((TYPE_NAME (type) != 0 && ! (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL && DECL_IGNORED_P (TYPE_NAME (type))) && !full) || TYPE_SIZE (type) == 0) { fprintf (asmfile, "xe"); CHARS (3); dbxout_type_name (type); typevec[TYPE_SYMTAB_ADDRESS (type)].status = TYPE_XREF; fprintf (asmfile, ":"); return; }#ifdef DBX_OUTPUT_ENUM DBX_OUTPUT_ENUM (asmfile, type);#else if (use_gnu_debug_info_extensions && TYPE_PRECISION (type) != TYPE_PRECISION (integer_type_node)) fprintf (asmfile, "@s%d;", TYPE_PRECISION (type)); putc ('e', asmfile); CHARS (1); for (tem = TYPE_VALUES (type); tem; tem = TREE_CHAIN (tem)) { fprintf (asmfile, "%s:", IDENTIFIER_POINTER (TREE_PURPOSE (tem))); if (TREE_INT_CST_HIGH (TREE_VALUE (tem)) == 0) fprintf (asmfile, "%lu", (unsigned long) TREE_INT_CST_LOW (TREE_VALUE (tem))); else if (TREE_INT_CST_HIGH (TREE_VALUE (tem)) == -1 && TREE_INT_CST_LOW (TREE_VALUE (tem)) < 0) fprintf (asmfile, "%ld", (long) TREE_INT_CST_LOW (TREE_VALUE (tem))); else print_int_cst_octal (TREE_VALUE (tem)); fprintf (asmfile, ","); CHARS (20 + IDENTIFIER_LENGTH (TREE_PURPOSE (tem))); if (TREE_CHAIN (tem) != 0) CONTIN; } putc (';', asmfile); CHARS (1);#endif break; case POINTER_TYPE: putc ('*', asmfile); CHARS (1); dbxout_type (TREE_TYPE (type), 0, 0); break; case METHOD_TYPE: if (use_gnu_debug_info_extensions) { have_used_extensions = 1; putc ('#', asmfile); CHARS (1); if (flag_minimal_debug && !show_arg_types) { /* Normally, just output the return type. The argument types are encoded in the method name. */ putc ('#', asmfile); CHARS (1); dbxout_type (TREE_TYPE (type), 0, 0); putc (';', asmfile); CHARS (1); } else { /* When outputting destructors, we need to write the argument types out longhand. */ dbxout_type (TYPE_METHOD_BASETYPE (type), 0, 0); putc (',', asmfile); CHARS (1); dbxout_type (TREE_TYPE (type), 0, 0); dbxout_args (TYPE_ARG_TYPES (type)); putc (';', asmfile); CHARS (1); } } else { /* Treat it as a function type. */ dbxout_type (TREE_TYPE (type), 0, 0); } break; case OFFSET_TYPE: if (use_gnu_debug_info_extensions) { have_used_extensions = 1; putc ('@', asmfile); CHARS (1); dbxout_type (TYPE_OFFSET_BASETYPE (type), 0, 0); putc (',', asmfile); CHARS (1); dbxout_type (TREE_TYPE (type), 0, 0); } else { /* Should print as an int, because it is really just an offset. */ dbxout_type (integer_type_node, 0, 0); } break; case REFERENCE_TYPE: if (use_gnu_debug_info_extensions) have_used_extensions = 1; putc (use_gnu_debug_info_extensions ? '&' : '*', asmfile); CHARS (1); dbxout_type (TREE_TYPE (type), 0, 0); break; case FUNCTION_TYPE: putc ('f', asmfile); CHARS (1); dbxout_type (TREE_TYPE (type), 0, 0); break; default: abort (); }}/* Print the value of integer constant C, in octal, handling double precision. */static voidprint_int_cst_octal (c) tree c;{ unsigned HOST_WIDE_INT high = TREE_INT_CST_HIGH (c); unsigned HOST_WIDE_INT low = TREE_INT_CST_LOW (c); int excess = (3 - (HOST_BITS_PER_WIDE_INT % 3)); int width = TYPE_PRECISION (TREE_TYPE (c)); /* GDB wants constants with no extra leading "1" bits, so we need to remove any sign-extension that might be present. */ if (width == HOST_BITS_PER_WIDE_INT * 2) ; else if (width > HOST_BITS_PER_WIDE_INT) high &= (((HOST_WIDE_INT) 1 << (width - HOST_BITS_PER_WIDE_INT)) - 1); else if (width == HOST_BITS_PER_WIDE_INT) high = 0; else high = 0, low &= (((HOST_WIDE_INT) 1 << width) - 1); fprintf (asmfile, "0"); if (excess == 3) { print_octal (high, HOST_BITS_PER_WIDE_INT / 3); print_octal (low, HOST_BITS_PER_WIDE_INT / 3); } else { unsigned HOST_WIDE_INT beg = high >> excess; unsigned HOST_WIDE_INT middle = ((high & (((HOST_WIDE_INT) 1 << excess) - 1)) << (3 - excess) | (low >> (HOST_BITS_PER_WIDE_INT / 3 * 3))); unsigned HOST_WIDE_INT end = low & (((unsigned HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT / 3 * 3)) - 1); fprintf (asmfile, "%o%01o", beg, middle); print_octal (end, HOST_BITS_PER_WIDE_INT / 3); }}static voidprint_octal (value, digits) unsigned HOST_WIDE_INT value; int digits;{ int i; for (i = digits - 1; i >= 0; i--) fprintf (asmfile, "%01o", ((value >> (3 * i)) & 7));}/* Output the name of type TYPE, with no punctuation. Such names can be set up either by typedef declarations or by struct, enum and union tags. */static voiddbxout_type_name (type) register tree type;{ tree t; if (TYPE_NAME (type) == 0) abort (); 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)); } else abort (); fprintf (asmfile, "%s", IDENTIFIER_POINTER (t)); CHARS (IDENTIFIER_LENGTH (t));}/* Output a .stabs for the symbol defined by DECL, which must be a ..._DECL node in the normal namespace. It may be a CONST_DECL, a FUNCTION_DECL, a PARM_DECL or a VAR_DECL. LOCAL is nonzero if the scope is less than the entire file. */voiddbxout_symbol (decl, local) tree decl; int local;{ tree type = TREE_TYPE (decl); tree context = NULL_TREE; /* Cast avoids warning in old compilers. */ current_sym_code = (STAB_CODE_TYPE) 0; current_sym_value = 0; current_sym_addr = 0; /* Ignore nameless syms, but don't ignore type tags. */ if ((DECL_NAME (decl) == 0 && TREE_CODE (decl) != TYPE_DECL) || DECL_IGNORED_P (decl)) return; dbxout_prepare_symbol (decl); /* The output will always start with the symbol name, so always count that in the length-output-so-far. */ if (DECL_NAME (decl) != 0) current_sym_nchars = 2 + IDENTIFIER_LENGTH (DECL_NAME (decl)); switch (TREE_CODE (decl)) { case CONST_DECL: /* Enum values are defined by defining the enum type. */ break; case FUNCTION_DECL: if (DECL_RTL (decl) == 0) return; if (DECL_EXTERNAL (decl)) break; /* Don't mention a nested function under its parent. */ context = decl_function_context (decl); if (context == current_function_decl) break; if (GET_CODE (DECL_RTL (decl)) != MEM || GET_CODE (XEXP (DECL_RTL (decl), 0)) != SYMBOL_REF) break; FORCE_TEXT; fprintf (asmfile, "%s \"%s:%c", ASM_STABS_OP, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)), TREE_PUBLIC (decl) ? 'F' : 'f'); current_sym_code = N_FUN; current_sym_addr = XEXP (DECL_RTL (decl), 0); if (TREE_TYPE (type)) dbxout_type (TREE_TYPE (type), 0, 0); else dbxout_type (void_type_node, 0, 0); /* For a nested function, when that function is compiled, mention the containing function name as well as (since dbx wants it) our own assembler-name. */ if (context != 0) fprintf (asmfile, ",%s,%s", IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)), IDENTIFIER_POINTER (DECL_NAME (context))); dbxout_finish_symbol (decl); break; case TYPE_DECL:#if 0 /* This seems all wrong. Outputting most kinds of types gives no name at all. A true definition gives no name; a cross-ref for a structure can give the tag name, but not a type name. It seems that no typedef name is defined by outputting a type. */ /* If this typedef name was defined by outputting the type, don't duplicate it. */ if (typevec[TYPE_SYMTAB_ADDRESS (type)].status == TYPE_DEFINED && TYPE_NAME (TREE_TYPE (decl)) == decl) return;#endif /* Don't output the same typedef twice. And don't output what language-specific stuff doesn't want output. */ if (TREE_ASM_WRITTEN (decl) || TYPE_DECL_SUPPRESS_DEBUG (decl)) return; FORCE_TEXT; { int tag_needed = 1; int did_output = 0; if (DECL_NAME (decl)) { /* Nonzero means we must output a tag as well as a typedef. */ tag_needed = 0; /* Handle the case of a C++ structure or union where the TYPE_NAME is a TYPE_DECL which gives both a typedef name and a tag. */ /* dbx requires the tag first and the typedef second. */ if ((TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE || TREE_CODE (type) == QUAL_UNION_TYPE) && TYPE_NAME (type) == decl && !(use_gnu_debug_info_extensions && have_used_extensions) && !TREE_ASM_WRITTEN (TYPE_NAME (type)) /* Distinguish the implicit typedefs of C++ from explicit ones that might be found in C. */ && DECL_ARTIFICIAL (decl)) { tree name = TYPE_NAME (type); if (TREE_CODE (name) == TYPE_DECL) name = DECL_NAME (name); current_sym_code = DBX_TYPE_DECL_STABS_CODE; current_sym_value = 0; current_sym_addr = 0; current_sym_nchars = 2 + IDENTIFIER_LENGTH (name); fprintf (asmfile, "%s \"%s:T", ASM_STABS_OP, IDENTIFIER_POINTER (name)); dbxout_type (type, 1, 0); dbxout_finish_symbol (NULL_TREE); } /* Output typedef name. */ fprintf (asmfile, "%s \"%s:", ASM_STABS_OP, IDENTIFIER_POINTER (DECL_NAME (decl))); /* Short cut way to output a tag also. */ if ((TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE || TREE_CODE (type) == QUAL_UNION_TYPE) && TYPE_NAME (type) == decl /* Distinguish the implicit typedefs of C++ from explicit ones that might be found in C. */ && DECL_ARTIFICIAL (decl)) { if (use_gnu_debug_info_extensions && have_used_extensions) {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?