return "DW_CFA_def_cfa_register";
case DW_CFA_def_cfa_offset:
return "DW_CFA_def_cfa_offset";
+
+ /* DWARF 3 */
case DW_CFA_def_cfa_expression:
return "DW_CFA_def_cfa_expression";
+ case DW_CFA_expression:
+ return "DW_CFA_expression";
+ case DW_CFA_offset_extended_sf:
+ return "DW_CFA_offset_extended_sf";
+ case DW_CFA_def_cfa_sf:
+ return "DW_CFA_def_cfa_sf";
+ case DW_CFA_def_cfa_offset_sf:
+ return "DW_CFA_def_cfa_offset_sf";
/* SGI/MIPS specific */
case DW_CFA_MIPS_advance_loc8:
#endif
offset /= DWARF_CIE_DATA_ALIGNMENT;
if (offset < 0)
- {
- cfi->dw_cfi_opc = DW_CFA_GNU_negative_offset_extended;
- offset = -offset;
- }
+ cfi->dw_cfi_opc = DW_CFA_offset_extended_sf;
cfi->dw_cfi_oprnd2.dw_cfi_offset = offset;
}
return 0;
offset = INTVAL (XEXP (src, 1));
+ if (code == PLUS)
+ offset = -offset;
}
else if (GET_CODE (dest) == MEM)
{
src = XEXP (dest, 0);
code = GET_CODE (src);
- if ((code != PRE_DEC && code != PRE_INC && code != PRE_MODIFY)
- || XEXP (src, 0) != stack_pointer_rtx)
- return 0;
+ switch (code)
+ {
+ case PRE_MODIFY:
+ case POST_MODIFY:
+ if (XEXP (src, 0) == stack_pointer_rtx)
+ {
+ rtx val = XEXP (XEXP (src, 1), 1);
+ /* We handle only adjustments by constant amount. */
+ if (GET_CODE (XEXP (src, 1)) != PLUS ||
+ GET_CODE (val) != CONST_INT)
+ abort();
+ offset = -INTVAL (val);
+ break;
+ }
+ return 0;
- if (code == PRE_MODIFY)
- {
- rtx val = XEXP (XEXP (src, 1), 1);
+ case PRE_DEC:
+ case POST_DEC:
+ if (XEXP (src, 0) == stack_pointer_rtx)
+ {
+ offset = GET_MODE_SIZE (GET_MODE (dest));
+ break;
+ }
+ return 0;
- /* We handle only adjustments by constant amount. */
- if (GET_CODE (XEXP (src, 1)) != PLUS ||
- GET_CODE (val) != CONST_INT)
- abort ();
+ case PRE_INC:
+ case POST_INC:
+ if (XEXP (src, 0) == stack_pointer_rtx)
+ {
+ offset = -GET_MODE_SIZE (GET_MODE (dest));
+ break;
+ }
+ return 0;
- offset = -INTVAL (val);
+ default:
+ return 0;
}
- else
- offset = GET_MODE_SIZE (GET_MODE (dest));
}
else
return 0;
- if (code == PLUS || code == PRE_INC)
- offset = -offset;
-
return offset;
}
break;
case DW_CFA_offset_extended:
- case DW_CFA_GNU_negative_offset_extended:
case DW_CFA_def_cfa:
dw2_asm_output_data_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_reg_num,
NULL);
dw2_asm_output_data_uleb128 (cfi->dw_cfi_oprnd2.dw_cfi_offset, NULL);
break;
+ case DW_CFA_offset_extended_sf:
+ case DW_CFA_def_cfa_sf:
+ dw2_asm_output_data_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_reg_num,
+ NULL);
+ dw2_asm_output_data_sleb128 (cfi->dw_cfi_oprnd2.dw_cfi_offset, NULL);
+ break;
+
case DW_CFA_restore_extended:
case DW_CFA_undefined:
case DW_CFA_same_value:
dw2_asm_output_data_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_offset, NULL);
break;
+ case DW_CFA_def_cfa_offset_sf:
+ dw2_asm_output_data_sleb128 (cfi->dw_cfi_oprnd1.dw_cfi_offset, NULL);
+ break;
+
case DW_CFA_GNU_window_save:
break;
case DW_CFA_def_cfa_expression:
+ case DW_CFA_expression:
output_cfa_loc (cfi);
break;
+ case DW_CFA_GNU_negative_offset_extended:
+ /* Obsoleted by DW_CFA_offset_extended_sf. */
+ abort ();
+
default:
break;
}
char label[MAX_ARTIFICIAL_LABEL_BYTES];
/* Output a label to mark the endpoint of the code generated for this
- function. */
+ function. */
ASM_GENERATE_INTERNAL_LABEL (label, FUNC_END_LABEL, current_funcdef_number);
ASM_OUTPUT_LABEL (asm_out_file, label);
fde = &fde_table[fde_table_in_use - 1];
/* The debug hooks structure. */
-struct gcc_debug_hooks dwarf2_debug_hooks =
+const struct gcc_debug_hooks dwarf2_debug_hooks =
{
dwarf2out_init,
dwarf2out_finish,
/* Information concerning the compilation unit's programming
language, and compiler version. */
-extern int flag_traditional;
-
/* Fixed size portion of the DWARF compilation unit header. */
#define DWARF_COMPILE_UNIT_HEADER_SIZE (2 * DWARF_OFFSET_SIZE + 3)
#endif
#endif
-/* Define the architecture-dependent minimum instruction length (in bytes).
- In this implementation of DWARF, this field is used for information
- purposes only. Since GCC generates assembly language, we have
- no a priori knowledge of how many instruction bytes are generated
- for each source line, and therefore can use only the DW_LNE_set_address
- and DW_LNS_fixed_advance_pc line information commands. */
-#ifndef DWARF_LINE_MIN_INSTR_LENGTH
-#define DWARF_LINE_MIN_INSTR_LENGTH 4
-#endif
-
/* Minimum line offset in a special line info. opcode.
This value was chosen to give a reasonable range of values. */
#define DWARF_LINE_BASE -10
tree decl;
dw_die_ref decl_die;
{
- unsigned decl_id = DECL_UID (decl);
- unsigned num_allocated;
+ unsigned int decl_id = DECL_UID (decl);
+ unsigned int num_allocated;
if (decl_id >= decl_die_table_allocated)
{
unmark_dies (die);
}
-/* The DWARF2 pubname for a nested thingy looks like "A::f". The output
- of decl_printable_name for C++ looks like "A::f(int)". Let's drop the
- argument list, and maybe the scope. */
+/* The DWARF2 pubname for a nested thingy looks like "A::f". The
+ output of lang_hooks.decl_printable_name for C++ looks like
+ "A::f(int)". Let's drop the argument list, and maybe the scope. */
static const char *
dwarf2_name (decl, scope)
tree decl;
int scope;
{
- return (*decl_printable_name) (decl, scope ? 1 : 0);
+ return (*lang_hooks.decl_printable_name) (decl, scope ? 1 : 0);
}
/* Add a new entry to .debug_pubnames if appropriate. */
dw2_asm_output_delta (DWARF_OFFSET_SIZE, p2, p1, "Prolog Length");
ASM_OUTPUT_LABEL (asm_out_file, p1);
- dw2_asm_output_data (1, DWARF_LINE_MIN_INSTR_LENGTH,
+ /* Define the architecture-dependent minimum instruction length (in
+ bytes). In this implementation of DWARF, this field is used for
+ information purposes only. Since GCC generates assembly language,
+ we have no a priori knowledge of how many instruction bytes are
+ generated for each source line, and therefore can use only the
+ DW_LNE_set_address and DW_LNS_fixed_advance_pc line information
+ commands. Accordingly, we fix this as `1', which is "correct
+ enough" for all architectures, and don't let the target override. */
+ dw2_asm_output_data (1, 1,
"Minimum Instruction Length");
+
dw2_asm_output_data (1, DWARF_LINE_DEFAULT_IS_STMT_START,
"Default is_stmt_start flag");
dw2_asm_output_data (1, DWARF_LINE_BASE,
copy was created to help us keep track of typedef names) and
that copy might have a different TYPE_UID from the original
..._TYPE node. */
- mod_type_die = lookup_type_die (type_main_variant (type));
+ if (TREE_CODE (type) != VECTOR_TYPE)
+ mod_type_die = lookup_type_die (type_main_variant (type));
+ else
+ /* Vectors have the debugging information in the type,
+ not the main variant. */
+ mod_type_die = lookup_type_die (type);
if (mod_type_die == NULL)
abort ();
}
by a different symbol. */
if (GET_CODE (rtl) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (rtl))
{
- rtx tmp = get_pool_constant (rtl);
+ bool marked;
+ rtx tmp = get_pool_constant_mark (rtl, &marked);
if (GET_CODE (tmp) == SYMBOL_REF)
- rtl = tmp;
+ {
+ rtl = tmp;
+ if (CONSTANT_POOL_ADDRESS_P (tmp))
+ get_pool_constant_mark (tmp, &marked);
+ else
+ marked = true;
+ }
+
+ /* If all references to this pool constant were optimized away,
+ it was not output and thus we can't represent it.
+ FIXME: might try to use DW_OP_const_value here, though
+ DW_OP_piece complicates it. */
+ if (!marked)
+ return 0;
}
mem_loc_result = new_loc_descr (DW_OP_addr, 0, 0);
the names of types. */
return 0;
+ case CALL_EXPR:
+ return 0;
+
+ case ADDR_EXPR:
+ /* We can support this only if we can look through conversions and
+ find an INDIRECT_EXPR. */
+ for (loc = TREE_OPERAND (loc, 0);
+ TREE_CODE (loc) == CONVERT_EXPR || TREE_CODE (loc) == NOP_EXPR
+ || TREE_CODE (loc) == NON_LVALUE_EXPR
+ || TREE_CODE (loc) == VIEW_CONVERT_EXPR
+ || TREE_CODE (loc) == SAVE_EXPR;
+ loc = TREE_OPERAND (loc, 0))
+ ;
+
+ return (TREE_CODE (loc) == INDIRECT_REF
+ ? loc_descriptor_from_tree (TREE_OPERAND (loc, 0), addressp)
+ : 0);
+
case VAR_DECL:
case PARM_DECL:
{
return 0;
break;
+ case TRUTH_AND_EXPR:
+ case TRUTH_ANDIF_EXPR:
case BIT_AND_EXPR:
op = DW_OP_and;
goto do_binop;
+ case TRUTH_XOR_EXPR:
case BIT_XOR_EXPR:
op = DW_OP_xor;
goto do_binop;
+ case TRUTH_OR_EXPR:
+ case TRUTH_ORIF_EXPR:
case BIT_IOR_EXPR:
op = DW_OP_or;
goto do_binop;
add_loc_descr (&ret, new_loc_descr (op, 0, 0));
break;
+ case TRUTH_NOT_EXPR:
case BIT_NOT_EXPR:
op = DW_OP_not;
goto do_unop;
TREE_OPERAND (loc, 0), TREE_OPERAND (loc, 1)),
TREE_OPERAND (loc, 1), TREE_OPERAND (loc, 0));
- /* ... fall through ... */
+ /* ... fall through ... */
case COND_EXPR:
{
and will have been substituted directly into all expressions that use it.
C does not have such a concept, but C++ and other languages do. */
else if (TREE_CODE (decl) == VAR_DECL && DECL_INITIAL (decl))
- rtl = expand_expr (DECL_INITIAL (decl), NULL_RTX, VOIDmode,
- EXPAND_INITIALIZER);
+ {
+ /* If a variable is initialized with a string constant without embedded
+ zeros, build CONST_STRING. */
+ if (TREE_CODE (DECL_INITIAL (decl)) == STRING_CST
+ && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
+ {
+ tree arrtype = TREE_TYPE (decl);
+ tree enttype = TREE_TYPE (arrtype);
+ tree domain = TYPE_DOMAIN (arrtype);
+ tree init = DECL_INITIAL (decl);
+ enum machine_mode mode = TYPE_MODE (enttype);
+
+ if (GET_MODE_CLASS (mode) == MODE_INT && GET_MODE_SIZE (mode) == 1
+ && domain
+ && integer_zerop (TYPE_MIN_VALUE (domain))
+ && compare_tree_int (TYPE_MAX_VALUE (domain),
+ TREE_STRING_LENGTH (init) - 1) == 0
+ && ((size_t) TREE_STRING_LENGTH (init)
+ == strlen (TREE_STRING_POINTER (init)) + 1))
+ rtl = gen_rtx_CONST_STRING (VOIDmode, TREE_STRING_POINTER (init));
+ }
+
+ if (rtl == NULL)
+ {
+ rtl = expand_expr (DECL_INITIAL (decl), NULL_RTX, VOIDmode,
+ EXPAND_INITIALIZER);
+ /* If expand_expr returned a MEM, we cannot use it, since
+ it won't be output, leading to unresolved symbol. */
+ if (rtl && GET_CODE (rtl) == MEM)
+ rtl = NULL;
+ }
+ }
return rtl;
}
case ERROR_MARK:
return;
- /* All fixed-bounds are represented by INTEGER_CST nodes. */
+ /* All fixed-bounds are represented by INTEGER_CST nodes. */
case INTEGER_CST:
if (! host_integerp (bound, 0)
|| (bound_attr == DW_AT_lower_bound
else
ctx = lookup_decl_die (current_function_decl);
+ /* If we weren't able to find a context, it's most likely the case
+ that we are processing the return type of the function. So
+ make a SAVE_EXPR to point to it and have the limbo DIE code
+ find the proper die. The save_expr function doesn't always
+ make a SAVE_EXPR, so do it ourselves. */
+ if (ctx == 0)
+ bound = build (SAVE_EXPR, TREE_TYPE (bound), bound,
+ current_function_decl, NULL_TREE);
+
decl_die = new_die (DW_TAG_variable, ctx, bound);
add_AT_flag (decl_die, DW_AT_artificial, 1);
add_type_attribute (decl_die, TREE_TYPE (bound), 1, 0, ctx);
decls_for_scope (stmt, subr_die, depth);
current_function_has_inlines = 1;
}
+ else
+ /* We may get here if we're the outer block of function A that was
+ inlined into function B that was inlined into function C. When
+ generating debugging info for C, dwarf2out_abstract_function(B)
+ would mark all inlined blocks as abstract, including this one.
+ So, we wouldn't (and shouldn't) expect labels to be generated
+ for this one. Instead, just emit debugging info for
+ declarations within the block. This is particularly important
+ in the case of initializers of arguments passed from B to us:
+ if they're statement expressions containing declarations, we
+ wouldn't generate dies for their abstract variables, and then,
+ when generating dies for the real variables, we'd die (pun
+ intended :-) */
+ gen_lexical_block_die (stmt, context_die, depth);
}
/* Generate a DIE for a field in a record, or structure. */
language = DW_LANG_Pascal83;
else if (strcmp (language_string, "GNU Java") == 0)
language = DW_LANG_Java;
- else if (flag_traditional)
- language = DW_LANG_C;
else
language = DW_LANG_C89;
add_AT_flag (type_die, DW_AT_declaration, 1);
/* We don't need to do this for function-local types. */
- if (! decl_function_context (TYPE_STUB_DECL (type)))
+ if (TYPE_STUB_DECL (type)
+ && ! decl_function_context (TYPE_STUB_DECL (type)))
VARRAY_PUSH_TREE (incomplete_types, type);
}
}
if (type == NULL_TREE || type == error_mark_node)
return;
- /* We are going to output a DIE to represent the unqualified version of
- this type (i.e. without any const or volatile qualifiers) so get the
- main variant (i.e. the unqualified version) of this type now. */
- type = type_main_variant (type);
+ /* We are going to output a DIE to represent the unqualified version
+ of this type (i.e. without any const or volatile qualifiers) so
+ get the main variant (i.e. the unqualified version) of this type
+ now. (Vectors are special because the debugging info is in the
+ cloned type itself). */
+ if (TREE_CODE (type) != VECTOR_TYPE)
+ type = type_main_variant (type);
if (TREE_ASM_WRITTEN (type))
return;
unsigned lineno ATTRIBUTE_UNUSED;
const char *buffer ATTRIBUTE_UNUSED;
{
- static int initialized = 0;
- if (!initialized)
- {
- dwarf2out_start_source_file (0, primary_filename);
- initialized = 1;
- }
-
if (debug_info_level >= DINFO_LEVEL_VERBOSE)
{
named_section_flags (DEBUG_MACINFO_SECTION, SECTION_DEBUG);
add_child_die (origin->die_parent, die);
else if (die == comp_unit_die)
;
+ /* If this was an expression for a bound involved in a function
+ return type, it may be a SAVE_EXPR for which we weren't able
+ to find a DIE previously. So try now. */
+ else if (node->created_for
+ && TREE_CODE (node->created_for) == SAVE_EXPR
+ && 0 != (origin = (lookup_decl_die
+ (SAVE_EXPR_CONTEXT
+ (node->created_for)))))
+ add_child_die (origin, die);
+ else if (errorcount > 0 || sorrycount > 0)
+ /* It's OK to be confused by errors in the input. */
+ add_child_die (comp_unit_die, die);
else if (node->created_for
&& ((DECL_P (node->created_for)
&& (context = DECL_CONTEXT (node->created_for)))
abort ();
add_child_die (origin, die);
}
- else if (errorcount > 0 || sorrycount > 0)
- /* It's OK to be confused by errors in the input. */
- add_child_die (comp_unit_die, die);
else
abort ();
}