📄 dbxout.c
字号:
and mark the type as partially described. If it later becomes defined, we will output its real definition. If the type has a name, don't nest its definition within another type's definition; instead, output an xref and let the definition come when the name is defined. */ fprintf (asmfile, (TREE_CODE (type) == RECORD_TYPE) ? "xs" : "xu"); CHARS (3);#if 0 /* This assertion is legitimately false in C++. */ /* We shouldn't be outputting a reference to a type before its definition unless the type has a tag name. A typedef name without a tag name should be impossible. */ if (TREE_CODE (TYPE_NAME (type)) != IDENTIFIER_NODE) abort ();#endif dbxout_type_name (type); fprintf (asmfile, ":"); typevec[TYPE_SYMTAB_ADDRESS (type)] = TYPE_XREF; break; } tem = size_in_bytes (type); fprintf (asmfile, (TREE_CODE (type) == RECORD_TYPE) ? "s%d" : "u%d", TREE_INT_CST_LOW (tem)); if (TYPE_BASETYPES (type) && use_gdb_dbx_extensions) { putc ('!', asmfile); putc ((TREE_PUBLIC (TYPE_BASETYPES (type)) ? '2' : '0'), asmfile); dbxout_type (TREE_VALUE (TYPE_BASETYPES (type)), 0); putc (',', asmfile); CHARS (3); } CHARS (11); for (tem = TYPE_FIELDS (type); tem; tem = TREE_CHAIN (tem)) /* Output the name, type, position (in bits), size (in bits) of each field. */ /* Omit here the nameless fields that are used to skip bits. */ if (DECL_NAME (tem) != 0) { /* Continue the line if necessary, but not before the first field. */ if (tem != TYPE_FIELDS (type)) CONTIN; fprintf (asmfile, "%s:", IDENTIFIER_POINTER (DECL_NAME (tem))); CHARS (2 + IDENTIFIER_LENGTH (DECL_NAME (tem)));#ifdef TREE_PRIVATE if (use_gdb_dbx_extensions && (TREE_PRIVATE (tem) || TREE_PROTECTED (tem) || TREE_CODE (tem) != FIELD_DECL)) { putc ('/', asmfile); putc ((TREE_PRIVATE (tem) ? '0' : TREE_PROTECTED (tem) ? '1' : '2'), asmfile); CHARS (2); if (TREE_CODE (tem) == FUNCTION_DECL) { putc (':', asmfile); CHARS (1); dbxout_type (TREE_TYPE (tem), 0); /* FUNCTION_TYPE */ dbxout_args (TYPE_ARG_TYPES (TREE_TYPE (tem)));#ifdef TREE_VIRTUAL fprintf (asmfile, ":%s;%c", XSTR (XEXP (DECL_RTL (tem), 0), 0), TREE_VIRTUAL (tem) ? '*' : '.');#endif CHARS (3 + strlen (XSTR (XEXP (DECL_RTL (tem), 0), 0))); } else dbxout_type (TREE_TYPE (tem), 0); } else#endif dbxout_type (TREE_TYPE (tem), 0); if (TREE_CODE (tem) == VAR_DECL) { if (use_gdb_dbx_extensions) { fprintf (asmfile, ":%s", XSTR (XEXP (DECL_RTL (tem), 0), 0)); CHARS (2 + strlen (XSTR (XEXP (DECL_RTL (tem), 0), 0))); } else { fprintf (asmfile, ",0,0;"); CHARS (5); } } else { fprintf (asmfile, ",%d,%d;", DECL_OFFSET (tem), (TREE_INT_CST_LOW (DECL_SIZE (tem)) * DECL_SIZE_UNIT (tem))); CHARS (23); } } putc (';', asmfile); CHARS (1); break; case ENUMERAL_TYPE: if ((TYPE_NAME (type) != 0 && !full) || TYPE_SIZE (type) == 0) { fprintf (asmfile, "xe"); CHARS (3); dbxout_type_name (type); typevec[TYPE_SYMTAB_ADDRESS (type)] = TYPE_XREF; fprintf (asmfile, ":"); return; } putc ('e', asmfile); CHARS (1); for (tem = TYPE_VALUES (type); tem; tem = TREE_CHAIN (tem)) { fprintf (asmfile, "%s:%d,", IDENTIFIER_POINTER (TREE_PURPOSE (tem)), TREE_INT_CST_LOW (TREE_VALUE (tem))); CHARS (11 + IDENTIFIER_LENGTH (TREE_PURPOSE (tem))); if (TREE_CHAIN (tem) != 0) CONTIN; } putc (';', asmfile); CHARS (1); break; case POINTER_TYPE: putc ('*', asmfile); CHARS (1); dbxout_type (TREE_TYPE (type), 0); break; case METHOD_TYPE: if (use_gdb_dbx_extensions) { putc ('@', asmfile); CHARS (1); dbxout_type (TYPE_METHOD_BASETYPE (type), 0); putc (',', asmfile); CHARS (1); dbxout_type (TREE_TYPE (type), 0); } else { /* Treat it as a function type. */ dbxout_type (TREE_TYPE (type), 0); } break; case OFFSET_TYPE: if (use_gdb_dbx_extensions) { putc ('@', asmfile); CHARS (1); dbxout_type (TYPE_OFFSET_BASETYPE (type), 0); putc (',', asmfile); CHARS (1); dbxout_type (TREE_TYPE (type), 0); } else { /* Treat it as a function type. */ dbxout_type (TREE_TYPE (type), 0); } break; case REFERENCE_TYPE: putc (use_gdb_dbx_extensions ? '&' : '*', asmfile); CHARS (1); dbxout_type (TREE_TYPE (type), 0); break; case FUNCTION_TYPE: putc ('f', asmfile); CHARS (1); dbxout_type (TREE_TYPE (type), 0); break; default: abort (); }}/* 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;{ int letter = 0; tree type = TREE_TYPE (decl); /* If global, first output all types and all struct, enum and union tags that have been created and not yet output. */ if (local == 0) { dbxout_tags (gettags ()); dbxout_types (get_permanent_types ()); } current_sym_code = 0; current_sym_value = 0; current_sym_addr = 0; /* The output will always start with the symbol name, so count that always in the length-output-so-far. */ 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 (TREE_EXTERNAL (decl)) break; if (GET_CODE (DECL_RTL (decl)) != MEM || GET_CODE (XEXP (DECL_RTL (decl), 0)) != SYMBOL_REF) break; FORCE_TEXT; fprintf (asmfile, ".stabs \"%s:%c", IDENTIFIER_POINTER (DECL_NAME (decl)), TREE_PUBLIC (decl) ? 'F' : 'f'); current_sym_code = N_FUN; current_sym_addr = XEXP (DECL_RTL (decl), 0); if (TREE_TYPE (TREE_TYPE (decl))) dbxout_type (TREE_TYPE (TREE_TYPE (decl)), 0); else dbxout_type (void_type_node, 0); dbxout_finish_symbol (); 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)] == TYPE_DEFINED && TYPE_NAME (TREE_TYPE (decl)) == decl) return;#endif /* Don't output the same typedef twice. */ if (TREE_ASM_WRITTEN (decl)) return; /* Output typedef name. */ FORCE_TEXT; fprintf (asmfile, ".stabs \"%s:t", IDENTIFIER_POINTER (DECL_NAME (decl))); current_sym_code = N_LSYM; dbxout_type (TREE_TYPE (decl), 1); dbxout_finish_symbol (); /* Prevent duplicate output of a typedef. */ TREE_ASM_WRITTEN (decl) = 1; break; case PARM_DECL: /* Parm decls go in their own separate chains and are output by dbxout_reg_parms and dbxout_parms. */ abort (); case VAR_DECL: if (DECL_RTL (decl) == 0) return; /* Don't mention a variable that is external. Let the file that defines it describe it. */ if (TREE_EXTERNAL (decl)) break; /* Don't mention a variable at all if it was completely optimized into nothingness. */ if (GET_CODE (DECL_RTL (decl)) == REG && (REGNO (DECL_RTL (decl)) < 0 || REGNO (DECL_RTL (decl)) >= FIRST_PSEUDO_REGISTER)) break; /* The kind-of-variable letter depends on where the variable is and on the scope of its name: G and N_GSYM for static storage and global scope, S for static storage and file scope, V for static storage and local scope, for those two, use N_LCSYM if data is in bss segment, N_STSYM if in data segment, N_FUN otherwise. (We used N_FUN originally, then changed to N_STSYM to please GDB. However, it seems that confused ld. Now GDB has been fixed to like N_FUN, says Kingdon.) no letter at all, and N_LSYM, for auto variable, r and N_RSYM for register variable. */ if (GET_CODE (DECL_RTL (decl)) == MEM && GET_CODE (XEXP (DECL_RTL (decl), 0)) == SYMBOL_REF) { if (TREE_PUBLIC (decl)) { letter = 'G'; current_sym_code = N_GSYM; } else { current_sym_addr = XEXP (DECL_RTL (decl), 0); letter = TREE_PERMANENT (decl) ? 'S' : 'V'; if (!DECL_INITIAL (decl)) current_sym_code = N_LCSYM; else if (TREE_READONLY (decl) && ! TREE_VOLATILE (decl)) /* This is not quite right, but it's the closest of all the codes that Unix defines. */ current_sym_code = N_FUN; else {/* Ultrix `as' seems to need this. */#ifdef DBX_STATIC_STAB_DATA_SECTION data_section ();#endif current_sym_code = N_STSYM; } } } else if (GET_CODE (DECL_RTL (decl)) == REG) { letter = 'r'; current_sym_code = N_RSYM; current_sym_value = DBX_REGISTER_NUMBER (REGNO (DECL_RTL (decl))); } else if (GET_CODE (DECL_RTL (decl)) == SUBREG) { rtx value = DECL_RTL (decl); int offset = 0; while (GET_CODE (value) == SUBREG) { offset += SUBREG_WORD (value); value = SUBREG_REG (value); } letter = 'r'; current_sym_code = N_RSYM; current_sym_value = DBX_REGISTER_NUMBER (REGNO (value) + offset); } else if (GET_CODE (DECL_RTL (decl)) == MEM && (GET_CODE (XEXP (DECL_RTL (decl), 0)) == MEM || (GET_CODE (XEXP (DECL_RTL (decl), 0)) == REG && REGNO (XEXP (DECL_RTL (decl), 0)) != FRAME_POINTER_REGNUM))) /* If the value is indirect by memory or by a register that isn't the frame pointer then it means the object is variable-sized and address through that register or stack slot. DBX has no way to represent this so all we can do is output the variable as a pointer. If it's not a parameter, ignore it. (VAR_DECLs like this can be made by integrate.c.) */ { if (GET_CODE (XEXP (DECL_RTL (decl), 0)) == REG) { letter = 'r'; current_sym_code = N_RSYM; current_sym_value = DBX_REGISTER_NUMBER (REGNO (XEXP (DECL_RTL (decl), 0))); } else { current_sym_code = N_LSYM; /* DECL_RTL looks like (MEM (MEM (PLUS (REG...) (CONST_INT...)))). We want the value of that CONST_INT. */ current_sym_value = INTVAL (XEXP (XEXP (XEXP (DECL_RTL (decl), 0), 0), 1)); } /* Effectively do build_pointer_type, but don't cache this type, since it might be temporary whereas the type it points to might have been saved for inlining. */ type = make_node (POINTER_TYPE); TREE_TYPE (type) = TREE_TYPE (decl); } else if (GET_CODE (DECL_RTL (decl)) == MEM && GET_CODE (XEXP (DECL_RTL (decl), 0)) == REG) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -