static void def_cfa_1 PARAMS ((const char *,
dw_cfa_location *));
-/* .debug_str support. */
-static hashnode indirect_string_alloc PARAMS ((hash_table *));
-static int output_indirect_string PARAMS ((struct cpp_reader *,
- hashnode, const PTR));
-
/* How to start an assembler comment. */
#ifndef ASM_COMMENT_START
#define ASM_COMMENT_START ";#"
#ifdef SET_ASM_OP
#ifndef ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL
-#define ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL(FILE, SY, HI, LO) \
- do { \
- fprintf (FILE, "%s", SET_ASM_OP); \
- assemble_name (FILE, SY); \
- fputc (',', FILE); \
- assemble_name (FILE, HI); \
- fputc ('-', FILE); \
- assemble_name (FILE, LO); \
- } while (0)
+#define ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL(FILE, SY, HI, LO) \
+ do \
+ { \
+ fprintf (FILE, "%s", SET_ASM_OP); \
+ assemble_name (FILE, SY); \
+ fputc (',', FILE); \
+ assemble_name (FILE, HI); \
+ fputc ('-', FILE); \
+ assemble_name (FILE, LO); \
+ } \
+ while (0)
#endif
#endif
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;
}
static long
stack_adjust_offset (pattern)
- rtx pattern;
+ rtx pattern;
{
rtx src = SET_SRC (pattern);
rtx dest = SET_DEST (pattern);
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;
-
- if (code == PRE_MODIFY)
+ switch (code)
{
- rtx val = XEXP (XEXP (src, 1), 1);
+ 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;
- /* We handle only adjustments by constant amount. */
- if (GET_CODE (XEXP (src, 1)) != PLUS ||
- GET_CODE (val) != CONST_INT)
- abort();
+ case PRE_DEC:
+ case POST_DEC:
+ if (XEXP (src, 0) == stack_pointer_rtx)
+ {
+ offset = GET_MODE_SIZE (GET_MODE (dest));
+ break;
+ }
+ return 0;
+
+ 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;
}
{
struct queued_reg_save *q, *next;
- for (q = queued_reg_saves; q ; q = next)
+ for (q = queued_reg_saves; q; q = next)
{
dwarf2out_reg_save (last_reg_save_label, REGNO (q->reg), q->cfa_offset);
next = q->next;
{
struct queued_reg_save *q;
- for (q = queued_reg_saves; q ; q = q->next)
+ for (q = queued_reg_saves; q; q = q->next)
if (modified_in_p (q->reg, insn))
return true;
return false;
}
-
+
/* A temporary register holding an integral value used in adjusting SP
or setting up the store_reg. The "offset" field holds the integer
stores the value, which will be used to adjust the
stack pointer. cfa_temp is also used like cfa_store,
to track stores to the stack via fp or a temp reg.
-
+
Rules 1- 4: Setting a register's value to cfa.reg or an expression
with cfa.reg as the first operand changes the cfa.reg and its
cfa.offset. Rule 1 and 4 also set cfa_temp.reg and
case PRE_MODIFY:
/* We can't handle variable size modifications. */
if (GET_CODE (XEXP (XEXP (XEXP (dest, 0), 1), 1)) != CONST_INT)
- abort();
+ abort ();
offset = -INTVAL (XEXP (XEXP (XEXP (dest, 0), 1), 1));
if (REGNO (XEXP (XEXP (dest, 0), 0)) != STACK_POINTER_REGNUM
if (! RTX_FRAME_RELATED_P (insn))
{
if (!ACCUMULATE_OUTGOING_ARGS)
- dwarf2out_stack_adjust (insn);
+ dwarf2out_stack_adjust (insn);
return;
}
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;
}
int per_encoding = DW_EH_PE_absptr;
int lsda_encoding = DW_EH_PE_absptr;
+ /* Don't emit a CIE if there won't be any FDEs. */
+ if (fde_table_in_use == 0)
+ return;
+
/* If we don't have any functions we'll want to unwind out of, don't emit any
EH unwind information. */
if (for_eh)
if (p > augmentation + 1)
{
augmentation[0] = 'z';
- *p = '\0';
+ *p = '\0';
}
/* Ug. Some platforms can't do unaligned dynamic relocations at all. */
output_cfi (cfi, NULL, for_eh);
/* Pad the CIE out to an address sized boundary. */
- ASM_OUTPUT_ALIGN (asm_out_file,
+ ASM_OUTPUT_ALIGN (asm_out_file,
floor_log2 (for_eh ? PTR_SIZE : DWARF2_ADDR_SIZE));
ASM_OUTPUT_LABEL (asm_out_file, l2);
fde = &fde_table[i];
/* Don't emit EH unwind info for leaf functions that don't need it. */
- if (for_eh && fde->nothrow && ! fde->uses_eh_lsda)
+ if (!flag_asynchronous_unwind_tables && for_eh && fde->nothrow
+ && ! fde->uses_eh_lsda)
continue;
ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, FDE_LABEL, for_eh + i * 2);
gen_rtx_SYMBOL_REF (Pmode, fde->dw_fde_begin),
"FDE initial location");
dw2_asm_output_delta (size_of_encoded_value (fde_encoding),
- fde->dw_fde_end, fde->dw_fde_begin,
+ fde->dw_fde_end, fde->dw_fde_begin,
"FDE address range");
}
else
{
dw2_asm_output_addr (DWARF2_ADDR_SIZE, fde->dw_fde_begin,
"FDE initial location");
- dw2_asm_output_delta (DWARF2_ADDR_SIZE,
- fde->dw_fde_end, fde->dw_fde_begin,
+ dw2_asm_output_delta (DWARF2_ADDR_SIZE,
+ fde->dw_fde_end, fde->dw_fde_begin,
"FDE address range");
}
output_cfi (cfi, fde, for_eh);
/* Pad the FDE out to an address sized boundary. */
- ASM_OUTPUT_ALIGN (asm_out_file,
+ ASM_OUTPUT_ALIGN (asm_out_file,
floor_log2 ((for_eh ? PTR_SIZE : DWARF2_ADDR_SIZE)));
ASM_OUTPUT_LABEL (asm_out_file, l2);
}
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];
/* And now, the support for symbolic debugging information. */
#ifdef DWARF2_DEBUGGING_INFO
+/* .debug_str support. */
+static hashnode indirect_string_alloc PARAMS ((hash_table *));
+static int output_indirect_string PARAMS ((struct cpp_reader *,
+ hashnode, const PTR));
+
+
static void dwarf2out_init PARAMS ((const char *));
static void dwarf2out_finish PARAMS ((const char *));
static void dwarf2out_define PARAMS ((unsigned int, const char *));
/* 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
static void gen_type_die_for_member PARAMS ((tree, tree, dw_die_ref));
static void splice_child_die PARAMS ((dw_die_ref, dw_die_ref));
static int file_info_cmp PARAMS ((const void *, const void *));
-static dw_loc_list_ref new_loc_list PARAMS ((dw_loc_descr_ref,
+static dw_loc_list_ref new_loc_list PARAMS ((dw_loc_descr_ref,
const char *, const char *,
const char *, unsigned));
static void add_loc_descr_to_loc_list PARAMS ((dw_loc_list_ref *,
return "DW_AT_body_begin";
case DW_AT_body_end:
return "DW_AT_body_end";
+ case DW_AT_GNU_vector:
+ return "DW_AT_GNU_vector";
+
case DW_AT_VMS_rtnbeg_pd_address:
return "DW_AT_VMS_rtnbeg_pd_address";
{
dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node));
struct indirect_string_node *node;
-
+
if (! debug_str_hash)
{
debug_str_hash = ht_create (10);
{
return (get_AT_unsigned (comp_unit_die, DW_AT_language)
== DW_LANG_C_plus_plus);
-}
+}
static inline int
is_fortran ()
lookup_type_die (type)
tree type;
{
- if (TREE_CODE (type) == VECTOR_TYPE)
- type = TYPE_DEBUG_REPRESENTATION_TYPE (type);
-
return (dw_die_ref) TYPE_SYMTAB_POINTER (type);
}
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)
{
dw_die_ref c;
{
return (is_type_die (c)
- || (get_AT (c, DW_AT_declaration)
+ || (get_AT (c, DW_AT_declaration)
&& !get_AT (c, DW_AT_specification)));
}
static char *
gen_internal_sym (prefix)
- const char *prefix;
+ const char *prefix;
{
char buf[256];
static int label_num;
dw_die_ref unit = NULL;
limbo_die_node *node;
- for (ptr = &(die->die_child); *ptr; )
+ for (ptr = &(die->die_child); *ptr;)
{
dw_die_ref c = *ptr;
output_location_lists (c);
}
+
/* The format of each DIE (and its attribute value pairs) is encoded in an
abbreviation table. This routine builds the abbreviation table and assigns
a unique abbreviation id for each abbreviation entry. The children of each
retlist->end = end;
retlist->expr = expr;
retlist->section = section;
- if (gensym)
+ if (gensym)
retlist->ll_symbol = gen_internal_sym ("LLST");
return retlist;
const char *section;
{
dw_loc_list_ref *d;
-
+
/* Find the end of the chain. */
for (d = list_head; (*d) != NULL; d = &(*d)->dw_loc_next)
;
if (strcmp (curr->section, ".text") == 0)
{
/* dw2_asm_output_data will mask off any extra bits in the ~0. */
- dw2_asm_output_data (DWARF2_ADDR_SIZE, ~(unsigned HOST_WIDE_INT)0,
+ dw2_asm_output_data (DWARF2_ADDR_SIZE, ~(unsigned HOST_WIDE_INT) 0,
"Location list base address specifier fake entry");
dw2_asm_output_offset (DWARF2_ADDR_SIZE, curr->section,
"Location list base address specifier base");
}
- for (curr = list_head; curr != NULL; curr=curr->dw_loc_next)
+ for (curr = list_head; curr != NULL; curr = curr->dw_loc_next)
{
unsigned long size;
"Location list end address (%s)",
list_head->ll_symbol);
size = size_of_locs (curr->expr);
-
+
/* Output the block length for this list of location operations. */
if (size > 0xffff)
abort ();
dw2_asm_output_data (1,
2 * HOST_BITS_PER_LONG / HOST_BITS_PER_CHAR,
- "%s", name);
+ "%s", name);
if (WORDS_BIG_ENDIAN)
{
unsigned int i;
dw2_asm_output_data (1, a->dw_attr_val.v.val_float.length * 4,
- "%s", name);
+ "%s", name);
for (i = 0; i < a->dw_attr_val.v.val_float.length; i++)
dw2_asm_output_data (4, a->dw_attr_val.v.val_float.array[i],
dw2_asm_output_data (1, AT_flag (a), "%s", name);
break;
- case dw_val_class_loc_list:
+ case dw_val_class_loc_list:
{
char *sym = AT_loc_list (a)->ll_symbol;
if (sym == 0)
- abort();
+ abort ();
dw2_asm_output_delta (DWARF_OFFSET_SIZE, sym,
loc_section_label, "%s", name);
}
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. */
if (die->die_tag == DW_TAG_subprogram)
{
dw2_asm_output_addr (DWARF2_ADDR_SIZE, get_AT_low_pc (die),
- "Address");
+ "Address");
dw2_asm_output_delta (DWARF2_ADDR_SIZE, get_AT_hi_pc (die),
get_AT_low_pc (die), "Length");
}
if (total > dirs[i].length + 1)
{
/* It's worthwhile adding. */
- for (j = i; j < ndirs; j++)
+ for (j = i; j < ndirs; j++)
if (savehere[j] > 0)
{
/* Remember how much we saved for this directory so far. */
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,
/* See if we already have the appropriately qualified variant of
this type. */
- qualified_type
+ qualified_type
= get_qualified_type (type,
((is_const_type ? TYPE_QUAL_CONST : 0)
- | (is_volatile_type
+ | (is_volatile_type
? TYPE_QUAL_VOLATILE : 0)));
/* If we do, then we can just use its DIE, if it exists. */
}
/* Handle C typedef types. */
- if (qualified_type && TYPE_NAME (qualified_type)
+ if (qualified_type && TYPE_NAME (qualified_type)
&& TREE_CODE (TYPE_NAME (qualified_type)) == TYPE_DECL
&& DECL_ORIGINAL_TYPE (TYPE_NAME (qualified_type)))
{
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 ();
}
is_based_loc (rtl)
rtx rtl;
{
- return (GET_CODE (rtl) == PLUS
- && ((GET_CODE (XEXP (rtl, 0)) == REG
- && REGNO (XEXP (rtl, 0)) < FIRST_PSEUDO_REGISTER
- && GET_CODE (XEXP (rtl, 1)) == CONST_INT)));
+ return (GET_CODE (rtl) == PLUS
+ && ((GET_CODE (XEXP (rtl, 0)) == REG
+ && REGNO (XEXP (rtl, 0)) < FIRST_PSEUDO_REGISTER
+ && GET_CODE (XEXP (rtl, 1)) == CONST_INT)));
}
/* The following routine converts the RTL for a variable or parameter
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);
mem_loc_result = int_loc_descriptor (INTVAL (rtl));
break;
+ case ADDRESSOF:
+ /* If this is a MEM, return its address. Otherwise, we can't
+ represent this. */
+ if (GET_CODE (XEXP (rtl, 0)) == MEM)
+ return mem_loc_descriptor (XEXP (XEXP (rtl, 0), 0), mode);
+ else
+ return 0;
+
default:
abort ();
}
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:
{
rtx rtl = rtl_for_decl_location (loc);
- enum machine_mode mode = GET_MODE (rtl);
if (rtl == NULL_RTX)
return 0;
}
else
{
+ enum machine_mode mode = GET_MODE (rtl);
+
if (GET_CODE (rtl) == MEM)
{
indirect_p = 1;
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:
{
out, and the CONST_INT rtx is assigned VOIDmode. */
{
HOST_WIDE_INT val = INTVAL (rtl);
-
+
/* ??? We really should be using HOST_WIDE_INT throughout. */
if (val < 0 && (long) val == val)
add_AT_int (die, DW_AT_const_value, (long) val);
if (GET_MODE_CLASS (mode) == MODE_FLOAT)
{
unsigned length = GET_MODE_SIZE (mode) / 4;
- long *array = (long *) xmalloc (sizeof (long) * length);
+ long *array = (long *) xmalloc (sizeof (long) * length);
REAL_VALUE_TYPE rv;
REAL_VALUE_FROM_CONST_DOUBLE (rv, rtl);
/* Use DECL_RTL as the "location" unless we find something better. */
rtl = DECL_RTL_IF_SET (decl);
- if (TREE_CODE (decl) == PARM_DECL)
+ /* When generating abstract instances, ignore everything except
+ constants and symbols living in memory. */
+ if (! reload_completed)
+ {
+ if (rtl
+ && (CONSTANT_P (rtl)
+ || (GET_CODE (rtl) == MEM
+ && CONSTANT_P (XEXP (rtl, 0)))))
+ {
+#ifdef ASM_SIMPLIFY_DWARF_ADDR
+ rtl = ASM_SIMPLIFY_DWARF_ADDR (rtl);
+#endif
+ return rtl;
+ }
+ rtl = NULL_RTX;
+ }
+ else if (TREE_CODE (decl) == PARM_DECL)
{
if (rtl == NULL_RTX || is_pseudo_reg (rtl))
{
/* A variable with no DECL_RTL but a DECL_INITIAL is a compile-time constant,
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 (DECL_INITIAL (decl))
- rtl = expand_expr (DECL_INITIAL (decl), NULL_RTX, VOIDmode,
- EXPAND_INITIALIZER);
+ else if (TREE_CODE (decl) == VAR_DECL && DECL_INITIAL (decl))
+ {
+ /* 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 the initializer is something that we know will expand into an
+ immediate RTL constant, expand it now. Expanding anything else
+ tends to produce unresolved symbols; see debug/5770 and c++/6381. */
+ else if (TREE_CODE (DECL_INITIAL (decl)) == INTEGER_CST
+ || TREE_CODE (DECL_INITIAL (decl)) == REAL_CST)
+ {
+ rtl = expand_expr (DECL_INITIAL (decl), NULL_RTX, VOIDmode,
+ EXPAND_INITIALIZER);
+ /* If expand_expr returns a MEM, it wasn't immediate. */
+ if (rtl && GET_CODE (rtl) == MEM)
+ abort ();
+ }
+ }
+#ifdef ASM_SIMPLIFY_DWARF_ADDR
+ if (rtl)
+ rtl = ASM_SIMPLIFY_DWARF_ADDR (rtl);
+#endif
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);
#endif
array_die = new_die (DW_TAG_array_type, scope_die, type);
+ add_name_attribute (array_die, type_tag (type));
+ equate_type_number_to_die (type, array_die);
+
+ if (TREE_CODE (type) == VECTOR_TYPE)
+ {
+ /* The frontend feeds us a representation for the vector as a struct
+ containing an array. Pull out the array type. */
+ type = TREE_TYPE (TYPE_FIELDS (TYPE_DEBUG_REPRESENTATION_TYPE (type)));
+ add_AT_flag (array_die, DW_AT_GNU_vector, 1);
+ }
#if 0
/* We default the array ordering. SDB will probably do
#endif
add_subscript_info (array_die, type);
- add_name_attribute (array_die, type_tag (type));
- equate_type_number_to_die (type, array_die);
-
/* Add representation of the type of the elements of this array type. */
element_type = TREE_TYPE (type);
}
else
arg = NULL_TREE;
-
+
first_parm_type = TYPE_ARG_TYPES (function_or_method_type);
/* Make our first pass over the list of formal parameter types and output a
/* Make sure we have the actual abstract inline, not a clone. */
decl = DECL_ORIGIN (decl);
- old_die = lookup_decl_die (decl);
+ old_die = lookup_decl_die (decl);
if (old_die && get_AT_unsigned (old_die, DW_AT_inline))
/* We've already generated the abstract instance. */
return;
gen_type_die_for_member
(context, decl, decl_function_context (decl) ? NULL : comp_unit_die);
}
-
+
/* Pretend we've just finished compiling this function. */
save_fn = current_function_decl;
current_function_decl = decl;
??? Duplicated blocks have been rewritten to use .debug_ranges. */
else if (old_die && TREE_STATIC (decl)
- && get_AT_flag (old_die, DW_AT_declaration) == 1)
+ && get_AT_flag (old_die, DW_AT_declaration) == 1)
{
/* This is a definition of a C++ class level static. */
add_AT_die_ref (var_die, DW_AT_specification, old_die);
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;
if (TYPE_NAME (type) && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
&& DECL_ORIGINAL_TYPE (TYPE_NAME (type)))
{
+ /* Prevent broken recursion; we can't hand off to the same type. */
+ if (DECL_ORIGINAL_TYPE (TYPE_NAME (type)) == type)
+ abort ();
+
TREE_ASM_WRITTEN (type) = 1;
gen_decl_die (TYPE_NAME (type), context_die);
return;
break;
case VECTOR_TYPE:
- gen_type_die (TYPE_DEBUG_REPRESENTATION_TYPE (type), context_die);
+ gen_array_type_die (type, context_die);
break;
case ENUMERAL_TYPE:
void *ptr ATTRIBUTE_UNUSED;
{
limbo_die_node *node;
- for (node = limbo_die_list; node ; node = node->next)
+ for (node = limbo_die_list; node; node = node->next)
ggc_mark_tree (node->created_for);
}
\f
file_table.last_lookup_index = i;
if (DWARF2_ASM_LINE_DEBUG_INFO)
- fprintf (asm_out_file, "\t.file %u \"%s\"\n", i, file_name);
+ {
+ fprintf (asm_out_file, "\t.file %u ", i);
+ output_quoted_string (asm_out_file, file_name);
+ fputc ('\n', asm_out_file);
+ }
return i;
}
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)))
+ && (context = DECL_CONTEXT (node->created_for)))
|| (TYPE_P (node->created_for)
&& (context = TYPE_CONTEXT (node->created_for))))
&& TREE_CODE (context) == FUNCTION_DECL)
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 ();
}
/* Have to end the primary source file. */
if (debug_info_level >= DINFO_LEVEL_VERBOSE)
- {
+ {
named_section_flags (DEBUG_MACINFO_SECTION, SECTION_DEBUG);
dw2_asm_output_data (1, DW_MACINFO_end_file, "End file");
+ dw2_asm_output_data (1, 0, "End compilation unit");
}
/* If we emitted any DW_FORM_strp form attribute, output the string