diff options
-rw-r--r-- | gcc/Makefile.in | 12 | ||||
-rw-r--r-- | gcc/config/mips/mips.c | 67 | ||||
-rw-r--r-- | gcc/config/mips/t-iris6 | 1 | ||||
-rw-r--r-- | gcc/dwarf2out.c | 909 | ||||
-rw-r--r-- | gcc/dwarfout.c | 335 | ||||
-rw-r--r-- | gcc/final.c | 5 | ||||
-rw-r--r-- | gcc/toplev.c | 76 | ||||
-rw-r--r-- | gcc/tree.c | 39 | ||||
-rw-r--r-- | gcc/varasm.c | 58 |
9 files changed, 1001 insertions, 501 deletions
diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 7ef5cfb..ddb4ad5 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -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. diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index 10545bb..c3a3b2d 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -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) diff --git a/gcc/config/mips/t-iris6 b/gcc/config/mips/t-iris6 index e831459..85a63f0 100644 --- a/gcc/config/mips/t-iris6 +++ b/gcc/config/mips/t-iris6 @@ -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 diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 6ac7d45..8902630 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -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, ®, &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 */ diff --git a/gcc/dwarfout.c b/gcc/dwarfout.c index daddd0e..1d29394 100644 --- a/gcc/dwarfout.c +++ b/gcc/dwarfout.c @@ -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) { diff --git a/gcc/final.c b/gcc/final.c index c38aada..40a0911 100644 --- a/gcc/final.c +++ b/gcc/final.c @@ -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); diff --git a/gcc/toplev.c b/gcc/toplev.c index 61528b0..a10f4d9 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -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. */ diff --git a/gcc/varasm.c b/gcc/varasm.c index 9490238..a8c15df 100644 --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -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] == '*') { |