static void sdbout_reg_parms (tree parms) { for (; parms; parms = TREE_CHAIN (parms)) if (DECL_NAME (parms)) { const char *name = IDENTIFIER_POINTER (DECL_NAME (parms)); /* Report parms that live in registers during the function but were passed in memory. */ if (REG_P (DECL_RTL (parms)) && REGNO (DECL_RTL (parms)) < FIRST_PSEUDO_REGISTER && PARM_PASSED_IN_MEMORY (parms)) { if (name == 0 || *name == 0) name = gen_fake_label (); PUT_SDB_DEF (name); PUT_SDB_INT_VAL (DBX_REGISTER_NUMBER (REGNO (DECL_RTL (parms)))); PUT_SDB_SCL (C_REG); PUT_SDB_TYPE (plain_type (TREE_TYPE (parms))); PUT_SDB_ENDEF; } /* Report parms that live in memory but not where they were passed. */ else if (MEM_P (DECL_RTL (parms)) && GET_CODE (XEXP (DECL_RTL (parms), 0)) == PLUS && CONST_INT_P (XEXP (XEXP (DECL_RTL (parms), 0), 1)) && PARM_PASSED_IN_MEMORY (parms) && ! rtx_equal_p (DECL_RTL (parms), DECL_INCOMING_RTL (parms))) { #if 0 /* ??? It is not clear yet what should replace this. */ int offset = DECL_OFFSET (parms) / BITS_PER_UNIT; /* A parm declared char is really passed as an int, so it occupies the least significant bytes. On a big-endian machine those are not the low-numbered ones. */ if (BYTES_BIG_ENDIAN && offset != -1 && TREE_TYPE (parms) != DECL_ARG_TYPE (parms)) offset += (GET_MODE_SIZE (TYPE_MODE (DECL_ARG_TYPE (parms))) - GET_MODE_SIZE (GET_MODE (DECL_RTL (parms)))); if (INTVAL (XEXP (XEXP (DECL_RTL (parms), 0), 1)) != offset) {...} #endif { if (name == 0 || *name == 0) name = gen_fake_label (); PUT_SDB_DEF (name); PUT_SDB_INT_VAL (DEBUGGER_AUTO_OFFSET (XEXP (DECL_RTL (parms), 0))); PUT_SDB_SCL (C_AUTO); PUT_SDB_TYPE (plain_type (TREE_TYPE (parms))); PUT_SDB_ENDEF; } } }
void print_node (FILE *file, const char *prefix, tree node, int indent) { int hash; struct bucket *b; machine_mode mode; enum tree_code_class tclass; int len; int i; expanded_location xloc; enum tree_code code; if (node == 0) return; code = TREE_CODE (node); tclass = TREE_CODE_CLASS (code); /* Don't get too deep in nesting. If the user wants to see deeper, it is easy to use the address of a lowest-level node as an argument in another call to debug_tree. */ if (indent > 24) { print_node_brief (file, prefix, node, indent); return; } if (indent > 8 && (tclass == tcc_type || tclass == tcc_declaration)) { print_node_brief (file, prefix, node, indent); return; } /* It is unsafe to look at any other fields of an ERROR_MARK node. */ if (code == ERROR_MARK) { print_node_brief (file, prefix, node, indent); return; } /* Allow this function to be called if the table is not there. */ if (table) { hash = ((uintptr_t) node) % HASH_SIZE; /* If node is in the table, just mention its address. */ for (b = table[hash]; b; b = b->next) if (b->node == node) { print_node_brief (file, prefix, node, indent); return; } /* Add this node to the table. */ b = XNEW (struct bucket); b->node = node; b->next = table[hash]; table[hash] = b; } /* Indent to the specified column, since this is the long form. */ indent_to (file, indent); /* Print the slot this node is in, and its code, and address. */ fprintf (file, "%s <%s", prefix, get_tree_code_name (code)); dump_addr (file, " ", node); /* Print the name, if any. */ if (tclass == tcc_declaration) { if (DECL_NAME (node)) fprintf (file, " %s", IDENTIFIER_POINTER (DECL_NAME (node))); else if (code == LABEL_DECL && LABEL_DECL_UID (node) != -1) { if (dump_flags & TDF_NOUID) fprintf (file, " L.xxxx"); else fprintf (file, " L.%d", (int) LABEL_DECL_UID (node)); } else { if (dump_flags & TDF_NOUID) fprintf (file, " %c.xxxx", code == CONST_DECL ? 'C' : 'D'); else fprintf (file, " %c.%u", code == CONST_DECL ? 'C' : 'D', DECL_UID (node)); } } else if (tclass == tcc_type) { if (TYPE_NAME (node)) { if (TREE_CODE (TYPE_NAME (node)) == IDENTIFIER_NODE) fprintf (file, " %s", IDENTIFIER_POINTER (TYPE_NAME (node))); else if (TREE_CODE (TYPE_NAME (node)) == TYPE_DECL && DECL_NAME (TYPE_NAME (node))) fprintf (file, " %s", IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (node)))); } } if (code == IDENTIFIER_NODE) fprintf (file, " %s", IDENTIFIER_POINTER (node)); if (code == INTEGER_CST) { if (indent <= 4) print_node_brief (file, "type", TREE_TYPE (node), indent + 4); } else if (CODE_CONTAINS_STRUCT (code, TS_TYPED)) { print_node (file, "type", TREE_TYPE (node), indent + 4); if (TREE_TYPE (node)) indent_to (file, indent + 3); } if (!TYPE_P (node) && TREE_SIDE_EFFECTS (node)) fputs (" side-effects", file); if (TYPE_P (node) ? TYPE_READONLY (node) : TREE_READONLY (node)) fputs (" readonly", file); if (TYPE_P (node) && TYPE_ATOMIC (node)) fputs (" atomic", file); if (!TYPE_P (node) && TREE_CONSTANT (node)) fputs (" constant", file); else if (TYPE_P (node) && TYPE_SIZES_GIMPLIFIED (node)) fputs (" sizes-gimplified", file); if (TYPE_P (node) && !ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (node))) fprintf (file, " address-space-%d", TYPE_ADDR_SPACE (node)); if (TREE_ADDRESSABLE (node)) fputs (" addressable", file); if (TREE_THIS_VOLATILE (node)) fputs (" volatile", file); if (TREE_ASM_WRITTEN (node)) fputs (" asm_written", file); if (TREE_USED (node)) fputs (" used", file); if (TREE_NOTHROW (node)) fputs (" nothrow", file); if (TREE_PUBLIC (node)) fputs (" public", file); if (TREE_PRIVATE (node)) fputs (" private", file); if (TREE_PROTECTED (node)) fputs (" protected", file); if (TREE_STATIC (node)) fputs (code == CALL_EXPR ? " must-tail-call" : " static", file); if (TREE_DEPRECATED (node)) fputs (" deprecated", file); if (TREE_VISITED (node)) fputs (" visited", file); if (code != TREE_VEC && code != INTEGER_CST && code != SSA_NAME) { if (TREE_LANG_FLAG_0 (node)) fputs (" tree_0", file); if (TREE_LANG_FLAG_1 (node)) fputs (" tree_1", file); if (TREE_LANG_FLAG_2 (node)) fputs (" tree_2", file); if (TREE_LANG_FLAG_3 (node)) fputs (" tree_3", file); if (TREE_LANG_FLAG_4 (node)) fputs (" tree_4", file); if (TREE_LANG_FLAG_5 (node)) fputs (" tree_5", file); if (TREE_LANG_FLAG_6 (node)) fputs (" tree_6", file); } /* DECL_ nodes have additional attributes. */ switch (TREE_CODE_CLASS (code)) { case tcc_declaration: if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON)) { if (DECL_UNSIGNED (node)) fputs (" unsigned", file); if (DECL_IGNORED_P (node)) fputs (" ignored", file); if (DECL_ABSTRACT_P (node)) fputs (" abstract", file); if (DECL_EXTERNAL (node)) fputs (" external", file); if (DECL_NONLOCAL (node)) fputs (" nonlocal", file); } if (CODE_CONTAINS_STRUCT (code, TS_DECL_WITH_VIS)) { if (DECL_WEAK (node)) fputs (" weak", file); if (DECL_IN_SYSTEM_HEADER (node)) fputs (" in_system_header", file); } if (CODE_CONTAINS_STRUCT (code, TS_DECL_WRTL) && code != LABEL_DECL && code != FUNCTION_DECL && DECL_REGISTER (node)) fputs (" regdecl", file); if (code == TYPE_DECL && TYPE_DECL_SUPPRESS_DEBUG (node)) fputs (" suppress-debug", file); if (code == FUNCTION_DECL && DECL_FUNCTION_SPECIFIC_TARGET (node)) fputs (" function-specific-target", file); if (code == FUNCTION_DECL && DECL_FUNCTION_SPECIFIC_OPTIMIZATION (node)) fputs (" function-specific-opt", file); if (code == FUNCTION_DECL && DECL_DECLARED_INLINE_P (node)) fputs (" autoinline", file); if (code == FUNCTION_DECL && DECL_BUILT_IN (node)) fputs (" built-in", file); if (code == FUNCTION_DECL && DECL_STATIC_CHAIN (node)) fputs (" static-chain", file); if (TREE_CODE (node) == FUNCTION_DECL && decl_is_tm_clone (node)) fputs (" tm-clone", file); if (code == FIELD_DECL && DECL_PACKED (node)) fputs (" packed", file); if (code == FIELD_DECL && DECL_BIT_FIELD (node)) fputs (" bit-field", file); if (code == FIELD_DECL && DECL_NONADDRESSABLE_P (node)) fputs (" nonaddressable", file); if (code == LABEL_DECL && EH_LANDING_PAD_NR (node)) fprintf (file, " landing-pad:%d", EH_LANDING_PAD_NR (node)); if (code == VAR_DECL && DECL_IN_TEXT_SECTION (node)) fputs (" in-text-section", file); if (code == VAR_DECL && DECL_IN_CONSTANT_POOL (node)) fputs (" in-constant-pool", file); if (code == VAR_DECL && DECL_COMMON (node)) fputs (" common", file); if (code == VAR_DECL && DECL_THREAD_LOCAL_P (node)) { fputs (" ", file); fputs (tls_model_names[DECL_TLS_MODEL (node)], file); } if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON)) { if (DECL_VIRTUAL_P (node)) fputs (" virtual", file); if (DECL_PRESERVE_P (node)) fputs (" preserve", file); if (DECL_LANG_FLAG_0 (node)) fputs (" decl_0", file); if (DECL_LANG_FLAG_1 (node)) fputs (" decl_1", file); if (DECL_LANG_FLAG_2 (node)) fputs (" decl_2", file); if (DECL_LANG_FLAG_3 (node)) fputs (" decl_3", file); if (DECL_LANG_FLAG_4 (node)) fputs (" decl_4", file); if (DECL_LANG_FLAG_5 (node)) fputs (" decl_5", file); if (DECL_LANG_FLAG_6 (node)) fputs (" decl_6", file); if (DECL_LANG_FLAG_7 (node)) fputs (" decl_7", file); mode = DECL_MODE (node); fprintf (file, " %s", GET_MODE_NAME (mode)); } if ((code == VAR_DECL || code == PARM_DECL || code == RESULT_DECL) && DECL_BY_REFERENCE (node)) fputs (" passed-by-reference", file); if (CODE_CONTAINS_STRUCT (code, TS_DECL_WITH_VIS) && DECL_DEFER_OUTPUT (node)) fputs (" defer-output", file); xloc = expand_location (DECL_SOURCE_LOCATION (node)); fprintf (file, " file %s line %d col %d", xloc.file, xloc.line, xloc.column); if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON)) { print_node (file, "size", DECL_SIZE (node), indent + 4); print_node (file, "unit size", DECL_SIZE_UNIT (node), indent + 4); if (code != FUNCTION_DECL || DECL_BUILT_IN (node)) indent_to (file, indent + 3); if (DECL_USER_ALIGN (node)) fprintf (file, " user"); fprintf (file, " align %d", DECL_ALIGN (node)); if (code == FIELD_DECL) fprintf (file, " offset_align " HOST_WIDE_INT_PRINT_UNSIGNED, DECL_OFFSET_ALIGN (node)); if (code == FUNCTION_DECL && DECL_BUILT_IN (node)) { if (DECL_BUILT_IN_CLASS (node) == BUILT_IN_MD) fprintf (file, " built-in BUILT_IN_MD %d", DECL_FUNCTION_CODE (node)); else fprintf (file, " built-in %s:%s", built_in_class_names[(int) DECL_BUILT_IN_CLASS (node)], built_in_names[(int) DECL_FUNCTION_CODE (node)]); } } if (code == FIELD_DECL) { print_node (file, "offset", DECL_FIELD_OFFSET (node), indent + 4); print_node (file, "bit offset", DECL_FIELD_BIT_OFFSET (node), indent + 4); if (DECL_BIT_FIELD_TYPE (node)) print_node (file, "bit_field_type", DECL_BIT_FIELD_TYPE (node), indent + 4); } print_node_brief (file, "context", DECL_CONTEXT (node), indent + 4); if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON)) { print_node_brief (file, "attributes", DECL_ATTRIBUTES (node), indent + 4); if (code != PARM_DECL) print_node_brief (file, "initial", DECL_INITIAL (node), indent + 4); } if (CODE_CONTAINS_STRUCT (code, TS_DECL_WRTL)) { print_node_brief (file, "abstract_origin", DECL_ABSTRACT_ORIGIN (node), indent + 4); } if (CODE_CONTAINS_STRUCT (code, TS_DECL_NON_COMMON)) { print_node (file, "result", DECL_RESULT_FLD (node), indent + 4); } lang_hooks.print_decl (file, node, indent); if (DECL_RTL_SET_P (node)) { indent_to (file, indent + 4); print_rtl (file, DECL_RTL (node)); } if (code == PARM_DECL) { print_node (file, "arg-type", DECL_ARG_TYPE (node), indent + 4); if (DECL_INCOMING_RTL (node) != 0) { indent_to (file, indent + 4); fprintf (file, "incoming-rtl "); print_rtl (file, DECL_INCOMING_RTL (node)); } } else if (code == FUNCTION_DECL && DECL_STRUCT_FUNCTION (node) != 0) { print_node (file, "arguments", DECL_ARGUMENTS (node), indent + 4); indent_to (file, indent + 4); dump_addr (file, "struct-function ", DECL_STRUCT_FUNCTION (node)); } if ((code == VAR_DECL || code == PARM_DECL) && DECL_HAS_VALUE_EXPR_P (node)) print_node (file, "value-expr", DECL_VALUE_EXPR (node), indent + 4); /* Print the decl chain only if decl is at second level. */ if (indent == 4) print_node (file, "chain", TREE_CHAIN (node), indent + 4); else print_node_brief (file, "chain", TREE_CHAIN (node), indent + 4); break; case tcc_type: if (TYPE_UNSIGNED (node)) fputs (" unsigned", file); if (TYPE_NO_FORCE_BLK (node)) fputs (" no-force-blk", file); if (TYPE_STRING_FLAG (node)) fputs (" string-flag", file); if (TYPE_NEEDS_CONSTRUCTING (node)) fputs (" needs-constructing", file); if ((code == RECORD_TYPE || code == UNION_TYPE || code == QUAL_UNION_TYPE || code == ARRAY_TYPE) && TYPE_REVERSE_STORAGE_ORDER (node)) fputs (" reverse-storage-order", file); /* The transparent-union flag is used for different things in different nodes. */ if ((code == UNION_TYPE || code == RECORD_TYPE) && TYPE_TRANSPARENT_AGGR (node)) fputs (" transparent-aggr", file); else if (code == ARRAY_TYPE && TYPE_NONALIASED_COMPONENT (node)) fputs (" nonaliased-component", file); if (TYPE_PACKED (node)) fputs (" packed", file); if (TYPE_RESTRICT (node)) fputs (" restrict", file); if (TYPE_LANG_FLAG_0 (node)) fputs (" type_0", file); if (TYPE_LANG_FLAG_1 (node)) fputs (" type_1", file); if (TYPE_LANG_FLAG_2 (node)) fputs (" type_2", file); if (TYPE_LANG_FLAG_3 (node)) fputs (" type_3", file); if (TYPE_LANG_FLAG_4 (node)) fputs (" type_4", file); if (TYPE_LANG_FLAG_5 (node)) fputs (" type_5", file); if (TYPE_LANG_FLAG_6 (node)) fputs (" type_6", file); if (TYPE_LANG_FLAG_7 (node)) fputs (" type_7", file); mode = TYPE_MODE (node); fprintf (file, " %s", GET_MODE_NAME (mode)); print_node (file, "size", TYPE_SIZE (node), indent + 4); print_node (file, "unit size", TYPE_SIZE_UNIT (node), indent + 4); indent_to (file, indent + 3); if (TYPE_USER_ALIGN (node)) fprintf (file, " user"); fprintf (file, " align %d symtab %d alias set " HOST_WIDE_INT_PRINT_DEC, TYPE_ALIGN (node), TYPE_SYMTAB_ADDRESS (node), (HOST_WIDE_INT) TYPE_ALIAS_SET (node)); if (TYPE_STRUCTURAL_EQUALITY_P (node)) fprintf (file, " structural equality"); else dump_addr (file, " canonical type ", TYPE_CANONICAL (node)); print_node (file, "attributes", TYPE_ATTRIBUTES (node), indent + 4); if (INTEGRAL_TYPE_P (node) || code == REAL_TYPE || code == FIXED_POINT_TYPE) { fprintf (file, " precision %d", TYPE_PRECISION (node)); print_node_brief (file, "min", TYPE_MIN_VALUE (node), indent + 4); print_node_brief (file, "max", TYPE_MAX_VALUE (node), indent + 4); } if (code == ENUMERAL_TYPE) print_node (file, "values", TYPE_VALUES (node), indent + 4); else if (code == ARRAY_TYPE) print_node (file, "domain", TYPE_DOMAIN (node), indent + 4); else if (code == VECTOR_TYPE) fprintf (file, " nunits %d", (int) TYPE_VECTOR_SUBPARTS (node)); else if (code == RECORD_TYPE || code == UNION_TYPE || code == QUAL_UNION_TYPE) print_node (file, "fields", TYPE_FIELDS (node), indent + 4); else if (code == FUNCTION_TYPE || code == METHOD_TYPE) { if (TYPE_METHOD_BASETYPE (node)) print_node_brief (file, "method basetype", TYPE_METHOD_BASETYPE (node), indent + 4); print_node (file, "arg-types", TYPE_ARG_TYPES (node), indent + 4); } else if (code == OFFSET_TYPE) print_node_brief (file, "basetype", TYPE_OFFSET_BASETYPE (node), indent + 4); if (TYPE_CONTEXT (node)) print_node_brief (file, "context", TYPE_CONTEXT (node), indent + 4); lang_hooks.print_type (file, node, indent); if (TYPE_POINTER_TO (node) || TREE_CHAIN (node)) indent_to (file, indent + 3); print_node_brief (file, "pointer_to_this", TYPE_POINTER_TO (node), indent + 4); print_node_brief (file, "reference_to_this", TYPE_REFERENCE_TO (node), indent + 4); print_node_brief (file, "chain", TREE_CHAIN (node), indent + 4); break; case tcc_expression: case tcc_comparison: case tcc_unary: case tcc_binary: case tcc_reference: case tcc_statement: case tcc_vl_exp: if (code == BIND_EXPR) { print_node (file, "vars", TREE_OPERAND (node, 0), indent + 4); print_node (file, "body", TREE_OPERAND (node, 1), indent + 4); print_node (file, "block", TREE_OPERAND (node, 2), indent + 4); break; } if (code == CALL_EXPR) { call_expr_arg_iterator iter; tree arg; print_node (file, "fn", CALL_EXPR_FN (node), indent + 4); print_node (file, "static_chain", CALL_EXPR_STATIC_CHAIN (node), indent + 4); i = 0; FOR_EACH_CALL_EXPR_ARG (arg, iter, node) { char temp[10]; sprintf (temp, "arg %d", i); print_node (file, temp, arg, indent + 4); i++; } }
static void sdbout_parms (tree parms) { for (; parms; parms = TREE_CHAIN (parms)) if (DECL_NAME (parms)) { int current_sym_value = 0; const char *name = IDENTIFIER_POINTER (DECL_NAME (parms)); if (name == 0 || *name == 0) name = gen_fake_label (); /* Perform any necessary register eliminations on the parameter's rtl, so that the debugging output will be accurate. */ DECL_INCOMING_RTL (parms) = eliminate_regs (DECL_INCOMING_RTL (parms), VOIDmode, NULL_RTX); SET_DECL_RTL (parms, eliminate_regs (DECL_RTL (parms), VOIDmode, NULL_RTX)); if (PARM_PASSED_IN_MEMORY (parms)) { rtx addr = XEXP (DECL_INCOMING_RTL (parms), 0); tree type; /* ??? Here we assume that the parm address is indexed off the frame pointer or arg pointer. If that is not true, we produce meaningless results, but do not crash. */ if (GET_CODE (addr) == PLUS && CONST_INT_P (XEXP (addr, 1))) current_sym_value = INTVAL (XEXP (addr, 1)); else current_sym_value = 0; if (REG_P (DECL_RTL (parms)) && REGNO (DECL_RTL (parms)) < FIRST_PSEUDO_REGISTER) type = DECL_ARG_TYPE (parms); else { int original_sym_value = current_sym_value; /* This is the case where the parm is passed as an int or double and it is converted to a char, short or float and stored back in the parmlist. In this case, describe the parm with the variable's declared type, and adjust the address if the least significant bytes (which we are using) are not the first ones. */ if (BYTES_BIG_ENDIAN && TREE_TYPE (parms) != DECL_ARG_TYPE (parms)) current_sym_value += (GET_MODE_SIZE (TYPE_MODE (DECL_ARG_TYPE (parms))) - GET_MODE_SIZE (GET_MODE (DECL_RTL (parms)))); if (MEM_P (DECL_RTL (parms)) && GET_CODE (XEXP (DECL_RTL (parms), 0)) == PLUS && (GET_CODE (XEXP (XEXP (DECL_RTL (parms), 0), 1)) == CONST_INT) && (INTVAL (XEXP (XEXP (DECL_RTL (parms), 0), 1)) == current_sym_value)) type = TREE_TYPE (parms); else { current_sym_value = original_sym_value; type = DECL_ARG_TYPE (parms); } } PUT_SDB_DEF (name); PUT_SDB_INT_VAL (DEBUGGER_ARG_OFFSET (current_sym_value, addr)); PUT_SDB_SCL (C_ARG); PUT_SDB_TYPE (plain_type (type)); PUT_SDB_ENDEF; } else if (REG_P (DECL_RTL (parms))) { rtx best_rtl; /* Parm passed in registers and lives in registers or nowhere. */ /* If parm lives in a register, use that register; pretend the parm was passed there. It would be more consistent to describe the register where the parm was passed, but in practice that register usually holds something else. */ if (REGNO (DECL_RTL (parms)) < FIRST_PSEUDO_REGISTER) best_rtl = DECL_RTL (parms); /* If the parm lives nowhere, use the register where it was passed. */ else best_rtl = DECL_INCOMING_RTL (parms); PUT_SDB_DEF (name); PUT_SDB_INT_VAL (DBX_REGISTER_NUMBER (REGNO (best_rtl))); PUT_SDB_SCL (C_REGPARM); PUT_SDB_TYPE (plain_type (TREE_TYPE (parms))); PUT_SDB_ENDEF; } else if (MEM_P (DECL_RTL (parms)) && XEXP (DECL_RTL (parms), 0) != const0_rtx) { /* Parm was passed in registers but lives on the stack. */ /* DECL_RTL looks like (MEM (PLUS (REG...) (CONST_INT...))), in which case we want the value of that CONST_INT, or (MEM (REG ...)) or (MEM (MEM ...)), in which case we use a value of zero. */ if (REG_P (XEXP (DECL_RTL (parms), 0)) || MEM_P (XEXP (DECL_RTL (parms), 0))) current_sym_value = 0; else current_sym_value = INTVAL (XEXP (XEXP (DECL_RTL (parms), 0), 1)); /* Again, this assumes the offset is based on the arg pointer. */ PUT_SDB_DEF (name); PUT_SDB_INT_VAL (DEBUGGER_ARG_OFFSET (current_sym_value, XEXP (DECL_RTL (parms), 0))); PUT_SDB_SCL (C_ARG); PUT_SDB_TYPE (plain_type (TREE_TYPE (parms))); PUT_SDB_ENDEF; } } }