sdbout.c
来自「GCC编译器源代码」· C语言 代码 · 共 1,635 行 · 第 1/4 页
C
1,635 行
{ offset += SUBREG_WORD (value); value = SUBREG_REG (value); } if (GET_CODE (value) == REG) { regno = REGNO (value); if (regno >= FIRST_PSEUDO_REGISTER) return; regno += offset; } alter_subreg (DECL_RTL (decl)); value = DECL_RTL (decl); } /* Don't output anything if an auto variable gets RTL that is static. GAS version 2.2 can't handle such output. */ else if (GET_CODE (value) == MEM && CONSTANT_P (XEXP (value, 0)) && ! TREE_STATIC (decl)) return; /* Emit any structure, union, or enum type that has not been output. This occurs for tag-less structs (et al) used to declare variables within functions. */ if (TREE_CODE (type) == ENUMERAL_TYPE || TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE || TREE_CODE (type) == QUAL_UNION_TYPE) { if (TYPE_SIZE (type) != 0 /* not a forward reference */ && KNOWN_TYPE_TAG (type) == 0) /* not yet declared */ sdbout_one_type (type); } /* Defer SDB information for top-level initialized variables! */ if (! local && GET_CODE (value) == MEM && DECL_INITIAL (decl)) return; /* C++ in 2.3 makes nameless symbols. That will be fixed later. For now, avoid crashing. */ if (DECL_NAME (decl) == NULL_TREE) return; /* Record the name for, starting a symtab entry. */ name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)); if (GET_CODE (value) == MEM && GET_CODE (XEXP (value, 0)) == SYMBOL_REF) { PUT_SDB_DEF (name); if (TREE_PUBLIC (decl)) { PUT_SDB_VAL (XEXP (value, 0)); PUT_SDB_SCL (C_EXT); } else { PUT_SDB_VAL (XEXP (value, 0)); PUT_SDB_SCL (C_STAT); } } else if (regno >= 0) { PUT_SDB_DEF (name); PUT_SDB_INT_VAL (DBX_REGISTER_NUMBER (regno)); PUT_SDB_SCL (C_REG); } else if (GET_CODE (value) == MEM && (GET_CODE (XEXP (value, 0)) == MEM || (GET_CODE (XEXP (value, 0)) == REG && REGNO (XEXP (value, 0)) != HARD_FRAME_POINTER_REGNUM && REGNO (XEXP (value, 0)) != STACK_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. COFF has no way to represent this so all we can do is output the variable as a pointer. */ { PUT_SDB_DEF (name); if (GET_CODE (XEXP (value, 0)) == REG) { PUT_SDB_INT_VAL (DBX_REGISTER_NUMBER (REGNO (XEXP (value, 0)))); PUT_SDB_SCL (C_REG); } else { /* DECL_RTL looks like (MEM (MEM (PLUS (REG...) (CONST_INT...)))). We want the value of that CONST_INT. */ /* Encore compiler hates a newline in a macro arg, it seems. */ PUT_SDB_INT_VAL (DEBUGGER_AUTO_OFFSET (XEXP (XEXP (value, 0), 0))); PUT_SDB_SCL (C_AUTO); } type = build_pointer_type (TREE_TYPE (decl)); } else if (GET_CODE (value) == MEM && ((GET_CODE (XEXP (value, 0)) == PLUS && GET_CODE (XEXP (XEXP (value, 0), 0)) == REG && GET_CODE (XEXP (XEXP (value, 0), 1)) == CONST_INT) /* This is for variables which are at offset zero from the frame pointer. This happens on the Alpha. Non-frame pointer registers are excluded above. */ || (GET_CODE (XEXP (value, 0)) == REG))) { /* DECL_RTL looks like (MEM (PLUS (REG...) (CONST_INT...))) or (MEM (REG...)). We want the value of that CONST_INT or zero. */ PUT_SDB_DEF (name); PUT_SDB_INT_VAL (DEBUGGER_AUTO_OFFSET (XEXP (value, 0))); PUT_SDB_SCL (C_AUTO); } else if (GET_CODE (value) == MEM && GET_CODE (XEXP (value, 0)) == CONST) { /* Handle an obscure case which can arise when optimizing and when there are few available registers. (This is *always* the case for i386/i486 targets). The DECL_RTL looks like (MEM (CONST ...)) even though this variable is a local `auto' or a local `register' variable. In effect, what has happened is that the reload pass has seen that all assignments and references for one such a local variable can be replaced by equivalent assignments and references to some static storage variable, thereby avoiding the need for a register. In such cases we're forced to lie to debuggers and tell them that this variable was itself `static'. */ PUT_SDB_DEF (name); PUT_SDB_VAL (XEXP (XEXP (value, 0), 0)); PUT_SDB_SCL (C_STAT); } else { /* It is something we don't know how to represent for SDB. */ return; } break; } PUT_SDB_TYPE (plain_type (type)); PUT_SDB_ENDEF;}/* Output SDB information for a top-level initialized variable that has been delayed. */voidsdbout_toplevel_data (decl) tree decl;{ tree type = TREE_TYPE (decl); if (DECL_IGNORED_P (decl)) return; if (! (TREE_CODE (decl) == VAR_DECL && GET_CODE (DECL_RTL (decl)) == MEM && DECL_INITIAL (decl))) abort (); PUT_SDB_DEF (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))); PUT_SDB_VAL (XEXP (DECL_RTL (decl), 0)); if (TREE_PUBLIC (decl)) { PUT_SDB_SCL (C_EXT); } else { PUT_SDB_SCL (C_STAT); } PUT_SDB_TYPE (plain_type (type)); PUT_SDB_ENDEF;}#ifdef SDB_ALLOW_FORWARD_REFERENCES/* Machinery to record and output anonymous types. */static tree anonymous_types;static voidsdbout_queue_anonymous_type (type) tree type;{ anonymous_types = saveable_tree_cons (NULL_TREE, type, anonymous_types);}static voidsdbout_dequeue_anonymous_types (){ register tree types, link; while (anonymous_types) { types = nreverse (anonymous_types); anonymous_types = NULL_TREE; for (link = types; link; link = TREE_CHAIN (link)) { register tree type = TREE_VALUE (link); if (type && ! TREE_ASM_WRITTEN (type)) sdbout_one_type (type); } }}#endif/* Given a chain of ..._TYPE nodes, all of which have names, output definitions of those names, as typedefs. */voidsdbout_types (types) register tree types;{ register tree link; for (link = types; link; link = TREE_CHAIN (link)) sdbout_one_type (link);#ifdef SDB_ALLOW_FORWARD_REFERENCES sdbout_dequeue_anonymous_types ();#endif}static voidsdbout_type (type) tree type;{ if (type == error_mark_node) type = integer_type_node; PUT_SDB_TYPE (plain_type (type));}/* Output types of the fields of type TYPE, if they are structs. Formerly did not chase through pointer types, since that could be circular. They must come before TYPE, since forward refs are not allowed. Now james@bigtex.cactus.org says to try them. */static voidsdbout_field_types (type) tree type;{ tree tail; for (tail = TYPE_FIELDS (type); tail; tail = TREE_CHAIN (tail)) if (TREE_CODE (TREE_TYPE (tail)) == POINTER_TYPE) sdbout_one_type (TREE_TYPE (TREE_TYPE (tail))); else sdbout_one_type (TREE_TYPE (tail));}/* Use this to put out the top level defined record and union types for later reference. If this is a struct with a name, then put that name out. Other unnamed structs will have .xxfake labels generated so that they may be referred to later. The label will be stored in the KNOWN_TYPE_TAG slot of a type. It may NOT be called recursively. */static voidsdbout_one_type (type) tree type;{ if (current_function_decl != NULL_TREE && DECL_SECTION_NAME (current_function_decl) != NULL_TREE) ; /* Don't change section amid function. */ else text_section (); switch (TREE_CODE (type)) { case RECORD_TYPE: case UNION_TYPE: case QUAL_UNION_TYPE: case ENUMERAL_TYPE: type = TYPE_MAIN_VARIANT (type); /* Don't output a type twice. */ if (TREE_ASM_WRITTEN (type)) /* James said test TREE_ASM_BEING_WRITTEN here. */ return; /* Output nothing if type is not yet defined. */ if (TYPE_SIZE (type) == 0) return; TREE_ASM_WRITTEN (type) = 1;#if 1 /* This is reputed to cause trouble with the following case, but perhaps checking TYPE_SIZE above will fix it. */ /* Here is a test case: struct foo { struct badstr *bbb; } forwardref; typedef struct intermediate { int aaaa; } intermediate_ref; typedef struct badstr { int ccccc; } badtype; */#if 0 TREE_ASM_BEING_WRITTEN (type) = 1;#endif /* This change, which ought to make better output, used to make the COFF assembler unhappy. Changes involving KNOWN_TYPE_TAG may fix the problem. */ /* Before really doing anything, output types we want to refer to. */ /* Note that in version 1 the following two lines are not used if forward references are in use. */ if (TREE_CODE (type) != ENUMERAL_TYPE) sdbout_field_types (type);#if 0 TREE_ASM_WRITTEN (type) = 1;#endif#endif /* Output a structure type. */ { int size = int_size_in_bytes (type); int member_scl; tree tem; int i, n_baseclasses = 0; /* Record the type tag, but not in its permanent place just yet. */ sdbout_record_type_name (type); PUT_SDB_DEF (KNOWN_TYPE_TAG (type)); switch (TREE_CODE (type)) { case UNION_TYPE: case QUAL_UNION_TYPE: PUT_SDB_SCL (C_UNTAG); PUT_SDB_TYPE (T_UNION); member_scl = C_MOU; break; case RECORD_TYPE: PUT_SDB_SCL (C_STRTAG); PUT_SDB_TYPE (T_STRUCT); member_scl = C_MOS; break; case ENUMERAL_TYPE: PUT_SDB_SCL (C_ENTAG); PUT_SDB_TYPE (T_ENUM); member_scl = C_MOE; break; } PUT_SDB_SIZE (size); PUT_SDB_ENDEF; /* Print out the base class information with fields named after the types they hold. */ if (TYPE_BINFO (type) && TYPE_BINFO_BASETYPES (type)) n_baseclasses = TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (type)); for (i = 0; i < n_baseclasses; i++) { tree child = TREE_VEC_ELT (BINFO_BASETYPES (TYPE_BINFO (type)), i); tree child_type = BINFO_TYPE (child); tree child_type_name; if (TYPE_NAME (child_type) == 0) continue; if (TREE_CODE (TYPE_NAME (child_type)) == IDENTIFIER_NODE) child_type_name = TYPE_NAME (child_type); else if (TREE_CODE (TYPE_NAME (child_type)) == TYPE_DECL) { child_type_name = DECL_NAME (TYPE_NAME (child_type)); if (child_type_name && template_name_p (child_type_name)) child_type_name = DECL_ASSEMBLER_NAME (TYPE_NAME (child_type)); } else continue; CONTIN; PUT_SDB_DEF (IDENTIFIER_POINTER (child_type_name)); PUT_SDB_INT_VAL (TREE_INT_CST_LOW (BINFO_OFFSET (child))); PUT_SDB_SCL (member_scl); sdbout_type (BINFO_TYPE (child)); PUT_SDB_ENDEF; } /* output the individual fields */ if (TREE_CODE (type) == ENUMERAL_TYPE) for (tem = TYPE_FIELDS (type); tem; tem = TREE_CHAIN (tem)) { PUT_SDB_DEF (IDENTIFIER_POINTER (TREE_PURPOSE (tem))); PUT_SDB_INT_VAL (TREE_INT_CST_LOW (TREE_VALUE (tem))); PUT_SDB_SCL (C_MOE); PUT_SDB_TYPE (T_MOE); PUT_SDB_ENDEF; } else /* record or union type */ 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. Also omit fields with variable size or position.
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?