Commit a94dbf2c by Jason Merrill

x

From-SVN: r13258
parent 19f5ce60
......@@ -1078,14 +1078,14 @@ sublibobjc.a: cc1obj specs stmp-int-hdrs libgcc2.ready
# linked using GCC on systems using COFF or ELF, for the sake of C++
# constructors.
$(T)crtbegin.o: crtstuff.c $(GCC_PASSES) $(CONFIG_H) gbl-ctors.h
$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(CRTSTUFF_T_CFLAGS) \
$(MULTILIB_CFLAGS) -finhibit-size-directive -fno-inline-functions \
-g0 -c $(srcdir)/crtstuff.c -DCRT_BEGIN -o $(T)crtbegin$(objext)
$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) -g0 \
-finhibit-size-directive -fno-inline-functions $(CRTSTUFF_T_CFLAGS) \
-c $(srcdir)/crtstuff.c -DCRT_BEGIN -o $(T)crtbegin$(objext)
$(T)crtend.o: crtstuff.c $(GCC_PASSES) $(CONFIG_H) gbl-ctors.h
$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(CRTSTUFF_T_CFLAGS) \
$(MULTILIB_CFLAGS) -finhibit-size-directive -fno-inline-functions \
-g0 -c $(srcdir)/crtstuff.c -DCRT_END -o $(T)crtend$(objext)
$(GCC_FOR_TARGET) $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) -g0 \
-finhibit-size-directive -fno-inline-functions $(CRTSTUFF_T_CFLAGS) \
-c $(srcdir)/crtstuff.c -DCRT_END -o $(T)crtend$(objext)
# On some systems we also want to install versions of these files
# compiled using PIC for use in shared libraries.
......
......@@ -4940,7 +4940,7 @@ compute_frame_size (size)
+ gp_reg_rounded + fp_reg_size
- fp_inc * UNITS_PER_FPREG);
current_frame_info.fp_sp_offset = offset;
current_frame_info.fp_save_offset = offset - total_size + UNITS_PER_WORD;
current_frame_info.fp_save_offset = offset - total_size;
}
else
{
......@@ -5066,7 +5066,25 @@ save_restore_insns (store_p, large_reg, large_offset, file)
GEN_INT (gp_offset - base_offset)));
if (store_p)
emit_move_insn (mem_rtx, reg_rtx);
{
rtx insn = emit_move_insn (mem_rtx, reg_rtx);
if (write_symbols == DWARF2_DEBUG)
{
int offset = (gp_offset
- current_frame_info.total_size);
if (regno == GP_REG_FIRST + 31)
REG_NOTES (insn)
= gen_rtx (EXPR_LIST, REG_RETURN_SAVE,
GEN_INT (offset), REG_NOTES (insn));
else
REG_NOTES (insn)
= gen_rtx (EXPR_LIST, REG_SAVE,
gen_rtx (EXPR_LIST, VOIDmode, reg_rtx,
GEN_INT (offset)),
REG_NOTES (insn));
}
}
else if (!TARGET_ABICALLS || mips_abi != ABI_32
|| regno != (PIC_OFFSET_TABLE_REGNUM - GP_REG_FIRST))
emit_move_insn (reg_rtx, mem_rtx);
......@@ -5179,7 +5197,20 @@ save_restore_insns (store_p, large_reg, large_offset, file)
GEN_INT (fp_offset - base_offset)));
if (store_p)
emit_move_insn (mem_rtx, reg_rtx);
{
rtx insn = emit_move_insn (mem_rtx, reg_rtx);
if (write_symbols == DWARF2_DEBUG)
{
int offset = (gp_offset
- current_frame_info.total_size);
REG_NOTES (insn)
= gen_rtx (EXPR_LIST, REG_SAVE,
gen_rtx (EXPR_LIST, VOIDmode, reg_rtx,
GEN_INT (offset)),
REG_NOTES (insn));
}
}
else
emit_move_insn (reg_rtx, mem_rtx);
}
......@@ -5405,6 +5436,8 @@ mips_expand_prologue ()
/* If we are doing svr4-abi, sp move is done by function_prologue. */
if (!TARGET_ABICALLS || mips_abi != ABI_32)
{
rtx insn;
if (tsize > 32767)
{
tmp_rtx = gen_rtx (REG, Pmode, MIPS_TEMP1_REGNUM);
......@@ -5413,21 +5446,37 @@ mips_expand_prologue ()
}
if (TARGET_LONG64)
emit_insn (gen_subdi3 (stack_pointer_rtx, stack_pointer_rtx,
tsize_rtx));
insn = emit_insn (gen_subdi3 (stack_pointer_rtx, stack_pointer_rtx,
tsize_rtx));
else
emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx,
tsize_rtx));
insn = emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx,
tsize_rtx));
if (write_symbols == DWARF2_DEBUG)
REG_NOTES (insn)
= gen_rtx (EXPR_LIST, REG_FRAME,
gen_rtx (PLUS, VOIDmode, stack_pointer_rtx,
GEN_INT (tsize)),
REG_NOTES (insn));
}
save_restore_insns (TRUE, tmp_rtx, tsize, (FILE *)0);
if (frame_pointer_needed)
{
rtx insn;
if (TARGET_64BIT)
emit_insn (gen_movdi (frame_pointer_rtx, stack_pointer_rtx));
insn= emit_insn (gen_movdi (frame_pointer_rtx, stack_pointer_rtx));
else
emit_insn (gen_movsi (frame_pointer_rtx, stack_pointer_rtx));
insn= emit_insn (gen_movsi (frame_pointer_rtx, stack_pointer_rtx));
if (write_symbols == DWARF2_DEBUG)
REG_NOTES (insn)
= gen_rtx (EXPR_LIST, REG_FRAME,
gen_rtx (PLUS, VOIDmode, frame_pointer_rtx,
GEN_INT (tsize)),
REG_NOTES (insn));
}
if (TARGET_ABICALLS && mips_abi != ABI_32)
......
......@@ -17,3 +17,4 @@ INSTALL_LIBGCC = install-multilib
# end labels to the .ctors and .dtors section when we link using gcc.
EXTRA_MULTILIB_PARTS=crtbegin.o crtend.o
CRTSTUFF_T_CFLAGS=-g1
......@@ -198,8 +198,7 @@ typedef struct dw_fde_struct
{
unsigned long dw_fde_offset;
char *dw_fde_begin;
char *dw_fde_end_prolog;
char *dw_fde_begin_epilogue;
char *dw_fde_current_label;
char *dw_fde_end;
dw_cfi_ref dw_fde_cfi;
}
......@@ -294,23 +293,12 @@ extern char *language_string;
#define DWARF_ARANGES_HEADER_SIZE \
(DWARF_ROUND (2 * DWARF_OFFSET_SIZE + 4, PTR_SIZE * 2) - DWARF_OFFSET_SIZE)
/* Length of the target-dependent instructions in the
Common Information Entry (CIE).
??? This should be computed when the frame info is genericized. */
#ifdef MIPS_DEBUGGING_INFO
#define DWARF_CIE_INSN_SIZE (2*3)
#endif
#ifndef DWARF_CIE_INSN_SIZE
#define DWARF_CIE_INSN_SIZE 0
#endif
/* Fixed size portion of the CIE (including the length field). */
#define DWARF_CIE_HEADER_SIZE (2 * DWARF_OFFSET_SIZE + 5 + DWARF_CIE_INSN_SIZE)
#define DWARF_CIE_HEADER_SIZE (2 * DWARF_OFFSET_SIZE + 5)
/* Fixed size of the Common Information Entry in the call frame
information (.debug_frame) section rounded up to a word boundary. */
#define DWARF_CIE_SIZE DWARF_ROUND (DWARF_CIE_HEADER_SIZE, PTR_SIZE)
/* The un-padded size of the CIE. Initialized in calc_fde_sizes, used
in output_call_frame_info. */
static unsigned cie_size;
/* Offsets recorded in opcodes are a multiple of this alignment factor. */
#define DWARF_CIE_DATA_ALIGNMENT -4
......@@ -355,6 +343,9 @@ static unsigned long next_fde_offset;
/* Record the root of the DIE's built for the current compilation unit. */
dw_die_ref comp_unit_die;
/* The number of DIEs with a NULL parent waiting to be relocated. */
static int limbo_die_count;
/* Pointer to an array of filenames referenced by this compilation unit. */
static char **file_table;
......@@ -381,21 +372,6 @@ static char *primary_filename;
assigns numbers to the blocks in the same way. */
static unsigned next_block_number = 2;
/* A pointer to the base of a list of references to DIE's that describe
types. The table is indexed by TYPE_UID() which is a unique number,
indentifying each type. */
static dw_die_ref *type_die_table;
/* Number of elements currently allocated for type_die_table. */
static unsigned type_die_table_allocated;
/* Number of elements in type_die_table currently in use. */
static unsigned type_die_table_in_use;
/* Size (in elements) of increments by which we may expand the
type_die_table. */
#define TYPE_DIE_TABLE_INCREMENT 4096
/* A pointer to the base of a table of references to DIE's that describe
declarations. The table is indexed by DECL_UID() which is a unique
number, indentifying each decl. */
......@@ -481,6 +457,9 @@ static unsigned fde_table_in_use;
fde_table. */
#define FDE_TABLE_INCREMENT 256
/* A list of call frame insns for the CIE. */
static dw_cfi_ref cie_cfi_head;
/* A pointer to the base of a table that contains a list of publicly
accessible names. */
static pubname_ref pubname_table;
......@@ -509,6 +488,26 @@ static unsigned arange_table_in_use;
arange_table. */
#define ARANGE_TABLE_INCREMENT 64
/* A pointer to the base of a list of pending types which we haven't
generated DIEs for yet, but which we will have to come back to
later on. */
static tree *pending_types_list;
/* Number of elements currently allocated for the pending_types_list. */
static unsigned pending_types_allocated;
/* Number of elements of pending_types_list currently in use. */
static unsigned pending_types;
/* Size (in elements) of increments by which we may expand the pending
types list. Actually, a single hunk of space of this size should
be enough for most typical programs. */
#define PENDING_TYPES_INCREMENT 64
/* The number of the current function definition for which debugging
information is being generated. These numbers range from 1 up to the
maximum number of function definitions contained within the current
......@@ -522,10 +521,6 @@ static unsigned current_funcdef_number = 1;
associated with the current function (body) definition. */
static unsigned current_funcdef_fde;
/* Record the size of the frame, so that the DW_AT_frame_base
attribute can be set properly in gen_subprogram_die. */
static long int current_funcdef_frame_size = 0;
/* Record whether the function being analyzed contains inlined functions. */
static int current_function_has_inlines;
static int comp_unit_has_inlines;
......@@ -544,6 +539,7 @@ static void gen_decl_die ();
static unsigned lookup_filename ();
static int constant_size PROTO((long unsigned));
static enum dwarf_form value_format PROTO((dw_val_ref));
static unsigned reg_number ();
/* Definitions of defaults for assembler-dependent names of various
pseudo-ops and section names.
......@@ -823,9 +819,14 @@ char text_end_label[MAX_ARTIFICIAL_LABEL_BYTES];
#endif
/* The DWARF 2 CFA column which tracks the return address. Normally this
is the first column after all of the hard registers. */
is the column for PC, or the first column after all of the hard
registers. */
#ifndef DWARF_FRAME_RETURN_COLUMN
#define DWARF_FRAME_RETURN_COLUMN FIRST_PSEUDO_REGISTER
#ifdef PC_REGNUM
#define DWARF_FRAME_RETURN_COLUMN DWARF_FRAME_REGNUM (PC_REGNUM)
#else
#define DWARF_FRAME_RETURN_COLUMN FIRST_PSEUDO_REGISTER + 1
#endif
#endif
/* The mapping from gcc register number to DWARF 2 CFA column number. By
......@@ -1851,13 +1852,12 @@ block_ultimate_origin (block)
of a virtual function may refer to a base class, so we check the 'this'
parameter. */
tree
static tree
decl_class_context (decl)
tree decl;
{
tree context = NULL_TREE;
if (TREE_CODE (decl) != FUNCTION_DECL
|| ! DECL_VIRTUAL_P (decl))
if (TREE_CODE (decl) != FUNCTION_DECL || ! DECL_VINDEX (decl))
context = DECL_CONTEXT (decl);
else
context = TYPE_MAIN_VARIANT
......@@ -2325,9 +2325,9 @@ new_die (tag_value, parent_die)
die->die_attr = NULL;
die->die_attr_last = NULL;
if (parent_die != NULL)
{
add_child_die (parent_die, die);
}
add_child_die (parent_die, die);
else
++limbo_die_count;
}
return die;
}
......@@ -2337,9 +2337,7 @@ inline dw_die_ref
lookup_type_die (type)
register tree type;
{
register unsigned type_id = TYPE_UID (type);
return (type_id < type_die_table_in_use)
? type_die_table[type_id] : NULL;
return (dw_die_ref) TYPE_SYMTAB_POINTER (type);
}
/* Equate a DIE to a given type specifier. */
......@@ -2348,25 +2346,7 @@ equate_type_number_to_die (type, type_die)
register tree type;
register dw_die_ref type_die;
{
register unsigned type_id = TYPE_UID (type);
register unsigned num_allocated;
if (type_id >= type_die_table_allocated)
{
num_allocated = (((type_id + 1)
+ TYPE_DIE_TABLE_INCREMENT - 1)
/ TYPE_DIE_TABLE_INCREMENT)
* TYPE_DIE_TABLE_INCREMENT;
type_die_table = (dw_die_ref *) xrealloc (type_die_table,
sizeof (dw_die_ref) * num_allocated);
bzero (&type_die_table[type_die_table_allocated],
(num_allocated - type_die_table_allocated) * sizeof (dw_die_ref));
type_die_table_allocated = num_allocated;
}
if (type_id >= type_die_table_in_use)
{
type_die_table_in_use = (type_id + 1);
}
type_die_table[type_id] = type_die;
TYPE_SYMTAB_POINTER (type) = (char *) type_die;
}
/* Return the DIE associated with a given declaration. */
......@@ -3657,6 +3637,212 @@ output_compilation_unit_header ()
fputc ('\n', asm_out_file);
}
/* Extract the register and offset values from RTL. If no register number
is specified, return -1 to indicate frame-relative addressing. */
static void
decode_cfi_rtl (rtl, regp, offsetp)
register rtx rtl;
register unsigned long *regp;
register long *offsetp;
{
switch (GET_CODE (rtl))
{
case REG:
*regp = reg_number (rtl);
*offsetp = 0;
break;
case PLUS:
*regp = reg_number (XEXP (rtl, 0));
*offsetp = INTVAL (XEXP (rtl, 1));
break;
case CONST_INT:
*regp = (unsigned long) -1;
*offsetp = INTVAL (rtl);
break;
default:
abort ();
}
}
/* Add CFI to the current fde at the PC value indicated by LABEL if specified,
or to the CIE if LABEL is NULL. */
static void
add_fde_cfi (label, cfi)
register char * label;
register dw_cfi_ref cfi;
{
if (label)
{
register dw_fde_ref fde = &fde_table[fde_table_in_use - 1];
if (fde->dw_fde_current_label == NULL
|| strcmp (label, fde->dw_fde_current_label) != 0)
{
register dw_cfi_ref xcfi;
fde->dw_fde_current_label = label = xstrdup (label);
/* Set the location counter to the new label. */
xcfi = new_cfi ();
xcfi->dw_cfi_opc = DW_CFA_advance_loc4;
xcfi->dw_cfi_oprnd1.dw_cfi_addr = label;
add_cfi (&fde->dw_fde_cfi, xcfi);
}
add_cfi (&fde->dw_fde_cfi, cfi);
}
else
add_cfi (&cie_cfi_head, cfi);
}
/* Subroutine of lookup_cfa. */
inline void
lookup_cfa_1 (cfi, regp, offsetp)
register dw_cfi_ref cfi;
register unsigned long *regp;
register long *offsetp;
{
switch (cfi->dw_cfi_opc)
{
case DW_CFA_def_cfa_offset:
*offsetp = cfi->dw_cfi_oprnd1.dw_cfi_offset;
break;
case DW_CFA_def_cfa_register:
*regp = cfi->dw_cfi_oprnd1.dw_cfi_reg_num;
break;
case DW_CFA_def_cfa:
*regp = cfi->dw_cfi_oprnd1.dw_cfi_reg_num;
*offsetp = cfi->dw_cfi_oprnd2.dw_cfi_offset;
break;
}
}
/* Find the previous value for the CFA. */
static void
lookup_cfa (regp, offsetp)
register unsigned long *regp;
register long *offsetp;
{
register dw_cfi_ref cfi;
*regp = (unsigned long) -1;
*offsetp = 0;
for (cfi = cie_cfi_head; cfi; cfi = cfi->dw_cfi_next)
lookup_cfa_1 (cfi, regp, offsetp);
if (fde_table_in_use)
{
register dw_fde_ref fde = &fde_table[fde_table_in_use - 1];
for (cfi = fde->dw_fde_cfi; cfi; cfi = cfi->dw_cfi_next)
lookup_cfa_1 (cfi, regp, offsetp);
}
}
/* Entry point to update the canonical frame address (CFA).
LABEL is passed to add_fde_cfi. RTL is either:
a REG: The frame is at 0(REG).
a PLUS of a REG and a CONST_INT: The frame is at CONST(REG). */
void
dwarf2out_def_cfa (label, rtl)
register char * label;
register rtx rtl;
{
register dw_cfi_ref cfi;
unsigned long reg, old_reg;
long offset, old_offset;
decode_cfi_rtl (rtl, &reg, &offset);
lookup_cfa (&old_reg, &old_offset);
if (reg == old_reg && offset == old_offset)
return;
cfi = new_cfi ();
if (reg == old_reg)
{
cfi->dw_cfi_opc = DW_CFA_def_cfa_offset;
cfi->dw_cfi_oprnd1.dw_cfi_offset = offset;
}
#ifndef MIPS_DEBUGGING_INFO /* SGI dbx thinks this means no offset. */
else if (offset == old_offset && old_reg != (unsigned long) -1)
{
cfi->dw_cfi_opc = DW_CFA_def_cfa_register;
cfi->dw_cfi_oprnd1.dw_cfi_reg_num = reg;
}
#endif
else
{
cfi->dw_cfi_opc = DW_CFA_def_cfa;
cfi->dw_cfi_oprnd1.dw_cfi_reg_num = reg;
cfi->dw_cfi_oprnd2.dw_cfi_offset = offset;
}
add_fde_cfi (label, cfi);
}
/* Add the CFI for saving a register. REG is the CFA column number.
LABEL is passed to add_fde_cfi.
RTL is either:
a REG: The register is saved in REG.
a CONST_INT: The register is saved at an offset of CONST
from the CFA. */
static void
reg_save (label, reg, rtl)
register char * label;
register unsigned long reg;
register rtx rtl;
{
register dw_cfi_ref cfi;
unsigned long sreg;
long offset;
cfi = new_cfi ();
cfi->dw_cfi_oprnd1.dw_cfi_reg_num = reg;
decode_cfi_rtl (rtl, &sreg, &offset);
offset /= DWARF_CIE_DATA_ALIGNMENT;
if (sreg == (unsigned long) -1)
{
if (reg & ~0x3f)
/* The register number won't fit in 6 bits, so we have to use
the long form. */
cfi->dw_cfi_opc = DW_CFA_offset_extended;
else
cfi->dw_cfi_opc = DW_CFA_offset;
cfi->dw_cfi_oprnd2.dw_cfi_offset = offset;
}
else
{
cfi->dw_cfi_opc = DW_CFA_register;
cfi->dw_cfi_oprnd2.dw_cfi_reg_num = sreg;
}
add_fde_cfi (label, cfi);
}
/* Entry point for saving a register. REG is the GCC register number.
LABEL and RTL are passed to reg_save. */
void
dwarf2out_reg_save (label, reg, rtl)
register char * label;
register unsigned long reg;
register rtx rtl;
{
reg_save (label, DWARF_FRAME_REGNUM (reg), rtl);
}
/* Entry point for saving the return address.
LABEL and RTL are passed to reg_save. */
void
dwarf2out_return_save (label, rtl)
register char * label;
register rtx rtl;
{
reg_save (label, DWARF_FRAME_RETURN_COLUMN, rtl);
}
/* Return the size of a Call Frame Instruction. */
static unsigned long
size_of_cfi (cfi)
......@@ -3741,7 +3927,16 @@ calc_fde_sizes ()
register unsigned long i;
register dw_fde_ref fde;
register unsigned long fde_size;
register dw_cfi_ref cfi;
unsigned long fde_pad;
cie_size = DWARF_CIE_HEADER_SIZE;
for (cfi = cie_cfi_head; cfi != NULL; cfi = cfi->dw_cfi_next)
cie_size += size_of_cfi (cfi);
/* Initialize the beginning FDE offset. */
next_fde_offset = DWARF_ROUND (cie_size, PTR_SIZE);
for (i = 0; i < fde_table_in_use; ++i)
{
fde = &fde_table[i];
......@@ -3816,14 +4011,16 @@ output_cfi (cfi, fde)
case DW_CFA_advance_loc2:
ASM_OUTPUT_DWARF_DELTA2 (asm_out_file,
cfi->dw_cfi_oprnd1.dw_cfi_addr,
fde->dw_fde_begin);
fde->dw_fde_current_label);
fputc ('\n', asm_out_file);
fde->dw_fde_current_label = cfi->dw_cfi_oprnd1.dw_cfi_addr;
break;
case DW_CFA_advance_loc4:
ASM_OUTPUT_DWARF_DELTA4 (asm_out_file,
cfi->dw_cfi_oprnd1.dw_cfi_addr,
fde->dw_fde_begin);
fde->dw_fde_current_label);
fputc ('\n', asm_out_file);
fde->dw_fde_current_label = cfi->dw_cfi_oprnd1.dw_cfi_addr;
break;
#ifdef MIPS_DEBUGGING_INFO
case DW_CFA_MIPS_advance_loc8:
......@@ -3873,12 +4070,14 @@ output_call_frame_info ()
register unsigned long i, j;
register dw_fde_ref fde;
register unsigned long fde_size;
dw_cfi_node cfi_node;
register dw_cfi_ref cfi;
unsigned long fde_pad;
/* (re-)initialize the beginning FDE offset. */
next_fde_offset = DWARF_ROUND (cie_size, PTR_SIZE);
/* Output the CIE. */
ASM_OUTPUT_DWARF_DATA (asm_out_file, DWARF_CIE_SIZE - DWARF_OFFSET_SIZE);
ASM_OUTPUT_DWARF_DATA (asm_out_file, next_fde_offset - DWARF_OFFSET_SIZE);
if (flag_verbose_asm)
{
fprintf (asm_out_file, "\t%s Length of Common Information Entry",
......@@ -3933,31 +4132,11 @@ output_call_frame_info ()
}
fputc ('\n', asm_out_file);
/* Output the CFA instructions common to all FDE's. */
#ifdef MIPS_DEBUGGING_INFO
bzero (&cfi_node, sizeof (dw_cfi_node));
cfi = &cfi_node;
/* On entry, the Call Frame Address is in the stack pointer register. */
cfi->dw_cfi_opc = DW_CFA_def_cfa;
cfi->dw_cfi_oprnd1.dw_cfi_reg_num
= DWARF_FRAME_REGNUM (STACK_POINTER_REGNUM);
cfi->dw_cfi_oprnd2.dw_cfi_offset = 0;
output_cfi (cfi);
/* Set the RA on entry to be the contents of r31. */
cfi->dw_cfi_opc = DW_CFA_register;
cfi->dw_cfi_oprnd1.dw_cfi_reg_num = DWARF_FRAME_RETURN_COLUMN;
cfi->dw_cfi_oprnd2.dw_cfi_reg_num
= DWARF_FRAME_REGNUM (GP_REG_FIRST + 31);
output_cfi (cfi);
#endif
for (cfi = cie_cfi_head; cfi != NULL; cfi = cfi->dw_cfi_next)
output_cfi (cfi);
/* Pad the CIE out to an address sized boundary. */
for (i = DWARF_CIE_HEADER_SIZE; i < DWARF_CIE_SIZE; ++i)
for (i = next_fde_offset - cie_size; i; --i)
{
/* Pad out to a pointer size boundary */
ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_CFA_nop);
......@@ -4006,10 +4185,9 @@ output_call_frame_info ()
/* Loop through the Call Frame Instructions associated with
this FDE. */
fde->dw_fde_current_label = fde->dw_fde_begin;
for (cfi = fde->dw_fde_cfi; cfi != NULL; cfi = cfi->dw_cfi_next)
{
output_cfi (cfi, fde);
}
output_cfi (cfi, fde);
/* Pad to a double word boundary. */
for (j = 0; j < fde_pad; ++j)
......@@ -4404,37 +4582,34 @@ output_line_info ()
}
fputc ('\n', asm_out_file);
}
if (line_info->dw_line_num != current_line)
line_offset = line_info->dw_line_num - current_line;
line_delta = line_offset - DWARF_LINE_BASE;
current_line = line_info->dw_line_num;
if (line_delta >= 0 && line_delta < (DWARF_LINE_RANGE - 1))
{
line_offset = line_info->dw_line_num - current_line;
line_delta = line_offset - DWARF_LINE_BASE;
current_line = line_info->dw_line_num;
if (line_delta >= 0 && line_delta < (DWARF_LINE_RANGE - 1))
ASM_OUTPUT_DWARF_DATA1 (asm_out_file,
DWARF_LINE_OPCODE_BASE + line_delta);
if (flag_verbose_asm)
{
ASM_OUTPUT_DWARF_DATA1 (asm_out_file,
DWARF_LINE_OPCODE_BASE + line_delta);
if (flag_verbose_asm)
{
fprintf (asm_out_file,
"\t%s line %d", ASM_COMMENT_START, current_line);
}
fputc ('\n', asm_out_file);
fprintf (asm_out_file,
"\t%s line %d", ASM_COMMENT_START, current_line);
}
else
fputc ('\n', asm_out_file);
}
else
{
ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_LNS_advance_line);
if (flag_verbose_asm)
{
ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_LNS_advance_line);
if (flag_verbose_asm)
{
fprintf (asm_out_file,
"\t%s advance to line %d",
ASM_COMMENT_START, current_line);
}
fputc ('\n', asm_out_file);
output_sleb128 (line_offset);
fputc ('\n', asm_out_file);
ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_LNS_copy);
fputc ('\n', asm_out_file);
fprintf (asm_out_file,
"\t%s advance to line %d",
ASM_COMMENT_START, current_line);
}
fputc ('\n', asm_out_file);
output_sleb128 (line_offset);
fputc ('\n', asm_out_file);
ASM_OUTPUT_DWARF_DATA1 (asm_out_file, DW_LNS_copy);
fputc ('\n', asm_out_file);
}
strcpy (prev_line_label, line_label);
}
......@@ -4771,15 +4946,36 @@ modified_type_die (type, is_const_type, is_volatile_type, context_die)
if (code != ERROR_MARK)
{
/* Take the MAIN_VARIANT here to avoid C typedef types. */
type = build_type_variant (TYPE_MAIN_VARIANT (type),
is_const_type, is_volatile_type);
type = build_type_variant (type, is_const_type, is_volatile_type);
mod_type_die = lookup_type_die (type);
if (mod_type_die)
return mod_type_die;
if (is_const_type)
/* Handle C typedef types. */
if (TYPE_NAME (type) && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
&& DECL_ORIGINAL_TYPE (TYPE_NAME (type)))
{
tree dtype = TREE_TYPE (TYPE_NAME (type));
if (type == dtype)
{
/* For a named type, use the typedef. */
gen_type_die (type, context_die);
mod_type_die = lookup_type_die (type);
}
else if (is_const_type < TYPE_READONLY (dtype)
|| is_volatile_type < TYPE_VOLATILE (dtype))
/* cv-unqualified version of named type. Just use the unnamed
type to which it refers. */
mod_type_die = modified_type_die
(DECL_ORIGINAL_TYPE (TYPE_NAME (type)),
is_const_type, is_volatile_type);
/* else cv-qualified version of named type; fall through. */
}
if (mod_type_die)
/* OK */;
else if (is_const_type)
{
mod_type_die = new_die (DW_TAG_const_type, comp_unit_die);
sub_die = modified_type_die (type, 0, is_volatile_type, context_die);
......@@ -4828,13 +5024,9 @@ modified_type_die (type, is_const_type, is_volatile_type, context_die)
might simply be a *copy* of some original type node (where the
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. (Note that when `equate_type_number_to_die' is
labeling a given type DIE for future reference, it always only
handles DIEs representing *main variants*, and it never even
knows about non-main-variants.). */
..._TYPE node. */
mod_type_die = lookup_type_die (type_main_variant (type));
if (mod_type_die == NULL)
abort ();
assert (mod_type_die != NULL);
}
}
if (sub_die != NULL)
......@@ -5841,11 +6033,15 @@ add_pure_or_virtual_attribute (die, func_decl)
register dw_die_ref die;
register tree func_decl;
{
if (DECL_VIRTUAL_P (func_decl))
if (DECL_VINDEX (func_decl))
{
add_AT_unsigned (die, DW_AT_virtuality, DW_VIRTUALITY_virtual);
add_AT_loc (die, DW_AT_vtable_elem_location, new_loc_descr
(DW_OP_constu, TREE_INT_CST_LOW (DECL_VINDEX (func_decl))));
/* GNU extension: Record what type this method came from originally. */
if (debug_info_level > DINFO_LEVEL_TERSE)
add_AT_die_ref (die, DW_AT_containing_type,
lookup_type_die (DECL_CONTEXT (func_decl)));
}
}
......@@ -5901,14 +6097,15 @@ scope_die_for (t, context_die)
/* Function-local tags and functions get stuck in limbo until they are
fixed up by decls_for_scope. */
if (context_die == NULL)
if (context_die == NULL
&& (TREE_CODE (t) == FUNCTION_DECL || is_tagged_type (t)))
return NULL;
/* Walk back up the declaration tree looking for a place to define
this type. */
if (TREE_CODE_CLASS (TREE_CODE (t)) == 't')
containing_scope = TYPE_CONTEXT (t);
else if (TREE_CODE (t) == FUNCTION_DECL && DECL_VIRTUAL_P (t))
else if (TREE_CODE (t) == FUNCTION_DECL && DECL_VINDEX (t))
containing_scope = decl_class_context (t);
else
containing_scope = DECL_CONTEXT (t);
......@@ -5999,14 +6196,13 @@ type_tag (type)
/* The g++ front end makes the TYPE_NAME of *each* tagged type point to
a TYPE_DECL node, regardless of whether or not a `typedef' was
involved. */
else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL)
else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
&& ! DECL_IGNORED_P (TYPE_NAME (type)))
t = DECL_NAME (TYPE_NAME (type));
/* Now get the name as a string, or invent one. */
if (t != 0)
{
name = IDENTIFIER_POINTER (t);
}
name = IDENTIFIER_POINTER (t);
}
return (name == 0 || *name == '\0') ? 0 : name;
}
......@@ -6145,6 +6341,43 @@ gen_entry_point_die (decl, context_die)
}
}
/* Remember a type in the pending_types_list. */
static void
pend_type (type)
register tree type;
{
if (pending_types == pending_types_allocated)
{
pending_types_allocated += PENDING_TYPES_INCREMENT;
pending_types_list
= (tree *) xrealloc (pending_types_list,
sizeof (tree) * pending_types_allocated);
}
pending_types_list[pending_types++] = type;
}
/* Output any pending types (from the pending_types list) which we can output
now (taking into account the scope that we are working on now).
For each type output, remove the given type from the pending_types_list
*before* we try to output it. */
static void
output_pending_types_for_scope (context_die)
register dw_die_ref context_die;
{
register tree type;
while (pending_types)
{
--pending_types;
type = pending_types_list[pending_types];
gen_type_die (type, context_die);
assert (TREE_ASM_WRITTEN (type));
}
}
/* Generate a DIE to represent an inlined instance of an enumeration type. */
static void
gen_inlined_enumeration_type_die (type, context_die)
......@@ -6241,7 +6474,7 @@ gen_enumeration_type_die (type, context_die)
it's the latter, then this function is only being called to output a
DW_TAG_formal_parameter DIE to stand as a placeholder for some formal
argument type of some subprogram type. */
static void
static dw_die_ref
gen_formal_parameter_die (node, context_die)
register tree node;
register dw_die_ref context_die;
......@@ -6255,9 +6488,7 @@ gen_formal_parameter_die (node, context_die)
case 'd':
origin = decl_ultimate_origin (node);
if (origin != NULL)
{
add_abstract_origin_attribute (parm_die, origin);
}
add_abstract_origin_attribute (parm_die, origin);
else
{
add_name_and_src_coords_attributes (parm_die, node);
......@@ -6269,13 +6500,9 @@ gen_formal_parameter_die (node, context_die)
add_AT_flag (parm_die, DW_AT_artificial, 1);
}
if (DECL_ABSTRACT (node))
{
equate_decl_number_to_die (node, parm_die);
}
equate_decl_number_to_die (node, parm_die);
else
{
add_location_or_const_value_attribute (parm_die, node);
}
add_location_or_const_value_attribute (parm_die, node);
break;
/* We were called with some kind of a ..._TYPE node. */
......@@ -6287,6 +6514,7 @@ gen_formal_parameter_die (node, context_die)
default:
abort ();
}
return parm_die;
}
/* Generate a special type of DIE used as a stand-in for a trailing ellipsis
......@@ -6334,12 +6562,17 @@ gen_formal_types_die (function_or_method_type, context_die)
DW_TAG_formal_parameter DIE for each one. */
for (link = first_parm_type; link; link = TREE_CHAIN (link))
{
register dw_die_ref parm_die;
formal_type = TREE_VALUE (link);
if (formal_type == void_type_node)
break;
/* Output a (nameless) DIE to represent the formal parameter itself. */
gen_formal_parameter_die (formal_type, context_die);
parm_die = gen_formal_parameter_die (formal_type, context_die);
if (TREE_CODE (function_or_method_type) == METHOD_TYPE
&& link == first_parm_type)
add_AT_flag (parm_die, DW_AT_artificial, 1);
}
/* If this function type has an ellipsis, add a
......@@ -6375,8 +6608,10 @@ gen_subprogram_die (decl, context_die)
register unsigned fp_reg;
register tree fn_arg_types;
register tree outer_scope;
dw_die_ref old_die = lookup_decl_die (decl);
int declaration = (current_function_decl != decl);
register dw_die_ref old_die = lookup_decl_die (decl);
register int declaration = (current_function_decl != decl
|| context_die->die_tag == DW_TAG_structure_type
|| context_die->die_tag == DW_TAG_union_type);
if (origin != NULL)
{
......@@ -6387,12 +6622,19 @@ gen_subprogram_die (decl, context_die)
{
register unsigned file_index
= lookup_filename (DECL_SOURCE_FILE (decl));
if (get_AT_flag (old_die, DW_AT_declaration) != 1)
abort ();
assert (get_AT_flag (old_die, DW_AT_declaration) == 1);
/* If the definition comes from the same place as the declaration,
use the old DIE. */
if (get_AT_unsigned (old_die, DW_AT_decl_file) == file_index
maybe use the old DIE. We always want the DIE for this function
that has the *_pc attributes to be under comp_unit_die so the
debugger can find it. For inlines, that is the concrete instance,
so we can use the old DIE here. For non-inline methods, we want a
specification DIE at toplevel, so we need a new DIE. For local
class methods, this does not apply. */
if ((DECL_ABSTRACT (decl) || old_die->die_parent == comp_unit_die
|| context_die == NULL)
&& get_AT_unsigned (old_die, DW_AT_decl_file) == file_index
&& (get_AT_unsigned (old_die, DW_AT_decl_line)
== DECL_SOURCE_LINE (decl)))
{
......@@ -6438,9 +6680,24 @@ gen_subprogram_die (decl, context_die)
add_pure_or_virtual_attribute (subr_die, decl);
if (DECL_ARTIFICIAL (decl))
add_AT_flag (subr_die, DW_AT_artificial, 1);
if (TREE_PROTECTED (decl))
add_AT_unsigned (subr_die, DW_AT_accessibility, DW_ACCESS_protected);
else if (TREE_PRIVATE (decl))
add_AT_unsigned (subr_die, DW_AT_accessibility, DW_ACCESS_private);
}
if (DECL_ABSTRACT (decl))
if (declaration)
{
add_AT_flag (subr_die, DW_AT_declaration, 1);
/* The first time we see a member function, it is in the context of
the class to which it belongs. We make sure of this by emitting
the class first. The next time is the definition, which is
handled above. The two may come from the same source text. */
if (decl_class_context (decl))
equate_decl_number_to_die (decl, subr_die);
}
else if (DECL_ABSTRACT (decl))
{
if (DECL_DEFER_OUTPUT (decl))
{
......@@ -6460,17 +6717,6 @@ gen_subprogram_die (decl, context_die)
equate_decl_number_to_die (decl, subr_die);
}
else if (declaration)
{
add_AT_flag (subr_die, DW_AT_declaration, 1);
/* The first time we see a member function, it is in the context of
the class to which it belongs. We make sure of this by emitting
the class first. The next time is the definition, which is
handled above. The two may come from the same source text. */
if (decl_class_context (decl))
equate_decl_number_to_die (decl, subr_die);
}
else if (!DECL_EXTERNAL (decl))
{
if (origin == NULL)
......@@ -6503,16 +6749,6 @@ gen_subprogram_die (decl, context_die)
if (current_function_needs_context)
add_AT_loc (subr_die, DW_AT_static_link,
loc_descriptor (lookup_static_chain (decl)));
#ifdef DWARF_GNU_EXTENSIONS
ASM_GENERATE_INTERNAL_LABEL (label_id, BODY_BEGIN_LABEL,
current_funcdef_number);
add_AT_lbl_id (subr_die, DW_AT_body_begin, label_id);
ASM_GENERATE_INTERNAL_LABEL (label_id, BODY_END_LABEL,
current_funcdef_number);
add_AT_lbl_id (subr_die, DW_AT_body_end, label_id);
#endif
}
/* Now output descriptions of the arguments for this function. This gets
......@@ -6631,7 +6867,9 @@ gen_variable_die (decl, context_die)
dw_die_ref old_die = lookup_decl_die (decl);
int declaration
= (DECL_EXTERNAL (decl)
|| current_function_decl != decl_function_context (decl));
|| current_function_decl != decl_function_context (decl)
|| context_die->die_tag == DW_TAG_structure_type
|| context_die->die_tag == DW_TAG_union_type);
if (origin != NULL)
{
......@@ -6639,8 +6877,7 @@ gen_variable_die (decl, context_die)
}
else if (old_die)
{
if (get_AT_flag (old_die, DW_AT_declaration) != 1)
abort ();
assert (get_AT_flag (old_die, DW_AT_declaration) == 1);
add_AT_die_ref (var_die, DW_AT_specification, old_die);
if (DECL_NAME (decl))
{
......@@ -6664,6 +6901,10 @@ gen_variable_die (decl, context_die)
add_AT_flag (var_die, DW_AT_external, 1);
if (DECL_ARTIFICIAL (decl))
add_AT_flag (var_die, DW_AT_artificial, 1);
if (TREE_PROTECTED (decl))
add_AT_unsigned (var_die, DW_AT_accessibility, DW_ACCESS_protected);
else if (TREE_PRIVATE (decl))
add_AT_unsigned (var_die, DW_AT_accessibility, DW_ACCESS_private);
}
if (declaration)
......@@ -6792,9 +7033,14 @@ gen_field_die (decl, context_die)
add_bit_size_attribute (decl_die, decl);
add_bit_offset_attribute (decl_die, decl);
}
add_data_member_location_attribute (decl_die, decl);
if (TREE_CODE (DECL_FIELD_CONTEXT (decl)) != UNION_TYPE)
add_data_member_location_attribute (decl_die, decl);
if (DECL_ARTIFICIAL (decl))
add_AT_flag (decl_die, DW_AT_artificial, 1);
if (TREE_PROTECTED (decl))
add_AT_unsigned (decl_die, DW_AT_accessibility, DW_ACCESS_protected);
else if (TREE_PRIVATE (decl))
add_AT_unsigned (decl_die, DW_AT_accessibility, DW_ACCESS_private);
}
#if 0
......@@ -6985,8 +7231,7 @@ gen_struct_or_union_type_die (type, context_die)
&& TREE_CODE_CLASS (TREE_CODE (TYPE_CONTEXT (type))) == 't')
nested = 1;
if (! type_die || nested)
scope_die = scope_die_for (type, context_die);
scope_die = scope_die_for (type, context_die);
if (! type_die || (nested && scope_die == comp_unit_die))
/* First occurrence of type or toplevel definition of nested class. */
......@@ -7003,13 +7248,16 @@ gen_struct_or_union_type_die (type, context_die)
else
remove_AT (type_die, DW_AT_declaration);
/* If we're not in the right context to be defining this type, defer to
avoid tricky recursion. */
if (TYPE_SIZE (type) && decl_scope_depth > 0 && scope_die == comp_unit_die)
{
add_AT_flag (type_die, DW_AT_declaration, 1);
pend_type (type);
}
/* If this type has been completed, then give it a byte_size attribute and
then give a list of members. */
if (TYPE_SIZE (type)
/* If we're getting a reference to one nested class from another
nested class, don't recurse. */
&& ! (nested && scope_die != context_die
&& scope_die == lookup_type_die (TYPE_CONTEXT (type))))
else if (TYPE_SIZE (type))
{
/* Prevent infinite recursion in cases where the type of some member of
this type is expressed in terms of this type itself. */
......@@ -7018,6 +7266,14 @@ gen_struct_or_union_type_die (type, context_die)
push_decl_scope (type);
gen_member_die (type, type_die);
pop_decl_scope ();
/* GNU extension: Record what type our vtable lives in. */
if (TYPE_VFIELD (type))
{
tree vtype = DECL_FCONTEXT (TYPE_VFIELD (type));
gen_type_die (vtype, context_die);
add_AT_die_ref (type_die, DW_AT_containing_type,
lookup_type_die (vtype));
}
}
else
add_AT_flag (type_die, DW_AT_declaration, 1);
......@@ -7035,7 +7291,7 @@ gen_subroutine_type_die (type, context_die)
equate_type_number_to_die (type, subr_die);
add_prototyped_attribute (subr_die, type);
add_type_attribute (subr_die, return_type, 0, 0, context_die);
gen_formal_types_die (type, context_die);
gen_formal_types_die (type, subr_die);
}
/* Generate a DIE for a type definition */
......@@ -7044,25 +7300,33 @@ gen_typedef_die (decl, context_die)
register tree decl;
register dw_die_ref context_die;
{
register tree origin = decl_ultimate_origin (decl);
register dw_die_ref type_die;
register tree origin;
if (TREE_ASM_WRITTEN (decl))
return;
TREE_ASM_WRITTEN (decl) = 1;
type_die = new_die (DW_TAG_typedef, scope_die_for (decl, context_die));
origin = decl_ultimate_origin (decl);
if (origin != NULL)
{
add_abstract_origin_attribute (type_die, origin);
}
add_abstract_origin_attribute (type_die, origin);
else
{
register tree type;
add_name_and_src_coords_attributes (type_die, decl);
add_type_attribute (type_die, TREE_TYPE (decl),
TREE_READONLY (decl),
TREE_THIS_VOLATILE (decl),
context_die);
if (DECL_ORIGINAL_TYPE (decl))
{
type = DECL_ORIGINAL_TYPE (decl);
equate_type_number_to_die (TREE_TYPE (decl), type_die);
}
else
type = TREE_TYPE (decl);
add_type_attribute (type_die, type, TREE_READONLY (decl),
TREE_THIS_VOLATILE (decl), context_die);
}
if (DECL_ABSTRACT (decl))
{
equate_decl_number_to_die (decl, type_die);
}
equate_decl_number_to_die (decl, type_die);
}
/* Generate a type description DIE. */
......@@ -7086,6 +7350,14 @@ gen_type_die (type, context_die)
return;
}
if (TYPE_NAME (type) && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
&& DECL_ORIGINAL_TYPE (TYPE_NAME (type)))
{
TREE_ASM_WRITTEN (type) = 1;
gen_decl_die (TYPE_NAME (type), context_die);
return;
}
switch (TREE_CODE (type))
{
case ERROR_MARK:
......@@ -7152,12 +7424,27 @@ gen_type_die (type, context_die)
if (TYPE_CONTEXT (type)
&& TREE_CODE_CLASS (TREE_CODE (TYPE_CONTEXT (type))) == 't'
&& ! TREE_ASM_WRITTEN (TYPE_CONTEXT (type)))
gen_type_die (TYPE_CONTEXT (type), context_die);
else if (TREE_CODE (type) == ENUMERAL_TYPE)
{
gen_type_die (TYPE_CONTEXT (type), context_die);
if (TREE_ASM_WRITTEN (TYPE_CONTEXT (type)))
return;
/* If that failed, attach ourselves to the stub. */
push_decl_scope (TYPE_CONTEXT (type));
context_die = lookup_type_die (TYPE_CONTEXT (type));
}
if (TREE_CODE (type) == ENUMERAL_TYPE)
gen_enumeration_type_die (type, context_die);
else
gen_struct_or_union_type_die (type, context_die);
if (TYPE_CONTEXT (type)
&& TREE_CODE_CLASS (TREE_CODE (TYPE_CONTEXT (type))) == 't'
&& ! TREE_ASM_WRITTEN (TYPE_CONTEXT (type)))
pop_decl_scope ();
/* Don't set TREE_ASM_WRITTEN on an incomplete struct; we want to fix
it up if it is ever completed. gen_*_type_die will set it for us
when appropriate. */
......@@ -7347,18 +7634,19 @@ decls_for_scope (stmt, context_die, depth)
for (decl = BLOCK_VARS (stmt);
decl != NULL; decl = TREE_CHAIN (decl))
{
register dw_die_ref die;
if (TREE_CODE (decl) == FUNCTION_DECL)
{
register dw_die_ref die = lookup_decl_die (decl);
add_child_die (context_die, die);
}
die = lookup_decl_die (decl);
else if (TREE_CODE (decl) == TYPE_DECL && TYPE_DECL_IS_STUB (decl))
die = lookup_type_die (TREE_TYPE (decl));
else
die = NULL;
if (die && die->die_parent == NULL)
{
register dw_die_ref die = lookup_type_die (TREE_TYPE (decl));
if (die)
add_child_die (context_die, die);
else
gen_decl_die (decl, context_die);
add_child_die (context_die, die);
--limbo_die_count;
}
else
gen_decl_die (decl, context_die);
......@@ -7374,6 +7662,23 @@ decls_for_scope (stmt, context_die, depth)
}
}
/* Is this a typedef we can avoid emitting? */
inline int
is_redundant_typedef (decl)
register tree decl;
{
if (TYPE_DECL_IS_STUB (decl))
return 1;
if (DECL_ARTIFICIAL (decl)
&& DECL_CONTEXT (decl)
&& is_tagged_type (DECL_CONTEXT (decl))
&& TREE_CODE (TYPE_NAME (DECL_CONTEXT (decl))) == TYPE_DECL
&& DECL_NAME (decl) == DECL_NAME (TYPE_NAME (DECL_CONTEXT (decl))))
/* Also ignore the artificial member typedef for the class name. */
return 1;
return 0;
}
/* Generate Dwarf debug information for a decl described by DECL. */
static void
gen_decl_die (decl, context_die)
......@@ -7417,10 +7722,21 @@ gen_decl_die (decl, context_die)
break;
}
/* Before we describe the FUNCTION_DECL itself, make sure that we have
described its return type. */
if (debug_info_level > DINFO_LEVEL_TERSE)
gen_type_die (TREE_TYPE (TREE_TYPE (decl)), context_die);
{
/* Before we describe the FUNCTION_DECL itself, make sure that we
have described its return type. */
gen_type_die (TREE_TYPE (TREE_TYPE (decl)), context_die);
/* And its containing type. */
origin = decl_class_context (decl);
if (origin)
gen_type_die (origin, context_die);
/* And its virtual context. */
if (DECL_VINDEX (decl))
gen_type_die (DECL_CONTEXT (decl), context_die);
}
/* Now output a DIE to represent the function itself. */
gen_subprogram_die (decl, context_die);
......@@ -7444,9 +7760,10 @@ gen_decl_die (decl, context_die)
gen_tagged_type_instantiation_die (TREE_TYPE (decl), context_die);
break;
}
gen_type_die (TREE_TYPE (decl), context_die);
if (! TYPE_DECL_IS_STUB (decl))
if (is_redundant_typedef (decl))
gen_type_die (TREE_TYPE (decl), context_die);
else
{
/* Output a DIE to represent the typedef itself. */
gen_typedef_die (decl, context_die);
......@@ -7472,6 +7789,11 @@ gen_decl_die (decl, context_die)
object. */
gen_type_die (TREE_TYPE (decl), context_die);
/* And its containing type. */
origin = decl_class_context (decl);
if (origin)
gen_type_die (origin, context_die);
/* Now output the DIE to represent the data object itself. This gets
complicated because of the possibility that the VAR_DECL really
represents an inlined instance of a formal parameter for an inline
......@@ -7488,8 +7810,9 @@ gen_decl_die (decl, context_die)
break;
case FIELD_DECL:
/* Ignore the nameless fields that are used to skip bits. */
if (DECL_NAME (decl) != 0)
/* Ignore the nameless fields that are used to skip bits, but
handle C++ anonymous unions. */
if (DECL_NAME (decl) != 0 || TREE_CODE (TREE_TYPE (decl)) == UNION_TYPE)
{
gen_type_die (member_declared_type (decl), context_die);
gen_field_die (decl, context_die);
......@@ -7610,7 +7933,15 @@ dwarf2out_decl (decl)
/* Don't bother trying to generate any DIEs to represent any of the
normal built-in types for the language we are compiling. */
if (DECL_SOURCE_LINE (decl) == 0)
return;
{
/* OK, we need to generate one for `bool' so GDB knows what type
comparisons have. */
if ((get_AT_unsigned (comp_unit_die, DW_AT_language)
== DW_LANG_C_plus_plus)
&& TREE_CODE (TREE_TYPE (decl)) == BOOLEAN_TYPE)
modified_type_die (TREE_TYPE (decl), 0, 0, NULL);
return;
}
/* If we are in terse mode, don't generate any DIEs for types. */
if (debug_info_level <= DINFO_LEVEL_TERSE)
......@@ -7628,6 +7959,7 @@ dwarf2out_decl (decl)
}
gen_decl_die (decl, context_die);
output_pending_types_for_scope (comp_unit_die);
if (TREE_CODE (decl) == FUNCTION_DECL
&& DECL_INITIAL (decl) != NULL)
......@@ -7700,8 +8032,7 @@ dwarf2out_begin_prologue ()
/* Add the new FDE at the end of the fde_table. */
fde = &fde_table[fde_table_in_use++];
fde->dw_fde_begin = xstrdup (label);
fde->dw_fde_end_prolog = NULL;
fde->dw_fde_begin_epilogue = NULL;
fde->dw_fde_current_label = NULL;
fde->dw_fde_end = NULL;
fde->dw_fde_cfi = NULL;
}
......@@ -7712,100 +8043,51 @@ dwarf2out_begin_prologue ()
void
dwarf2out_begin_function ()
{
#ifdef MIPS_DEBUGGING_INFO
char label[MAX_ARTIFICIAL_LABEL_BYTES];
register long int offset;
register dw_fde_ref fde;
register dw_cfi_ref cfi;
register int regno, fp_inc;
function_section (current_function_decl);
ASM_GENERATE_INTERNAL_LABEL (label, BODY_BEGIN_LABEL,
current_funcdef_number);
ASM_OUTPUT_LABEL (asm_out_file, label);
/* Record the end-of-prolog location in the FDE. */
fde = &fde_table[fde_table_in_use - 1];
fde->dw_fde_end_prolog = xstrdup (label);
#ifdef MIPS_DEBUGGING_INFO
/* Set the location counter to the end of the function prolog. */
cfi = new_cfi ();
cfi->dw_cfi_opc = DW_CFA_advance_loc4;
cfi->dw_cfi_oprnd1.dw_cfi_addr = xstrdup (label);
add_cfi (&fde->dw_fde_cfi, cfi);
/* Define the CFA as an offset from either the frame pointer
or the stack pointer. */
cfi = new_cfi ();
cfi->dw_cfi_opc = DW_CFA_def_cfa;
cfi->dw_cfi_oprnd1.dw_cfi_reg_num
= DWARF_FRAME_REGNUM (frame_pointer_needed ? FRAME_POINTER_REGNUM
: STACK_POINTER_REGNUM);
offset = current_frame_info.total_size;
cfi->dw_cfi_oprnd2.dw_cfi_offset = offset;
add_cfi (&fde->dw_fde_cfi, cfi);
/* record the frame size for later definition of the DW_AT_frame_base
attribute. */
current_funcdef_frame_size = offset;
/* Define the rule for restoring the stack pointer. */
if (frame_pointer_needed)
{
/* Restore the stack register from the frame pointer. */
cfi = new_cfi ();
cfi->dw_cfi_opc = DW_CFA_register;
cfi->dw_cfi_oprnd1.dw_cfi_reg_num
= DWARF_FRAME_REGNUM (STACK_POINTER_REGNUM);
cfi->dw_cfi_oprnd2.dw_cfi_reg_num
= DWARF_FRAME_REGNUM (FRAME_POINTER_REGNUM);
add_cfi (&fde->dw_fde_cfi, cfi);
}
/* If RA is saved on the stack, define it here. */
if (regs_ever_live[31])
{
offset = current_frame_info.gp_save_offset / DWARF_CIE_DATA_ALIGNMENT;
assert (offset >= 0);
cfi = new_cfi ();
cfi->dw_cfi_opc = DW_CFA_offset_extended;
cfi->dw_cfi_oprnd1.dw_cfi_reg_num = DWARF_FRAME_RETURN_COLUMN;
cfi->dw_cfi_oprnd2.dw_cfi_offset = offset;
add_cfi (&fde->dw_fde_cfi, cfi);
}
dwarf2out_def_cfa
(label, gen_rtx (PLUS, VOIDmode,
gen_rtx (REG, VOIDmode,
(frame_pointer_needed ? FRAME_POINTER_REGNUM
: STACK_POINTER_REGNUM)),
GEN_INT (current_frame_info.total_size)));
/* Record the locations of the return address and any callee-saved regs. */
offset = current_frame_info.gp_save_offset / DWARF_CIE_DATA_ALIGNMENT;
for (regno = GP_REG_LAST; regno >= GP_REG_FIRST; --regno)
if (current_frame_info.mask & (1<<regno))
{
assert (offset >= 0);
/* If FP is saved on the stack, define it here. */
if (current_frame_info.mask & (1 << 30))
{
offset = (current_frame_info.gp_save_offset
- (((current_frame_info.mask >> 31) & 1) * UNITS_PER_WORD))
/ DWARF_CIE_DATA_ALIGNMENT;
assert (offset >= 0);
cfi = new_cfi ();
cfi->dw_cfi_opc = DW_CFA_offset;
cfi->dw_cfi_oprnd1.dw_cfi_reg_num
= DWARF_FRAME_REGNUM (FRAME_POINTER_REGNUM);
cfi->dw_cfi_oprnd2.dw_cfi_offset = offset;
add_cfi (&fde->dw_fde_cfi, cfi);
}
if (regno == 31)
dwarf2out_return_save (label, GEN_INT (offset));
else
dwarf2out_reg_save (label, regno, GEN_INT (offset));
offset -= UNITS_PER_WORD / DWARF_CIE_DATA_ALIGNMENT;
}
fp_inc = (TARGET_FLOAT64 || TARGET_SINGLE_FLOAT) ? 1 : 2;
offset = current_frame_info.fp_save_offset / DWARF_CIE_DATA_ALIGNMENT;
for (regno = FP_REG_LAST - 1; regno >= FP_REG_FIRST; regno -= fp_inc)
if (current_frame_info.fmask & (1 << (regno - FP_REG_FIRST)))
{
assert (offset >= 0);
dwarf2out_reg_save (label, regno, GEN_INT (offset));
offset -= (fp_inc * UNITS_PER_FPREG) / DWARF_CIE_DATA_ALIGNMENT;
}
#endif
}
/* Output a marker (i.e. a label) for the point in the generated code where
the real body of the function ends (just before the epilogue code). */
void
dwarf2out_end_function ()
{
dw_fde_ref fde;
char label[MAX_ARTIFICIAL_LABEL_BYTES];
function_section (current_function_decl);
ASM_GENERATE_INTERNAL_LABEL (label, BODY_END_LABEL, current_funcdef_number);
ASM_OUTPUT_LABEL (asm_out_file, label);
/* Record the ending code location in the FDE. */
fde = &fde_table[fde_table_in_use - 1];
fde->dw_fde_begin_epilogue = xstrdup(label);
}
/* Output a marker (i.e. a label) for the absolute end of the generated code
......@@ -7998,13 +8280,6 @@ dwarf2out_init (asm_out_file, main_input_filename)
/* skip the first entry - file numbers begin at 1 */
file_table_in_use = 1;
/* Allocate the initial hunk of the type_die_table. */
type_die_table
= (dw_die_ref *) xmalloc (TYPE_DIE_TABLE_INCREMENT * sizeof (dw_die_ref));
bzero (type_die_table, TYPE_DIE_TABLE_INCREMENT * sizeof (dw_die_ref));
type_die_table_allocated = TYPE_DIE_TABLE_INCREMENT;
type_die_table_in_use = 0;
/* Allocate the initial hunk of the decl_die_table. */
decl_die_table
= (dw_die_ref *) xmalloc (DECL_DIE_TABLE_INCREMENT * sizeof (dw_die_ref));
......@@ -8052,6 +8327,16 @@ dwarf2out_init (asm_out_file, main_input_filename)
gen_compile_unit_die (main_input_filename);
ASM_GENERATE_INTERNAL_LABEL (text_end_label, TEXT_END_LABEL, 0);
/* Generate the CFA instructions common to all FDE's. Do it now for the
sake of lookup_cfa. */
#ifdef MIPS_DEBUGGING_INFO
/* On entry, the Call Frame Address is in the stack pointer register. */
dwarf2out_def_cfa (NULL, gen_rtx (REG, VOIDmode, STACK_POINTER_REGNUM));
/* Set the RA on entry to be the contents of r31. */
dwarf2out_return_save (NULL, gen_rtx (REG, VOIDmode, GP_REG_FIRST + 31));
#endif
}
/* Output stuff that dwarf requires at the end of every file,
......@@ -8107,8 +8392,7 @@ dwarf2out_finish ()
next_die_offset = DWARF_COMPILE_UNIT_HEADER_SIZE;
calc_die_sizes (comp_unit_die);
/* Initialize the beginning FDE offset - and calculate sizes/offsets. */
next_fde_offset = DWARF_CIE_SIZE;
/* calculate sizes/offsets for FDEs. */
calc_fde_sizes ();
/* Output debugging information. */
......@@ -8127,15 +8411,20 @@ dwarf2out_finish ()
if (fde_table_in_use)
{
#ifdef MIPS_DEBUGGING_INFO /* Not currently useful otherwise. */
/* Output call frame information. */
fputc ('\n', asm_out_file);
ASM_OUTPUT_SECTION (asm_out_file, FRAME_SECTION);
output_call_frame_info ();
#endif
/* Output the address range information. */
fputc ('\n', asm_out_file);
ASM_OUTPUT_SECTION (asm_out_file, ARANGES_SECTION);
output_aranges ();
}
/* The only DIE we should have with a parent of NULL is comp_unit_die. */
assert (limbo_die_count == 1);
}
#endif /* DWARF2_DEBUGGING_INFO */
......@@ -97,6 +97,21 @@ extern char *rindex ();
#define TYPE_USED_FOR_FUNCTION(tagged_type) (TYPE_SIZE (tagged_type) == 0)
/* Define a macro which returns non-zero for a TYPE_DECL which was
implicitly generated for a tagged type.
Note that unlike the gcc front end (which generates a NULL named
TYPE_DECL node for each complete tagged type, each array type, and
each function type node created) the g++ front end generates a
_named_ TYPE_DECL node for each tagged type node created.
These TYPE_DECLs have DECL_ARTIFICIAL set, so we know not to
generate a DW_TAG_typedef DIE for them. */
#define TYPE_DECL_IS_STUB(decl) \
(DECL_NAME (decl) == NULL \
|| (DECL_ARTIFICIAL (decl) \
&& is_tagged_type (TREE_TYPE (decl)) \
&& decl == TYPE_STUB_DECL (TREE_TYPE (decl))))
extern int flag_traditional;
extern char *version_string;
extern char *language_string;
......@@ -284,6 +299,12 @@ static unsigned current_funcdef_number = 1;
static tree dwarf_last_decl;
/* A flag indicating that we are emitting the member declarations of a
class, so member functions and variables should not be entirely emitted.
This is a kludge to avoid passing a second argument to output_*_die. */
static int in_class;
/* Forward declarations for functions defined in this file. */
static char *dwarf_tag_name PROTO((unsigned));
......@@ -1169,6 +1190,27 @@ block_ultimate_origin (block)
}
}
/* Get the class to which DECL belongs, if any. In g++, the DECL_CONTEXT
of a virtual function may refer to a base class, so we check the 'this'
parameter. */
static tree
decl_class_context (decl)
tree decl;
{
tree context = NULL_TREE;
if (TREE_CODE (decl) != FUNCTION_DECL || ! DECL_VINDEX (decl))
context = DECL_CONTEXT (decl);
else
context = TYPE_MAIN_VARIANT
(TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (decl)))));
if (context && TREE_CODE_CLASS (TREE_CODE (context)) != 't')
context = NULL_TREE;
return context;
}
static void
output_unsigned_leb128 (value)
register unsigned long value;
......@@ -3007,8 +3049,8 @@ type_tag (type)
/* The g++ front end makes the TYPE_NAME of *each* tagged type point to
a TYPE_DECL node, regardless of whether or not a `typedef' was
involved. */
else
if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL)
else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
&& ! DECL_IGNORED_P (TYPE_NAME (type)))
t = DECL_NAME (TYPE_NAME (type));
/* Now get the name as a string, or invent one. */
......@@ -3302,17 +3344,21 @@ output_global_subroutine_die (arg)
equate_decl_number_to_die_number (decl);
else
{
if (! DECL_EXTERNAL (decl))
if (! DECL_EXTERNAL (decl) && ! in_class
&& decl == current_function_decl)
{
char label[MAX_ARTIFICIAL_LABEL_BYTES];
low_pc_attribute (function_start_label (decl));
sprintf (label, FUNC_END_LABEL_FMT, current_funcdef_number);
high_pc_attribute (label);
sprintf (label, BODY_BEGIN_LABEL_FMT, current_funcdef_number);
body_begin_attribute (label);
sprintf (label, BODY_END_LABEL_FMT, current_funcdef_number);
body_end_attribute (label);
if (use_gnu_debug_info_extensions)
{
sprintf (label, BODY_BEGIN_LABEL_FMT, current_funcdef_number);
body_begin_attribute (label);
sprintf (label, BODY_END_LABEL_FMT, current_funcdef_number);
body_end_attribute (label);
}
}
}
}
......@@ -3342,7 +3388,8 @@ output_global_variable_die (arg)
equate_decl_number_to_die_number (decl);
else
{
if (!DECL_EXTERNAL (decl))
if (! DECL_EXTERNAL (decl) && ! in_class
&& current_function_decl == decl_function_context (decl))
location_or_const_value_attribute (decl);
}
}
......@@ -3566,7 +3613,7 @@ output_compile_unit_die (arg)
comp_dir_attribute (wd);
}
if (debug_info_level >= DINFO_LEVEL_NORMAL)
if (debug_info_level >= DINFO_LEVEL_NORMAL && use_gnu_debug_info_extensions)
{
sf_names_attribute (SFNAMES_BEGIN_LABEL);
src_info_attribute (SRCINFO_BEGIN_LABEL);
......@@ -3681,10 +3728,13 @@ output_local_subroutine_die (arg)
low_pc_attribute (function_start_label (decl));
sprintf (label, FUNC_END_LABEL_FMT, current_funcdef_number);
high_pc_attribute (label);
sprintf (label, BODY_BEGIN_LABEL_FMT, current_funcdef_number);
body_begin_attribute (label);
sprintf (label, BODY_END_LABEL_FMT, current_funcdef_number);
body_end_attribute (label);
if (use_gnu_debug_info_extensions)
{
sprintf (label, BODY_BEGIN_LABEL_FMT, current_funcdef_number);
body_begin_attribute (label);
sprintf (label, BODY_END_LABEL_FMT, current_funcdef_number);
body_end_attribute (label);
}
}
}
}
......@@ -3990,7 +4040,9 @@ type_ok_for_scope (type, scope)
(for C and C++ anyway) will be array types and function types. */
return is_tagged_type (type)
? (TYPE_CONTEXT (type) == scope)
? (TYPE_CONTEXT (type) == scope
|| (scope == NULL_TREE && is_tagged_type (TYPE_CONTEXT (type))
&& TREE_ASM_WRITTEN (TYPE_CONTEXT (type))))
: (scope == NULL_TREE || ! is_tagged_type (scope));
}
......@@ -4058,6 +4110,17 @@ output_type (type, containing_scope)
if (TREE_ASM_WRITTEN (type))
return;
/* If this is a nested type whose containing class hasn't been
written out yet, writing it out will cover this one, too. */
if (TYPE_CONTEXT (type)
&& TREE_CODE_CLASS (TREE_CODE (TYPE_CONTEXT (type))) == 't'
&& ! TREE_ASM_WRITTEN (TYPE_CONTEXT (type)))
{
output_type (TYPE_CONTEXT (type), containing_scope);
return;
}
/* Don't generate any DIEs for this type now unless it is OK to do so
(based upon what `type_ok_for_scope' tells us). */
......@@ -4168,13 +4231,9 @@ output_type (type, containing_scope)
time, we will certainly know as much about each file-scope tagged
type as we are ever going to know, so at that point in time, we
can safely generate correct Dwarf descriptions for these file-
scope tagged types.
This loses for C++ nested types that are defined after their
containing class, but I don't see a good way to fix it. I doubt
many people will be using DWARF 1 for C++ in any case. */
scope tagged types. */
if (TYPE_SIZE (type) == 0 && TYPE_CONTEXT (type) == NULL && !finalizing)
if (TYPE_SIZE (type) == 0 && !finalizing)
return; /* EARLY EXIT! Avoid setting TREE_ASM_WRITTEN. */
/* Prevent infinite recursion in cases where the type of some
......@@ -4233,6 +4292,8 @@ output_type (type, containing_scope)
output_die (output_inheritance_die, TREE_VEC_ELT (bases, i));
}
++in_class;
{
register tree normal_member;
......@@ -4255,6 +4316,8 @@ output_type (type, containing_scope)
output_decl (func_member, type);
}
--in_class;
/* RECORD_TYPEs, UNION_TYPEs, and QUAL_UNION_TYPEs are themselves
scopes (at least in C++) so we must now output any nested
pending types which are local just to this type. */
......@@ -4458,6 +4521,24 @@ output_decls_for_scope (stmt, depth)
}
}
/* Is this a typedef we can avoid emitting? */
inline int
is_redundant_typedef (decl)
register tree decl;
{
if (TYPE_DECL_IS_STUB (decl))
return 1;
if (DECL_ARTIFICIAL (decl)
&& DECL_CONTEXT (decl)
&& is_tagged_type (DECL_CONTEXT (decl))
&& TREE_CODE (TYPE_NAME (DECL_CONTEXT (decl))) == TYPE_DECL
&& DECL_NAME (decl) == DECL_NAME (TYPE_NAME (DECL_CONTEXT (decl))))
/* Also ignore the artificial member typedef for the class name. */
return 1;
return 0;
}
/* Output Dwarf .debug information for a decl described by DECL. */
static void
......@@ -4518,6 +4599,13 @@ output_decl (decl, containing_scope)
output_type (TREE_TYPE (TREE_TYPE (decl)), containing_scope);
{
/* And its containing type. */
register tree origin = decl_class_context (decl);
if (origin)
output_type (origin, containing_scope);
}
/* If the following DIE will represent a function definition for a
function with "extern" linkage, output a special "pubnames" DIE
label just ahead of the actual DIE. A reference to this label
......@@ -4554,7 +4642,7 @@ output_decl (decl, containing_scope)
we need to do here (and all we *can* do here) is to describe
the *types* of its formal parameters. */
if (DECL_INITIAL (decl) == NULL_TREE)
if (decl != current_function_decl || in_class)
output_formal_types (TREE_TYPE (decl));
else
{
......@@ -4644,45 +4732,45 @@ output_decl (decl, containing_scope)
output_die (output_unspecified_parameters_die, decl);
}
}
}
/* Output Dwarf info for all of the stuff within the body of the
function (if it has one - it may be just a declaration). */
/* Output Dwarf info for all of the stuff within the body of the
function (if it has one - it may be just a declaration). */
{
register tree outer_scope = DECL_INITIAL (decl);
if (outer_scope && TREE_CODE (outer_scope) != ERROR_MARK)
{
/* Note that here, `outer_scope' is a pointer to the outermost
BLOCK node created to represent a function.
This outermost BLOCK actually represents the outermost
binding contour for the function, i.e. the contour in which
the function's formal parameters and labels get declared.
Curiously, it appears that the front end doesn't actually
put the PARM_DECL nodes for the current function onto the
BLOCK_VARS list for this outer scope. (They are strung
off of the DECL_ARGUMENTS list for the function instead.)
The BLOCK_VARS list for the `outer_scope' does provide us
with a list of the LABEL_DECL nodes for the function however,
and we output DWARF info for those here.
Just within the `outer_scope' there will be a BLOCK node
representing the function's outermost pair of curly braces,
and any blocks used for the base and member initializers of
a C++ constructor function. */
output_decls_for_scope (outer_scope, 0);
/* Finally, force out any pending types which are local to the
outermost block of this function definition. These will
all have a TYPE_CONTEXT which points to the FUNCTION_DECL
node itself. */
output_pending_types_for_scope (decl);
register tree outer_scope = DECL_INITIAL (decl);
if (outer_scope && TREE_CODE (outer_scope) != ERROR_MARK)
{
/* Note that here, `outer_scope' is a pointer to the outermost
BLOCK node created to represent a function.
This outermost BLOCK actually represents the outermost
binding contour for the function, i.e. the contour in which
the function's formal parameters and labels get declared.
Curiously, it appears that the front end doesn't actually
put the PARM_DECL nodes for the current function onto the
BLOCK_VARS list for this outer scope. (They are strung
off of the DECL_ARGUMENTS list for the function instead.)
The BLOCK_VARS list for the `outer_scope' does provide us
with a list of the LABEL_DECL nodes for the function however,
and we output DWARF info for those here.
Just within the `outer_scope' there will be a BLOCK node
representing the function's outermost pair of curly braces,
and any blocks used for the base and member initializers of
a C++ constructor function. */
output_decls_for_scope (outer_scope, 0);
/* Finally, force out any pending types which are local to the
outermost block of this function definition. These will
all have a TYPE_CONTEXT which points to the FUNCTION_DECL
node itself. */
output_pending_types_for_scope (decl);
}
}
}
}
/* Generate a terminator for the list of stuff `owned' by this
function. */
......@@ -4699,19 +4787,19 @@ output_decl (decl, containing_scope)
a return type or a formal parameter type of some function. */
if (debug_info_level <= DINFO_LEVEL_TERSE)
if (DECL_NAME (decl) != NULL
|| ! TYPE_USED_FOR_FUNCTION (TREE_TYPE (decl)))
if (! TYPE_DECL_IS_STUB (decl)
|| (! TYPE_USED_FOR_FUNCTION (TREE_TYPE (decl)) && ! in_class))
return;
/* In the special case of a null-named TYPE_DECL node (representing
the declaration of some type tag), if the given TYPE_DECL is
/* In the special case of a TYPE_DECL node representing
the declaration of some type tag, if the given TYPE_DECL is
marked as having been instantiated from some other (original)
TYPE_DECL node (e.g. one which was generated within the original
definition of an inline function) we have to generate a special
(abbreviated) TAG_structure_type, TAG_union_type, or
TAG_enumeration-type DIE here. */
if (! DECL_NAME (decl) && DECL_ABSTRACT_ORIGIN (decl))
if (TYPE_DECL_IS_STUB (decl) && DECL_ABSTRACT_ORIGIN (decl))
{
output_tagged_type_instantiation (TREE_TYPE (decl));
return;
......@@ -4719,13 +4807,7 @@ output_decl (decl, containing_scope)
output_type (TREE_TYPE (decl), containing_scope);
/* Note that unlike the gcc front end (which generates a NULL named
TYPE_DECL node for each complete tagged type, each array type,
and each function type node created) the g++ front end generates
a *named* TYPE_DECL node for each tagged type node created.
These TYPE_DECLs have DECL_ARTIFICIAL set, so we know not to
generate a DW_TAG_typedef DIE for them. */
if (DECL_NAME (decl) && ! DECL_ARTIFICIAL (decl))
if (! is_redundant_typedef (decl))
/* Output a DIE to represent the typedef itself. */
output_die (output_typedef_die, decl);
break;
......@@ -4755,6 +4837,13 @@ output_decl (decl, containing_scope)
output_type (TREE_TYPE (decl), containing_scope);
{
/* And its containing type. */
register tree origin = decl_class_context (decl);
if (origin)
output_type (origin, containing_scope);
}
/* If the following DIE will represent a data object definition for a
data object with "extern" linkage, output a special "pubnames" DIE
label just ahead of the actual DIE. A reference to this label
......@@ -5076,6 +5165,8 @@ dwarfout_begin_function ()
{
char label[MAX_ARTIFICIAL_LABEL_BYTES];
if (! use_gnu_debug_info_extensions)
return;
function_section (current_function_decl);
sprintf (label, BODY_BEGIN_LABEL_FMT, current_funcdef_number);
ASM_OUTPUT_LABEL (asm_out_file, label);
......@@ -5089,6 +5180,8 @@ dwarfout_end_function ()
{
char label[MAX_ARTIFICIAL_LABEL_BYTES];
if (! use_gnu_debug_info_extensions)
return;
function_section (current_function_decl);
sprintf (label, BODY_END_LABEL_FMT, current_funcdef_number);
ASM_OUTPUT_LABEL (asm_out_file, label);
......@@ -5263,7 +5356,7 @@ dwarfout_line (filename, line)
char label[MAX_ARTIFICIAL_LABEL_BYTES];
static unsigned last_line_entry_num = 0;
static unsigned prev_file_entry_num = (unsigned) -1;
register unsigned this_file_entry_num = lookup_filename (filename);
register unsigned this_file_entry_num;
function_section (current_function_decl);
sprintf (label, LINE_CODE_LABEL_FMT, ++last_line_entry_num);
......@@ -5272,6 +5365,11 @@ dwarfout_line (filename, line)
fputc ('\n', asm_out_file);
ASM_OUTPUT_PUSH_SECTION (asm_out_file, LINE_SECTION);
if (use_gnu_debug_info_extensions)
this_file_entry_num = lookup_filename (filename);
else
this_file_entry_num = (unsigned) -1;
if (this_file_entry_num != prev_file_entry_num)
{
char line_entry_label[MAX_ARTIFICIAL_LABEL_BYTES];
......@@ -5307,6 +5405,9 @@ generate_macinfo_entry (type_and_offset, string)
register char *type_and_offset;
register char *string;
{
if (! use_gnu_debug_info_extensions)
return;
fputc ('\n', asm_out_file);
ASM_OUTPUT_PUSH_SECTION (asm_out_file, MACINFO_SECTION);
fprintf (asm_out_file, "\t%s\t%s\n", UNALIGNED_INT_ASM_OP, type_and_offset);
......@@ -5466,32 +5567,36 @@ dwarfout_init (asm_out_file, main_input_filename)
if (debug_info_level >= DINFO_LEVEL_NORMAL)
{
/* Output a starting label and an initial (compilation directory)
entry for the .debug_sfnames section. The starting label will be
referenced by the initial entry in the .debug_srcinfo section. */
if (use_gnu_debug_info_extensions)
{
/* Output a starting label and an initial (compilation directory)
entry for the .debug_sfnames section. The starting label will be
referenced by the initial entry in the .debug_srcinfo section. */
fputc ('\n', asm_out_file);
ASM_OUTPUT_PUSH_SECTION (asm_out_file, SFNAMES_SECTION);
ASM_OUTPUT_LABEL (asm_out_file, SFNAMES_BEGIN_LABEL);
{
register char *pwd;
register unsigned len;
register char *dirname;
pwd = getpwd ();
if (!pwd)
pfatal_with_name ("getpwd");
len = strlen (pwd);
dirname = (char *) xmalloc (len + 2);
fputc ('\n', asm_out_file);
ASM_OUTPUT_PUSH_SECTION (asm_out_file, SFNAMES_SECTION);
ASM_OUTPUT_LABEL (asm_out_file, SFNAMES_BEGIN_LABEL);
{
register char *pwd;
register unsigned len;
register char *dirname;
pwd = getpwd ();
if (!pwd)
pfatal_with_name ("getpwd");
len = strlen (pwd);
dirname = (char *) xmalloc (len + 2);
strcpy (dirname, pwd);
strcpy (dirname + len, "/");
ASM_OUTPUT_DWARF_STRING (asm_out_file, dirname);
free (dirname);
}
ASM_OUTPUT_POP_SECTION (asm_out_file);
strcpy (dirname, pwd);
strcpy (dirname + len, "/");
ASM_OUTPUT_DWARF_STRING (asm_out_file, dirname);
free (dirname);
}
ASM_OUTPUT_POP_SECTION (asm_out_file);
}
if (debug_info_level >= DINFO_LEVEL_VERBOSE)
if (debug_info_level >= DINFO_LEVEL_VERBOSE
&& use_gnu_debug_info_extensions)
{
/* Output a starting label for the .debug_macinfo section. This
label will be referenced by the AT_mac_info attribute in the
......@@ -5512,21 +5617,24 @@ dwarfout_init (asm_out_file, main_input_filename)
ASM_OUTPUT_DWARF_ADDR (asm_out_file, TEXT_BEGIN_LABEL);
ASM_OUTPUT_POP_SECTION (asm_out_file);
/* Generate the initial entry for the .debug_srcinfo section. */
fputc ('\n', asm_out_file);
ASM_OUTPUT_PUSH_SECTION (asm_out_file, SRCINFO_SECTION);
ASM_OUTPUT_LABEL (asm_out_file, SRCINFO_BEGIN_LABEL);
ASM_OUTPUT_DWARF_ADDR (asm_out_file, LINE_BEGIN_LABEL);
ASM_OUTPUT_DWARF_ADDR (asm_out_file, SFNAMES_BEGIN_LABEL);
ASM_OUTPUT_DWARF_ADDR (asm_out_file, TEXT_BEGIN_LABEL);
ASM_OUTPUT_DWARF_ADDR (asm_out_file, TEXT_END_LABEL);
if (use_gnu_debug_info_extensions)
{
/* Generate the initial entry for the .debug_srcinfo section. */
fputc ('\n', asm_out_file);
ASM_OUTPUT_PUSH_SECTION (asm_out_file, SRCINFO_SECTION);
ASM_OUTPUT_LABEL (asm_out_file, SRCINFO_BEGIN_LABEL);
ASM_OUTPUT_DWARF_ADDR (asm_out_file, LINE_BEGIN_LABEL);
ASM_OUTPUT_DWARF_ADDR (asm_out_file, SFNAMES_BEGIN_LABEL);
ASM_OUTPUT_DWARF_ADDR (asm_out_file, TEXT_BEGIN_LABEL);
ASM_OUTPUT_DWARF_ADDR (asm_out_file, TEXT_END_LABEL);
#ifdef DWARF_TIMESTAMPS
ASM_OUTPUT_DWARF_DATA4 (asm_out_file, time (NULL));
ASM_OUTPUT_DWARF_DATA4 (asm_out_file, time (NULL));
#else
ASM_OUTPUT_DWARF_DATA4 (asm_out_file, -1);
ASM_OUTPUT_DWARF_DATA4 (asm_out_file, -1);
#endif
ASM_OUTPUT_POP_SECTION (asm_out_file);
ASM_OUTPUT_POP_SECTION (asm_out_file);
}
/* Generate the initial entry for the .debug_pubnames section. */
......@@ -5664,14 +5772,17 @@ dwarfout_finish ()
ASM_OUTPUT_LABEL (asm_out_file, LINE_END_LABEL);
ASM_OUTPUT_POP_SECTION (asm_out_file);
/* Output a terminating entry for the .debug_srcinfo section. */
fputc ('\n', asm_out_file);
ASM_OUTPUT_PUSH_SECTION (asm_out_file, SRCINFO_SECTION);
ASM_OUTPUT_DWARF_DELTA4 (asm_out_file,
LINE_LAST_ENTRY_LABEL, LINE_BEGIN_LABEL);
ASM_OUTPUT_DWARF_DATA4 (asm_out_file, -1);
ASM_OUTPUT_POP_SECTION (asm_out_file);
if (use_gnu_debug_info_extensions)
{
/* Output a terminating entry for the .debug_srcinfo section. */
fputc ('\n', asm_out_file);
ASM_OUTPUT_PUSH_SECTION (asm_out_file, SRCINFO_SECTION);
ASM_OUTPUT_DWARF_DELTA4 (asm_out_file,
LINE_LAST_ENTRY_LABEL, LINE_BEGIN_LABEL);
ASM_OUTPUT_DWARF_DATA4 (asm_out_file, -1);
ASM_OUTPUT_POP_SECTION (asm_out_file);
}
if (debug_info_level >= DINFO_LEVEL_VERBOSE)
{
......
......@@ -1066,11 +1066,6 @@ final_end_function (first, file, optimize)
dwarfout_end_function ();
#endif
#ifdef DWARF2_DEBUGGING_INFO
if (write_symbols == DWARF2_DEBUG)
dwarf2out_end_function ();
#endif
#ifdef XCOFF_DEBUGGING_INFO
if (write_symbols == XCOFF_DEBUG)
xcoffout_end_function (file, high_function_linenum);
......
......@@ -2776,15 +2776,6 @@ rest_of_type_compilation (type, toplev)
if (write_symbols == SDB_DEBUG)
TIMEVAR (symout_time, sdbout_symbol (TYPE_STUB_DECL (type), !toplev));
#endif
#ifdef DWARF_DEBUGGING_INFO
/* Don't write out function-scope types here. */
if (write_symbols == DWARF_DEBUG && toplev)
TIMEVAR (symout_time, dwarfout_file_scope_decl (TYPE_STUB_DECL (type), 0));
#endif
#ifdef DWARF2_DEBUGGING_INFO
if (write_symbols == DWARF2_DEBUG)
TIMEVAR (symout_time, dwarf2out_decl (TYPE_STUB_DECL (type)));
#endif
}
/* This is called from finish_function (within yyparse)
......@@ -3904,19 +3895,11 @@ main (argc, argv, envp)
{ "gstabs+", DBX_DEBUG, 1 },
#endif
#ifdef DWARF_DEBUGGING_INFO
{ "gdwarf-1", DWARF_DEBUG, 0 },
{ "gdwarf-1+", DWARF_DEBUG, 1 },
#endif
#ifdef DWARF2_DEBUGGING_INFO
{ "gdwarf-2", DWARF2_DEBUG, 0 },
#endif
#if defined (DWARF_DEBUGGING_INFO) || defined (DWARF2_DEBUGGING_INFO)
#if PREFERRED_DEBUGGING_TYPE == DWARF_DEBUG || !defined (DWARF2_DEBUGGING_INFO)
{ "gdwarf", DWARF_DEBUG, 0 },
{ "gdwarf+", DWARF_DEBUG, 1 },
#else
{ "gdwarf", DWARF2_DEBUG, 0 },
#endif
#ifdef DWARF2_DEBUGGING_INFO
{ "gdwarf-2", DWARF2_DEBUG, 0 },
#endif
#ifdef XCOFF_DEBUGGING_INFO
{ "gxcoff", XCOFF_DEBUG, 0 },
......@@ -4398,3 +4381,58 @@ debug_undef (lineno, buffer)
dwarf2out_undef (lineno, buffer);
#endif /* DWARF2_DEBUGGING_INFO */
}
/* Record the relative location of the current stack frame at the PC value
indicated by LABEL if specified, or at the beginning of the function
if LABEL is NULL. RTL is either:
a REG: The frame is at 0(REG).
a PLUS of a REG and a CONST_INT: The frame is at CONST(REG). */
void
debug_frame (label, rtl)
char *label;
rtx rtl;
{
#ifdef DWARF2_DEBUGGING_INFO
if (write_symbols == DWARF2_DEBUG)
dwarf2out_def_cfa (label, rtl);
#endif
}
/* Record that REGNO, a callee-saved register, has been saved somewhere.
LABEL is as for debug_frame. RTL is either:
a REG: The register is saved in REG.
a CONST_INT: The register is saved at an offset of CONST
from the frame. */
void
debug_reg_save (label, regno, rtl)
char *label;
unsigned regno;
rtx rtl;
{
#ifdef DWARF2_DEBUGGING_INFO
if (write_symbols == DWARF2_DEBUG)
dwarf2out_reg_save (label, regno, rtl);
#endif
}
/* Record the location of the return address for the current frame.
LABEL is as for debug_frame. RTL is either:
a REG: The return address is saved in REG.
a CONST_INT: The return address is saved at an offset of CONST
from the frame. */
void
debug_return_save (label, rtl)
char *label;
rtx rtl;
{
#ifdef DWARF2_DEBUGGING_INFO
if (write_symbols == DWARF2_DEBUG)
dwarf2out_return_save (label, rtl);
#endif
}
......@@ -1268,6 +1268,45 @@ get_identifier (text)
return idp; /* <-- return if created */
}
/* If an identifier with the name TEXT (a null-terminated string) has
previously been referred to, return that node; otherwise return
NULL_TREE. */
tree
maybe_get_identifier (text)
register char *text;
{
register int hi;
register int i;
register tree idp;
register int len, hash_len;
/* Compute length of text in len. */
for (len = 0; text[len]; len++);
/* Decide how much of that length to hash on */
hash_len = len;
if (warn_id_clash && len > id_clash_len)
hash_len = id_clash_len;
/* Compute hash code */
hi = hash_len * 613 + (unsigned) text[0];
for (i = 1; i < hash_len; i += 2)
hi = ((hi * 613) + (unsigned) (text[i]));
hi &= (1 << HASHBITS) - 1;
hi %= MAX_HASH_TABLE;
/* Search table for identifier */
for (idp = hash_table[hi]; idp; idp = TREE_CHAIN (idp))
if (IDENTIFIER_LENGTH (idp) == len
&& IDENTIFIER_POINTER (idp)[0] == text[0]
&& !bcmp (IDENTIFIER_POINTER (idp), text, len))
return idp; /* <-- return if found */
return NULL_TREE;
}
/* Enable warnings on similar identifiers (if requested).
Done after the built-in identifiers are created. */
......
......@@ -1175,25 +1175,15 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
&& (TREE_PUBLIC (decl) == 0 || DECL_INITIAL (decl) == 0))
sdbout_symbol (decl, 0);
#endif
#ifdef DWARF_DEBUGGING_INFO
if (write_symbols == DWARF_DEBUG && top_level
&& DECL_CONTEXT (decl))
dwarfout_file_scope_decl (decl, 0);
#endif
#ifdef DWARF2_DEBUGGING_INFO
if (write_symbols == DWARF2_DEBUG && top_level
&& DECL_CONTEXT (decl))
dwarf2out_decl (decl);
#endif
}
/* Only output DWARF debugging information for record-scope variables
here. In the case of function-scope variables, the information
for them is output when we do our recursive traversal of the tree
representation for the entire containing function. In the case of
file-scope variables, we output information for all of them at the
very end of compilation while we are doing our final traversal of
the chain of file-scope declarations. */
/* Don't output any DWARF debugging information for variables here.
In the case of local variables, the information for them is output
when we do our recursive traversal of the tree representation for
the entire containing function. In the case of file-scope variables,
we output information for all of them at the very end of compilation
while we are doing our final traversal of the chain of file-scope
declarations. */
return;
}
......@@ -1308,24 +1298,14 @@ assemble_variable (decl, top_level, at_end, dont_output_data)
&& (TREE_PUBLIC (decl) == 0 || DECL_INITIAL (decl) == 0))
sdbout_symbol (decl, 0);
#endif
#ifdef DWARF_DEBUGGING_INFO
if (write_symbols == DWARF_DEBUG && top_level
&& DECL_CONTEXT (decl))
dwarfout_file_scope_decl (decl, 0);
#endif
#ifdef DWARF2_DEBUGGING_INFO
if (write_symbols == DWARF2_DEBUG && top_level
&& DECL_CONTEXT (decl))
dwarf2out_decl (decl);
#endif
/* Only output DWARF debugging information for record-scope variables
here. In the case of function-scope variables, the information
for them is output when we do our recursive traversal of the tree
representation for the entire containing function. In the case of
file-scope variables, we output information for all of them at the
very end of compilation while we are doing our final traversal of
the chain of file-scope declarations. */
/* Don't output any DWARF debugging information for variables here.
In the case of local variables, the information for them is output
when we do our recursive traversal of the tree representation for
the entire containing function. In the case of file-scope variables,
we output information for all of them at the very end of compilation
while we are doing our final traversal of the chain of file-scope
declarations. */
#if 0 /* ??? We should either delete this or add a comment describing what
it was intended to do and why we shouldn't delete it. */
......@@ -1729,15 +1709,13 @@ assemble_name (file, name)
char *name;
{
char *real_name;
int save_warn_id_clash = warn_id_clash;
tree id;
STRIP_NAME_ENCODING (real_name, name);
/* Don't warn about an identifier name length clash on this name, since
it can be a user symbol suffixed by a number. */
warn_id_clash = 0;
TREE_SYMBOL_REFERENCED (get_identifier (real_name)) = 1;
warn_id_clash = save_warn_id_clash;
id = maybe_get_identifier (real_name);
if (id)
TREE_SYMBOL_REFERENCED (id) = 1;
if (name[0] == '*')
{
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment