📄 sdbout.c
字号:
return (TREE_UNSIGNED (type) ? T_ULONG : T_LONG); return 0; } case REAL_TYPE: { int size = int_size_in_bytes (type) * BITS_PER_UNIT; if (size == FLOAT_TYPE_SIZE) return T_FLOAT; if (size == DOUBLE_TYPE_SIZE) return T_DOUBLE; 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_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 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; if (DECL_EXTERNAL (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);#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) { 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 ();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -