diff options
author | kan <kan@FreeBSD.org> | 2004-07-28 03:11:36 +0000 |
---|---|---|
committer | kan <kan@FreeBSD.org> | 2004-07-28 03:11:36 +0000 |
commit | 5e00ec74d8ce58f99801200d4d3d0412c7cc1b28 (patch) | |
tree | 052f4bb635f2bea2c5e350bd60c902be100a0d1e /contrib/gcc/dwarf2out.c | |
parent | 87b8398a7d9f9bf0e28bbcd54a4fc27db2125f38 (diff) | |
download | FreeBSD-src-5e00ec74d8ce58f99801200d4d3d0412c7cc1b28.zip FreeBSD-src-5e00ec74d8ce58f99801200d4d3d0412c7cc1b28.tar.gz |
Gcc 3.4.2 20040728.
Diffstat (limited to 'contrib/gcc/dwarf2out.c')
-rw-r--r-- | contrib/gcc/dwarf2out.c | 3846 |
1 files changed, 2126 insertions, 1720 deletions
diff --git a/contrib/gcc/dwarf2out.c b/contrib/gcc/dwarf2out.c index bd86bc4..a2d8669 100644 --- a/contrib/gcc/dwarf2out.c +++ b/contrib/gcc/dwarf2out.c @@ -1,6 +1,6 @@ -/* Output Dwarf2 format symbol table information from the GNU C compiler. - Copyright (C) 1992, 1993, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 - Free Software Foundation, Inc. +/* Output Dwarf2 format symbol table information from GCC. + Copyright (C) 1992, 1993, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, + 2003, 2004 Free Software Foundation, Inc. Contributed by Gary Funck (gary@intrepid.com). Derived from DWARF 1 implementation of Ron Guilmette (rfg@monkeys.com). Extensively modified by Jason Merrill (jason@cygnus.com). @@ -36,6 +36,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "config.h" #include "system.h" +#include "coretypes.h" +#include "tm.h" #include "tree.h" #include "flags.h" #include "real.h" @@ -61,11 +63,11 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "debug.h" #include "target.h" #include "langhooks.h" -#include "hashtable.h" #include "hashtab.h" +#include "cgraph.h" #ifdef DWARF2_DEBUGGING_INFO -static void dwarf2out_source_line PARAMS ((unsigned int, const char *)); +static void dwarf2out_source_line (unsigned int, const char *); #endif /* DWARF2 Abbreviation Glossary: @@ -90,7 +92,7 @@ static void dwarf2out_source_line PARAMS ((unsigned int, const char *)); translation unit. */ int -dwarf2out_do_frame () +dwarf2out_do_frame (void) { return (write_symbols == DWARF2_DEBUG || write_symbols == VMS_AND_DWARF2_DEBUG @@ -109,12 +111,12 @@ dwarf2out_do_frame () #define PTR_SIZE (POINTER_SIZE / BITS_PER_UNIT) #endif -/* Default version of targetm.eh_frame_section. Note this must appear - outside the DWARF2_DEBUGGING_INFO || DWARF2_UNWIND_INFO macro - guards. */ +/* Various versions of targetm.eh_frame_section. Note these must appear + outside the DWARF2_DEBUGGING_INFO || DWARF2_UNWIND_INFO macro guards. */ +/* Version of targetm.eh_frame_section for systems with named sections. */ void -default_eh_frame_section () +named_section_eh_frame_section (void) { #ifdef EH_FRAME_SECTION_NAME #ifdef HAVE_LD_RO_RW_SECTION_MIXING @@ -135,13 +137,29 @@ default_eh_frame_section () #else named_section_flags (EH_FRAME_SECTION_NAME, SECTION_WRITE); #endif -#else +#endif +} + +/* Version of targetm.eh_frame_section for systems using collect2. */ +void +collect2_eh_frame_section (void) +{ tree label = get_file_function_name ('F'); data_section (); ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (PTR_SIZE)); (*targetm.asm_out.globalize_label) (asm_out_file, IDENTIFIER_POINTER (label)); ASM_OUTPUT_LABEL (asm_out_file, IDENTIFIER_POINTER (label)); +} + +/* Default version of targetm.eh_frame_section. */ +void +default_eh_frame_section (void) +{ +#ifdef EH_FRAME_SECTION_NAME + named_section_eh_frame_section (); +#else + collect2_eh_frame_section (); #endif } @@ -161,8 +179,6 @@ static GTY(()) varray_type incomplete_types; define type declaration DIE's. */ static GTY(()) varray_type decl_scope_table; -#if defined (DWARF2_DEBUGGING_INFO) || defined (DWARF2_UNWIND_INFO) - /* How to start an assembler comment. */ #ifndef ASM_COMMENT_START #define ASM_COMMENT_START ";#" @@ -177,21 +193,31 @@ typedef union dw_cfi_oprnd_struct *dw_cfi_oprnd_ref; and address fields are provided as possible operands; their use is selected by the opcode field. */ -typedef union dw_cfi_oprnd_struct +enum dw_cfi_oprnd_type { + dw_cfi_oprnd_unused, + dw_cfi_oprnd_reg_num, + dw_cfi_oprnd_offset, + dw_cfi_oprnd_addr, + dw_cfi_oprnd_loc +}; + +typedef union dw_cfi_oprnd_struct GTY(()) { - unsigned long dw_cfi_reg_num; - long int dw_cfi_offset; - const char *dw_cfi_addr; - struct dw_loc_descr_struct *dw_cfi_loc; + unsigned long GTY ((tag ("dw_cfi_oprnd_reg_num"))) dw_cfi_reg_num; + HOST_WIDE_INT GTY ((tag ("dw_cfi_oprnd_offset"))) dw_cfi_offset; + const char * GTY ((tag ("dw_cfi_oprnd_addr"))) dw_cfi_addr; + struct dw_loc_descr_struct * GTY ((tag ("dw_cfi_oprnd_loc"))) dw_cfi_loc; } dw_cfi_oprnd; -typedef struct dw_cfi_struct +typedef struct dw_cfi_struct GTY(()) { dw_cfi_ref dw_cfi_next; enum dwarf_call_frame_info dw_cfi_opc; - dw_cfi_oprnd dw_cfi_oprnd1; - dw_cfi_oprnd dw_cfi_oprnd2; + dw_cfi_oprnd GTY ((desc ("dw_cfi_oprnd1_desc (%1.dw_cfi_opc)"))) + dw_cfi_oprnd1; + dw_cfi_oprnd GTY ((desc ("dw_cfi_oprnd2_desc (%1.dw_cfi_opc)"))) + dw_cfi_oprnd2; } dw_cfi_node; @@ -200,11 +226,11 @@ dw_cfi_node; It can now be either REG + CFA_OFFSET or *(REG + BASE_OFFSET) + CFA_OFFSET. Instead of passing around REG and OFFSET, we pass a copy of this structure. */ -typedef struct cfa_loc +typedef struct cfa_loc GTY(()) { unsigned long reg; - long offset; - long base_offset; + HOST_WIDE_INT offset; + HOST_WIDE_INT base_offset; int indirect; /* 1 if CFA is accessed via a dereference. */ } dw_cfa_location; @@ -214,7 +240,7 @@ typedef struct cfa_loc CIE obviates the need to keep track of multiple CIE's in the DWARF generation routines below. */ -typedef struct dw_fde_struct +typedef struct dw_fde_struct GTY(()) { const char *dw_fde_begin; const char *dw_fde_current_label; @@ -248,6 +274,18 @@ dw_fde_node; #define DWARF_OFFSET_SIZE 4 #endif +/* According to the (draft) DWARF 3 specification, the initial length + should either be 4 or 12 bytes. When it's 12 bytes, the first 4 + bytes are 0xffffffff, followed by the length stored in the next 8 + bytes. + + However, the SGI/MIPS ABI uses an initial length which is equal to + DWARF_OFFSET_SIZE. It is defined (elsewhere) accordingly. */ + +#ifndef DWARF_INITIAL_LENGTH_SIZE +#define DWARF_INITIAL_LENGTH_SIZE (DWARF_OFFSET_SIZE == 4 ? 4 : 12) +#endif + #define DWARF_VERSION 2 /* Round SIZE up to the nearest BOUNDARY. */ @@ -265,67 +303,71 @@ dw_fde_node; /* A pointer to the base of a table that contains frame description information for each routine. */ -static dw_fde_ref fde_table; +static GTY((length ("fde_table_allocated"))) dw_fde_ref fde_table; /* Number of elements currently allocated for fde_table. */ -static unsigned fde_table_allocated; +static GTY(()) unsigned fde_table_allocated; /* Number of elements in fde_table currently in use. */ -static unsigned fde_table_in_use; +static GTY(()) unsigned fde_table_in_use; /* Size (in elements) of increments by which we may expand the fde_table. */ #define FDE_TABLE_INCREMENT 256 /* A list of call frame insns for the CIE. */ -static dw_cfi_ref cie_cfi_head; +static GTY(()) dw_cfi_ref cie_cfi_head; +#if defined (DWARF2_DEBUGGING_INFO) || defined (DWARF2_UNWIND_INFO) /* Some DWARF extensions (e.g., MIPS/SGI) implement a subprogram attribute that accelerates the lookup of the FDE associated with the subprogram. This variable holds the table index of the FDE associated with the current function (body) definition. */ static unsigned current_funcdef_fde; +#endif -struct ht *debug_str_hash; - -struct indirect_string_node +struct indirect_string_node GTY(()) { - struct ht_identifier id; + const char *str; unsigned int refcount; unsigned int form; char *label; }; +static GTY ((param_is (struct indirect_string_node))) htab_t debug_str_hash; + +static GTY(()) int dw2_string_counter; +static GTY(()) unsigned long dwarf2out_cfi_label_num; + +#if defined (DWARF2_DEBUGGING_INFO) || defined (DWARF2_UNWIND_INFO) + /* Forward declarations for functions defined in this file. */ -static char *stripattributes PARAMS ((const char *)); -static const char *dwarf_cfi_name PARAMS ((unsigned)); -static dw_cfi_ref new_cfi PARAMS ((void)); -static void add_cfi PARAMS ((dw_cfi_ref *, dw_cfi_ref)); -static void add_fde_cfi PARAMS ((const char *, dw_cfi_ref)); -static void lookup_cfa_1 PARAMS ((dw_cfi_ref, - dw_cfa_location *)); -static void lookup_cfa PARAMS ((dw_cfa_location *)); -static void reg_save PARAMS ((const char *, unsigned, - unsigned, long)); -static void initial_return_save PARAMS ((rtx)); -static long stack_adjust_offset PARAMS ((rtx)); -static void output_cfi PARAMS ((dw_cfi_ref, dw_fde_ref, int)); -static void output_call_frame_info PARAMS ((int)); -static void dwarf2out_stack_adjust PARAMS ((rtx)); -static void queue_reg_save PARAMS ((const char *, rtx, long)); -static void flush_queued_reg_saves PARAMS ((void)); -static bool clobbers_queued_reg_save PARAMS ((rtx)); -static void dwarf2out_frame_debug_expr PARAMS ((rtx, const char *)); +static char *stripattributes (const char *); +static const char *dwarf_cfi_name (unsigned); +static dw_cfi_ref new_cfi (void); +static void add_cfi (dw_cfi_ref *, dw_cfi_ref); +static void add_fde_cfi (const char *, dw_cfi_ref); +static void lookup_cfa_1 (dw_cfi_ref, dw_cfa_location *); +static void lookup_cfa (dw_cfa_location *); +static void reg_save (const char *, unsigned, unsigned, HOST_WIDE_INT); +static void initial_return_save (rtx); +static HOST_WIDE_INT stack_adjust_offset (rtx); +static void output_cfi (dw_cfi_ref, dw_fde_ref, int); +static void output_call_frame_info (int); +static void dwarf2out_stack_adjust (rtx); +static void queue_reg_save (const char *, rtx, HOST_WIDE_INT); +static void flush_queued_reg_saves (void); +static bool clobbers_queued_reg_save (rtx); +static void dwarf2out_frame_debug_expr (rtx, const char *); /* Support for complex CFA locations. */ -static void output_cfa_loc PARAMS ((dw_cfi_ref)); -static void get_cfa_from_loc_descr PARAMS ((dw_cfa_location *, - struct dw_loc_descr_struct *)); +static void output_cfa_loc (dw_cfi_ref); +static void get_cfa_from_loc_descr (dw_cfa_location *, + struct dw_loc_descr_struct *); static struct dw_loc_descr_struct *build_cfa_loc - PARAMS ((dw_cfa_location *)); -static void def_cfa_1 PARAMS ((const char *, - dw_cfa_location *)); + (dw_cfa_location *); +static void def_cfa_1 (const char *, dw_cfa_location *); /* How to start an assembler comment. */ #ifndef ASM_COMMENT_START @@ -365,9 +407,9 @@ static void def_cfa_1 PARAMS ((const char *, registers. */ #ifndef DWARF_FRAME_RETURN_COLUMN #ifdef PC_REGNUM -#define DWARF_FRAME_RETURN_COLUMN DWARF_FRAME_REGNUM (PC_REGNUM) +#define DWARF_FRAME_RETURN_COLUMN DWARF_FRAME_REGNUM (PC_REGNUM) #else -#define DWARF_FRAME_RETURN_COLUMN DWARF_FRAME_REGISTERS +#define DWARF_FRAME_RETURN_COLUMN DWARF_FRAME_REGISTERS #endif #endif @@ -386,7 +428,7 @@ static void def_cfa_1 PARAMS ((const char *, /* Hook used by __throw. */ rtx -expand_builtin_dwarf_sp_column () +expand_builtin_dwarf_sp_column (void) { return GEN_INT (DWARF_FRAME_REGNUM (STACK_POINTER_REGNUM)); } @@ -395,8 +437,7 @@ expand_builtin_dwarf_sp_column () attributes stripped off, and an asterisk prepended (for assemble_name). */ static inline char * -stripattributes (s) - const char *s; +stripattributes (const char *s) { char *stripped = xmalloc (strlen (s) + 2); char *p = stripped; @@ -413,20 +454,30 @@ stripattributes (s) /* Generate code to initialize the register size table. */ void -expand_builtin_init_dwarf_reg_sizes (address) - tree address; +expand_builtin_init_dwarf_reg_sizes (tree address) { int i; enum machine_mode mode = TYPE_MODE (char_type_node); rtx addr = expand_expr (address, NULL_RTX, VOIDmode, 0); rtx mem = gen_rtx_MEM (BLKmode, addr); + bool wrote_return_column = false; for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) if (DWARF_FRAME_REGNUM (i) < DWARF_FRAME_REGISTERS) { HOST_WIDE_INT offset = DWARF_FRAME_REGNUM (i) * GET_MODE_SIZE (mode); - HOST_WIDE_INT size = GET_MODE_SIZE (reg_raw_mode[i]); + enum machine_mode save_mode = reg_raw_mode[i]; + HOST_WIDE_INT size; + if (HARD_REGNO_CALL_PART_CLOBBERED (i, save_mode)) + save_mode = choose_hard_reg_mode (i, 1, true); + if (DWARF_FRAME_REGNUM (i) == DWARF_FRAME_RETURN_COLUMN) + { + if (save_mode == VOIDmode) + continue; + wrote_return_column = true; + } + size = GET_MODE_SIZE (save_mode); if (offset < 0) continue; @@ -434,20 +485,27 @@ expand_builtin_init_dwarf_reg_sizes (address) } #ifdef DWARF_ALT_FRAME_RETURN_COLUMN - { - enum machine_mode save_mode = Pmode; - HOST_WIDE_INT offset = DWARF_ALT_FRAME_RETURN_COLUMN * GET_MODE_SIZE (mode); - HOST_WIDE_INT size = GET_MODE_SIZE (save_mode); - emit_move_insn (adjust_address (mem, mode, offset), GEN_INT (size)); - } + if (! wrote_return_column) + abort (); + i = DWARF_ALT_FRAME_RETURN_COLUMN; + wrote_return_column = false; +#else + i = DWARF_FRAME_RETURN_COLUMN; #endif + + if (! wrote_return_column) + { + enum machine_mode save_mode = Pmode; + HOST_WIDE_INT offset = i * GET_MODE_SIZE (mode); + HOST_WIDE_INT size = GET_MODE_SIZE (save_mode); + emit_move_insn (adjust_address (mem, mode, offset), GEN_INT (size)); + } } /* Convert a DWARF call frame info. operation to its string name */ static const char * -dwarf_cfi_name (cfi_opc) - unsigned cfi_opc; +dwarf_cfi_name (unsigned int cfi_opc) { switch (cfi_opc) { @@ -520,9 +578,9 @@ dwarf_cfi_name (cfi_opc) /* Return a pointer to a newly allocated Call Frame Instruction. */ static inline dw_cfi_ref -new_cfi () +new_cfi (void) { - dw_cfi_ref cfi = (dw_cfi_ref) xmalloc (sizeof (dw_cfi_node)); + dw_cfi_ref cfi = ggc_alloc (sizeof (dw_cfi_node)); cfi->dw_cfi_next = NULL; cfi->dw_cfi_oprnd1.dw_cfi_reg_num = 0; @@ -534,9 +592,7 @@ new_cfi () /* Add a Call Frame Instruction to list of instructions. */ static inline void -add_cfi (list_head, cfi) - dw_cfi_ref *list_head; - dw_cfi_ref cfi; +add_cfi (dw_cfi_ref *list_head, dw_cfi_ref cfi) { dw_cfi_ref *p; @@ -550,12 +606,11 @@ add_cfi (list_head, cfi) /* Generate a new label for the CFI info to refer to. */ char * -dwarf2out_cfi_label () +dwarf2out_cfi_label (void) { static char label[20]; - static unsigned long label_num = 0; - ASM_GENERATE_INTERNAL_LABEL (label, "LCFI", label_num++); + ASM_GENERATE_INTERNAL_LABEL (label, "LCFI", dwarf2out_cfi_label_num++); ASM_OUTPUT_LABEL (asm_out_file, label); return label; } @@ -564,9 +619,7 @@ dwarf2out_cfi_label () or to the CIE if LABEL is NULL. */ static void -add_fde_cfi (label, cfi) - const char *label; - dw_cfi_ref cfi; +add_fde_cfi (const char *label, dw_cfi_ref cfi) { if (label) { @@ -599,9 +652,7 @@ add_fde_cfi (label, cfi) /* Subroutine of lookup_cfa. */ static inline void -lookup_cfa_1 (cfi, loc) - dw_cfi_ref cfi; - dw_cfa_location *loc; +lookup_cfa_1 (dw_cfi_ref cfi, dw_cfa_location *loc) { switch (cfi->dw_cfi_opc) { @@ -626,8 +677,7 @@ lookup_cfa_1 (cfi, loc) /* Find the previous value for the CFA. */ static void -lookup_cfa (loc) - dw_cfa_location *loc; +lookup_cfa (dw_cfa_location *loc) { dw_cfi_ref cfi; @@ -655,20 +705,17 @@ static dw_cfa_location cfa; static dw_cfa_location cfa_store; /* The running total of the size of arguments pushed onto the stack. */ -static long args_size; +static HOST_WIDE_INT args_size; /* The last args_size we actually output. */ -static long old_args_size; +static HOST_WIDE_INT old_args_size; /* Entry point to update the canonical frame address (CFA). LABEL is passed to add_fde_cfi. The value of CFA is now to be calculated from REG+OFFSET. */ void -dwarf2out_def_cfa (label, reg, offset) - const char *label; - unsigned reg; - long offset; +dwarf2out_def_cfa (const char *label, unsigned int reg, HOST_WIDE_INT offset) { dw_cfa_location loc; loc.indirect = 0; @@ -682,9 +729,7 @@ dwarf2out_def_cfa (label, reg, offset) the dw_cfa_location structure. */ static void -def_cfa_1 (label, loc_p) - const char *label; - dw_cfa_location *loc_p; +def_cfa_1 (const char *label, dw_cfa_location *loc_p) { dw_cfi_ref cfi; dw_cfa_location old_cfa, loc; @@ -757,11 +802,7 @@ def_cfa_1 (label, loc_p) otherwise it is saved in SREG. */ static void -reg_save (label, reg, sreg, offset) - const char *label; - unsigned reg; - unsigned sreg; - long offset; +reg_save (const char *label, unsigned int reg, unsigned int sreg, HOST_WIDE_INT offset) { dw_cfi_ref cfi = new_cfi (); @@ -784,7 +825,7 @@ reg_save (label, reg, sreg, offset) DWARF_CIE_DATA_ALIGNMENT, there is either a bug in the definition of DWARF_CIE_DATA_ALIGNMENT, or a bug in the machine description. */ - long check_offset = offset / DWARF_CIE_DATA_ALIGNMENT; + HOST_WIDE_INT check_offset = offset / DWARF_CIE_DATA_ALIGNMENT; if (check_offset * DWARF_CIE_DATA_ALIGNMENT != offset) abort (); @@ -816,8 +857,7 @@ reg_save (label, reg, sreg, offset) assuming 0(cfa)) and what registers are in the window. */ void -dwarf2out_window_save (label) - const char *label; +dwarf2out_window_save (const char *label) { dw_cfi_ref cfi = new_cfi (); @@ -829,9 +869,7 @@ dwarf2out_window_save (label) pushed onto the stack. */ void -dwarf2out_args_size (label, size) - const char *label; - long size; +dwarf2out_args_size (const char *label, HOST_WIDE_INT size) { dw_cfi_ref cfi; @@ -850,10 +888,7 @@ dwarf2out_args_size (label, size) number. LABEL and OFFSET are passed to reg_save. */ void -dwarf2out_reg_save (label, reg, offset) - const char *label; - unsigned reg; - long offset; +dwarf2out_reg_save (const char *label, unsigned int reg, HOST_WIDE_INT offset) { reg_save (label, DWARF_FRAME_REGNUM (reg), -1, offset); } @@ -862,9 +897,7 @@ dwarf2out_reg_save (label, reg, offset) LABEL and OFFSET are passed to reg_save. */ void -dwarf2out_return_save (label, offset) - const char *label; - long offset; +dwarf2out_return_save (const char *label, HOST_WIDE_INT offset) { reg_save (label, DWARF_FRAME_RETURN_COLUMN, -1, offset); } @@ -873,9 +906,7 @@ dwarf2out_return_save (label, offset) LABEL and SREG are passed to reg_save. */ void -dwarf2out_return_reg (label, sreg) - const char *label; - unsigned sreg; +dwarf2out_return_reg (const char *label, unsigned int sreg) { reg_save (label, DWARF_FRAME_RETURN_COLUMN, sreg, 0); } @@ -884,8 +915,7 @@ dwarf2out_return_reg (label, sreg) INCOMING_RETURN_ADDR_RTX. */ static void -initial_return_save (rtl) - rtx rtl; +initial_return_save (rtx rtl) { unsigned int reg = (unsigned int) -1; HOST_WIDE_INT offset = 0; @@ -945,9 +975,8 @@ initial_return_save (rtl) /* Given a SET, calculate the amount of stack adjustment it contains. */ -static long -stack_adjust_offset (pattern) - rtx pattern; +static HOST_WIDE_INT +stack_adjust_offset (rtx pattern) { rtx src = SET_SRC (pattern); rtx dest = SET_DEST (pattern); @@ -1022,13 +1051,19 @@ stack_adjust_offset (pattern) much extra space it needs to pop off the stack. */ static void -dwarf2out_stack_adjust (insn) - rtx insn; +dwarf2out_stack_adjust (rtx insn) { HOST_WIDE_INT offset; const char *label; int i; + /* Don't handle epilogues at all. Certainly it would be wrong to do so + with this function. Proper support would require all frame-related + insns to be marked, and to be able to handle saving state around + epilogues textually in the middle of the function. */ + if (prologue_epilogue_contains (insn) || sibcall_epilogue_contains (insn)) + return; + if (!flag_asynchronous_unwind_tables && GET_CODE (insn) == CALL_INSN) { /* Extract the size of the args from the CALL rtx itself. */ @@ -1093,27 +1128,28 @@ dwarf2out_stack_adjust (insn) dwarf2out_args_size (label, args_size); } +#endif + /* We delay emitting a register save until either (a) we reach the end of the prologue or (b) the register is clobbered. This clusters register saves so that there are fewer pc advances. */ -struct queued_reg_save +struct queued_reg_save GTY(()) { struct queued_reg_save *next; rtx reg; - long cfa_offset; + HOST_WIDE_INT cfa_offset; }; -static struct queued_reg_save *queued_reg_saves; +static GTY(()) struct queued_reg_save *queued_reg_saves; + +#if defined (DWARF2_DEBUGGING_INFO) || defined (DWARF2_UNWIND_INFO) static const char *last_reg_save_label; static void -queue_reg_save (label, reg, offset) - const char *label; - rtx reg; - long offset; +queue_reg_save (const char *label, rtx reg, HOST_WIDE_INT offset) { - struct queued_reg_save *q = (struct queued_reg_save *) xmalloc (sizeof (*q)); + struct queued_reg_save *q = ggc_alloc (sizeof (*q)); q->next = queued_reg_saves; q->reg = reg; @@ -1124,7 +1160,7 @@ queue_reg_save (label, reg, offset) } static void -flush_queued_reg_saves () +flush_queued_reg_saves (void) { struct queued_reg_save *q, *next; @@ -1132,7 +1168,6 @@ flush_queued_reg_saves () { dwarf2out_reg_save (last_reg_save_label, REGNO (q->reg), q->cfa_offset); next = q->next; - free (q); } queued_reg_saves = NULL; @@ -1140,8 +1175,7 @@ flush_queued_reg_saves () } static bool -clobbers_queued_reg_save (insn) - rtx insn; +clobbers_queued_reg_save (rtx insn) { struct queued_reg_save *q; @@ -1204,7 +1238,7 @@ static dw_cfa_location cfa_temp; to track stores to the stack via fp or a temp reg. Rules 1- 4: Setting a register's value to cfa.reg or an expression - with cfa.reg as the first operand changes the cfa.reg and its + with cfa.reg as the first operand changes the cfa.reg and its cfa.offset. Rule 1 and 4 also set cfa_temp.reg and cfa_temp.offset. @@ -1227,7 +1261,7 @@ static dw_cfa_location cfa_temp; Rule 1: (set <reg1> <reg2>:cfa.reg) effects: cfa.reg = <reg1> - cfa.offset unchanged + cfa.offset unchanged cfa_temp.reg = <reg1> cfa_temp.offset = cfa.offset @@ -1235,19 +1269,19 @@ static dw_cfa_location cfa_temp; (set sp ({minus,plus,losum} {sp,fp}:cfa.reg {<const_int>,<reg>:cfa_temp.reg})) effects: cfa.reg = sp if fp used - cfa.offset += {+/- <const_int>, cfa_temp.offset} if cfa.reg==sp + cfa.offset += {+/- <const_int>, cfa_temp.offset} if cfa.reg==sp cfa_store.offset += {+/- <const_int>, cfa_temp.offset} if cfa_store.reg==sp Rule 3: (set fp ({minus,plus,losum} <reg>:cfa.reg <const_int>)) effects: cfa.reg = fp - cfa_offset += +/- <const_int> + cfa_offset += +/- <const_int> Rule 4: (set <reg1> ({plus,losum} <reg2>:cfa.reg <const_int>)) constraints: <reg1> != fp - <reg1> != sp + <reg1> != sp effects: cfa.reg = <reg1> cfa_temp.reg = <reg1> cfa_temp.offset = cfa.offset @@ -1255,14 +1289,14 @@ static dw_cfa_location cfa_temp; Rule 5: (set <reg1> (plus <reg2>:cfa_temp.reg sp:cfa.reg)) constraints: <reg1> != fp - <reg1> != sp + <reg1> != sp effects: cfa_store.reg = <reg1> - cfa_store.offset = cfa.offset - cfa_temp.offset + cfa_store.offset = cfa.offset - cfa_temp.offset Rule 6: (set <reg> <const_int>) effects: cfa_temp.reg = <reg> - cfa_temp.offset = <const_int> + cfa_temp.offset = <const_int> Rule 7: (set <reg1>:cfa_temp.reg (ior <reg2>:cfa_temp.reg <const_int>)) @@ -1276,7 +1310,7 @@ static dw_cfa_location cfa_temp; Rule 9: (set <reg> (lo_sum <exp> <const_int>)) effects: cfa_temp.reg = <reg> - cfa_temp.offset = <const_int> + cfa_temp.offset = <const_int> Rule 10: (set (mem (pre_modify sp:cfa_store (???? <reg1> <const_int>))) <reg2>) @@ -1311,9 +1345,7 @@ static dw_cfa_location cfa_temp; cfa_temp.offset -= mode_size(mem) */ static void -dwarf2out_frame_debug_expr (expr, label) - rtx expr; - const char *label; +dwarf2out_frame_debug_expr (rtx expr, const char *label) { rtx src, dest; HOST_WIDE_INT offset; @@ -1348,7 +1380,7 @@ dwarf2out_frame_debug_expr (expr, label) case REG: /* Rule 1 */ /* Update the CFA rule wrt SP or FP. Make sure src is - relative to the current CFA register. */ + relative to the current CFA register. */ switch (GET_CODE (src)) { /* Setting FP from SP. */ @@ -1611,7 +1643,7 @@ dwarf2out_frame_debug_expr (expr, label) else { /* Otherwise, we'll need to look in the stack to - calculate the CFA. */ + calculate the CFA. */ rtx x = XEXP (dest, 0); if (GET_CODE (x) != REG) @@ -1641,8 +1673,7 @@ dwarf2out_frame_debug_expr (expr, label) register to the stack. If INSN is NULL_RTX, initialize our state. */ void -dwarf2out_frame_debug (insn) - rtx insn; +dwarf2out_frame_debug (rtx insn) { const char *label; rtx src; @@ -1685,32 +1716,111 @@ dwarf2out_frame_debug (insn) dwarf2out_frame_debug_expr (insn, label); } +#endif + +/* Describe for the GTY machinery what parts of dw_cfi_oprnd1 are used. */ +static enum dw_cfi_oprnd_type dw_cfi_oprnd1_desc + (enum dwarf_call_frame_info cfi); + +static enum dw_cfi_oprnd_type +dw_cfi_oprnd1_desc (enum dwarf_call_frame_info cfi) +{ + switch (cfi) + { + case DW_CFA_nop: + case DW_CFA_GNU_window_save: + return dw_cfi_oprnd_unused; + + case DW_CFA_set_loc: + case DW_CFA_advance_loc1: + case DW_CFA_advance_loc2: + case DW_CFA_advance_loc4: + case DW_CFA_MIPS_advance_loc8: + return dw_cfi_oprnd_addr; + + case DW_CFA_offset: + case DW_CFA_offset_extended: + case DW_CFA_def_cfa: + case DW_CFA_offset_extended_sf: + case DW_CFA_def_cfa_sf: + case DW_CFA_restore_extended: + case DW_CFA_undefined: + case DW_CFA_same_value: + case DW_CFA_def_cfa_register: + case DW_CFA_register: + return dw_cfi_oprnd_reg_num; + + case DW_CFA_def_cfa_offset: + case DW_CFA_GNU_args_size: + case DW_CFA_def_cfa_offset_sf: + return dw_cfi_oprnd_offset; + + case DW_CFA_def_cfa_expression: + case DW_CFA_expression: + return dw_cfi_oprnd_loc; + + default: + abort (); + } +} + +/* Describe for the GTY machinery what parts of dw_cfi_oprnd2 are used. */ +static enum dw_cfi_oprnd_type dw_cfi_oprnd2_desc + (enum dwarf_call_frame_info cfi); + +static enum dw_cfi_oprnd_type +dw_cfi_oprnd2_desc (enum dwarf_call_frame_info cfi) +{ + switch (cfi) + { + case DW_CFA_def_cfa: + case DW_CFA_def_cfa_sf: + case DW_CFA_offset: + case DW_CFA_offset_extended_sf: + case DW_CFA_offset_extended: + return dw_cfi_oprnd_offset; + + case DW_CFA_register: + return dw_cfi_oprnd_reg_num; + + default: + return dw_cfi_oprnd_unused; + } +} + +#if defined (DWARF2_DEBUGGING_INFO) || defined (DWARF2_UNWIND_INFO) + +/* Map register numbers held in the call frame info that gcc has + collected using DWARF_FRAME_REGNUM to those that should be output in + .debug_frame and .eh_frame. */ +#ifndef DWARF2_FRAME_REG_OUT +#define DWARF2_FRAME_REG_OUT(REGNO, FOR_EH) (REGNO) +#endif + /* Output a Call Frame Information opcode and its operand(s). */ static void -output_cfi (cfi, fde, for_eh) - dw_cfi_ref cfi; - dw_fde_ref fde; - int for_eh; +output_cfi (dw_cfi_ref cfi, dw_fde_ref fde, int for_eh) { + unsigned long r; if (cfi->dw_cfi_opc == DW_CFA_advance_loc) dw2_asm_output_data (1, (cfi->dw_cfi_opc | (cfi->dw_cfi_oprnd1.dw_cfi_offset & 0x3f)), - "DW_CFA_advance_loc 0x%lx", + "DW_CFA_advance_loc " HOST_WIDE_INT_PRINT_HEX, cfi->dw_cfi_oprnd1.dw_cfi_offset); else if (cfi->dw_cfi_opc == DW_CFA_offset) { - dw2_asm_output_data (1, (cfi->dw_cfi_opc - | (cfi->dw_cfi_oprnd1.dw_cfi_reg_num & 0x3f)), - "DW_CFA_offset, column 0x%lx", - cfi->dw_cfi_oprnd1.dw_cfi_reg_num); + r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, for_eh); + dw2_asm_output_data (1, (cfi->dw_cfi_opc | (r & 0x3f)), + "DW_CFA_offset, column 0x%lx", r); dw2_asm_output_data_uleb128 (cfi->dw_cfi_oprnd2.dw_cfi_offset, NULL); } else if (cfi->dw_cfi_opc == DW_CFA_restore) - dw2_asm_output_data (1, (cfi->dw_cfi_opc - | (cfi->dw_cfi_oprnd1.dw_cfi_reg_num & 0x3f)), - "DW_CFA_restore, column 0x%lx", - cfi->dw_cfi_oprnd1.dw_cfi_reg_num); + { + r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, for_eh); + dw2_asm_output_data (1, (cfi->dw_cfi_opc | (r & 0x3f)), + "DW_CFA_restore, column 0x%lx", r); + } else { dw2_asm_output_data (1, cfi->dw_cfi_opc, @@ -1755,15 +1865,15 @@ output_cfi (cfi, fde, for_eh) case DW_CFA_offset_extended: case DW_CFA_def_cfa: - dw2_asm_output_data_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, - NULL); + r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, for_eh); + dw2_asm_output_data_uleb128 (r, NULL); dw2_asm_output_data_uleb128 (cfi->dw_cfi_oprnd2.dw_cfi_offset, NULL); break; case DW_CFA_offset_extended_sf: case DW_CFA_def_cfa_sf: - dw2_asm_output_data_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, - NULL); + r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, for_eh); + dw2_asm_output_data_uleb128 (r, NULL); dw2_asm_output_data_sleb128 (cfi->dw_cfi_oprnd2.dw_cfi_offset, NULL); break; @@ -1771,15 +1881,15 @@ output_cfi (cfi, fde, for_eh) case DW_CFA_undefined: case DW_CFA_same_value: case DW_CFA_def_cfa_register: - dw2_asm_output_data_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, - NULL); + r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, for_eh); + dw2_asm_output_data_uleb128 (r, NULL); break; case DW_CFA_register: - dw2_asm_output_data_uleb128 (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, - NULL); - dw2_asm_output_data_uleb128 (cfi->dw_cfi_oprnd2.dw_cfi_reg_num, - NULL); + r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, for_eh); + dw2_asm_output_data_uleb128 (r, NULL); + r = DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd2.dw_cfi_reg_num, for_eh); + dw2_asm_output_data_uleb128 (r, NULL); break; case DW_CFA_def_cfa_offset: @@ -1809,13 +1919,12 @@ output_cfi (cfi, fde, for_eh) } } -/* Output the call frame information used to used to record information +/* Output the call frame information used to record information that relates to calculating the frame pointer, and records the location of saved registers. */ static void -output_call_frame_info (for_eh) - int for_eh; +output_call_frame_info (int for_eh) { unsigned int i; dw_fde_ref fde; @@ -1843,7 +1952,8 @@ output_call_frame_info (for_eh) for (i = 0; i < fde_table_in_use; i++) if (fde_table[i].uses_eh_lsda) any_eh_needed = any_lsda_needed = true; - else if (! fde_table[i].nothrow) + else if (! fde_table[i].nothrow + && ! fde_table[i].all_throwers_are_sibcalls) any_eh_needed = true; if (! any_eh_needed) @@ -1885,7 +1995,7 @@ output_call_frame_info (for_eh) /* Augmentation: z Indicates that a uleb128 is present to size the - augmentation section. + augmentation section. L Indicates the encoding (and thus presence) of an LSDA pointer in the FDE augmentation. R Indicates a non-default pointer encoding for @@ -1987,7 +2097,7 @@ output_call_frame_info (for_eh) && !fde->uses_eh_lsda) continue; - ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, FDE_LABEL, for_eh + i * 2); + (*targetm.asm_out.internal_label) (asm_out_file, FDE_LABEL, for_eh + i * 2); ASM_GENERATE_INTERNAL_LABEL (l1, FDE_AFTER_SIZE_LABEL, for_eh + i * 2); ASM_GENERATE_INTERNAL_LABEL (l2, FDE_END_LABEL, for_eh + i * 2); dw2_asm_output_delta (for_eh ? 4 : DWARF_OFFSET_SIZE, l2, l1, @@ -2040,13 +2150,13 @@ output_call_frame_info (for_eh) dw2_asm_output_data_uleb128 (size, "Augmentation size"); if (fde->uses_eh_lsda) - { - ASM_GENERATE_INTERNAL_LABEL (l1, "LLSDA", + { + ASM_GENERATE_INTERNAL_LABEL (l1, "LLSDA", fde->funcdef_number); - dw2_asm_output_encoded_addr_rtx ( + dw2_asm_output_encoded_addr_rtx ( lsda_encoding, gen_rtx_SYMBOL_REF (Pmode, l1), - "Language Specific Data Area"); - } + "Language Specific Data Area"); + } else { if (lsda_encoding == DW_EH_PE_aligned) @@ -2068,7 +2178,7 @@ output_call_frame_info (for_eh) /* Pad the FDE out to an address sized boundary. */ ASM_OUTPUT_ALIGN (asm_out_file, - floor_log2 ((for_eh ? PTR_SIZE : DWARF2_ADDR_SIZE))); + floor_log2 ((for_eh ? PTR_SIZE : DWARF2_ADDR_SIZE))); ASM_OUTPUT_LABEL (asm_out_file, l2); } @@ -2089,9 +2199,8 @@ output_call_frame_info (for_eh) the prologue. */ void -dwarf2out_begin_prologue (line, file) - unsigned int line ATTRIBUTE_UNUSED; - const char *file ATTRIBUTE_UNUSED; +dwarf2out_begin_prologue (unsigned int line ATTRIBUTE_UNUSED, + const char *file ATTRIBUTE_UNUSED) { char label[MAX_ARTIFICIAL_LABEL_BYTES]; dw_fde_ref fde; @@ -2127,9 +2236,10 @@ dwarf2out_begin_prologue (line, file) if (fde_table_in_use == fde_table_allocated) { fde_table_allocated += FDE_TABLE_INCREMENT; - fde_table - = (dw_fde_ref) xrealloc (fde_table, - fde_table_allocated * sizeof (dw_fde_node)); + fde_table = ggc_realloc (fde_table, + fde_table_allocated * sizeof (dw_fde_node)); + memset (fde_table + fde_table_in_use, 0, + FDE_TABLE_INCREMENT * sizeof (dw_fde_node)); } /* Record the FDE associated with this function. */ @@ -2161,9 +2271,8 @@ dwarf2out_begin_prologue (line, file) been generated. */ void -dwarf2out_end_epilogue (line, file) - unsigned int line ATTRIBUTE_UNUSED; - const char *file ATTRIBUTE_UNUSED; +dwarf2out_end_epilogue (unsigned int line ATTRIBUTE_UNUSED, + const char *file ATTRIBUTE_UNUSED) { dw_fde_ref fde; char label[MAX_ARTIFICIAL_LABEL_BYTES]; @@ -2178,10 +2287,10 @@ dwarf2out_end_epilogue (line, file) } void -dwarf2out_frame_init () +dwarf2out_frame_init (void) { /* Allocate the initial hunk of the fde_table. */ - fde_table = (dw_fde_ref) xcalloc (FDE_TABLE_INCREMENT, sizeof (dw_fde_node)); + fde_table = ggc_alloc_cleared (FDE_TABLE_INCREMENT * sizeof (dw_fde_node)); fde_table_allocated = FDE_TABLE_INCREMENT; fde_table_in_use = 0; @@ -2196,7 +2305,7 @@ dwarf2out_frame_init () } void -dwarf2out_frame_finish () +dwarf2out_frame_finish (void) { /* Output call frame information. */ if (write_symbols == DWARF2_DEBUG || write_symbols == VMS_AND_DWARF2_DEBUG) @@ -2205,6 +2314,7 @@ dwarf2out_frame_finish () if (! USING_SJLJ_EXCEPTIONS && (flag_unwind_tables || flag_exceptions)) output_call_frame_info (1); } +#endif /* And now, the subset of the debugging information support code necessary for emitting location expressions. */ @@ -2223,7 +2333,7 @@ typedef struct dw_loc_list_struct *dw_loc_list_ref; can take on several forms. The forms that are used in this implementation are listed below. */ -typedef enum +enum dw_val_class { dw_val_class_addr, dw_val_class_offset, @@ -2233,69 +2343,69 @@ typedef enum dw_val_class_const, dw_val_class_unsigned_const, dw_val_class_long_long, - dw_val_class_float, + dw_val_class_vec, dw_val_class_flag, dw_val_class_die_ref, dw_val_class_fde_ref, dw_val_class_lbl_id, dw_val_class_lbl_offset, dw_val_class_str -} -dw_val_class; +}; /* Describe a double word constant value. */ /* ??? Every instance of long_long in the code really means CONST_DOUBLE. */ -typedef struct dw_long_long_struct +typedef struct dw_long_long_struct GTY(()) { unsigned long hi; unsigned long low; } dw_long_long_const; -/* Describe a floating point constant value. */ +/* Describe a floating point constant value, or a vector constant value. */ -typedef struct dw_fp_struct +typedef struct dw_vec_struct GTY(()) { - long *array; + unsigned char * GTY((length ("%h.length"))) array; unsigned length; + unsigned elt_size; } -dw_float_const; +dw_vec_const; /* The dw_val_node describes an attribute's value, as it is represented internally. */ -typedef struct dw_val_struct +typedef struct dw_val_struct GTY(()) { - dw_val_class val_class; - union + enum dw_val_class val_class; + union dw_val_struct_union { - rtx val_addr; - long unsigned val_offset; - dw_loc_list_ref val_loc_list; - dw_loc_descr_ref val_loc; - long int val_int; - long unsigned val_unsigned; - dw_long_long_const val_long_long; - dw_float_const val_float; - struct + rtx GTY ((tag ("dw_val_class_addr"))) val_addr; + unsigned HOST_WIDE_INT GTY ((tag ("dw_val_class_offset"))) val_offset; + dw_loc_list_ref GTY ((tag ("dw_val_class_loc_list"))) val_loc_list; + dw_loc_descr_ref GTY ((tag ("dw_val_class_loc"))) val_loc; + HOST_WIDE_INT GTY ((default (""))) val_int; + unsigned HOST_WIDE_INT GTY ((tag ("dw_val_class_unsigned_const"))) val_unsigned; + dw_long_long_const GTY ((tag ("dw_val_class_long_long"))) val_long_long; + dw_vec_const GTY ((tag ("dw_val_class_vec"))) val_vec; + struct dw_val_die_union { dw_die_ref die; int external; - } val_die_ref; - unsigned val_fde_index; - struct indirect_string_node *val_str; - char *val_lbl_id; - unsigned char val_flag; + } GTY ((tag ("dw_val_class_die_ref"))) val_die_ref; + unsigned GTY ((tag ("dw_val_class_fde_ref"))) val_fde_index; + struct indirect_string_node * GTY ((tag ("dw_val_class_str"))) val_str; + char * GTY ((tag ("dw_val_class_lbl_id"))) val_lbl_id; + unsigned char GTY ((tag ("dw_val_class_flag"))) val_flag; } - v; + GTY ((desc ("%1.val_class"))) v; } dw_val_node; /* Locations in memory are described using a sequence of stack machine operations. */ -typedef struct dw_loc_descr_struct +typedef struct dw_loc_descr_struct GTY(()) { dw_loc_descr_ref dw_loc_next; enum dwarf_location_atom dw_loc_opc; @@ -2308,7 +2418,7 @@ dw_loc_descr_node; /* Location lists are ranges + location descriptions for that range, so you can track variables that are in different places over their entire life. */ -typedef struct dw_loc_list_struct +typedef struct dw_loc_list_struct GTY(()) { dw_loc_list_ref dw_loc_next; const char *begin; /* Label for begin address of range */ @@ -2319,22 +2429,21 @@ typedef struct dw_loc_list_struct dw_loc_descr_ref expr; } dw_loc_list_node; -static const char *dwarf_stack_op_name PARAMS ((unsigned)); -static dw_loc_descr_ref new_loc_descr PARAMS ((enum dwarf_location_atom, - unsigned long, - unsigned long)); -static void add_loc_descr PARAMS ((dw_loc_descr_ref *, - dw_loc_descr_ref)); -static unsigned long size_of_loc_descr PARAMS ((dw_loc_descr_ref)); -static unsigned long size_of_locs PARAMS ((dw_loc_descr_ref)); -static void output_loc_operands PARAMS ((dw_loc_descr_ref)); -static void output_loc_sequence PARAMS ((dw_loc_descr_ref)); +#if defined (DWARF2_DEBUGGING_INFO) || defined (DWARF2_UNWIND_INFO) + +static const char *dwarf_stack_op_name (unsigned); +static dw_loc_descr_ref new_loc_descr (enum dwarf_location_atom, + unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT); +static void add_loc_descr (dw_loc_descr_ref *, dw_loc_descr_ref); +static unsigned long size_of_loc_descr (dw_loc_descr_ref); +static unsigned long size_of_locs (dw_loc_descr_ref); +static void output_loc_operands (dw_loc_descr_ref); +static void output_loc_sequence (dw_loc_descr_ref); /* Convert a DWARF stack opcode into its string name. */ static const char * -dwarf_stack_op_name (op) - unsigned op; +dwarf_stack_op_name (unsigned int op) { switch (op) { @@ -2649,15 +2758,10 @@ dwarf_stack_op_name (op) together to form more complicated location (address) descriptions. */ static inline dw_loc_descr_ref -new_loc_descr (op, oprnd1, oprnd2) - enum dwarf_location_atom op; - unsigned long oprnd1; - unsigned long oprnd2; +new_loc_descr (enum dwarf_location_atom op, unsigned HOST_WIDE_INT oprnd1, + unsigned HOST_WIDE_INT oprnd2) { - /* Use xcalloc here so we clear out all of the long_long constant in - the union. */ - dw_loc_descr_ref descr - = (dw_loc_descr_ref) xcalloc (1, sizeof (dw_loc_descr_node)); + dw_loc_descr_ref descr = ggc_alloc_cleared (sizeof (dw_loc_descr_node)); descr->dw_loc_opc = op; descr->dw_loc_oprnd1.val_class = dw_val_class_unsigned_const; @@ -2672,9 +2776,7 @@ new_loc_descr (op, oprnd1, oprnd2) /* Add a location description term to a location description expression. */ static inline void -add_loc_descr (list_head, descr) - dw_loc_descr_ref *list_head; - dw_loc_descr_ref descr; +add_loc_descr (dw_loc_descr_ref *list_head, dw_loc_descr_ref descr) { dw_loc_descr_ref *d; @@ -2688,8 +2790,7 @@ add_loc_descr (list_head, descr) /* Return the size of a location descriptor. */ static unsigned long -size_of_loc_descr (loc) - dw_loc_descr_ref loc; +size_of_loc_descr (dw_loc_descr_ref loc) { unsigned long size = 1; @@ -2801,8 +2902,7 @@ size_of_loc_descr (loc) /* Return the size of a series of location descriptors. */ static unsigned long -size_of_locs (loc) - dw_loc_descr_ref loc; +size_of_locs (dw_loc_descr_ref loc) { unsigned long size; @@ -2818,8 +2918,7 @@ size_of_locs (loc) /* Output location description stack opcode's operands (if any). */ static void -output_loc_operands (loc) - dw_loc_descr_ref loc; +output_loc_operands (dw_loc_descr_ref loc) { dw_val_ref val1 = &loc->dw_loc_oprnd1; dw_val_ref val2 = &loc->dw_loc_oprnd2; @@ -2868,9 +2967,9 @@ output_loc_operands (loc) case DW_OP_skip: case DW_OP_bra: /* We currently don't make any attempt to make sure these are - aligned properly like we do for the main unwind info, so - don't support emitting things larger than a byte if we're - only doing unwinding. */ + aligned properly like we do for the main unwind info, so + don't support emitting things larger than a byte if we're + only doing unwinding. */ abort (); #endif case DW_OP_const1u: @@ -2960,8 +3059,7 @@ output_loc_operands (loc) /* Output a sequence of location operations. */ static void -output_loc_sequence (loc) - dw_loc_descr_ref loc; +output_loc_sequence (dw_loc_descr_ref loc) { for (; loc != NULL; loc = loc->dw_loc_next) { @@ -2978,8 +3076,7 @@ output_loc_sequence (loc) description based on a cfi entry with a complex address. */ static void -output_cfa_loc (cfi) - dw_cfi_ref cfi; +output_cfa_loc (dw_cfi_ref cfi) { dw_loc_descr_ref loc; unsigned long size; @@ -2997,8 +3094,7 @@ output_cfa_loc (cfi) a dw_cfa_location. */ static struct dw_loc_descr_struct * -build_cfa_loc (cfa) - dw_cfa_location *cfa; +build_cfa_loc (dw_cfa_location *cfa) { struct dw_loc_descr_struct *head, *tmp; @@ -3033,9 +3129,7 @@ build_cfa_loc (cfa) descriptor sequence. */ static void -get_cfa_from_loc_descr (cfa, loc) - dw_cfa_location *cfa; - struct dw_loc_descr_struct *loc; +get_cfa_from_loc_descr (dw_cfa_location *cfa, struct dw_loc_descr_struct *loc) { struct dw_loc_descr_struct *ptr; cfa->offset = 0; @@ -3143,22 +3237,19 @@ get_cfa_from_loc_descr (cfa, loc) #ifdef DWARF2_DEBUGGING_INFO /* .debug_str support. */ -static hashnode indirect_string_alloc PARAMS ((hash_table *)); -static int output_indirect_string PARAMS ((struct cpp_reader *, - hashnode, const PTR)); - - -static void dwarf2out_init PARAMS ((const char *)); -static void dwarf2out_finish PARAMS ((const char *)); -static void dwarf2out_define PARAMS ((unsigned int, const char *)); -static void dwarf2out_undef PARAMS ((unsigned int, const char *)); -static void dwarf2out_start_source_file PARAMS ((unsigned, const char *)); -static void dwarf2out_end_source_file PARAMS ((unsigned)); -static void dwarf2out_begin_block PARAMS ((unsigned, unsigned)); -static void dwarf2out_end_block PARAMS ((unsigned, unsigned)); -static bool dwarf2out_ignore_block PARAMS ((tree)); -static void dwarf2out_global_decl PARAMS ((tree)); -static void dwarf2out_abstract_function PARAMS ((tree)); +static int output_indirect_string (void **, void *); + +static void dwarf2out_init (const char *); +static void dwarf2out_finish (const char *); +static void dwarf2out_define (unsigned int, const char *); +static void dwarf2out_undef (unsigned int, const char *); +static void dwarf2out_start_source_file (unsigned, const char *); +static void dwarf2out_end_source_file (unsigned); +static void dwarf2out_begin_block (unsigned, unsigned); +static void dwarf2out_end_block (unsigned, unsigned); +static bool dwarf2out_ignore_block (tree); +static void dwarf2out_global_decl (tree); +static void dwarf2out_abstract_function (tree); /* The debug hooks structure. */ @@ -3186,8 +3277,10 @@ const struct gcc_debug_hooks dwarf2_debug_hooks = emitting the abstract description of inline functions until something tries to reference them. */ dwarf2out_abstract_function, /* outlining_inline_function */ - debug_nothing_rtx /* label */ + debug_nothing_rtx, /* label */ + debug_nothing_int /* handle_pch */ }; +#endif /* NOTE: In the comments in this file, many references are made to "Debugging Information Entries". This term is abbreviated as `DIE' @@ -3216,7 +3309,7 @@ typedef struct dw_ranges_struct *dw_ranges_ref; entry. The label gives the PC value associated with the line number entry. */ -typedef struct dw_line_info_struct +typedef struct dw_line_info_struct GTY(()) { unsigned long dw_file_num; unsigned long dw_line_num; @@ -3225,7 +3318,7 @@ dw_line_info_entry; /* Line information for functions in separate sections; each one gets its own sequence. */ -typedef struct dw_separate_line_info_struct +typedef struct dw_separate_line_info_struct GTY(()) { unsigned long dw_file_num; unsigned long dw_line_num; @@ -3237,7 +3330,7 @@ dw_separate_line_info_entry; a link to the next attribute in the chain, and an attribute value. Attributes are typically linked below the DIE they modify. */ -typedef struct dw_attr_struct +typedef struct dw_attr_struct GTY(()) { enum dwarf_attribute dw_attr; dw_attr_ref dw_attr_next; @@ -3247,7 +3340,7 @@ dw_attr_node; /* The Debugging Information Entry (DIE) structure */ -typedef struct die_struct +typedef struct die_struct GTY(()) { enum dwarf_tag die_tag; char *die_symbol; @@ -3255,6 +3348,7 @@ typedef struct die_struct dw_die_ref die_parent; dw_die_ref die_child; dw_die_ref die_sib; + dw_die_ref die_definition; /* ref from a specification to its definition */ dw_offset die_offset; unsigned long die_abbrev; int die_mark; @@ -3263,20 +3357,20 @@ die_node; /* The pubname structure */ -typedef struct pubname_struct +typedef struct pubname_struct GTY(()) { dw_die_ref die; char *name; } pubname_entry; -struct dw_ranges_struct +struct dw_ranges_struct GTY(()) { int block_num; }; /* The limbo die list structure. */ -typedef struct limbo_die_struct +typedef struct limbo_die_struct GTY(()) { dw_die_ref die; tree created_for; @@ -3314,21 +3408,24 @@ limbo_die_node; language, and compiler version. */ /* Fixed size portion of the DWARF compilation unit header. */ -#define DWARF_COMPILE_UNIT_HEADER_SIZE (2 * DWARF_OFFSET_SIZE + 3) +#define DWARF_COMPILE_UNIT_HEADER_SIZE \ + (DWARF_INITIAL_LENGTH_SIZE + DWARF_OFFSET_SIZE + 3) /* Fixed size portion of public names info. */ #define DWARF_PUBNAMES_HEADER_SIZE (2 * DWARF_OFFSET_SIZE + 2) /* Fixed size portion of the address range info. */ #define DWARF_ARANGES_HEADER_SIZE \ - (DWARF_ROUND (2 * DWARF_OFFSET_SIZE + 4, DWARF2_ADDR_SIZE * 2) \ - - DWARF_OFFSET_SIZE) + (DWARF_ROUND (DWARF_INITIAL_LENGTH_SIZE + DWARF_OFFSET_SIZE + 4, \ + DWARF2_ADDR_SIZE * 2) \ + - DWARF_INITIAL_LENGTH_SIZE) /* Size of padding portion in the address range info. It must be aligned to twice the pointer size. */ #define DWARF_ARANGES_PAD_SIZE \ - (DWARF_ROUND (2 * DWARF_OFFSET_SIZE + 4, DWARF2_ADDR_SIZE * 2) \ - - (2 * DWARF_OFFSET_SIZE + 4)) + (DWARF_ROUND (DWARF_INITIAL_LENGTH_SIZE + DWARF_OFFSET_SIZE + 4, \ + DWARF2_ADDR_SIZE * 2) \ + - (DWARF_INITIAL_LENGTH_SIZE + DWARF_OFFSET_SIZE + 4)) /* Use assembler line directives if available. */ #ifndef DWARF2_ASM_LINE_DEBUG_INFO @@ -3355,50 +3452,33 @@ limbo_die_node; is not made available by the GCC front-end. */ #define DWARF_LINE_DEFAULT_IS_STMT_START 1 +#ifdef DWARF2_DEBUGGING_INFO /* This location is used by calc_die_sizes() to keep track the offset of each DIE within the .debug_info section. */ static unsigned long next_die_offset; +#endif /* Record the root of the DIE's built for the current compilation unit. */ -static dw_die_ref comp_unit_die; - -/* We need special handling in dwarf2out_start_source_file if it is - first one. */ -static int is_main_source; +static GTY(()) dw_die_ref comp_unit_die; /* A list of DIEs with a NULL parent waiting to be relocated. */ -static limbo_die_node *limbo_die_list = 0; - -/* Structure used by lookup_filename to manage sets of filenames. */ -struct file_table -{ - char **table; - unsigned allocated; - unsigned in_use; - unsigned last_lookup_index; -}; - -/* Size (in elements) of increments by which we may expand the filename - table. */ -#define FILE_TABLE_INCREMENT 64 +static GTY(()) limbo_die_node *limbo_die_list; /* Filenames referenced by this compilation unit. */ -static struct file_table file_table; - -/* Local pointer to the name of the main input file. Initialized in - dwarf2out_init. */ -static const char *primary_filename; +static GTY(()) varray_type file_table; +static GTY(()) varray_type file_table_emitted; +static GTY(()) size_t file_table_last_lookup_index; /* 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 identifying each decl. */ -static dw_die_ref *decl_die_table; +static GTY((length ("decl_die_table_allocated"))) dw_die_ref *decl_die_table; /* Number of elements currently allocated for the decl_die_table. */ -static unsigned decl_die_table_allocated; +static GTY(()) unsigned decl_die_table_allocated; /* Number of elements in decl_die_table currently in use. */ -static unsigned decl_die_table_in_use; +static GTY(()) unsigned decl_die_table_in_use; /* Size (in elements) of increments by which we may expand the decl_die_table. */ @@ -3407,13 +3487,14 @@ static unsigned decl_die_table_in_use; /* A pointer to the base of a list of references to DIE's that are uniquely identified by their tag, presence/absence of children DIE's, and list of attribute/value pairs. */ -static dw_die_ref *abbrev_die_table; +static GTY((length ("abbrev_die_table_allocated"))) + dw_die_ref *abbrev_die_table; /* Number of elements currently allocated for abbrev_die_table. */ -static unsigned abbrev_die_table_allocated; +static GTY(()) unsigned abbrev_die_table_allocated; /* Number of elements in type_die_table currently in use. */ -static unsigned abbrev_die_table_in_use; +static GTY(()) unsigned abbrev_die_table_in_use; /* Size (in elements) of increments by which we may expand the abbrev_die_table. */ @@ -3421,23 +3502,25 @@ static unsigned abbrev_die_table_in_use; /* A pointer to the base of a table that contains line information for each source code line in .text in the compilation unit. */ -static dw_line_info_ref line_info_table; +static GTY((length ("line_info_table_allocated"))) + dw_line_info_ref line_info_table; /* Number of elements currently allocated for line_info_table. */ -static unsigned line_info_table_allocated; +static GTY(()) unsigned line_info_table_allocated; -/* Number of elements in separate_line_info_table currently in use. */ -static unsigned separate_line_info_table_in_use; +/* Number of elements in line_info_table currently in use. */ +static GTY(()) unsigned line_info_table_in_use; /* A pointer to the base of a table that contains line information for each source code line outside of .text in the compilation unit. */ -static dw_separate_line_info_ref separate_line_info_table; +static GTY ((length ("separate_line_info_table_allocated"))) + dw_separate_line_info_ref separate_line_info_table; /* Number of elements currently allocated for separate_line_info_table. */ -static unsigned separate_line_info_table_allocated; +static GTY(()) unsigned separate_line_info_table_allocated; -/* Number of elements in line_info_table currently in use. */ -static unsigned line_info_table_in_use; +/* Number of elements in separate_line_info_table currently in use. */ +static GTY(()) unsigned separate_line_info_table_in_use; /* Size (in elements) of increments by which we may expand the line_info_table. */ @@ -3445,312 +3528,302 @@ static unsigned line_info_table_in_use; /* A pointer to the base of a table that contains a list of publicly accessible names. */ -static pubname_ref pubname_table; +static GTY ((length ("pubname_table_allocated"))) pubname_ref pubname_table; /* Number of elements currently allocated for pubname_table. */ -static unsigned pubname_table_allocated; +static GTY(()) unsigned pubname_table_allocated; /* Number of elements in pubname_table currently in use. */ -static unsigned pubname_table_in_use; +static GTY(()) unsigned pubname_table_in_use; /* Size (in elements) of increments by which we may expand the pubname_table. */ #define PUBNAME_TABLE_INCREMENT 64 /* Array of dies for which we should generate .debug_arange info. */ -static dw_die_ref *arange_table; +static GTY((length ("arange_table_allocated"))) dw_die_ref *arange_table; /* Number of elements currently allocated for arange_table. */ -static unsigned arange_table_allocated; +static GTY(()) unsigned arange_table_allocated; /* Number of elements in arange_table currently in use. */ -static unsigned arange_table_in_use; +static GTY(()) unsigned arange_table_in_use; /* Size (in elements) of increments by which we may expand the arange_table. */ #define ARANGE_TABLE_INCREMENT 64 /* Array of dies for which we should generate .debug_ranges info. */ -static dw_ranges_ref ranges_table; +static GTY ((length ("ranges_table_allocated"))) dw_ranges_ref ranges_table; /* Number of elements currently allocated for ranges_table. */ -static unsigned ranges_table_allocated; +static GTY(()) unsigned ranges_table_allocated; /* Number of elements in ranges_table currently in use. */ -static unsigned ranges_table_in_use; +static GTY(()) unsigned ranges_table_in_use; /* Size (in elements) of increments by which we may expand the ranges_table. */ #define RANGES_TABLE_INCREMENT 64 /* Whether we have location lists that need outputting */ -static unsigned have_location_lists; +static GTY(()) unsigned have_location_lists; +#ifdef DWARF2_DEBUGGING_INFO /* Record whether the function being analyzed contains inlined functions. */ static int current_function_has_inlines; +#endif #if 0 && defined (MIPS_DEBUGGING_INFO) static int comp_unit_has_inlines; #endif +/* Number of file tables emitted in maybe_emit_file(). */ +static GTY(()) int emitcount = 0; + +/* Number of internal labels generated by gen_internal_sym(). */ +static GTY(()) int label_num; + +#ifdef DWARF2_DEBUGGING_INFO + /* Forward declarations for functions defined in this file. */ -static int is_pseudo_reg PARAMS ((rtx)); -static tree type_main_variant PARAMS ((tree)); -static int is_tagged_type PARAMS ((tree)); -static const char *dwarf_tag_name PARAMS ((unsigned)); -static const char *dwarf_attr_name PARAMS ((unsigned)); -static const char *dwarf_form_name PARAMS ((unsigned)); +static int is_pseudo_reg (rtx); +static tree type_main_variant (tree); +static int is_tagged_type (tree); +static const char *dwarf_tag_name (unsigned); +static const char *dwarf_attr_name (unsigned); +static const char *dwarf_form_name (unsigned); #if 0 -static const char *dwarf_type_encoding_name PARAMS ((unsigned)); +static const char *dwarf_type_encoding_name (unsigned); #endif -static tree decl_ultimate_origin PARAMS ((tree)); -static tree block_ultimate_origin PARAMS ((tree)); -static tree decl_class_context PARAMS ((tree)); -static void add_dwarf_attr PARAMS ((dw_die_ref, dw_attr_ref)); -static inline dw_val_class AT_class PARAMS ((dw_attr_ref)); -static void add_AT_flag PARAMS ((dw_die_ref, - enum dwarf_attribute, - unsigned)); -static inline unsigned AT_flag PARAMS ((dw_attr_ref)); -static void add_AT_int PARAMS ((dw_die_ref, - enum dwarf_attribute, long)); -static inline long int AT_int PARAMS ((dw_attr_ref)); -static void add_AT_unsigned PARAMS ((dw_die_ref, - enum dwarf_attribute, - unsigned long)); -static inline unsigned long AT_unsigned PARAMS ((dw_attr_ref)); -static void add_AT_long_long PARAMS ((dw_die_ref, - enum dwarf_attribute, - unsigned long, - unsigned long)); -static void add_AT_float PARAMS ((dw_die_ref, - enum dwarf_attribute, - unsigned, long *)); -static void add_AT_string PARAMS ((dw_die_ref, - enum dwarf_attribute, - const char *)); -static inline const char *AT_string PARAMS ((dw_attr_ref)); -static int AT_string_form PARAMS ((dw_attr_ref)); -static void add_AT_die_ref PARAMS ((dw_die_ref, - enum dwarf_attribute, - dw_die_ref)); -static inline dw_die_ref AT_ref PARAMS ((dw_attr_ref)); -static inline int AT_ref_external PARAMS ((dw_attr_ref)); -static inline void set_AT_ref_external PARAMS ((dw_attr_ref, int)); -static void add_AT_fde_ref PARAMS ((dw_die_ref, - enum dwarf_attribute, - unsigned)); -static void add_AT_loc PARAMS ((dw_die_ref, - enum dwarf_attribute, - dw_loc_descr_ref)); -static inline dw_loc_descr_ref AT_loc PARAMS ((dw_attr_ref)); -static void add_AT_loc_list PARAMS ((dw_die_ref, - enum dwarf_attribute, - dw_loc_list_ref)); -static inline dw_loc_list_ref AT_loc_list PARAMS ((dw_attr_ref)); -static void add_AT_addr PARAMS ((dw_die_ref, - enum dwarf_attribute, - rtx)); -static inline rtx AT_addr PARAMS ((dw_attr_ref)); -static void add_AT_lbl_id PARAMS ((dw_die_ref, - enum dwarf_attribute, - const char *)); -static void add_AT_lbl_offset PARAMS ((dw_die_ref, - enum dwarf_attribute, - const char *)); -static void add_AT_offset PARAMS ((dw_die_ref, - enum dwarf_attribute, - unsigned long)); -static void add_AT_range_list PARAMS ((dw_die_ref, - enum dwarf_attribute, - unsigned long)); -static inline const char *AT_lbl PARAMS ((dw_attr_ref)); -static dw_attr_ref get_AT PARAMS ((dw_die_ref, - enum dwarf_attribute)); -static const char *get_AT_low_pc PARAMS ((dw_die_ref)); -static const char *get_AT_hi_pc PARAMS ((dw_die_ref)); -static const char *get_AT_string PARAMS ((dw_die_ref, - enum dwarf_attribute)); -static int get_AT_flag PARAMS ((dw_die_ref, - enum dwarf_attribute)); -static unsigned get_AT_unsigned PARAMS ((dw_die_ref, - enum dwarf_attribute)); -static inline dw_die_ref get_AT_ref PARAMS ((dw_die_ref, - enum dwarf_attribute)); -static int is_c_family PARAMS ((void)); -static int is_cxx PARAMS ((void)); -static int is_java PARAMS ((void)); -static int is_fortran PARAMS ((void)); -static void remove_AT PARAMS ((dw_die_ref, - enum dwarf_attribute)); -static inline void free_die PARAMS ((dw_die_ref)); -static void remove_children PARAMS ((dw_die_ref)); -static void add_child_die PARAMS ((dw_die_ref, dw_die_ref)); -static dw_die_ref new_die PARAMS ((enum dwarf_tag, dw_die_ref, - tree)); -static dw_die_ref lookup_type_die PARAMS ((tree)); -static void equate_type_number_to_die PARAMS ((tree, dw_die_ref)); -static dw_die_ref lookup_decl_die PARAMS ((tree)); -static void equate_decl_number_to_die PARAMS ((tree, dw_die_ref)); -static void print_spaces PARAMS ((FILE *)); -static void print_die PARAMS ((dw_die_ref, FILE *)); -static void print_dwarf_line_table PARAMS ((FILE *)); -static void reverse_die_lists PARAMS ((dw_die_ref)); -static void reverse_all_dies PARAMS ((dw_die_ref)); -static dw_die_ref push_new_compile_unit PARAMS ((dw_die_ref, dw_die_ref)); -static dw_die_ref pop_compile_unit PARAMS ((dw_die_ref)); -static void loc_checksum PARAMS ((dw_loc_descr_ref, - struct md5_ctx *)); -static void attr_checksum PARAMS ((dw_attr_ref, - struct md5_ctx *, - int *)); -static void die_checksum PARAMS ((dw_die_ref, - struct md5_ctx *, - int *)); -static int same_loc_p PARAMS ((dw_loc_descr_ref, - dw_loc_descr_ref, int *)); -static int same_dw_val_p PARAMS ((dw_val_node *, dw_val_node *, - int *)); -static int same_attr_p PARAMS ((dw_attr_ref, dw_attr_ref, int *)); -static int same_die_p PARAMS ((dw_die_ref, dw_die_ref, int *)); -static int same_die_p_wrap PARAMS ((dw_die_ref, dw_die_ref)); -static void compute_section_prefix PARAMS ((dw_die_ref)); -static int is_type_die PARAMS ((dw_die_ref)); -static int is_comdat_die PARAMS ((dw_die_ref)); -static int is_symbol_die PARAMS ((dw_die_ref)); -static void assign_symbol_names PARAMS ((dw_die_ref)); -static void break_out_includes PARAMS ((dw_die_ref)); -static hashval_t htab_cu_hash PARAMS ((const void *)); -static int htab_cu_eq PARAMS ((const void *, const void *)); -static void htab_cu_del PARAMS ((void *)); -static int check_duplicate_cu PARAMS ((dw_die_ref, htab_t, unsigned *)); -static void record_comdat_symbol_number PARAMS ((dw_die_ref, htab_t, unsigned)); -static void add_sibling_attributes PARAMS ((dw_die_ref)); -static void build_abbrev_table PARAMS ((dw_die_ref)); -static void output_location_lists PARAMS ((dw_die_ref)); -static int constant_size PARAMS ((long unsigned)); -static unsigned long size_of_die PARAMS ((dw_die_ref)); -static void calc_die_sizes PARAMS ((dw_die_ref)); -static void mark_dies PARAMS ((dw_die_ref)); -static void unmark_dies PARAMS ((dw_die_ref)); -static void unmark_all_dies PARAMS ((dw_die_ref)); -static unsigned long size_of_pubnames PARAMS ((void)); -static unsigned long size_of_aranges PARAMS ((void)); -static enum dwarf_form value_format PARAMS ((dw_attr_ref)); -static void output_value_format PARAMS ((dw_attr_ref)); -static void output_abbrev_section PARAMS ((void)); -static void output_die_symbol PARAMS ((dw_die_ref)); -static void output_die PARAMS ((dw_die_ref)); -static void output_compilation_unit_header PARAMS ((void)); -static void output_comp_unit PARAMS ((dw_die_ref, int)); -static const char *dwarf2_name PARAMS ((tree, int)); -static void add_pubname PARAMS ((tree, dw_die_ref)); -static void output_pubnames PARAMS ((void)); -static void add_arange PARAMS ((tree, dw_die_ref)); -static void output_aranges PARAMS ((void)); -static unsigned int add_ranges PARAMS ((tree)); -static void output_ranges PARAMS ((void)); -static void output_line_info PARAMS ((void)); -static void output_file_names PARAMS ((void)); -static dw_die_ref base_type_die PARAMS ((tree)); -static tree root_type PARAMS ((tree)); -static int is_base_type PARAMS ((tree)); -static dw_die_ref modified_type_die PARAMS ((tree, int, int, dw_die_ref)); -static int type_is_enum PARAMS ((tree)); -static unsigned int reg_number PARAMS ((rtx)); -static dw_loc_descr_ref reg_loc_descriptor PARAMS ((rtx)); -static dw_loc_descr_ref int_loc_descriptor PARAMS ((HOST_WIDE_INT)); -static dw_loc_descr_ref based_loc_descr PARAMS ((unsigned, long)); -static int is_based_loc PARAMS ((rtx)); -static dw_loc_descr_ref mem_loc_descriptor PARAMS ((rtx, enum machine_mode mode)); -static dw_loc_descr_ref concat_loc_descriptor PARAMS ((rtx, rtx)); -static dw_loc_descr_ref loc_descriptor PARAMS ((rtx)); -static dw_loc_descr_ref loc_descriptor_from_tree PARAMS ((tree, int)); -static HOST_WIDE_INT ceiling PARAMS ((HOST_WIDE_INT, unsigned int)); -static tree field_type PARAMS ((tree)); -static unsigned int simple_type_align_in_bits PARAMS ((tree)); -static unsigned int simple_decl_align_in_bits PARAMS ((tree)); -static unsigned HOST_WIDE_INT simple_type_size_in_bits PARAMS ((tree)); -static HOST_WIDE_INT field_byte_offset PARAMS ((tree)); -static void add_AT_location_description PARAMS ((dw_die_ref, - enum dwarf_attribute, - dw_loc_descr_ref)); -static void add_data_member_location_attribute PARAMS ((dw_die_ref, tree)); -static void add_const_value_attribute PARAMS ((dw_die_ref, rtx)); -static rtx rtl_for_decl_location PARAMS ((tree)); -static void add_location_or_const_value_attribute PARAMS ((dw_die_ref, tree)); -static void tree_add_const_value_attribute PARAMS ((dw_die_ref, tree)); -static void add_name_attribute PARAMS ((dw_die_ref, const char *)); -static void add_bound_info PARAMS ((dw_die_ref, - enum dwarf_attribute, tree)); -static void add_subscript_info PARAMS ((dw_die_ref, tree)); -static void add_byte_size_attribute PARAMS ((dw_die_ref, tree)); -static void add_bit_offset_attribute PARAMS ((dw_die_ref, tree)); -static void add_bit_size_attribute PARAMS ((dw_die_ref, tree)); -static void add_prototyped_attribute PARAMS ((dw_die_ref, tree)); -static void add_abstract_origin_attribute PARAMS ((dw_die_ref, tree)); -static void add_pure_or_virtual_attribute PARAMS ((dw_die_ref, tree)); -static void add_src_coords_attributes PARAMS ((dw_die_ref, tree)); -static void add_name_and_src_coords_attributes PARAMS ((dw_die_ref, tree)); -static void push_decl_scope PARAMS ((tree)); -static void pop_decl_scope PARAMS ((void)); -static dw_die_ref scope_die_for PARAMS ((tree, dw_die_ref)); -static inline int local_scope_p PARAMS ((dw_die_ref)); -static inline int class_scope_p PARAMS ((dw_die_ref)); -static void add_type_attribute PARAMS ((dw_die_ref, tree, int, int, - dw_die_ref)); -static const char *type_tag PARAMS ((tree)); -static tree member_declared_type PARAMS ((tree)); +static tree decl_ultimate_origin (tree); +static tree block_ultimate_origin (tree); +static tree decl_class_context (tree); +static void add_dwarf_attr (dw_die_ref, dw_attr_ref); +static inline enum dw_val_class AT_class (dw_attr_ref); +static void add_AT_flag (dw_die_ref, enum dwarf_attribute, unsigned); +static inline unsigned AT_flag (dw_attr_ref); +static void add_AT_int (dw_die_ref, enum dwarf_attribute, HOST_WIDE_INT); +static inline HOST_WIDE_INT AT_int (dw_attr_ref); +static void add_AT_unsigned (dw_die_ref, enum dwarf_attribute, unsigned HOST_WIDE_INT); +static inline unsigned HOST_WIDE_INT AT_unsigned (dw_attr_ref); +static void add_AT_long_long (dw_die_ref, enum dwarf_attribute, unsigned long, + unsigned long); +static inline void add_AT_vec (dw_die_ref, enum dwarf_attribute, unsigned int, + unsigned int, unsigned char *); +static hashval_t debug_str_do_hash (const void *); +static int debug_str_eq (const void *, const void *); +static void add_AT_string (dw_die_ref, enum dwarf_attribute, const char *); +static inline const char *AT_string (dw_attr_ref); +static int AT_string_form (dw_attr_ref); +static void add_AT_die_ref (dw_die_ref, enum dwarf_attribute, dw_die_ref); +static void add_AT_specification (dw_die_ref, dw_die_ref); +static inline dw_die_ref AT_ref (dw_attr_ref); +static inline int AT_ref_external (dw_attr_ref); +static inline void set_AT_ref_external (dw_attr_ref, int); +static void add_AT_fde_ref (dw_die_ref, enum dwarf_attribute, unsigned); +static void add_AT_loc (dw_die_ref, enum dwarf_attribute, dw_loc_descr_ref); +static inline dw_loc_descr_ref AT_loc (dw_attr_ref); +static void add_AT_loc_list (dw_die_ref, enum dwarf_attribute, + dw_loc_list_ref); +static inline dw_loc_list_ref AT_loc_list (dw_attr_ref); +static void add_AT_addr (dw_die_ref, enum dwarf_attribute, rtx); +static inline rtx AT_addr (dw_attr_ref); +static void add_AT_lbl_id (dw_die_ref, enum dwarf_attribute, const char *); +static void add_AT_lbl_offset (dw_die_ref, enum dwarf_attribute, const char *); +static void add_AT_offset (dw_die_ref, enum dwarf_attribute, + unsigned HOST_WIDE_INT); +static void add_AT_range_list (dw_die_ref, enum dwarf_attribute, + unsigned long); +static inline const char *AT_lbl (dw_attr_ref); +static dw_attr_ref get_AT (dw_die_ref, enum dwarf_attribute); +static const char *get_AT_low_pc (dw_die_ref); +static const char *get_AT_hi_pc (dw_die_ref); +static const char *get_AT_string (dw_die_ref, enum dwarf_attribute); +static int get_AT_flag (dw_die_ref, enum dwarf_attribute); +static unsigned get_AT_unsigned (dw_die_ref, enum dwarf_attribute); +static inline dw_die_ref get_AT_ref (dw_die_ref, enum dwarf_attribute); +static bool is_c_family (void); +static bool is_cxx (void); +static bool is_java (void); +static bool is_fortran (void); +static bool is_ada (void); +static void remove_AT (dw_die_ref, enum dwarf_attribute); +static inline void free_die (dw_die_ref); +static void remove_children (dw_die_ref); +static void add_child_die (dw_die_ref, dw_die_ref); +static dw_die_ref new_die (enum dwarf_tag, dw_die_ref, tree); +static dw_die_ref lookup_type_die (tree); +static void equate_type_number_to_die (tree, dw_die_ref); +static dw_die_ref lookup_decl_die (tree); +static void equate_decl_number_to_die (tree, dw_die_ref); +static void print_spaces (FILE *); +static void print_die (dw_die_ref, FILE *); +static void print_dwarf_line_table (FILE *); +static void reverse_die_lists (dw_die_ref); +static void reverse_all_dies (dw_die_ref); +static dw_die_ref push_new_compile_unit (dw_die_ref, dw_die_ref); +static dw_die_ref pop_compile_unit (dw_die_ref); +static void loc_checksum (dw_loc_descr_ref, struct md5_ctx *); +static void attr_checksum (dw_attr_ref, struct md5_ctx *, int *); +static void die_checksum (dw_die_ref, struct md5_ctx *, int *); +static int same_loc_p (dw_loc_descr_ref, dw_loc_descr_ref, int *); +static int same_dw_val_p (dw_val_node *, dw_val_node *, int *); +static int same_attr_p (dw_attr_ref, dw_attr_ref, int *); +static int same_die_p (dw_die_ref, dw_die_ref, int *); +static int same_die_p_wrap (dw_die_ref, dw_die_ref); +static void compute_section_prefix (dw_die_ref); +static int is_type_die (dw_die_ref); +static int is_comdat_die (dw_die_ref); +static int is_symbol_die (dw_die_ref); +static void assign_symbol_names (dw_die_ref); +static void break_out_includes (dw_die_ref); +static hashval_t htab_cu_hash (const void *); +static int htab_cu_eq (const void *, const void *); +static void htab_cu_del (void *); +static int check_duplicate_cu (dw_die_ref, htab_t, unsigned *); +static void record_comdat_symbol_number (dw_die_ref, htab_t, unsigned); +static void add_sibling_attributes (dw_die_ref); +static void build_abbrev_table (dw_die_ref); +static void output_location_lists (dw_die_ref); +static int constant_size (long unsigned); +static unsigned long size_of_die (dw_die_ref); +static void calc_die_sizes (dw_die_ref); +static void mark_dies (dw_die_ref); +static void unmark_dies (dw_die_ref); +static void unmark_all_dies (dw_die_ref); +static unsigned long size_of_pubnames (void); +static unsigned long size_of_aranges (void); +static enum dwarf_form value_format (dw_attr_ref); +static void output_value_format (dw_attr_ref); +static void output_abbrev_section (void); +static void output_die_symbol (dw_die_ref); +static void output_die (dw_die_ref); +static void output_compilation_unit_header (void); +static void output_comp_unit (dw_die_ref, int); +static const char *dwarf2_name (tree, int); +static void add_pubname (tree, dw_die_ref); +static void output_pubnames (void); +static void add_arange (tree, dw_die_ref); +static void output_aranges (void); +static unsigned int add_ranges (tree); +static void output_ranges (void); +static void output_line_info (void); +static void output_file_names (void); +static dw_die_ref base_type_die (tree); +static tree root_type (tree); +static int is_base_type (tree); +static bool is_subrange_type (tree); +static dw_die_ref subrange_type_die (tree, dw_die_ref); +static dw_die_ref modified_type_die (tree, int, int, dw_die_ref); +static int type_is_enum (tree); +static unsigned int dbx_reg_number (rtx); +static dw_loc_descr_ref reg_loc_descriptor (rtx); +static dw_loc_descr_ref one_reg_loc_descriptor (unsigned int); +static dw_loc_descr_ref multiple_reg_loc_descriptor (rtx, rtx); +static dw_loc_descr_ref int_loc_descriptor (HOST_WIDE_INT); +static dw_loc_descr_ref based_loc_descr (unsigned, HOST_WIDE_INT); +static int is_based_loc (rtx); +static dw_loc_descr_ref mem_loc_descriptor (rtx, enum machine_mode mode); +static dw_loc_descr_ref concat_loc_descriptor (rtx, rtx); +static dw_loc_descr_ref loc_descriptor (rtx); +static dw_loc_descr_ref loc_descriptor_from_tree (tree, int); +static HOST_WIDE_INT ceiling (HOST_WIDE_INT, unsigned int); +static tree field_type (tree); +static unsigned int simple_type_align_in_bits (tree); +static unsigned int simple_decl_align_in_bits (tree); +static unsigned HOST_WIDE_INT simple_type_size_in_bits (tree); +static HOST_WIDE_INT field_byte_offset (tree); +static void add_AT_location_description (dw_die_ref, enum dwarf_attribute, + dw_loc_descr_ref); +static void add_data_member_location_attribute (dw_die_ref, tree); +static void add_const_value_attribute (dw_die_ref, rtx); +static void insert_int (HOST_WIDE_INT, unsigned, unsigned char *); +static HOST_WIDE_INT extract_int (const unsigned char *, unsigned); +static void insert_float (rtx, unsigned char *); +static rtx rtl_for_decl_location (tree); +static void add_location_or_const_value_attribute (dw_die_ref, tree); +static void tree_add_const_value_attribute (dw_die_ref, tree); +static void add_name_attribute (dw_die_ref, const char *); +static void add_comp_dir_attribute (dw_die_ref); +static void add_bound_info (dw_die_ref, enum dwarf_attribute, tree); +static void add_subscript_info (dw_die_ref, tree); +static void add_byte_size_attribute (dw_die_ref, tree); +static void add_bit_offset_attribute (dw_die_ref, tree); +static void add_bit_size_attribute (dw_die_ref, tree); +static void add_prototyped_attribute (dw_die_ref, tree); +static void add_abstract_origin_attribute (dw_die_ref, tree); +static void add_pure_or_virtual_attribute (dw_die_ref, tree); +static void add_src_coords_attributes (dw_die_ref, tree); +static void add_name_and_src_coords_attributes (dw_die_ref, tree); +static void push_decl_scope (tree); +static void pop_decl_scope (void); +static dw_die_ref scope_die_for (tree, dw_die_ref); +static inline int local_scope_p (dw_die_ref); +static inline int class_or_namespace_scope_p (dw_die_ref); +static void add_type_attribute (dw_die_ref, tree, int, int, dw_die_ref); +static const char *type_tag (tree); +static tree member_declared_type (tree); #if 0 -static const char *decl_start_label PARAMS ((tree)); +static const char *decl_start_label (tree); #endif -static void gen_array_type_die PARAMS ((tree, dw_die_ref)); -static void gen_set_type_die PARAMS ((tree, dw_die_ref)); +static void gen_array_type_die (tree, dw_die_ref); +static void gen_set_type_die (tree, dw_die_ref); #if 0 -static void gen_entry_point_die PARAMS ((tree, dw_die_ref)); +static void gen_entry_point_die (tree, dw_die_ref); #endif -static void gen_inlined_enumeration_type_die PARAMS ((tree, dw_die_ref)); -static void gen_inlined_structure_type_die PARAMS ((tree, dw_die_ref)); -static void gen_inlined_union_type_die PARAMS ((tree, dw_die_ref)); -static void gen_enumeration_type_die PARAMS ((tree, dw_die_ref)); -static dw_die_ref gen_formal_parameter_die PARAMS ((tree, dw_die_ref)); -static void gen_unspecified_parameters_die PARAMS ((tree, dw_die_ref)); -static void gen_formal_types_die PARAMS ((tree, dw_die_ref)); -static void gen_subprogram_die PARAMS ((tree, dw_die_ref)); -static void gen_variable_die PARAMS ((tree, dw_die_ref)); -static void gen_label_die PARAMS ((tree, dw_die_ref)); -static void gen_lexical_block_die PARAMS ((tree, dw_die_ref, int)); -static void gen_inlined_subroutine_die PARAMS ((tree, dw_die_ref, int)); -static void gen_field_die PARAMS ((tree, dw_die_ref)); -static void gen_ptr_to_mbr_type_die PARAMS ((tree, dw_die_ref)); -static dw_die_ref gen_compile_unit_die PARAMS ((const char *)); -static void gen_string_type_die PARAMS ((tree, dw_die_ref)); -static void gen_inheritance_die PARAMS ((tree, dw_die_ref)); -static void gen_member_die PARAMS ((tree, dw_die_ref)); -static void gen_struct_or_union_type_die PARAMS ((tree, dw_die_ref)); -static void gen_subroutine_type_die PARAMS ((tree, dw_die_ref)); -static void gen_typedef_die PARAMS ((tree, dw_die_ref)); -static void gen_type_die PARAMS ((tree, dw_die_ref)); -static void gen_tagged_type_instantiation_die PARAMS ((tree, dw_die_ref)); -static void gen_block_die PARAMS ((tree, dw_die_ref, int)); -static void decls_for_scope PARAMS ((tree, dw_die_ref, int)); -static int is_redundant_typedef PARAMS ((tree)); -static void gen_decl_die PARAMS ((tree, dw_die_ref)); -static unsigned lookup_filename PARAMS ((const char *)); -static void init_file_table PARAMS ((void)); -static void retry_incomplete_types PARAMS ((void)); -static void gen_type_die_for_member PARAMS ((tree, tree, dw_die_ref)); -static void splice_child_die PARAMS ((dw_die_ref, dw_die_ref)); -static int file_info_cmp PARAMS ((const void *, const void *)); -static dw_loc_list_ref new_loc_list PARAMS ((dw_loc_descr_ref, - const char *, const char *, - const char *, unsigned)); -static void add_loc_descr_to_loc_list PARAMS ((dw_loc_list_ref *, - dw_loc_descr_ref, - const char *, const char *, const char *)); -static void output_loc_list PARAMS ((dw_loc_list_ref)); -static char *gen_internal_sym PARAMS ((const char *)); -static void mark_limbo_die_list PARAMS ((void *)); +static void gen_inlined_enumeration_type_die (tree, dw_die_ref); +static void gen_inlined_structure_type_die (tree, dw_die_ref); +static void gen_inlined_union_type_die (tree, dw_die_ref); +static dw_die_ref gen_enumeration_type_die (tree, dw_die_ref); +static dw_die_ref gen_formal_parameter_die (tree, dw_die_ref); +static void gen_unspecified_parameters_die (tree, dw_die_ref); +static void gen_formal_types_die (tree, dw_die_ref); +static void gen_subprogram_die (tree, dw_die_ref); +static void gen_variable_die (tree, dw_die_ref); +static void gen_label_die (tree, dw_die_ref); +static void gen_lexical_block_die (tree, dw_die_ref, int); +static void gen_inlined_subroutine_die (tree, dw_die_ref, int); +static void gen_field_die (tree, dw_die_ref); +static void gen_ptr_to_mbr_type_die (tree, dw_die_ref); +static dw_die_ref gen_compile_unit_die (const char *); +static void gen_string_type_die (tree, dw_die_ref); +static void gen_inheritance_die (tree, tree, dw_die_ref); +static void gen_member_die (tree, dw_die_ref); +static void gen_struct_or_union_type_die (tree, dw_die_ref); +static void gen_subroutine_type_die (tree, dw_die_ref); +static void gen_typedef_die (tree, dw_die_ref); +static void gen_type_die (tree, dw_die_ref); +static void gen_tagged_type_instantiation_die (tree, dw_die_ref); +static void gen_block_die (tree, dw_die_ref, int); +static void decls_for_scope (tree, dw_die_ref, int); +static int is_redundant_typedef (tree); +static void gen_namespace_die (tree); +static void gen_decl_die (tree, dw_die_ref); +static dw_die_ref force_namespace_die (tree); +static dw_die_ref setup_namespace_context (tree, dw_die_ref); +static void declare_in_namespace (tree, dw_die_ref); +static unsigned lookup_filename (const char *); +static void init_file_table (void); +static void retry_incomplete_types (void); +static void gen_type_die_for_member (tree, tree, dw_die_ref); +static void splice_child_die (dw_die_ref, dw_die_ref); +static int file_info_cmp (const void *, const void *); +static dw_loc_list_ref new_loc_list (dw_loc_descr_ref, const char *, + const char *, const char *, unsigned); +static void add_loc_descr_to_loc_list (dw_loc_list_ref *, dw_loc_descr_ref, + const char *, const char *, + const char *); +static void output_loc_list (dw_loc_list_ref); +static char *gen_internal_sym (const char *); + +static void prune_unmark_dies (dw_die_ref); +static void prune_unused_types_mark (dw_die_ref, int); +static void prune_unused_types_walk (dw_die_ref); +static void prune_unused_types_walk_attribs (dw_die_ref); +static void prune_unused_types_prune (dw_die_ref); +static void prune_unused_types (void); +static int maybe_emit_file (int); /* Section names used to hold DWARF debugging information. */ #ifndef DEBUG_INFO_SECTION @@ -3787,12 +3860,10 @@ static void mark_limbo_die_list PARAMS ((void *)); #endif /* Section flags for .debug_str section. */ -#ifdef HAVE_GAS_SHF_MERGE #define DEBUG_STR_SECTION_FLAGS \ - (SECTION_DEBUG | SECTION_MERGE | SECTION_STRINGS | 1) -#else -#define DEBUG_STR_SECTION_FLAGS SECTION_DEBUG -#endif + (HAVE_GAS_SHF_MERGE && flag_merge_constants \ + ? SECTION_DEBUG | SECTION_MERGE | SECTION_STRINGS | 1 \ + : SECTION_DEBUG) /* Labels we insert at beginning sections we can reference instead of the section names themselves. */ @@ -3821,7 +3892,7 @@ static void mark_limbo_die_list PARAMS ((void *)); /* Definitions of defaults for formats and names of various special (artificial) labels which may be generated within this file (when the -g - options is used and DWARF_DEBUGGING_INFO is in effect. + options is used and DWARF2_DEBUGGING_INFO is in effect. If necessary, these may be overridden from within the tm.h file, but typically, overriding these defaults is unnecessary. */ @@ -3853,11 +3924,10 @@ static char ranges_section_label[2 * MAX_ARTIFICIAL_LABEL_BYTES]; /* We allow a language front-end to designate a function that is to be called to "demangle" any name before it it put into a DIE. */ -static const char *(*demangle_name_func) PARAMS ((const char *)); +static const char *(*demangle_name_func) (const char *); void -dwarf2out_set_demangle_name_func (func) - const char *(*func) PARAMS ((const char *)); +dwarf2out_set_demangle_name_func (const char *(*func) (const char *)) { demangle_name_func = func; } @@ -3865,8 +3935,7 @@ dwarf2out_set_demangle_name_func (func) /* Test if rtl node points to a pseudo register. */ static inline int -is_pseudo_reg (rtl) - rtx rtl; +is_pseudo_reg (rtx rtl) { return ((GET_CODE (rtl) == REG && REGNO (rtl) >= FIRST_PSEUDO_REGISTER) || (GET_CODE (rtl) == SUBREG @@ -3877,8 +3946,7 @@ is_pseudo_reg (rtl) removed. */ static inline tree -type_main_variant (type) - tree type; +type_main_variant (tree type) { type = TYPE_MAIN_VARIANT (type); @@ -3897,8 +3965,7 @@ type_main_variant (type) /* Return nonzero if the given type node represents a tagged type. */ static inline int -is_tagged_type (type) - tree type; +is_tagged_type (tree type) { enum tree_code code = TREE_CODE (type); @@ -3909,8 +3976,7 @@ is_tagged_type (type) /* Convert a DIE tag into its string name. */ static const char * -dwarf_tag_name (tag) - unsigned tag; +dwarf_tag_name (unsigned int tag) { switch (tag) { @@ -3992,6 +4058,8 @@ dwarf_tag_name (tag) return "DW_TAG_namelist"; case DW_TAG_namelist_item: return "DW_TAG_namelist_item"; + case DW_TAG_namespace: + return "DW_TAG_namespace"; case DW_TAG_packed_type: return "DW_TAG_packed_type"; case DW_TAG_subprogram: @@ -4030,8 +4098,7 @@ dwarf_tag_name (tag) /* Convert a DWARF attribute code into its string name. */ static const char * -dwarf_attr_name (attr) - unsigned attr; +dwarf_attr_name (unsigned int attr) { switch (attr) { @@ -4234,8 +4301,7 @@ dwarf_attr_name (attr) /* Convert a DWARF value form code into its string name. */ static const char * -dwarf_form_name (form) - unsigned form; +dwarf_form_name (unsigned int form) { switch (form) { @@ -4290,8 +4356,7 @@ dwarf_form_name (form) #if 0 static const char * -dwarf_type_encoding_name (enc) - unsigned enc; +dwarf_type_encoding_name (unsigned enc) { switch (enc) { @@ -4324,8 +4389,7 @@ dwarf_type_encoding_name (enc) given block. */ static tree -decl_ultimate_origin (decl) - tree decl; +decl_ultimate_origin (tree decl) { /* output_inline_function sets DECL_ABSTRACT_ORIGIN for all the nodes in the function to point to themselves; ignore that if @@ -4350,8 +4414,7 @@ decl_ultimate_origin (decl) given block. */ static tree -block_ultimate_origin (block) - tree block; +block_ultimate_origin (tree block) { tree immediate_origin = BLOCK_ABSTRACT_ORIGIN (block); @@ -4385,8 +4448,7 @@ block_ultimate_origin (block) parameter. */ static tree -decl_class_context (decl) - tree decl; +decl_class_context (tree decl) { tree context = NULL_TREE; @@ -4406,9 +4468,7 @@ decl_class_context (decl) addition order, and correct that in reverse_all_dies. */ static inline void -add_dwarf_attr (die, attr) - dw_die_ref die; - dw_attr_ref attr; +add_dwarf_attr (dw_die_ref die, dw_attr_ref attr) { if (die != NULL && attr != NULL) { @@ -4417,9 +4477,8 @@ add_dwarf_attr (die, attr) } } -static inline dw_val_class -AT_class (a) - dw_attr_ref a; +static inline enum dw_val_class +AT_class (dw_attr_ref a) { return a->dw_attr_val.val_class; } @@ -4427,12 +4486,9 @@ AT_class (a) /* Add a flag value attribute to a DIE. */ static inline void -add_AT_flag (die, attr_kind, flag) - dw_die_ref die; - enum dwarf_attribute attr_kind; - unsigned flag; +add_AT_flag (dw_die_ref die, enum dwarf_attribute attr_kind, unsigned int flag) { - dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); + dw_attr_ref attr = ggc_alloc (sizeof (dw_attr_node)); attr->dw_attr_next = NULL; attr->dw_attr = attr_kind; @@ -4442,8 +4498,7 @@ add_AT_flag (die, attr_kind, flag) } static inline unsigned -AT_flag (a) - dw_attr_ref a; +AT_flag (dw_attr_ref a) { if (a && AT_class (a) == dw_val_class_flag) return a->dw_attr_val.v.val_flag; @@ -4454,12 +4509,9 @@ AT_flag (a) /* Add a signed integer attribute value to a DIE. */ static inline void -add_AT_int (die, attr_kind, int_val) - dw_die_ref die; - enum dwarf_attribute attr_kind; - long int int_val; +add_AT_int (dw_die_ref die, enum dwarf_attribute attr_kind, HOST_WIDE_INT int_val) { - dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); + dw_attr_ref attr = ggc_alloc (sizeof (dw_attr_node)); attr->dw_attr_next = NULL; attr->dw_attr = attr_kind; @@ -4468,9 +4520,8 @@ add_AT_int (die, attr_kind, int_val) add_dwarf_attr (die, attr); } -static inline long int -AT_int (a) - dw_attr_ref a; +static inline HOST_WIDE_INT +AT_int (dw_attr_ref a) { if (a && AT_class (a) == dw_val_class_const) return a->dw_attr_val.v.val_int; @@ -4481,12 +4532,10 @@ AT_int (a) /* Add an unsigned integer attribute value to a DIE. */ static inline void -add_AT_unsigned (die, attr_kind, unsigned_val) - dw_die_ref die; - enum dwarf_attribute attr_kind; - unsigned long unsigned_val; +add_AT_unsigned (dw_die_ref die, enum dwarf_attribute attr_kind, + unsigned HOST_WIDE_INT unsigned_val) { - dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); + dw_attr_ref attr = ggc_alloc (sizeof (dw_attr_node)); attr->dw_attr_next = NULL; attr->dw_attr = attr_kind; @@ -4495,9 +4544,8 @@ add_AT_unsigned (die, attr_kind, unsigned_val) add_dwarf_attr (die, attr); } -static inline unsigned long -AT_unsigned (a) - dw_attr_ref a; +static inline unsigned HOST_WIDE_INT +AT_unsigned (dw_attr_ref a) { if (a && AT_class (a) == dw_val_class_unsigned_const) return a->dw_attr_val.v.val_unsigned; @@ -4508,13 +4556,10 @@ AT_unsigned (a) /* Add an unsigned double integer attribute value to a DIE. */ static inline void -add_AT_long_long (die, attr_kind, val_hi, val_low) - dw_die_ref die; - enum dwarf_attribute attr_kind; - unsigned long val_hi; - unsigned long val_low; +add_AT_long_long (dw_die_ref die, enum dwarf_attribute attr_kind, + long unsigned int val_hi, long unsigned int val_low) { - dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); + dw_attr_ref attr = ggc_alloc (sizeof (dw_attr_node)); attr->dw_attr_next = NULL; attr->dw_attr = attr_kind; @@ -4527,42 +4572,54 @@ add_AT_long_long (die, attr_kind, val_hi, val_low) /* Add a floating point attribute value to a DIE and return it. */ static inline void -add_AT_float (die, attr_kind, length, array) - dw_die_ref die; - enum dwarf_attribute attr_kind; - unsigned length; - long *array; +add_AT_vec (dw_die_ref die, enum dwarf_attribute attr_kind, + unsigned int length, unsigned int elt_size, unsigned char *array) { - dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); + dw_attr_ref attr = ggc_alloc (sizeof (dw_attr_node)); attr->dw_attr_next = NULL; attr->dw_attr = attr_kind; - attr->dw_attr_val.val_class = dw_val_class_float; - attr->dw_attr_val.v.val_float.length = length; - attr->dw_attr_val.v.val_float.array = array; + attr->dw_attr_val.val_class = dw_val_class_vec; + attr->dw_attr_val.v.val_vec.length = length; + attr->dw_attr_val.v.val_vec.elt_size = elt_size; + attr->dw_attr_val.v.val_vec.array = array; add_dwarf_attr (die, attr); } +/* Hash and equality functions for debug_str_hash. */ + +static hashval_t +debug_str_do_hash (const void *x) +{ + return htab_hash_string (((const struct indirect_string_node *)x)->str); +} + +static int +debug_str_eq (const void *x1, const void *x2) +{ + return strcmp ((((const struct indirect_string_node *)x1)->str), + (const char *)x2) == 0; +} + /* Add a string attribute value to a DIE. */ static inline void -add_AT_string (die, attr_kind, str) - dw_die_ref die; - enum dwarf_attribute attr_kind; - const char *str; +add_AT_string (dw_die_ref die, enum dwarf_attribute attr_kind, const char *str) { - dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); + dw_attr_ref attr = ggc_alloc (sizeof (dw_attr_node)); struct indirect_string_node *node; + void **slot; if (! debug_str_hash) - { - debug_str_hash = ht_create (10); - debug_str_hash->alloc_node = indirect_string_alloc; - } - - node = (struct indirect_string_node *) - ht_lookup (debug_str_hash, (const unsigned char *) str, - strlen (str), HT_ALLOC); + debug_str_hash = htab_create_ggc (10, debug_str_do_hash, + debug_str_eq, NULL); + + slot = htab_find_slot_with_hash (debug_str_hash, str, + htab_hash_string (str), INSERT); + if (*slot == NULL) + *slot = ggc_alloc_cleared (sizeof (struct indirect_string_node)); + node = (struct indirect_string_node *) *slot; + node->str = ggc_strdup (str); node->refcount++; attr->dw_attr_next = NULL; @@ -4573,11 +4630,10 @@ add_AT_string (die, attr_kind, str) } static inline const char * -AT_string (a) - dw_attr_ref a; +AT_string (dw_attr_ref a) { if (a && AT_class (a) == dw_val_class_str) - return (const char *) HT_STR (&a->dw_attr_val.v.val_str->id); + return a->dw_attr_val.v.val_str->str; abort (); } @@ -4586,21 +4642,19 @@ AT_string (a) or out-of-line in .debug_str section. */ static int -AT_string_form (a) - dw_attr_ref a; +AT_string_form (dw_attr_ref a) { if (a && AT_class (a) == dw_val_class_str) { struct indirect_string_node *node; unsigned int len; - extern int const_labelno; char label[32]; node = a->dw_attr_val.v.val_str; if (node->form) return node->form; - len = HT_LEN (&node->id) + 1; + len = strlen (node->str) + 1; /* If the string is shorter or equal to the size of the reference, it is always better to put it inline. */ @@ -4614,8 +4668,8 @@ AT_string_form (a) && (len - DWARF_OFFSET_SIZE) * node->refcount <= len) return node->form = DW_FORM_string; - ASM_GENERATE_INTERNAL_LABEL (label, "LC", const_labelno); - ++const_labelno; + ASM_GENERATE_INTERNAL_LABEL (label, "LASF", dw2_string_counter); + ++dw2_string_counter; node->label = xstrdup (label); return node->form = DW_FORM_strp; @@ -4627,12 +4681,9 @@ AT_string_form (a) /* Add a DIE reference attribute value to a DIE. */ static inline void -add_AT_die_ref (die, attr_kind, targ_die) - dw_die_ref die; - enum dwarf_attribute attr_kind; - dw_die_ref targ_die; +add_AT_die_ref (dw_die_ref die, enum dwarf_attribute attr_kind, dw_die_ref targ_die) { - dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); + dw_attr_ref attr = ggc_alloc (sizeof (dw_attr_node)); attr->dw_attr_next = NULL; attr->dw_attr = attr_kind; @@ -4642,9 +4693,20 @@ add_AT_die_ref (die, attr_kind, targ_die) add_dwarf_attr (die, attr); } +/* Add an AT_specification attribute to a DIE, and also make the back + pointer from the specification to the definition. */ + +static inline void +add_AT_specification (dw_die_ref die, dw_die_ref targ_die) +{ + add_AT_die_ref (die, DW_AT_specification, targ_die); + if (targ_die->die_definition) + abort (); + targ_die->die_definition = die; +} + static inline dw_die_ref -AT_ref (a) - dw_attr_ref a; +AT_ref (dw_attr_ref a) { if (a && AT_class (a) == dw_val_class_die_ref) return a->dw_attr_val.v.val_die_ref.die; @@ -4653,8 +4715,7 @@ AT_ref (a) } static inline int -AT_ref_external (a) - dw_attr_ref a; +AT_ref_external (dw_attr_ref a) { if (a && AT_class (a) == dw_val_class_die_ref) return a->dw_attr_val.v.val_die_ref.external; @@ -4663,9 +4724,7 @@ AT_ref_external (a) } static inline void -set_AT_ref_external (a, i) - dw_attr_ref a; - int i; +set_AT_ref_external (dw_attr_ref a, int i) { if (a && AT_class (a) == dw_val_class_die_ref) a->dw_attr_val.v.val_die_ref.external = i; @@ -4676,12 +4735,9 @@ set_AT_ref_external (a, i) /* Add an FDE reference attribute value to a DIE. */ static inline void -add_AT_fde_ref (die, attr_kind, targ_fde) - dw_die_ref die; - enum dwarf_attribute attr_kind; - unsigned targ_fde; +add_AT_fde_ref (dw_die_ref die, enum dwarf_attribute attr_kind, unsigned int targ_fde) { - dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); + dw_attr_ref attr = ggc_alloc (sizeof (dw_attr_node)); attr->dw_attr_next = NULL; attr->dw_attr = attr_kind; @@ -4693,12 +4749,9 @@ add_AT_fde_ref (die, attr_kind, targ_fde) /* Add a location description attribute value to a DIE. */ static inline void -add_AT_loc (die, attr_kind, loc) - dw_die_ref die; - enum dwarf_attribute attr_kind; - dw_loc_descr_ref loc; +add_AT_loc (dw_die_ref die, enum dwarf_attribute attr_kind, dw_loc_descr_ref loc) { - dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); + dw_attr_ref attr = ggc_alloc (sizeof (dw_attr_node)); attr->dw_attr_next = NULL; attr->dw_attr = attr_kind; @@ -4708,8 +4761,7 @@ add_AT_loc (die, attr_kind, loc) } static inline dw_loc_descr_ref -AT_loc (a) - dw_attr_ref a; +AT_loc (dw_attr_ref a) { if (a && AT_class (a) == dw_val_class_loc) return a->dw_attr_val.v.val_loc; @@ -4718,12 +4770,9 @@ AT_loc (a) } static inline void -add_AT_loc_list (die, attr_kind, loc_list) - dw_die_ref die; - enum dwarf_attribute attr_kind; - dw_loc_list_ref loc_list; +add_AT_loc_list (dw_die_ref die, enum dwarf_attribute attr_kind, dw_loc_list_ref loc_list) { - dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); + dw_attr_ref attr = ggc_alloc (sizeof (dw_attr_node)); attr->dw_attr_next = NULL; attr->dw_attr = attr_kind; @@ -4734,8 +4783,7 @@ add_AT_loc_list (die, attr_kind, loc_list) } static inline dw_loc_list_ref -AT_loc_list (a) - dw_attr_ref a; +AT_loc_list (dw_attr_ref a) { if (a && AT_class (a) == dw_val_class_loc_list) return a->dw_attr_val.v.val_loc_list; @@ -4746,12 +4794,9 @@ AT_loc_list (a) /* Add an address constant attribute value to a DIE. */ static inline void -add_AT_addr (die, attr_kind, addr) - dw_die_ref die; - enum dwarf_attribute attr_kind; - rtx addr; +add_AT_addr (dw_die_ref die, enum dwarf_attribute attr_kind, rtx addr) { - dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); + dw_attr_ref attr = ggc_alloc (sizeof (dw_attr_node)); attr->dw_attr_next = NULL; attr->dw_attr = attr_kind; @@ -4761,8 +4806,7 @@ add_AT_addr (die, attr_kind, addr) } static inline rtx -AT_addr (a) - dw_attr_ref a; +AT_addr (dw_attr_ref a) { if (a && AT_class (a) == dw_val_class_addr) return a->dw_attr_val.v.val_addr; @@ -4773,12 +4817,9 @@ AT_addr (a) /* Add a label identifier attribute value to a DIE. */ static inline void -add_AT_lbl_id (die, attr_kind, lbl_id) - dw_die_ref die; - enum dwarf_attribute attr_kind; - const char *lbl_id; +add_AT_lbl_id (dw_die_ref die, enum dwarf_attribute attr_kind, const char *lbl_id) { - dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); + dw_attr_ref attr = ggc_alloc (sizeof (dw_attr_node)); attr->dw_attr_next = NULL; attr->dw_attr = attr_kind; @@ -4790,12 +4831,9 @@ add_AT_lbl_id (die, attr_kind, lbl_id) /* Add a section offset attribute value to a DIE. */ static inline void -add_AT_lbl_offset (die, attr_kind, label) - dw_die_ref die; - enum dwarf_attribute attr_kind; - const char *label; +add_AT_lbl_offset (dw_die_ref die, enum dwarf_attribute attr_kind, const char *label) { - dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); + dw_attr_ref attr = ggc_alloc (sizeof (dw_attr_node)); attr->dw_attr_next = NULL; attr->dw_attr = attr_kind; @@ -4807,12 +4845,10 @@ add_AT_lbl_offset (die, attr_kind, label) /* Add an offset attribute value to a DIE. */ static inline void -add_AT_offset (die, attr_kind, offset) - dw_die_ref die; - enum dwarf_attribute attr_kind; - unsigned long offset; +add_AT_offset (dw_die_ref die, enum dwarf_attribute attr_kind, + unsigned HOST_WIDE_INT offset) { - dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); + dw_attr_ref attr = ggc_alloc (sizeof (dw_attr_node)); attr->dw_attr_next = NULL; attr->dw_attr = attr_kind; @@ -4824,12 +4860,10 @@ add_AT_offset (die, attr_kind, offset) /* Add an range_list attribute value to a DIE. */ static void -add_AT_range_list (die, attr_kind, offset) - dw_die_ref die; - enum dwarf_attribute attr_kind; - unsigned long offset; +add_AT_range_list (dw_die_ref die, enum dwarf_attribute attr_kind, + long unsigned int offset) { - dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); + dw_attr_ref attr = ggc_alloc (sizeof (dw_attr_node)); attr->dw_attr_next = NULL; attr->dw_attr = attr_kind; @@ -4839,8 +4873,7 @@ add_AT_range_list (die, attr_kind, offset) } static inline const char * -AT_lbl (a) - dw_attr_ref a; +AT_lbl (dw_attr_ref a) { if (a && (AT_class (a) == dw_val_class_lbl_id || AT_class (a) == dw_val_class_lbl_offset)) @@ -4851,10 +4884,8 @@ AT_lbl (a) /* Get the attribute of type attr_kind. */ -static inline dw_attr_ref -get_AT (die, attr_kind) - dw_die_ref die; - enum dwarf_attribute attr_kind; +static dw_attr_ref +get_AT (dw_die_ref die, enum dwarf_attribute attr_kind) { dw_attr_ref a; dw_die_ref spec = NULL; @@ -4880,8 +4911,7 @@ get_AT (die, attr_kind) cannot be represented as an assembler label identifier. */ static inline const char * -get_AT_low_pc (die) - dw_die_ref die; +get_AT_low_pc (dw_die_ref die) { dw_attr_ref a = get_AT (die, DW_AT_low_pc); @@ -4893,8 +4923,7 @@ get_AT_low_pc (die) cannot be represented as an assembler label identifier. */ static inline const char * -get_AT_hi_pc (die) - dw_die_ref die; +get_AT_hi_pc (dw_die_ref die) { dw_attr_ref a = get_AT (die, DW_AT_high_pc); @@ -4905,9 +4934,7 @@ get_AT_hi_pc (die) NULL if it is not present. */ static inline const char * -get_AT_string (die, attr_kind) - dw_die_ref die; - enum dwarf_attribute attr_kind; +get_AT_string (dw_die_ref die, enum dwarf_attribute attr_kind) { dw_attr_ref a = get_AT (die, attr_kind); @@ -4918,9 +4945,7 @@ get_AT_string (die, attr_kind) if it is not present. */ static inline int -get_AT_flag (die, attr_kind) - dw_die_ref die; - enum dwarf_attribute attr_kind; +get_AT_flag (dw_die_ref die, enum dwarf_attribute attr_kind) { dw_attr_ref a = get_AT (die, attr_kind); @@ -4931,9 +4956,7 @@ get_AT_flag (die, attr_kind) if it is not present. */ static inline unsigned -get_AT_unsigned (die, attr_kind) - dw_die_ref die; - enum dwarf_attribute attr_kind; +get_AT_unsigned (dw_die_ref die, enum dwarf_attribute attr_kind) { dw_attr_ref a = get_AT (die, attr_kind); @@ -4941,83 +4964,78 @@ get_AT_unsigned (die, attr_kind) } static inline dw_die_ref -get_AT_ref (die, attr_kind) - dw_die_ref die; - enum dwarf_attribute attr_kind; +get_AT_ref (dw_die_ref die, enum dwarf_attribute attr_kind) { dw_attr_ref a = get_AT (die, attr_kind); return a ? AT_ref (a) : NULL; } -static inline int -is_c_family () +/* Return TRUE if the language is C or C++. */ + +static inline bool +is_c_family (void) { - unsigned lang = get_AT_unsigned (comp_unit_die, DW_AT_language); + unsigned int lang = get_AT_unsigned (comp_unit_die, DW_AT_language); return (lang == DW_LANG_C || lang == DW_LANG_C89 || lang == DW_LANG_C_plus_plus); } -static inline int -is_cxx () +/* Return TRUE if the language is C++. */ + +static inline bool +is_cxx (void) { return (get_AT_unsigned (comp_unit_die, DW_AT_language) == DW_LANG_C_plus_plus); } -static inline int -is_fortran () +/* Return TRUE if the language is Fortran. */ + +static inline bool +is_fortran (void) { - unsigned lang = get_AT_unsigned (comp_unit_die, DW_AT_language); + unsigned int lang = get_AT_unsigned (comp_unit_die, DW_AT_language); - return (lang == DW_LANG_Fortran77 || lang == DW_LANG_Fortran90); + return lang == DW_LANG_Fortran77 || lang == DW_LANG_Fortran90; } -static inline int -is_java () +/* Return TRUE if the language is Java. */ + +static inline bool +is_java (void) { - unsigned lang = get_AT_unsigned (comp_unit_die, DW_AT_language); + unsigned int lang = get_AT_unsigned (comp_unit_die, DW_AT_language); - return (lang == DW_LANG_Java); + return lang == DW_LANG_Java; } -/* Free up the memory used by A. */ +/* Return TRUE if the language is Ada. */ -static inline void free_AT PARAMS ((dw_attr_ref)); -static inline void -free_AT (a) - dw_attr_ref a; +static inline bool +is_ada (void) { - switch (AT_class (a)) - { - case dw_val_class_str: - if (a->dw_attr_val.v.val_str->refcount) - a->dw_attr_val.v.val_str->refcount--; - break; + unsigned int lang = get_AT_unsigned (comp_unit_die, DW_AT_language); - case dw_val_class_lbl_id: - case dw_val_class_lbl_offset: - free (a->dw_attr_val.v.val_lbl_id); - break; - - case dw_val_class_float: - free (a->dw_attr_val.v.val_float.array); - break; + return lang == DW_LANG_Ada95 || lang == DW_LANG_Ada83; +} - default: - break; - } +/* Free up the memory used by A. */ - free (a); +static inline void free_AT (dw_attr_ref); +static inline void +free_AT (dw_attr_ref a) +{ + if (AT_class (a) == dw_val_class_str) + if (a->dw_attr_val.v.val_str->refcount) + a->dw_attr_val.v.val_str->refcount--; } /* Remove the specified attribute if present. */ static void -remove_AT (die, attr_kind) - dw_die_ref die; - enum dwarf_attribute attr_kind; +remove_AT (dw_die_ref die, enum dwarf_attribute attr_kind) { dw_attr_ref *p; dw_attr_ref removed = NULL; @@ -5040,18 +5058,15 @@ remove_AT (die, attr_kind) /* Free up the memory used by DIE. */ static inline void -free_die (die) - dw_die_ref die; +free_die (dw_die_ref die) { remove_children (die); - free (die); } /* Discard the children of this DIE. */ static void -remove_children (die) - dw_die_ref die; +remove_children (dw_die_ref die) { dw_die_ref child_die = die->die_child; @@ -5080,9 +5095,7 @@ remove_children (die) addition order, and correct that in reverse_all_dies. */ static inline void -add_child_die (die, child_die) - dw_die_ref die; - dw_die_ref child_die; +add_child_die (dw_die_ref die, dw_die_ref child_die) { if (die != NULL && child_die != NULL) { @@ -5099,8 +5112,7 @@ add_child_die (die, child_die) is the specification, to the front of PARENT's list of children. */ static void -splice_child_die (parent, child) - dw_die_ref parent, child; +splice_child_die (dw_die_ref parent, dw_die_ref child) { dw_die_ref *p; @@ -5125,6 +5137,7 @@ splice_child_die (parent, child) break; } + child->die_parent = parent; child->die_sib = parent->die_child; parent->die_child = child; } @@ -5132,12 +5145,9 @@ splice_child_die (parent, child) /* Return a pointer to a newly created DIE node. */ static inline dw_die_ref -new_die (tag_value, parent_die, t) - enum dwarf_tag tag_value; - dw_die_ref parent_die; - tree t; +new_die (enum dwarf_tag tag_value, dw_die_ref parent_die, tree t) { - dw_die_ref die = (dw_die_ref) xcalloc (1, sizeof (die_node)); + dw_die_ref die = ggc_alloc_cleared (sizeof (die_node)); die->die_tag = tag_value; @@ -5147,7 +5157,7 @@ new_die (tag_value, parent_die, t) { limbo_die_node *limbo_node; - limbo_node = (limbo_die_node *) xmalloc (sizeof (limbo_die_node)); + limbo_node = ggc_alloc_cleared (sizeof (limbo_die_node)); limbo_node->die = die; limbo_node->created_for = t; limbo_node->next = limbo_die_list; @@ -5160,8 +5170,7 @@ new_die (tag_value, parent_die, t) /* Return the DIE associated with the given type specifier. */ static inline dw_die_ref -lookup_type_die (type) - tree type; +lookup_type_die (tree type) { return TYPE_SYMTAB_DIE (type); } @@ -5169,9 +5178,7 @@ lookup_type_die (type) /* Equate a DIE to a given type specifier. */ static inline void -equate_type_number_to_die (type, type_die) - tree type; - dw_die_ref type_die; +equate_type_number_to_die (tree type, dw_die_ref type_die) { TYPE_SYMTAB_DIE (type) = type_die; } @@ -5179,8 +5186,7 @@ equate_type_number_to_die (type, type_die) /* Return the DIE associated with a given declaration. */ static inline dw_die_ref -lookup_decl_die (decl) - tree decl; +lookup_decl_die (tree decl) { unsigned decl_id = DECL_UID (decl); @@ -5190,9 +5196,7 @@ lookup_decl_die (decl) /* Equate a DIE to a particular declaration. */ static void -equate_decl_number_to_die (decl, decl_die) - tree decl; - dw_die_ref decl_die; +equate_decl_number_to_die (tree decl, dw_die_ref decl_die) { unsigned int decl_id = DECL_UID (decl); unsigned int num_allocated; @@ -5204,11 +5208,10 @@ equate_decl_number_to_die (decl, decl_die) / DECL_DIE_TABLE_INCREMENT) * DECL_DIE_TABLE_INCREMENT; - decl_die_table - = (dw_die_ref *) xrealloc (decl_die_table, - sizeof (dw_die_ref) * num_allocated); + decl_die_table = ggc_realloc (decl_die_table, + sizeof (dw_die_ref) * num_allocated); - memset ((char *) &decl_die_table[decl_die_table_allocated], 0, + memset (&decl_die_table[decl_die_table_allocated], 0, (num_allocated - decl_die_table_allocated) * sizeof (dw_die_ref)); decl_die_table_allocated = num_allocated; } @@ -5227,8 +5230,7 @@ static int print_indent; /* Indent the line the number of spaces given by print_indent. */ static inline void -print_spaces (outfile) - FILE *outfile; +print_spaces (FILE *outfile) { fprintf (outfile, "%*s", print_indent, ""); } @@ -5237,9 +5239,7 @@ print_spaces (outfile) This routine is a debugging aid only. */ static void -print_die (die, outfile) - dw_die_ref die; - FILE *outfile; +print_die (dw_die_ref die, FILE *outfile) { dw_attr_ref a; dw_die_ref c; @@ -5275,18 +5275,18 @@ print_die (die, outfile) fprintf (outfile, "range list"); break; case dw_val_class_const: - fprintf (outfile, "%ld", AT_int (a)); + fprintf (outfile, HOST_WIDE_INT_PRINT_DEC, AT_int (a)); break; case dw_val_class_unsigned_const: - fprintf (outfile, "%lu", AT_unsigned (a)); + fprintf (outfile, HOST_WIDE_INT_PRINT_UNSIGNED, AT_unsigned (a)); break; case dw_val_class_long_long: fprintf (outfile, "constant (%lu,%lu)", a->dw_attr_val.v.val_long_long.hi, a->dw_attr_val.v.val_long_long.low); break; - case dw_val_class_float: - fprintf (outfile, "floating-point constant"); + case dw_val_class_vec: + fprintf (outfile, "floating-point or vector constant"); break; case dw_val_class_flag: fprintf (outfile, "%u", AT_flag (a)); @@ -5335,8 +5335,7 @@ print_die (die, outfile) This routine is a debugging aid only. */ static void -print_dwarf_line_table (outfile) - FILE *outfile; +print_dwarf_line_table (FILE *outfile) { unsigned i; dw_line_info_ref line_info; @@ -5346,7 +5345,8 @@ print_dwarf_line_table (outfile) { line_info = &line_info_table[i]; fprintf (outfile, "%5d: ", i); - fprintf (outfile, "%-20s", file_table.table[line_info->dw_file_num]); + fprintf (outfile, "%-20s", + VARRAY_CHAR_PTR (file_table, line_info->dw_file_num)); fprintf (outfile, "%6ld", line_info->dw_line_num); fprintf (outfile, "\n"); } @@ -5357,8 +5357,7 @@ print_dwarf_line_table (outfile) /* Print the information collected for a given DIE. */ void -debug_dwarf_die (die) - dw_die_ref die; +debug_dwarf_die (dw_die_ref die) { print_die (die, stderr); } @@ -5367,7 +5366,7 @@ debug_dwarf_die (die) This routine is a debugging aid only. */ void -debug_dwarf () +debug_dwarf (void) { print_indent = 0; print_die (comp_unit_die, stderr); @@ -5380,8 +5379,7 @@ debug_dwarf () they are in order of addition. */ static void -reverse_die_lists (die) - dw_die_ref die; +reverse_die_lists (dw_die_ref die) { dw_die_ref c, cp, cn; dw_attr_ref a, ap, an; @@ -5412,8 +5410,7 @@ reverse_die_lists (die) recursively reverse all the dies. This is that routine. */ static void -reverse_all_dies (die) - dw_die_ref die; +reverse_all_dies (dw_die_ref die) { dw_die_ref c; @@ -5428,8 +5425,7 @@ reverse_all_dies (die) DIE that marks the start of the DIEs for this include file. */ static dw_die_ref -push_new_compile_unit (old_unit, bincl_die) - dw_die_ref old_unit, bincl_die; +push_new_compile_unit (dw_die_ref old_unit, dw_die_ref bincl_die) { const char *filename = get_AT_string (bincl_die, DW_AT_name); dw_die_ref new_unit = gen_compile_unit_die (filename); @@ -5441,8 +5437,7 @@ push_new_compile_unit (old_unit, bincl_die) /* Close an include-file CU and reopen the enclosing one. */ static dw_die_ref -pop_compile_unit (old_unit) - dw_die_ref old_unit; +pop_compile_unit (dw_die_ref old_unit) { dw_die_ref new_unit = old_unit->die_sib; @@ -5456,9 +5451,7 @@ pop_compile_unit (old_unit) /* Calculate the checksum of a location expression. */ static inline void -loc_checksum (loc, ctx) - dw_loc_descr_ref loc; - struct md5_ctx *ctx; +loc_checksum (dw_loc_descr_ref loc, struct md5_ctx *ctx) { CHECKSUM (loc->dw_loc_opc); CHECKSUM (loc->dw_loc_oprnd1); @@ -5468,10 +5461,7 @@ loc_checksum (loc, ctx) /* Calculate the checksum of an attribute. */ static void -attr_checksum (at, ctx, mark) - dw_attr_ref at; - struct md5_ctx *ctx; - int *mark; +attr_checksum (dw_attr_ref at, struct md5_ctx *ctx, int *mark) { dw_loc_descr_ref loc; rtx r; @@ -5496,8 +5486,8 @@ attr_checksum (at, ctx, mark) case dw_val_class_long_long: CHECKSUM (at->dw_attr_val.v.val_long_long); break; - case dw_val_class_float: - CHECKSUM (at->dw_attr_val.v.val_float); + case dw_val_class_vec: + CHECKSUM (at->dw_attr_val.v.val_vec); break; case dw_val_class_flag: CHECKSUM (at->dw_attr_val.v.val_flag); @@ -5545,10 +5535,7 @@ attr_checksum (at, ctx, mark) /* Calculate the checksum of a DIE. */ static void -die_checksum (die, ctx, mark) - dw_die_ref die; - struct md5_ctx *ctx; - int *mark; +die_checksum (dw_die_ref die, struct md5_ctx *ctx, int *mark) { dw_die_ref c; dw_attr_ref a; @@ -5575,10 +5562,7 @@ die_checksum (die, ctx, mark) /* Do the location expressions look same? */ static inline int -same_loc_p (loc1, loc2, mark) - dw_loc_descr_ref loc1; - dw_loc_descr_ref loc2; - int *mark; +same_loc_p (dw_loc_descr_ref loc1, dw_loc_descr_ref loc2, int *mark) { return loc1->dw_loc_opc == loc2->dw_loc_opc && same_dw_val_p (&loc1->dw_loc_oprnd1, &loc2->dw_loc_oprnd1, mark) @@ -5587,14 +5571,10 @@ same_loc_p (loc1, loc2, mark) /* Do the values look the same? */ static int -same_dw_val_p (v1, v2, mark) - dw_val_node *v1; - dw_val_node *v2; - int *mark; +same_dw_val_p (dw_val_node *v1, dw_val_node *v2, int *mark) { dw_loc_descr_ref loc1, loc2; rtx r1, r2; - unsigned i; if (v1->val_class != v2->val_class) return 0; @@ -5607,19 +5587,19 @@ same_dw_val_p (v1, v2, mark) return v1->v.val_unsigned == v2->v.val_unsigned; case dw_val_class_long_long: return v1->v.val_long_long.hi == v2->v.val_long_long.hi - && v1->v.val_long_long.low == v2->v.val_long_long.low; - case dw_val_class_float: - if (v1->v.val_float.length != v2->v.val_float.length) + && v1->v.val_long_long.low == v2->v.val_long_long.low; + case dw_val_class_vec: + if (v1->v.val_vec.length != v2->v.val_vec.length + || v1->v.val_vec.elt_size != v2->v.val_vec.elt_size) + return 0; + if (memcmp (v1->v.val_vec.array, v2->v.val_vec.array, + v1->v.val_vec.length * v1->v.val_vec.elt_size)) return 0; - for (i = 0; i < v1->v.val_float.length; i++) - if (v1->v.val_float.array[i] != v2->v.val_float.array[i]) - return 0; return 1; case dw_val_class_flag: return v1->v.val_flag == v2->v.val_flag; case dw_val_class_str: - return !strcmp((const char *) HT_STR (&v1->v.val_str->id), - (const char *) HT_STR (&v2->v.val_str->id)); + return !strcmp(v1->v.val_str->str, v2->v.val_str->str); case dw_val_class_addr: r1 = v1->v.val_addr; @@ -5662,10 +5642,7 @@ same_dw_val_p (v1, v2, mark) /* Do the attributes look the same? */ static int -same_attr_p (at1, at2, mark) - dw_attr_ref at1; - dw_attr_ref at2; - int *mark; +same_attr_p (dw_attr_ref at1, dw_attr_ref at2, int *mark) { if (at1->dw_attr != at2->dw_attr) return 0; @@ -5683,10 +5660,7 @@ same_attr_p (at1, at2, mark) /* Do the dies look the same? */ static int -same_die_p (die1, die2, mark) - dw_die_ref die1; - dw_die_ref die2; - int *mark; +same_die_p (dw_die_ref die1, dw_die_ref die2, int *mark) { dw_die_ref c1, c2; dw_attr_ref a1, a2; @@ -5721,9 +5695,7 @@ same_die_p (die1, die2, mark) /* Do the dies look the same? Wrapper around same_die_p. */ static int -same_die_p_wrap (die1, die2) - dw_die_ref die1; - dw_die_ref die2; +same_die_p_wrap (dw_die_ref die1, dw_die_ref die2) { int mark = 0; int ret = same_die_p (die1, die2, &mark); @@ -5745,12 +5717,11 @@ static unsigned int comdat_symbol_number; children, and set comdat_symbol_id accordingly. */ static void -compute_section_prefix (unit_die) - dw_die_ref unit_die; +compute_section_prefix (dw_die_ref unit_die) { const char *die_name = get_AT_string (unit_die, DW_AT_name); const char *base = die_name ? lbasename (die_name) : "anonymous"; - char *name = (char *) alloca (strlen (base) + 64); + char *name = alloca (strlen (base) + 64); char *p; int i, mark; unsigned char checksum[16]; @@ -5782,8 +5753,7 @@ compute_section_prefix (unit_die) /* Returns nonzero if DIE represents a type, in the sense of TYPE_P. */ static int -is_type_die (die) - dw_die_ref die; +is_type_die (dw_die_ref die) { switch (die->die_tag) { @@ -5817,8 +5787,7 @@ is_type_die (die) compilations (functions). */ static int -is_comdat_die (c) - dw_die_ref c; +is_comdat_die (dw_die_ref c) { /* I think we want to leave base types and __vtbl_ptr_type in the main CU, as we do for stabs. The advantage is a greater likelihood of sharing between @@ -5845,8 +5814,7 @@ is_comdat_die (c) compilation unit. */ static int -is_symbol_die (c) - dw_die_ref c; +is_symbol_die (dw_die_ref c) { return (is_type_die (c) || (get_AT (c, DW_AT_declaration) @@ -5854,11 +5822,9 @@ is_symbol_die (c) } static char * -gen_internal_sym (prefix) - const char *prefix; +gen_internal_sym (const char *prefix) { char buf[256]; - static int label_num; ASM_GENERATE_INTERNAL_LABEL (buf, prefix, label_num++); return xstrdup (buf); @@ -5867,8 +5833,7 @@ gen_internal_sym (prefix) /* Assign symbols to all worthy DIEs under DIE. */ static void -assign_symbol_names (die) - dw_die_ref die; +assign_symbol_names (dw_die_ref die) { dw_die_ref c; @@ -5899,8 +5864,7 @@ struct cu_hash_table_entry /* Routines to manipulate hash table of CUs. */ static hashval_t -htab_cu_hash (of) - const void *of; +htab_cu_hash (const void *of) { const struct cu_hash_table_entry *entry = of; @@ -5908,9 +5872,7 @@ htab_cu_hash (of) } static int -htab_cu_eq (of1, of2) - const void *of1; - const void *of2; +htab_cu_eq (const void *of1, const void *of2) { const struct cu_hash_table_entry *entry1 = of1; const struct die_struct *entry2 = of2; @@ -5919,8 +5881,7 @@ htab_cu_eq (of1, of2) } static void -htab_cu_del (what) - void *what; +htab_cu_del (void *what) { struct cu_hash_table_entry *next, *entry = what; @@ -5935,10 +5896,7 @@ htab_cu_del (what) /* Check whether we have already seen this CU and set up SYM_NUM accordingly. */ static int -check_duplicate_cu (cu, htable, sym_num) - dw_die_ref cu; - htab_t htable; - unsigned *sym_num; +check_duplicate_cu (dw_die_ref cu, htab_t htable, unsigned int *sym_num) { struct cu_hash_table_entry dummy; struct cu_hash_table_entry **slot, *entry, *last = &dummy; @@ -5973,10 +5931,7 @@ check_duplicate_cu (cu, htable, sym_num) /* Record SYM_NUM to record of CU in HTABLE. */ static void -record_comdat_symbol_number (cu, htable, sym_num) - dw_die_ref cu; - htab_t htable; - unsigned sym_num; +record_comdat_symbol_number (dw_die_ref cu, htab_t htable, unsigned int sym_num) { struct cu_hash_table_entry **slot, *entry; @@ -5993,8 +5948,7 @@ record_comdat_symbol_number (cu, htable, sym_num) bracketed by BINCL/EINCL. */ static void -break_out_includes (die) - dw_die_ref die; +break_out_includes (dw_die_ref die) { dw_die_ref *ptr; dw_die_ref unit = NULL; @@ -6054,7 +6008,7 @@ break_out_includes (die) if (is_dupl) *pnode = node->next; else - { + { pnode = &node->next; record_comdat_symbol_number (node->die, cu_hash_table, comdat_symbol_number); @@ -6068,8 +6022,7 @@ break_out_includes (die) avoid generating sibling attributes for DIE's without children. */ static void -add_sibling_attributes (die) - dw_die_ref die; +add_sibling_attributes (dw_die_ref die) { dw_die_ref c; @@ -6085,8 +6038,7 @@ add_sibling_attributes (die) /* Output all location lists for the DIE and its children. */ static void -output_location_lists (die) - dw_die_ref die; +output_location_lists (dw_die_ref die) { dw_die_ref c; dw_attr_ref d_attr; @@ -6106,8 +6058,7 @@ output_location_lists (die) die are visited recursively. */ static void -build_abbrev_table (die) - dw_die_ref die; +build_abbrev_table (dw_die_ref die) { unsigned long abbrev_id; unsigned int n_alloc; @@ -6158,11 +6109,10 @@ build_abbrev_table (die) if (abbrev_die_table_in_use >= abbrev_die_table_allocated) { n_alloc = abbrev_die_table_allocated + ABBREV_DIE_TABLE_INCREMENT; - abbrev_die_table - = (dw_die_ref *) xrealloc (abbrev_die_table, - sizeof (dw_die_ref) * n_alloc); + abbrev_die_table = ggc_realloc (abbrev_die_table, + sizeof (dw_die_ref) * n_alloc); - memset ((char *) &abbrev_die_table[abbrev_die_table_allocated], 0, + memset (&abbrev_die_table[abbrev_die_table_allocated], 0, (n_alloc - abbrev_die_table_allocated) * sizeof (dw_die_ref)); abbrev_die_table_allocated = n_alloc; } @@ -6179,8 +6129,7 @@ build_abbrev_table (die) /* Return the power-of-two number of bytes necessary to represent VALUE. */ static int -constant_size (value) - long unsigned value; +constant_size (long unsigned int value) { int log; @@ -6199,8 +6148,7 @@ constant_size (value) .debug_info section. */ static unsigned long -size_of_die (die) - dw_die_ref die; +size_of_die (dw_die_ref die) { unsigned long size = 0; dw_attr_ref a; @@ -6240,14 +6188,18 @@ size_of_die (die) case dw_val_class_long_long: size += 1 + 2*HOST_BITS_PER_LONG/HOST_BITS_PER_CHAR; /* block */ break; - case dw_val_class_float: - size += 1 + a->dw_attr_val.v.val_float.length * 4; /* block */ + case dw_val_class_vec: + size += 1 + (a->dw_attr_val.v.val_vec.length + * a->dw_attr_val.v.val_vec.elt_size); /* block */ break; case dw_val_class_flag: size += 1; break; case dw_val_class_die_ref: - size += DWARF_OFFSET_SIZE; + if (AT_ref_external (a)) + size += DWARF2_ADDR_SIZE; + else + size += DWARF_OFFSET_SIZE; break; case dw_val_class_fde_ref: size += DWARF_OFFSET_SIZE; @@ -6262,7 +6214,7 @@ size_of_die (die) if (AT_string_form (a) == DW_FORM_strp) size += DWARF_OFFSET_SIZE; else - size += HT_LEN (&a->dw_attr_val.v.val_str->id) + 1; + size += strlen (a->dw_attr_val.v.val_str->str) + 1; break; default: abort (); @@ -6278,8 +6230,7 @@ size_of_die (die) die_offset field in each DIE. */ static void -calc_die_sizes (die) - dw_die_ref die; +calc_die_sizes (dw_die_ref die) { dw_die_ref c; @@ -6300,14 +6251,13 @@ calc_die_sizes (die) and use that as the flag, but ran into ordering problems. */ static void -mark_dies (die) - dw_die_ref die; +mark_dies (dw_die_ref die) { dw_die_ref c; if (die->die_mark) abort (); - + die->die_mark = 1; for (c = die->die_child; c; c = c->die_sib) mark_dies (c); @@ -6316,14 +6266,13 @@ mark_dies (die) /* Clear the marks for a die and its children. */ static void -unmark_dies (die) - dw_die_ref die; +unmark_dies (dw_die_ref die) { dw_die_ref c; if (!die->die_mark) abort (); - + die->die_mark = 0; for (c = die->die_child; c; c = c->die_sib) unmark_dies (c); @@ -6332,8 +6281,7 @@ unmark_dies (die) /* Clear the marks for a die, its children and referred dies. */ static void -unmark_all_dies (die) - dw_die_ref die; +unmark_all_dies (dw_die_ref die) { dw_die_ref c; dw_attr_ref a; @@ -6354,7 +6302,7 @@ unmark_all_dies (die) compilation unit. */ static unsigned long -size_of_pubnames () +size_of_pubnames (void) { unsigned long size; unsigned i; @@ -6373,7 +6321,7 @@ size_of_pubnames () /* Return the size of the information in the .debug_aranges section. */ static unsigned long -size_of_aranges () +size_of_aranges (void) { unsigned long size; @@ -6391,8 +6339,7 @@ size_of_aranges () /* Select the encoding of an attribute value. */ static enum dwarf_form -value_format (a) - dw_attr_ref a; +value_format (dw_attr_ref a) { switch (a->dw_attr_val.val_class) { @@ -6437,7 +6384,7 @@ value_format (a) } case dw_val_class_long_long: return DW_FORM_block1; - case dw_val_class_float: + case dw_val_class_vec: return DW_FORM_block1; case dw_val_class_flag: return DW_FORM_flag; @@ -6463,8 +6410,7 @@ value_format (a) /* Output the encoding of an attribute value. */ static void -output_value_format (a) - dw_attr_ref a; +output_value_format (dw_attr_ref a) { enum dwarf_form form = value_format (a); @@ -6475,7 +6421,7 @@ output_value_format (a) table. */ static void -output_abbrev_section () +output_abbrev_section (void) { unsigned long abbrev_id; @@ -6513,8 +6459,7 @@ output_abbrev_section () /* Output a symbol we can use to refer to this DIE from another CU. */ static inline void -output_die_symbol (die) - dw_die_ref die; +output_die_symbol (dw_die_ref die) { char *sym = die->die_symbol; @@ -6535,15 +6480,10 @@ output_die_symbol (die) this location list node, which is done for the head of the list only. */ static inline dw_loc_list_ref -new_loc_list (expr, begin, end, section, gensym) - dw_loc_descr_ref expr; - const char *begin; - const char *end; - const char *section; - unsigned gensym; +new_loc_list (dw_loc_descr_ref expr, const char *begin, const char *end, + const char *section, unsigned int gensym) { - dw_loc_list_ref retlist - = (dw_loc_list_ref) xcalloc (1, sizeof (dw_loc_list_node)); + dw_loc_list_ref retlist = ggc_alloc_cleared (sizeof (dw_loc_list_node)); retlist->begin = begin; retlist->end = end; @@ -6555,15 +6495,12 @@ new_loc_list (expr, begin, end, section, gensym) return retlist; } -/* Add a location description expression to a location list */ +/* Add a location description expression to a location list. */ static inline void -add_loc_descr_to_loc_list (list_head, descr, begin, end, section) - dw_loc_list_ref *list_head; - dw_loc_descr_ref descr; - const char *begin; - const char *end; - const char *section; +add_loc_descr_to_loc_list (dw_loc_list_ref *list_head, dw_loc_descr_ref descr, + const char *begin, const char *end, + const char *section) { dw_loc_list_ref *d; @@ -6571,15 +6508,14 @@ add_loc_descr_to_loc_list (list_head, descr, begin, end, section) for (d = list_head; (*d) != NULL; d = &(*d)->dw_loc_next) ; - /* Add a new location list node to the list */ + /* Add a new location list node to the list. */ *d = new_loc_list (descr, begin, end, section, 0); } -/* Output the location list given to us */ +/* Output the location list given to us. */ static void -output_loc_list (list_head) - dw_loc_list_ref list_head; +output_loc_list (dw_loc_list_ref list_head) { dw_loc_list_ref curr = list_head; @@ -6629,8 +6565,7 @@ output_loc_list (list_head) the definitions of each child DIE. */ static void -output_die (die) - dw_die_ref die; +output_die (dw_die_ref die) { dw_attr_ref a; dw_die_ref c; @@ -6663,7 +6598,8 @@ output_die (die) { char *p = strchr (ranges_section_label, '\0'); - sprintf (p, "+0x%lx", a->dw_attr_val.v.val_offset); + sprintf (p, "+" HOST_WIDE_INT_PRINT_HEX, + a->dw_attr_val.v.val_offset); dw2_asm_output_offset (DWARF_OFFSET_SIZE, ranges_section_label, "%s", name); *p = '\0'; @@ -6717,16 +6653,24 @@ output_die (die) } break; - case dw_val_class_float: + case dw_val_class_vec: { + unsigned int elt_size = a->dw_attr_val.v.val_vec.elt_size; + unsigned int len = a->dw_attr_val.v.val_vec.length; unsigned int i; + unsigned char *p; - dw2_asm_output_data (1, a->dw_attr_val.v.val_float.length * 4, - "%s", name); - - for (i = 0; i < a->dw_attr_val.v.val_float.length; i++) - dw2_asm_output_data (4, a->dw_attr_val.v.val_float.array[i], - "fp constant word %u", i); + dw2_asm_output_data (1, len * elt_size, "%s", name); + if (elt_size > sizeof (HOST_WIDE_INT)) + { + elt_size /= 2; + len *= 2; + } + for (i = 0, p = a->dw_attr_val.v.val_vec.array; + i < len; + i++, p += elt_size) + dw2_asm_output_data (elt_size, extract_int (p, elt_size), + "fp or vector constant word %u", i); break; } @@ -6806,9 +6750,13 @@ output_die (die) .debug_info section, and precedes the DIE descriptions. */ static void -output_compilation_unit_header () +output_compilation_unit_header (void) { - dw2_asm_output_data (DWARF_OFFSET_SIZE, next_die_offset - DWARF_OFFSET_SIZE, + if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4) + dw2_asm_output_data (4, 0xffffffff, + "Initial length escape value indicating 64-bit DWARF extension"); + dw2_asm_output_data (DWARF_OFFSET_SIZE, + next_die_offset - DWARF_INITIAL_LENGTH_SIZE, "Length of Compilation Unit Info"); dw2_asm_output_data (2, DWARF_VERSION, "DWARF version number"); dw2_asm_output_offset (DWARF_OFFSET_SIZE, abbrev_section_label, @@ -6819,9 +6767,7 @@ output_compilation_unit_header () /* Output the compilation unit DIE and its children. */ static void -output_comp_unit (die, output_if_empty) - dw_die_ref die; - int output_if_empty; +output_comp_unit (dw_die_ref die, int output_if_empty) { const char *secname; char *oldsym, *tmp; @@ -6846,7 +6792,7 @@ output_comp_unit (die, output_if_empty) oldsym = die->die_symbol; if (oldsym) { - tmp = (char *) alloca (strlen (oldsym) + 24); + tmp = alloca (strlen (oldsym) + 24); sprintf (tmp, ".gnu.linkonce.wi.%s", oldsym); secname = tmp; @@ -6874,9 +6820,7 @@ output_comp_unit (die, output_if_empty) "A::f(int)". Let's drop the argument list, and maybe the scope. */ static const char * -dwarf2_name (decl, scope) - tree decl; - int scope; +dwarf2_name (tree decl, int scope) { return (*lang_hooks.decl_printable_name) (decl, scope ? 1 : 0); } @@ -6884,9 +6828,7 @@ dwarf2_name (decl, scope) /* Add a new entry to .debug_pubnames if appropriate. */ static void -add_pubname (decl, die) - tree decl; - dw_die_ref die; +add_pubname (tree decl, dw_die_ref die) { pubname_ref p; @@ -6897,9 +6839,10 @@ add_pubname (decl, die) { pubname_table_allocated += PUBNAME_TABLE_INCREMENT; pubname_table - = (pubname_ref) xrealloc (pubname_table, - (pubname_table_allocated - * sizeof (pubname_entry))); + = ggc_realloc (pubname_table, + (pubname_table_allocated * sizeof (pubname_entry))); + memset (pubname_table + pubname_table_in_use, 0, + PUBNAME_TABLE_INCREMENT * sizeof (pubname_entry)); } p = &pubname_table[pubname_table_in_use++]; @@ -6912,11 +6855,14 @@ add_pubname (decl, die) visible procedures. */ static void -output_pubnames () +output_pubnames (void) { unsigned i; unsigned long pubnames_length = size_of_pubnames (); + if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4) + dw2_asm_output_data (4, 0xffffffff, + "Initial length escape value indicating 64-bit DWARF extension"); dw2_asm_output_data (DWARF_OFFSET_SIZE, pubnames_length, "Length of Public Names Info"); dw2_asm_output_data (2, DWARF_VERSION, "DWARF Version"); @@ -6945,9 +6891,7 @@ output_pubnames () /* Add a new entry to .debug_aranges if appropriate. */ static void -add_arange (decl, die) - tree decl; - dw_die_ref die; +add_arange (tree decl, dw_die_ref die) { if (! DECL_SECTION_NAME (decl)) return; @@ -6955,8 +6899,11 @@ add_arange (decl, die) if (arange_table_in_use == arange_table_allocated) { arange_table_allocated += ARANGE_TABLE_INCREMENT; - arange_table = (dw_die_ref *) - xrealloc (arange_table, arange_table_allocated * sizeof (dw_die_ref)); + arange_table = ggc_realloc (arange_table, + (arange_table_allocated + * sizeof (dw_die_ref))); + memset (arange_table + arange_table_in_use, 0, + ARANGE_TABLE_INCREMENT * sizeof (dw_die_ref)); } arange_table[arange_table_in_use++] = die; @@ -6967,11 +6914,14 @@ add_arange (decl, die) text section generated for this compilation unit. */ static void -output_aranges () +output_aranges (void) { unsigned i; unsigned long aranges_length = size_of_aranges (); + if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4) + dw2_asm_output_data (4, 0xffffffff, + "Initial length escape value indicating 64-bit DWARF extension"); dw2_asm_output_data (DWARF_OFFSET_SIZE, aranges_length, "Length of Address Ranges Info"); dw2_asm_output_data (2, DWARF_VERSION, "DWARF Version"); @@ -6984,7 +6934,7 @@ output_aranges () if (DWARF_ARANGES_PAD_SIZE) { /* Pad using a 2 byte words so that padding is correct for any - pointer size. */ + pointer size. */ dw2_asm_output_data (2, 0, "Pad to %d byte boundary", 2 * DWARF2_ADDR_SIZE); for (i = 2; i < (unsigned) DWARF_ARANGES_PAD_SIZE; i += 2) @@ -7042,17 +6992,18 @@ output_aranges () was placed. */ static unsigned int -add_ranges (block) - tree block; +add_ranges (tree block) { unsigned int in_use = ranges_table_in_use; if (in_use == ranges_table_allocated) { ranges_table_allocated += RANGES_TABLE_INCREMENT; - ranges_table = (dw_ranges_ref) - xrealloc (ranges_table, (ranges_table_allocated - * sizeof (struct dw_ranges_struct))); + ranges_table + = ggc_realloc (ranges_table, (ranges_table_allocated + * sizeof (struct dw_ranges_struct))); + memset (ranges_table + ranges_table_in_use, 0, + RANGES_TABLE_INCREMENT * sizeof (struct dw_ranges_struct)); } ranges_table[in_use].block_num = (block ? BLOCK_NUMBER (block) : 0); @@ -7062,7 +7013,7 @@ add_ranges (block) } static void -output_ranges () +output_ranges (void) { unsigned i; static const char *const start_fmt = "Offset 0x%x"; @@ -7140,9 +7091,7 @@ struct dir_info the directories in the path. */ static int -file_info_cmp (p1, p2) - const void *p1; - const void *p2; +file_info_cmp (const void *p1, const void *p2) { const struct file_info *s1 = p1; const struct file_info *s2 = p2; @@ -7181,31 +7130,37 @@ file_info_cmp (p1, p2) slowdowns with many input files. */ static void -output_file_names () +output_file_names (void) { struct file_info *files; struct dir_info *dirs; int *saved; int *savehere; int *backmap; - int ndirs; + size_t ndirs; int idx_offset; - int i; + size_t i; int idx; + /* Handle the case where file_table is empty. */ + if (VARRAY_ACTIVE_SIZE (file_table) <= 1) + { + dw2_asm_output_data (1, 0, "End directory table"); + dw2_asm_output_data (1, 0, "End file name table"); + return; + } + /* Allocate the various arrays we need. */ - files = (struct file_info *) alloca (file_table.in_use - * sizeof (struct file_info)); - dirs = (struct dir_info *) alloca (file_table.in_use - * sizeof (struct dir_info)); + files = alloca (VARRAY_ACTIVE_SIZE (file_table) * sizeof (struct file_info)); + dirs = alloca (VARRAY_ACTIVE_SIZE (file_table) * sizeof (struct dir_info)); /* Sort the file names. */ - for (i = 1; i < (int) file_table.in_use; i++) + for (i = 1; i < VARRAY_ACTIVE_SIZE (file_table); i++) { char *f; /* Skip all leading "./". */ - f = file_table.table[i]; + f = VARRAY_CHAR_PTR (file_table, i); while (f[0] == '.' && f[1] == '/') f += 2; @@ -7219,7 +7174,8 @@ output_file_names () files[i].fname = f == NULL ? files[i].path : f + 1; } - qsort (files + 1, file_table.in_use - 1, sizeof (files[0]), file_info_cmp); + qsort (files + 1, VARRAY_ACTIVE_SIZE (file_table) - 1, + sizeof (files[0]), file_info_cmp); /* Find all the different directories used. */ dirs[0].path = files[1].path; @@ -7231,7 +7187,7 @@ output_file_names () files[1].dir_idx = 0; ndirs = 1; - for (i = 2; i < (int) file_table.in_use; i++) + for (i = 2; i < VARRAY_ACTIVE_SIZE (file_table); i++) if (files[i].fname - files[i].path == dirs[ndirs - 1].length && memcmp (dirs[ndirs - 1].path, files[i].path, dirs[ndirs - 1].length) == 0) @@ -7242,7 +7198,7 @@ output_file_names () } else { - int j; + size_t j; /* This is a new directory. */ dirs[ndirs].path = files[i].path; @@ -7271,13 +7227,13 @@ output_file_names () where we would have to check out every combination of every single possible prefix. Instead we use a heuristic which provides nearly optimal results in most cases and never is much off. */ - saved = (int *) alloca (ndirs * sizeof (int)); - savehere = (int *) alloca (ndirs * sizeof (int)); + saved = alloca (ndirs * sizeof (int)); + savehere = alloca (ndirs * sizeof (int)); memset (saved, '\0', ndirs * sizeof (saved[0])); for (i = 0; i < ndirs; i++) { - int j; + size_t j; int total; /* We can always save some space for the current directory. But this @@ -7295,10 +7251,10 @@ output_file_names () int k; k = dirs[j].prefix; - while (k != -1 && k != i) + while (k != -1 && k != (int) i) k = dirs[k].prefix; - if (k == i) + if (k == (int) i) { /* Yes it is. We can possibly safe some memory but writing the filenames in dirs[j] relative to @@ -7329,8 +7285,8 @@ output_file_names () /* We have to emit them in the order they appear in the file_table array since the index is used in the debug info generation. To do this efficiently we generate a back-mapping of the indices first. */ - backmap = (int *) alloca (file_table.in_use * sizeof (int)); - for (i = 1; i < (int) file_table.in_use; i++) + backmap = alloca (VARRAY_ACTIVE_SIZE (file_table) * sizeof (int)); + for (i = 1; i < VARRAY_ACTIVE_SIZE (file_table); i++) { backmap[files[i].file_idx] = i; @@ -7361,13 +7317,13 @@ output_file_names () dirs[0].used = 0; /* Now write all the file names. */ - for (i = 1; i < (int) file_table.in_use; i++) + for (i = 1; i < VARRAY_ACTIVE_SIZE (file_table); i++) { int file_idx = backmap[i]; int dir_idx = dirs[files[file_idx].dir_idx].dir_idx; dw2_asm_output_nstring (files[file_idx].path + dirs[dir_idx].length, -1, - "File Entry: 0x%x", i); + "File Entry: 0x%lx", (unsigned long) i); /* Include directory index. */ dw2_asm_output_data_uleb128 (dirs[dir_idx].used, NULL); @@ -7387,7 +7343,7 @@ output_file_names () information goes into the .debug_line section. */ static void -output_line_info () +output_line_info (void) { char l1[20], l2[20], p1[20], p2[20]; char line_label[MAX_ARTIFICIAL_LABEL_BYTES]; @@ -7406,6 +7362,9 @@ output_line_info () ASM_GENERATE_INTERNAL_LABEL (p1, LN_PROLOG_AS_LABEL, 0); ASM_GENERATE_INTERNAL_LABEL (p2, LN_PROLOG_END_LABEL, 0); + if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4) + dw2_asm_output_data (4, 0xffffffff, + "Initial length escape value indicating 64-bit DWARF extension"); dw2_asm_output_delta (DWARF_OFFSET_SIZE, l2, l1, "Length of Source Line Info"); ASM_OUTPUT_LABEL (asm_out_file, l1); @@ -7477,8 +7436,8 @@ output_line_info () prologue. */ /* Don't emit anything for redundant notes. Just updating the - address doesn't accomplish anything, because we already assume - that anything after the last address is this line. */ + address doesn't accomplish anything, because we already assume + that anything after the last address is this line. */ if (line_info->dw_line_num == current_line && line_info->dw_file_num == current_file) continue; @@ -7504,7 +7463,7 @@ output_line_info () else { /* This can handle any delta. This takes - 4+DWARF2_ADDR_SIZE bytes. */ + 4+DWARF2_ADDR_SIZE bytes. */ dw2_asm_output_data (1, 0, "DW_LNE_set_address"); dw2_asm_output_data_uleb128 (1 + DWARF2_ADDR_SIZE, NULL); dw2_asm_output_data (1, DW_LNE_set_address, NULL); @@ -7520,7 +7479,8 @@ output_line_info () current_file = line_info->dw_file_num; dw2_asm_output_data (1, DW_LNS_set_file, "DW_LNS_set_file"); dw2_asm_output_data_uleb128 (current_file, "(\"%s\")", - file_table.table[current_file]); + VARRAY_CHAR_PTR (file_table, + current_file)); } /* Emit debug info for the current line number, choosing the encoding @@ -7595,7 +7555,7 @@ output_line_info () { function = line_info->function; - /* Set the address register to the first line in the function */ + /* Set the address register to the first line in the function. */ dw2_asm_output_data (1, 0, "DW_LNE_set_address"); dw2_asm_output_data_uleb128 (1 + DWARF2_ADDR_SIZE, NULL); dw2_asm_output_data (1, DW_LNE_set_address, NULL); @@ -7628,7 +7588,8 @@ output_line_info () current_file = line_info->dw_file_num; dw2_asm_output_data (1, DW_LNS_set_file, "DW_LNS_set_file"); dw2_asm_output_data_uleb128 (current_file, "(\"%s\")", - file_table.table[current_file]); + VARRAY_CHAR_PTR (file_table, + current_file)); } /* Emit debug info for the current line number, choosing the encoding @@ -7699,8 +7660,7 @@ output_line_info () Dwarf base (fundamental) types. */ static dw_die_ref -base_type_die (type) - tree type; +base_type_die (tree type) { dw_die_ref base_type_result; const char *type_name; @@ -7724,9 +7684,9 @@ base_type_die (type) { case INTEGER_TYPE: /* Carefully distinguish the C character types, without messing - up if the language is not C. Note that we check only for the names - that contain spaces; other names might occur by coincidence in other - languages. */ + up if the language is not C. Note that we check only for the names + that contain spaces; other names might occur by coincidence in other + languages. */ if (! (TYPE_PRECISION (type) == CHAR_TYPE_SIZE && (type == char_type_node || ! strcmp (type_name, "signed char") @@ -7793,8 +7753,7 @@ base_type_die (type) root type of the given type without the qualifiers. */ static tree -root_type (type) - tree type; +root_type (tree type) { if (TREE_CODE (type) == ERROR_MARK) return error_mark_node; @@ -7817,8 +7776,7 @@ root_type (type) given input type is a Dwarf "fundamental" type. Otherwise return null. */ static inline int -is_base_type (type) - tree type; +is_base_type (tree type) { switch (TREE_CODE (type)) { @@ -7854,15 +7812,96 @@ is_base_type (type) return 0; } +/* Given a pointer to a tree node, assumed to be some kind of a ..._TYPE + node, return the size in bits for the type if it is a constant, or else + return the alignment for the type if the type's size is not constant, or + else return BITS_PER_WORD if the type actually turns out to be an + ERROR_MARK node. */ + +static inline unsigned HOST_WIDE_INT +simple_type_size_in_bits (tree type) +{ + if (TREE_CODE (type) == ERROR_MARK) + return BITS_PER_WORD; + else if (TYPE_SIZE (type) == NULL_TREE) + return 0; + else if (host_integerp (TYPE_SIZE (type), 1)) + return tree_low_cst (TYPE_SIZE (type), 1); + else + return TYPE_ALIGN (type); +} + +/* Return true if the debug information for the given type should be + emitted as a subrange type. */ + +static inline bool +is_subrange_type (tree type) +{ + tree subtype = TREE_TYPE (type); + + if (TREE_CODE (type) == INTEGER_TYPE + && subtype != NULL_TREE) + { + if (TREE_CODE (subtype) == INTEGER_TYPE) + return true; + if (TREE_CODE (subtype) == ENUMERAL_TYPE) + return true; + } + return false; +} + +/* Given a pointer to a tree node for a subrange type, return a pointer + to a DIE that describes the given type. */ + +static dw_die_ref +subrange_type_die (tree type, dw_die_ref context_die) +{ + dw_die_ref subtype_die; + dw_die_ref subrange_die; + tree name = TYPE_NAME (type); + const HOST_WIDE_INT size_in_bytes = int_size_in_bytes (type); + + if (context_die == NULL) + context_die = comp_unit_die; + + if (TREE_CODE (TREE_TYPE (type)) == ENUMERAL_TYPE) + subtype_die = gen_enumeration_type_die (TREE_TYPE (type), context_die); + else + subtype_die = base_type_die (TREE_TYPE (type)); + + subrange_die = new_die (DW_TAG_subrange_type, context_die, type); + + if (name != NULL) + { + if (TREE_CODE (name) == TYPE_DECL) + name = DECL_NAME (name); + add_name_attribute (subrange_die, IDENTIFIER_POINTER (name)); + } + + if (int_size_in_bytes (TREE_TYPE (type)) != size_in_bytes) + { + /* The size of the subrange type and its base type do not match, + so we need to generate a size attribute for the subrange type. */ + add_AT_unsigned (subrange_die, DW_AT_byte_size, size_in_bytes); + } + + if (TYPE_MIN_VALUE (type) != NULL) + add_bound_info (subrange_die, DW_AT_lower_bound, + TYPE_MIN_VALUE (type)); + if (TYPE_MAX_VALUE (type) != NULL) + add_bound_info (subrange_die, DW_AT_upper_bound, + TYPE_MAX_VALUE (type)); + add_AT_die_ref (subrange_die, DW_AT_type, subtype_die); + + return subrange_die; +} + /* Given a pointer to an arbitrary ..._TYPE tree node, return a debugging entry that chains various modifiers in front of the given type. */ static dw_die_ref -modified_type_die (type, is_const_type, is_volatile_type, context_die) - tree type; - int is_const_type; - int is_volatile_type; - dw_die_ref context_die; +modified_type_die (tree type, int is_const_type, int is_volatile_type, + dw_die_ref context_die) { enum tree_code code = TREE_CODE (type); dw_die_ref mod_type_die = NULL; @@ -7931,7 +7970,8 @@ modified_type_die (type, is_const_type, is_volatile_type, context_die) else if (code == POINTER_TYPE) { mod_type_die = new_die (DW_TAG_pointer_type, comp_unit_die, type); - add_AT_unsigned (mod_type_die, DW_AT_byte_size, PTR_SIZE); + add_AT_unsigned (mod_type_die, DW_AT_byte_size, + simple_type_size_in_bits (type) / BITS_PER_UNIT); #if 0 add_AT_unsigned (mod_type_die, DW_AT_address_class, 0); #endif @@ -7940,12 +7980,15 @@ modified_type_die (type, is_const_type, is_volatile_type, context_die) else if (code == REFERENCE_TYPE) { mod_type_die = new_die (DW_TAG_reference_type, comp_unit_die, type); - add_AT_unsigned (mod_type_die, DW_AT_byte_size, PTR_SIZE); + add_AT_unsigned (mod_type_die, DW_AT_byte_size, + simple_type_size_in_bits (type) / BITS_PER_UNIT); #if 0 add_AT_unsigned (mod_type_die, DW_AT_address_class, 0); #endif item_type = TREE_TYPE (type); } + else if (is_subrange_type (type)) + mod_type_die = subrange_type_die (type, context_die); else if (is_base_type (type)) mod_type_die = base_type_die (type); else @@ -7994,17 +8037,15 @@ modified_type_die (type, is_const_type, is_volatile_type, context_die) an enumerated type. */ static inline int -type_is_enum (type) - tree type; +type_is_enum (tree type) { return TREE_CODE (type) == ENUMERAL_TYPE; } -/* Return the register number described by a given RTL node. */ +/* Return the DBX register number described by a given RTL node. */ static unsigned int -reg_number (rtl) - rtx rtl; +dbx_reg_number (rtx rtl) { unsigned regno = REGNO (rtl); @@ -8015,32 +8056,94 @@ reg_number (rtl) } /* Return a location descriptor that designates a machine register or - zero if there is no such. */ + zero if there is none. */ static dw_loc_descr_ref -reg_loc_descriptor (rtl) - rtx rtl; +reg_loc_descriptor (rtx rtl) { - dw_loc_descr_ref loc_result = NULL; unsigned reg; + rtx regs; if (REGNO (rtl) >= FIRST_PSEUDO_REGISTER) return 0; - reg = reg_number (rtl); - if (reg <= 31) - loc_result = new_loc_descr (DW_OP_reg0 + reg, 0, 0); + reg = dbx_reg_number (rtl); + regs = (*targetm.dwarf_register_span) (rtl); + + if (HARD_REGNO_NREGS (REGNO (rtl), GET_MODE (rtl)) > 1 + || regs) + return multiple_reg_loc_descriptor (rtl, regs); + else + return one_reg_loc_descriptor (reg); +} + +/* Return a location descriptor that designates a machine register for + a given hard register number. */ + +static dw_loc_descr_ref +one_reg_loc_descriptor (unsigned int regno) +{ + if (regno <= 31) + return new_loc_descr (DW_OP_reg0 + regno, 0, 0); else - loc_result = new_loc_descr (DW_OP_regx, reg, 0); + return new_loc_descr (DW_OP_regx, regno, 0); +} + +/* Given an RTL of a register, return a location descriptor that + designates a value that spans more than one register. */ + +static dw_loc_descr_ref +multiple_reg_loc_descriptor (rtx rtl, rtx regs) +{ + int nregs, size, i; + unsigned reg; + dw_loc_descr_ref loc_result = NULL; + + reg = dbx_reg_number (rtl); + nregs = HARD_REGNO_NREGS (REGNO (rtl), GET_MODE (rtl)); + + /* Simple, contiguous registers. */ + if (regs == NULL_RTX) + { + size = GET_MODE_SIZE (GET_MODE (rtl)) / nregs; + + loc_result = NULL; + while (nregs--) + { + dw_loc_descr_ref t; + + t = one_reg_loc_descriptor (reg); + add_loc_descr (&loc_result, t); + add_loc_descr (&loc_result, new_loc_descr (DW_OP_piece, size, 0)); + ++reg; + } + return loc_result; + } + + /* Now onto stupid register sets in non contiguous locations. */ + if (GET_CODE (regs) != PARALLEL) + abort (); + + size = GET_MODE_SIZE (GET_MODE (XVECEXP (regs, 0, 0))); + loc_result = NULL; + + for (i = 0; i < XVECLEN (regs, 0); ++i) + { + dw_loc_descr_ref t; + + t = one_reg_loc_descriptor (REGNO (XVECEXP (regs, 0, i))); + add_loc_descr (&loc_result, t); + size = GET_MODE_SIZE (GET_MODE (XVECEXP (regs, 0, 0))); + add_loc_descr (&loc_result, new_loc_descr (DW_OP_piece, size, 0)); + } return loc_result; } /* Return a location descriptor that designates a constant. */ static dw_loc_descr_ref -int_loc_descriptor (i) - HOST_WIDE_INT i; +int_loc_descriptor (HOST_WIDE_INT i) { enum dwarf_location_atom op; @@ -8079,9 +8182,7 @@ int_loc_descriptor (i) /* Return a location descriptor that designates a base+offset location. */ static dw_loc_descr_ref -based_loc_descr (reg, offset) - unsigned reg; - long int offset; +based_loc_descr (unsigned int reg, HOST_WIDE_INT offset) { dw_loc_descr_ref loc_result; /* For the "frame base", we use the frame pointer or stack pointer @@ -8104,8 +8205,7 @@ based_loc_descr (reg, offset) /* Return true if this RTL expression describes a base+offset calculation. */ static inline int -is_based_loc (rtl) - rtx rtl; +is_based_loc (rtx rtl) { return (GET_CODE (rtl) == PLUS && ((GET_CODE (XEXP (rtl, 0)) == REG @@ -8129,9 +8229,7 @@ is_based_loc (rtl) Return 0 if we can't represent the location. */ static dw_loc_descr_ref -mem_loc_descriptor (rtl, mode) - rtx rtl; - enum machine_mode mode; +mem_loc_descriptor (rtx rtl, enum machine_mode mode) { dw_loc_descr_ref mem_loc_result = NULL; @@ -8140,9 +8238,7 @@ mem_loc_descriptor (rtl, mode) actually within the array. That's *not* necessarily the same as the zeroth element of the array. */ -#ifdef ASM_SIMPLIFY_DWARF_ADDR - rtl = ASM_SIMPLIFY_DWARF_ADDR (rtl); -#endif + rtl = (*targetm.delegitimize_address) (rtl); switch (GET_CODE (rtl)) { @@ -8156,30 +8252,30 @@ mem_loc_descriptor (rtl, mode) case SUBREG: /* The case of a subreg may arise when we have a local (register) - variable or a formal (register) parameter which doesn't quite fill - up an entire register. For now, just assume that it is - legitimate to make the Dwarf info refer to the whole register which - contains the given subreg. */ + variable or a formal (register) parameter which doesn't quite fill + up an entire register. For now, just assume that it is + legitimate to make the Dwarf info refer to the whole register which + contains the given subreg. */ rtl = SUBREG_REG (rtl); /* ... fall through ... */ case REG: /* Whenever a register number forms a part of the description of the - method for calculating the (dynamic) address of a memory resident - object, DWARF rules require the register number be referred to as - a "base register". This distinction is not based in any way upon - what category of register the hardware believes the given register - belongs to. This is strictly DWARF terminology we're dealing with - here. Note that in cases where the location of a memory-resident - data object could be expressed as: OP_ADD (OP_BASEREG (basereg), - OP_CONST (0)) the actual DWARF location descriptor that we generate - may just be OP_BASEREG (basereg). This may look deceptively like - the object in question was allocated to a register (rather than in - memory) so DWARF consumers need to be aware of the subtle - distinction between OP_REG and OP_BASEREG. */ + method for calculating the (dynamic) address of a memory resident + object, DWARF rules require the register number be referred to as + a "base register". This distinction is not based in any way upon + what category of register the hardware believes the given register + belongs to. This is strictly DWARF terminology we're dealing with + here. Note that in cases where the location of a memory-resident + data object could be expressed as: OP_ADD (OP_BASEREG (basereg), + OP_CONST (0)) the actual DWARF location descriptor that we generate + may just be OP_BASEREG (basereg). This may look deceptively like + the object in question was allocated to a register (rather than in + memory) so DWARF consumers need to be aware of the subtle + distinction between OP_REG and OP_BASEREG. */ if (REGNO (rtl) < FIRST_PSEUDO_REGISTER) - mem_loc_result = based_loc_descr (reg_number (rtl), 0); + mem_loc_result = based_loc_descr (dbx_reg_number (rtl), 0); break; case MEM: @@ -8195,8 +8291,8 @@ mem_loc_descriptor (rtl, mode) case LABEL_REF: /* Some ports can transform a symbol ref into a label ref, because - the symbol ref is too far away and has to be dumped into a constant - pool. */ + the symbol ref is too far away and has to be dumped into a constant + pool. */ case CONST: case SYMBOL_REF: /* Alternatively, the symbol in the constant pool might be referenced @@ -8231,7 +8327,7 @@ mem_loc_descriptor (rtl, mode) case PRE_MODIFY: /* Extract the PLUS expression nested inside and fall into - PLUS code below. */ + PLUS code below. */ rtl = XEXP (rtl, 1); goto plus; @@ -8249,7 +8345,7 @@ mem_loc_descriptor (rtl, mode) case PLUS: plus: if (is_based_loc (rtl)) - mem_loc_result = based_loc_descr (reg_number (XEXP (rtl, 0)), + mem_loc_result = based_loc_descr (dbx_reg_number (XEXP (rtl, 0)), INTVAL (XEXP (rtl, 1))); else { @@ -8311,8 +8407,7 @@ mem_loc_descriptor (rtl, mode) This is typically a complex variable. */ static dw_loc_descr_ref -concat_loc_descriptor (x0, x1) - rtx x0, x1; +concat_loc_descriptor (rtx x0, rtx x1) { dw_loc_descr_ref cc_loc_result = NULL; dw_loc_descr_ref x0_ref = loc_descriptor (x0); @@ -8343,8 +8438,7 @@ concat_loc_descriptor (x0, x1) If we don't know how to describe it, return 0. */ static dw_loc_descr_ref -loc_descriptor (rtl) - rtx rtl; +loc_descriptor (rtx rtl) { dw_loc_descr_ref loc_result = NULL; @@ -8352,10 +8446,10 @@ loc_descriptor (rtl) { case SUBREG: /* The case of a subreg may arise when we have a local (register) - variable or a formal (register) parameter which doesn't quite fill - up an entire register. For now, just assume that it is - legitimate to make the Dwarf info refer to the whole register which - contains the given subreg. */ + variable or a formal (register) parameter which doesn't quite fill + up an entire register. For now, just assume that it is + legitimate to make the Dwarf info refer to the whole register which + contains the given subreg. */ rtl = SUBREG_REG (rtl); /* ... fall through ... */ @@ -8385,9 +8479,7 @@ loc_descriptor (rtl) descriptor, return 0. */ static dw_loc_descr_ref -loc_descriptor_from_tree (loc, addressp) - tree loc; - int addressp; +loc_descriptor_from_tree (tree loc, int addressp) { dw_loc_descr_ref ret, ret1; int indirect_p = 0; @@ -8414,6 +8506,13 @@ loc_descriptor_from_tree (loc, addressp) case CALL_EXPR: return 0; + case PREINCREMENT_EXPR: + case PREDECREMENT_EXPR: + case POSTINCREMENT_EXPR: + case POSTDECREMENT_EXPR: + /* There are no opcodes for these operations. */ + return 0; + case ADDR_EXPR: /* We can support this only if we can look through conversions and find an INDIRECT_EXPR. */ @@ -8464,7 +8563,7 @@ loc_descriptor_from_tree (loc, addressp) indirect_p = 1; break; } - /* FALLTHRU */ + /* Fall through. */ case PARM_DECL: { @@ -8507,6 +8606,7 @@ loc_descriptor_from_tree (loc, addressp) case NON_LVALUE_EXPR: case VIEW_CONVERT_EXPR: case SAVE_EXPR: + case MODIFY_EXPR: return loc_descriptor_from_tree (TREE_OPERAND (loc, 0), addressp); case COMPONENT_REF: @@ -8558,6 +8658,24 @@ loc_descriptor_from_tree (loc, addressp) return 0; break; + case CONSTRUCTOR: + { + /* Get an RTL for this, if something has been emitted. */ + rtx rtl = lookup_constant_def (loc); + enum machine_mode mode; + + if (GET_CODE (rtl) != MEM) + return 0; + mode = GET_MODE (rtl); + rtl = XEXP (rtl, 0); + + rtl = (*targetm.delegitimize_address) (rtl); + + indirect_p = 1; + ret = mem_loc_descriptor (rtl, mode); + break; + } + case TRUTH_AND_EXPR: case TRUTH_ANDIF_EXPR: case BIT_AND_EXPR: @@ -8575,6 +8693,9 @@ loc_descriptor_from_tree (loc, addressp) op = DW_OP_or; goto do_binop; + case FLOOR_DIV_EXPR: + case CEIL_DIV_EXPR: + case ROUND_DIV_EXPR: case TRUNC_DIV_EXPR: op = DW_OP_div; goto do_binop; @@ -8583,6 +8704,9 @@ loc_descriptor_from_tree (loc, addressp) op = DW_OP_minus; goto do_binop; + case FLOOR_MOD_EXPR: + case CEIL_MOD_EXPR: + case ROUND_MOD_EXPR: case TRUNC_MOD_EXPR: op = DW_OP_mod; goto do_binop; @@ -8724,7 +8848,18 @@ loc_descriptor_from_tree (loc, addressp) } break; + case EXPR_WITH_FILE_LOCATION: + return loc_descriptor_from_tree (EXPR_WFL_NODE (loc), addressp); + default: + /* Leave front-end specific codes as simply unknown. This comes + up, for instance, with the C STMT_EXPR. */ + if ((unsigned int) TREE_CODE (loc) + >= (unsigned int) LAST_AND_UNUSED_TREE_CODE) + return 0; + + /* Otherwise this is a generic code; we should just lists all of + these explicitly. Aborting means we forgot one. */ abort (); } @@ -8754,9 +8889,7 @@ loc_descriptor_from_tree (loc, addressp) which is not less than the value itself. */ static inline HOST_WIDE_INT -ceiling (value, boundary) - HOST_WIDE_INT value; - unsigned int boundary; +ceiling (HOST_WIDE_INT value, unsigned int boundary) { return (((value + boundary - 1) / boundary) * boundary); } @@ -8767,8 +8900,7 @@ ceiling (value, boundary) ERROR_MARK node. */ static inline tree -field_type (decl) - tree decl; +field_type (tree decl) { tree type; @@ -8787,40 +8919,17 @@ field_type (decl) be an ERROR_MARK node. */ static inline unsigned -simple_type_align_in_bits (type) - tree type; +simple_type_align_in_bits (tree type) { return (TREE_CODE (type) != ERROR_MARK) ? TYPE_ALIGN (type) : BITS_PER_WORD; } static inline unsigned -simple_decl_align_in_bits (decl) - tree decl; +simple_decl_align_in_bits (tree decl) { return (TREE_CODE (decl) != ERROR_MARK) ? DECL_ALIGN (decl) : BITS_PER_WORD; } -/* Given a pointer to a tree node, assumed to be some kind of a ..._TYPE - node, return the size in bits for the type if it is a constant, or else - return the alignment for the type if the type's size is not constant, or - else return BITS_PER_WORD if the type actually turns out to be an - ERROR_MARK node. */ - -static inline unsigned HOST_WIDE_INT -simple_type_size_in_bits (type) - tree type; -{ - - if (TREE_CODE (type) == ERROR_MARK) - return BITS_PER_WORD; - else if (TYPE_SIZE (type) == NULL_TREE) - return 0; - else if (host_integerp (TYPE_SIZE (type), 1)) - return tree_low_cst (TYPE_SIZE (type), 1); - else - return TYPE_ALIGN (type); -} - /* Given a pointer to a FIELD_DECL, compute and return the byte offset of the lowest addressed byte of the "containing object" for the given FIELD_DECL, or return 0 if we are unable to determine what that offset is, either @@ -8829,8 +8938,7 @@ simple_type_size_in_bits (type) just yet). */ static HOST_WIDE_INT -field_byte_offset (decl) - tree decl; +field_byte_offset (tree decl) { unsigned int type_align_in_bits; unsigned int decl_align_in_bits; @@ -8949,10 +9057,8 @@ field_byte_offset (decl) generated by the routine `data_member_location_attribute' below. */ static inline void -add_AT_location_description (die, attr_kind, descr) - dw_die_ref die; - enum dwarf_attribute attr_kind; - dw_loc_descr_ref descr; +add_AT_location_description (dw_die_ref die, enum dwarf_attribute attr_kind, + dw_loc_descr_ref descr) { if (descr != 0) add_AT_loc (die, attr_kind, descr); @@ -8978,11 +9084,9 @@ add_AT_location_description (die, attr_kind, descr) function below.) */ static void -add_data_member_location_attribute (die, decl) - dw_die_ref die; - tree decl; +add_data_member_location_attribute (dw_die_ref die, tree decl) { - long offset; + HOST_WIDE_INT offset; dw_loc_descr_ref loc_descr = 0; if (TREE_CODE (decl) == TREE_VEC) @@ -9056,80 +9160,93 @@ add_data_member_location_attribute (die, decl) add_AT_loc (die, DW_AT_data_member_location, loc_descr); } -/* Attach an DW_AT_const_value attribute for a variable or a parameter which +/* Writes integer values to dw_vec_const array. */ + +static void +insert_int (HOST_WIDE_INT val, unsigned int size, unsigned char *dest) +{ + while (size != 0) + { + *dest++ = val & 0xff; + val >>= 8; + --size; + } +} + +/* Reads integers from dw_vec_const array. Inverse of insert_int. */ + +static HOST_WIDE_INT +extract_int (const unsigned char *src, unsigned int size) +{ + HOST_WIDE_INT val = 0; + + src += size; + while (size != 0) + { + val <<= 8; + val |= *--src & 0xff; + --size; + } + return val; +} + +/* Writes floating point values to dw_vec_const array. */ + +static void +insert_float (rtx rtl, unsigned char *array) +{ + REAL_VALUE_TYPE rv; + long val[4]; + int i; + + REAL_VALUE_FROM_CONST_DOUBLE (rv, rtl); + real_to_target (val, &rv, GET_MODE (rtl)); + + /* real_to_target puts 32-bit pieces in each long. Pack them. */ + for (i = 0; i < GET_MODE_SIZE (GET_MODE (rtl)) / 4; i++) + { + insert_int (val[i], 4, array); + array += 4; + } +} + +/* Attach a DW_AT_const_value attribute for a variable or a parameter which does not have a "location" either in memory or in a register. These things can arise in GNU C when a constant is passed as an actual parameter to an inlined function. They can also arise in C++ where declared constants do not necessarily get memory "homes". */ static void -add_const_value_attribute (die, rtl) - dw_die_ref die; - rtx rtl; +add_const_value_attribute (dw_die_ref die, rtx rtl) { switch (GET_CODE (rtl)) { case CONST_INT: - /* Note that a CONST_INT rtx could represent either an integer - or a floating-point constant. A CONST_INT is used whenever - the constant will fit into a single word. In all such - cases, the original mode of the constant value is wiped - out, and the CONST_INT rtx is assigned VOIDmode. */ { HOST_WIDE_INT val = INTVAL (rtl); - /* ??? We really should be using HOST_WIDE_INT throughout. */ - if (val < 0 && (long) val == val) - add_AT_int (die, DW_AT_const_value, (long) val); - else if ((unsigned long) val == (unsigned HOST_WIDE_INT) val) - add_AT_unsigned (die, DW_AT_const_value, (unsigned long) val); - else - { -#if HOST_BITS_PER_LONG * 2 == HOST_BITS_PER_WIDE_INT - add_AT_long_long (die, DW_AT_const_value, - val >> HOST_BITS_PER_LONG, val); -#else - abort (); -#endif - } + if (val < 0) + add_AT_int (die, DW_AT_const_value, val); + else + add_AT_unsigned (die, DW_AT_const_value, (unsigned HOST_WIDE_INT) val); } break; case CONST_DOUBLE: /* Note that a CONST_DOUBLE rtx could represent either an integer or a - floating-point constant. A CONST_DOUBLE is used whenever the - constant requires more than one word in order to be adequately - represented. We output CONST_DOUBLEs as blocks. */ + floating-point constant. A CONST_DOUBLE is used whenever the + constant requires more than one word in order to be adequately + represented. We output CONST_DOUBLEs as blocks. */ { enum machine_mode mode = GET_MODE (rtl); if (GET_MODE_CLASS (mode) == MODE_FLOAT) { - unsigned length = GET_MODE_SIZE (mode) / 4; - long *array = (long *) xmalloc (sizeof (long) * length); - REAL_VALUE_TYPE rv; - - REAL_VALUE_FROM_CONST_DOUBLE (rv, rtl); - switch (mode) - { - case SFmode: - REAL_VALUE_TO_TARGET_SINGLE (rv, array[0]); - break; - - case DFmode: - REAL_VALUE_TO_TARGET_DOUBLE (rv, array); - break; - - case XFmode: - case TFmode: - REAL_VALUE_TO_TARGET_LONG_DOUBLE (rv, array); - break; + unsigned int length = GET_MODE_SIZE (mode); + unsigned char *array = ggc_alloc (length); - default: - abort (); - } - - add_AT_float (die, DW_AT_const_value, length, array); + insert_float (rtl, array); + add_AT_vec (die, DW_AT_const_value, length / 4, 4, array); } else { @@ -9143,6 +9260,68 @@ add_const_value_attribute (die, rtl) } break; + case CONST_VECTOR: + { + enum machine_mode mode = GET_MODE (rtl); + unsigned int elt_size = GET_MODE_UNIT_SIZE (mode); + unsigned int length = CONST_VECTOR_NUNITS (rtl); + unsigned char *array = ggc_alloc (length * elt_size); + unsigned int i; + unsigned char *p; + + if (GET_MODE_CLASS (mode) == MODE_VECTOR_INT) + { + for (i = 0, p = array; i < length; i++, p += elt_size) + { + rtx elt = CONST_VECTOR_ELT (rtl, i); + HOST_WIDE_INT lo, hi; + if (GET_CODE (elt) == CONST_INT) + { + lo = INTVAL (elt); + hi = -(lo < 0); + } + else if (GET_CODE (elt) == CONST_DOUBLE) + { + lo = CONST_DOUBLE_LOW (elt); + hi = CONST_DOUBLE_HIGH (elt); + } + else + abort (); + + if (elt_size <= sizeof (HOST_WIDE_INT)) + insert_int (lo, elt_size, p); + else if (elt_size == 2 * sizeof (HOST_WIDE_INT)) + { + unsigned char *p0 = p; + unsigned char *p1 = p + sizeof (HOST_WIDE_INT); + + if (WORDS_BIG_ENDIAN) + { + p0 = p1; + p1 = p; + } + insert_int (lo, sizeof (HOST_WIDE_INT), p0); + insert_int (hi, sizeof (HOST_WIDE_INT), p1); + } + else + abort (); + } + } + else if (GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT) + { + for (i = 0, p = array; i < length; i++, p += elt_size) + { + rtx elt = CONST_VECTOR_ELT (rtl, i); + insert_float (elt, p); + } + } + else + abort (); + + add_AT_vec (die, DW_AT_const_value, length, elt_size, array); + } + break; + case CONST_STRING: add_AT_string (die, DW_AT_const_value, XSTR (rtl, 0)); break; @@ -9156,16 +9335,16 @@ add_const_value_attribute (die, rtl) case PLUS: /* In cases where an inlined instance of an inline function is passed - the address of an `auto' variable (which is local to the caller) we - can get a situation where the DECL_RTL of the artificial local - variable (for the inlining) which acts as a stand-in for the - corresponding formal parameter (of the inline function) will look - like (plus:SI (reg:SI FRAME_PTR) (const_int ...)). This is not - exactly a compile-time constant expression, but it isn't the address - of the (artificial) local variable either. Rather, it represents the - *value* which the artificial local variable always has during its - lifetime. We currently have no way to represent such quasi-constant - values in Dwarf, so for now we just punt and generate nothing. */ + the address of an `auto' variable (which is local to the caller) we + can get a situation where the DECL_RTL of the artificial local + variable (for the inlining) which acts as a stand-in for the + corresponding formal parameter (of the inline function) will look + like (plus:SI (reg:SI FRAME_PTR) (const_int ...)). This is not + exactly a compile-time constant expression, but it isn't the address + of the (artificial) local variable either. Rather, it represents the + *value* which the artificial local variable always has during its + lifetime. We currently have no way to represent such quasi-constant + values in Dwarf, so for now we just punt and generate nothing. */ break; default: @@ -9176,8 +9355,7 @@ add_const_value_attribute (die, rtl) } static rtx -rtl_for_decl_location (decl) - tree decl; +rtl_for_decl_location (tree decl) { rtx rtl; @@ -9270,9 +9448,7 @@ rtl_for_decl_location (decl) && TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl)))) { -#ifdef ASM_SIMPLIFY_DWARF_ADDR - rtl = ASM_SIMPLIFY_DWARF_ADDR (rtl); -#endif + rtl = (*targetm.delegitimize_address) (rtl); return rtl; } rtl = NULL_RTX; @@ -9378,10 +9554,8 @@ rtl_for_decl_location (decl) } } -#ifdef ASM_SIMPLIFY_DWARF_ADDR if (rtl) - rtl = ASM_SIMPLIFY_DWARF_ADDR (rtl); -#endif + rtl = (*targetm.delegitimize_address) (rtl); /* If we don't look past the constant pool, we risk emitting a reference to a constant pool entry that isn't referenced from @@ -9392,7 +9566,7 @@ rtl_for_decl_location (decl) return rtl; } -/* Generate *either* an DW_AT_location attribute or else an DW_AT_const_value +/* Generate *either* a DW_AT_location attribute or else a DW_AT_const_value data attribute for a variable or a parameter. We generate the DW_AT_const_value attribute only in those cases where the given variable or parameter does not have a true "location" either in memory or in a @@ -9404,9 +9578,7 @@ rtl_for_decl_location (decl) function call evaluates to a compile-time constant address. */ static void -add_location_or_const_value_attribute (die, decl) - dw_die_ref die; - tree decl; +add_location_or_const_value_attribute (dw_die_ref die, tree decl) { rtx rtl; dw_loc_descr_ref descr; @@ -9429,6 +9601,7 @@ add_location_or_const_value_attribute (die, decl) case CONST_INT: case CONST_DOUBLE: + case CONST_VECTOR: case CONST_STRING: case SYMBOL_REF: case LABEL_REF: @@ -9456,7 +9629,34 @@ add_location_or_const_value_attribute (die, decl) } add_AT_location_description (die, DW_AT_location, descr); break; - + + case PARALLEL: + { + rtvec par_elems = XVEC (rtl, 0); + int num_elem = GET_NUM_ELEM (par_elems); + enum machine_mode mode; + int i; + + /* Create the first one, so we have something to add to. */ + descr = loc_descriptor (XEXP (RTVEC_ELT (par_elems, 0), 0)); + mode = GET_MODE (XEXP (RTVEC_ELT (par_elems, 0), 0)); + add_loc_descr (&descr, + new_loc_descr (DW_OP_piece, GET_MODE_SIZE (mode), 0)); + for (i = 1; i < num_elem; i++) + { + dw_loc_descr_ref temp; + + temp = loc_descriptor (XEXP (RTVEC_ELT (par_elems, i), 0)); + add_loc_descr (&descr, temp); + mode = GET_MODE (XEXP (RTVEC_ELT (par_elems, i), 0)); + add_loc_descr (&descr, + new_loc_descr (DW_OP_piece, + GET_MODE_SIZE (mode), 0)); + } + } + add_AT_location_description (die, DW_AT_location, descr); + break; + default: abort (); } @@ -9467,9 +9667,7 @@ add_location_or_const_value_attribute (die, decl) we should tell the debugger about the constant value. */ static void -tree_add_const_value_attribute (var_die, decl) - dw_die_ref var_die; - tree decl; +tree_add_const_value_attribute (dw_die_ref var_die, tree decl) { tree init = DECL_INITIAL (decl); tree type = TREE_TYPE (decl); @@ -9496,13 +9694,11 @@ tree_add_const_value_attribute (var_die, decl) } } -/* Generate an DW_AT_name attribute given some string value to be included as +/* Generate a DW_AT_name attribute given some string value to be included as the value of the attribute. */ -static inline void -add_name_attribute (die, name_string) - dw_die_ref die; - const char *name_string; +static void +add_name_attribute (dw_die_ref die, const char *name_string) { if (name_string != NULL && *name_string != 0) { @@ -9513,14 +9709,21 @@ add_name_attribute (die, name_string) } } +/* Generate a DW_AT_comp_dir attribute for DIE. */ + +static void +add_comp_dir_attribute (dw_die_ref die) +{ + const char *wd = get_src_pwd (); + if (wd != NULL) + add_AT_string (die, DW_AT_comp_dir, wd); +} + /* Given a tree node describing an array bound (either lower or upper) output a representation for that bound. */ static void -add_bound_info (subrange_die, bound_attr, bound) - dw_die_ref subrange_die; - enum dwarf_attribute bound_attr; - tree bound; +add_bound_info (dw_die_ref subrange_die, enum dwarf_attribute bound_attr, tree bound) { switch (TREE_CODE (bound)) { @@ -9548,23 +9751,23 @@ add_bound_info (subrange_die, bound_attr, bound) case SAVE_EXPR: /* If optimization is turned on, the SAVE_EXPRs that describe how to - access the upper bound values may be bogus. If they refer to a - register, they may only describe how to get at these values at the - points in the generated code right after they have just been - computed. Worse yet, in the typical case, the upper bound values - will not even *be* computed in the optimized code (though the - number of elements will), so these SAVE_EXPRs are entirely - bogus. In order to compensate for this fact, we check here to see - if optimization is enabled, and if so, we don't add an attribute - for the (unknown and unknowable) upper bound. This should not - cause too much trouble for existing (stupid?) debuggers because - they have to deal with empty upper bounds location descriptions - anyway in order to be able to deal with incomplete array types. - Of course an intelligent debugger (GDB?) should be able to - comprehend that a missing upper bound specification in an array - type used for a storage class `auto' local array variable - indicates that the upper bound is both unknown (at compile- time) - and unknowable (at run-time) due to optimization. + access the upper bound values may be bogus. If they refer to a + register, they may only describe how to get at these values at the + points in the generated code right after they have just been + computed. Worse yet, in the typical case, the upper bound values + will not even *be* computed in the optimized code (though the + number of elements will), so these SAVE_EXPRs are entirely + bogus. In order to compensate for this fact, we check here to see + if optimization is enabled, and if so, we don't add an attribute + for the (unknown and unknowable) upper bound. This should not + cause too much trouble for existing (stupid?) debuggers because + they have to deal with empty upper bounds location descriptions + anyway in order to be able to deal with incomplete array types. + Of course an intelligent debugger (GDB?) should be able to + comprehend that a missing upper bound specification in an array + type used for a storage class `auto' local array variable + indicates that the upper bound is both unknown (at compile- time) + and unknowable (at run-time) due to optimization. We assume that a MEM rtx is safe because gcc wouldn't put the value there unless it was going to be used repeatedly in the @@ -9652,9 +9855,7 @@ add_bound_info (subrange_die, bound_attr, bound) includes information about the element type of type given array type. */ static void -add_subscript_info (type_die, type) - dw_die_ref type_die; - tree type; +add_subscript_info (dw_die_ref type_die, tree type) { #ifndef MIPS_DEBUGGING_INFO unsigned dimension_number; @@ -9685,7 +9886,7 @@ add_subscript_info (type_die, type) /* Arrays come in three flavors: Unspecified bounds, fixed bounds, and (in GNU C only) variable bounds. Handle all three forms - here. */ + here. */ subrange_die = new_die (DW_TAG_subrange_type, type_die, NULL); if (domain) { @@ -9693,7 +9894,7 @@ add_subscript_info (type_die, type) lower = TYPE_MIN_VALUE (domain); upper = TYPE_MAX_VALUE (domain); - /* define the index type. */ + /* Define the index type. */ if (TREE_TYPE (domain)) { /* ??? This is probably an Ada unnamed subrange type. Ignore the @@ -9712,7 +9913,7 @@ add_subscript_info (type_die, type) /* ??? If upper is NULL, the array has unspecified length, but it does have a lower bound. This happens with Fortran dimension arr(N:*) - Since the debugger is definitely going to need to know N + Since the debugger is definitely going to need to know N to produce useful results, go ahead and output the lower bound solo, and hope the debugger can cope. */ @@ -9728,9 +9929,7 @@ add_subscript_info (type_die, type) } static void -add_byte_size_attribute (die, tree_node) - dw_die_ref die; - tree tree_node; +add_byte_size_attribute (dw_die_ref die, tree tree_node) { unsigned size; @@ -9747,9 +9946,9 @@ add_byte_size_attribute (die, tree_node) break; case FIELD_DECL: /* For a data member of a struct or union, the DW_AT_byte_size is - generally given as the number of bytes normally allocated for an - object of the *declared* type of the member itself. This is true - even for bit-fields. */ + generally given as the number of bytes normally allocated for an + object of the *declared* type of the member itself. This is true + even for bit-fields. */ size = simple_type_size_in_bits (field_type (tree_node)) / BITS_PER_UNIT; break; default: @@ -9780,9 +9979,7 @@ add_byte_size_attribute (die, tree_node) (See `byte_size_attribute' above). */ static inline void -add_bit_offset_attribute (die, decl) - dw_die_ref die; - tree decl; +add_bit_offset_attribute (dw_die_ref die, tree decl) { HOST_WIDE_INT object_offset_in_bytes = field_byte_offset (decl); tree type = DECL_BIT_FIELD_TYPE (decl); @@ -9831,9 +10028,7 @@ add_bit_offset_attribute (die, decl) which specifies the length in bits of the given field. */ static inline void -add_bit_size_attribute (die, decl) - dw_die_ref die; - tree decl; +add_bit_size_attribute (dw_die_ref die, tree decl) { /* Must be a field and a bit field. */ if (TREE_CODE (decl) != FIELD_DECL @@ -9848,9 +10043,7 @@ add_bit_size_attribute (die, decl) attribute, if arg types are given for the parameters of a function. */ static inline void -add_prototyped_attribute (die, func_type) - dw_die_ref die; - tree func_type; +add_prototyped_attribute (dw_die_ref die, tree func_type) { if (get_AT_unsigned (comp_unit_die, DW_AT_language) == DW_LANG_C89 && TYPE_ARG_TYPES (func_type) != NULL) @@ -9862,9 +10055,7 @@ add_prototyped_attribute (die, func_type) equate table. */ static inline void -add_abstract_origin_attribute (die, origin) - dw_die_ref die; - tree origin; +add_abstract_origin_attribute (dw_die_ref die, tree origin) { dw_die_ref origin_die = NULL; @@ -9874,7 +10065,7 @@ add_abstract_origin_attribute (die, origin) function, if we're in an exception handler or some such; make sure that the abstract function has been written out. - Doing this for nested functions is wrong, however; functions are + Doing this for nested functions is wrong, however; functions are distinct units, and our context might not even be inline. */ tree fn = origin; @@ -9900,9 +10091,7 @@ add_abstract_origin_attribute (die, origin) /* We do not currently support the pure_virtual attribute. */ static inline void -add_pure_or_virtual_attribute (die, func_decl) - dw_die_ref die; - tree func_decl; +add_pure_or_virtual_attribute (dw_die_ref die, tree func_decl) { if (DECL_VINDEX (func_decl)) { @@ -9924,9 +10113,7 @@ add_pure_or_virtual_attribute (die, func_decl) /* Add source coordinate attributes for the given decl. */ static void -add_src_coords_attributes (die, decl) - dw_die_ref die; - tree decl; +add_src_coords_attributes (dw_die_ref die, tree decl) { unsigned file_index = lookup_filename (DECL_SOURCE_FILE (decl)); @@ -9934,13 +10121,11 @@ add_src_coords_attributes (die, decl) add_AT_unsigned (die, DW_AT_decl_line, DECL_SOURCE_LINE (decl)); } -/* Add an DW_AT_name attribute and source coordinate attribute for the +/* Add a DW_AT_name attribute and source coordinate attribute for the given decl, but only if it actually has a name. */ static void -add_name_and_src_coords_attributes (die, decl) - dw_die_ref die; - tree decl; +add_name_and_src_coords_attributes (dw_die_ref die, tree decl) { tree decl_name; @@ -9974,8 +10159,7 @@ add_name_and_src_coords_attributes (die, decl) /* Push a new declaration scope. */ static void -push_decl_scope (scope) - tree scope; +push_decl_scope (tree scope) { VARRAY_PUSH_TREE (decl_scope_table, scope); } @@ -9983,7 +10167,7 @@ push_decl_scope (scope) /* Pop a declaration scope. */ static inline void -pop_decl_scope () +pop_decl_scope (void) { if (VARRAY_ACTIVE_SIZE (decl_scope_table) <= 0) abort (); @@ -9998,9 +10182,7 @@ pop_decl_scope () the current active scope. */ static dw_die_ref -scope_die_for (t, context_die) - tree t; - dw_die_ref context_die; +scope_die_for (tree t, dw_die_ref context_die) { dw_die_ref scope_die = NULL; tree containing_scope; @@ -10012,9 +10194,14 @@ scope_die_for (t, context_die) containing_scope = TYPE_CONTEXT (t); - /* Ignore namespaces for the moment. */ + /* Use the containing namespace if it was passed in (for a declaration). */ if (containing_scope && TREE_CODE (containing_scope) == NAMESPACE_DECL) - containing_scope = NULL_TREE; + { + if (context_die == lookup_decl_die (containing_scope)) + /* OK */; + else + containing_scope = NULL_TREE; + } /* Ignore function type "scopes" from the C frontend. They mean that a tagged type is local to a parmlist of a function declarator, but @@ -10054,8 +10241,7 @@ scope_die_for (t, context_die) /* Returns nonzero if CONTEXT_DIE is internal to a function. */ static inline int -local_scope_p (context_die) - dw_die_ref context_die; +local_scope_p (dw_die_ref context_die) { for (; context_die; context_die = context_die->die_parent) if (context_die->die_tag == DW_TAG_inlined_subroutine @@ -10065,28 +10251,25 @@ local_scope_p (context_die) return 0; } -/* Returns nonzero if CONTEXT_DIE is a class. */ +/* Returns nonzero if CONTEXT_DIE is a class or namespace, for deciding + whether or not to treat a DIE in this context as a declaration. */ static inline int -class_scope_p (context_die) - dw_die_ref context_die; +class_or_namespace_scope_p (dw_die_ref context_die) { return (context_die && (context_die->die_tag == DW_TAG_structure_type - || context_die->die_tag == DW_TAG_union_type)); + || context_die->die_tag == DW_TAG_union_type + || context_die->die_tag == DW_TAG_namespace)); } /* Many forms of DIEs require a "type description" attribute. This routine locates the proper "type descriptor" die for the type given - by 'type', and adds an DW_AT_type attribute below the given die. */ + by 'type', and adds a DW_AT_type attribute below the given die. */ static void -add_type_attribute (object_die, type, decl_const, decl_volatile, context_die) - dw_die_ref object_die; - tree type; - int decl_const; - int decl_volatile; - dw_die_ref context_die; +add_type_attribute (dw_die_ref object_die, tree type, int decl_const, + int decl_volatile, dw_die_ref context_die) { enum tree_code code = TREE_CODE (type); dw_die_ref type_die = NULL; @@ -10120,8 +10303,7 @@ add_type_attribute (object_die, type, decl_const, decl_volatile, context_die) was declared without a tag. */ static const char * -type_tag (type) - tree type; +type_tag (tree type) { const char *name = 0; @@ -10134,8 +10316,8 @@ type_tag (type) t = TYPE_NAME (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. */ + a TYPE_DECL node, regardless of whether or not a `typedef' was + involved. */ else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL && ! DECL_IGNORED_P (TYPE_NAME (type))) t = DECL_NAME (TYPE_NAME (type)); @@ -10152,8 +10334,7 @@ type_tag (type) for bit field types. */ static inline tree -member_declared_type (member) - tree member; +member_declared_type (tree member) { return (DECL_BIT_FIELD_TYPE (member) ? DECL_BIT_FIELD_TYPE (member) : TREE_TYPE (member)); @@ -10164,8 +10345,7 @@ member_declared_type (member) #if 0 static const char * -decl_start_label (decl) - tree decl; +decl_start_label (tree decl) { rtx x; const char *fnname; @@ -10188,9 +10368,7 @@ decl_start_label (decl) the declaration trees passed in from dwarf2out_decl(). */ static void -gen_array_type_die (type, context_die) - tree type; - dw_die_ref context_die; +gen_array_type_die (tree type, dw_die_ref context_die) { dw_die_ref scope_die = scope_die_for (type, context_die); dw_die_ref array_die; @@ -10230,7 +10408,7 @@ gen_array_type_die (type, context_die) /* The SGI compilers handle arrays of unknown bound by setting AT_declaration and not emitting any subrange DIEs. */ if (! TYPE_DOMAIN (type)) - add_AT_unsigned (array_die, DW_AT_declaration, 1); + add_AT_flag (array_die, DW_AT_declaration, 1); else #endif add_subscript_info (array_die, type); @@ -10253,9 +10431,7 @@ gen_array_type_die (type, context_die) } static void -gen_set_type_die (type, context_die) - tree type; - dw_die_ref context_die; +gen_set_type_die (tree type, dw_die_ref context_die) { dw_die_ref type_die = new_die (DW_TAG_set_type, scope_die_for (type, context_die), type); @@ -10266,9 +10442,7 @@ gen_set_type_die (type, context_die) #if 0 static void -gen_entry_point_die (decl, context_die) - tree decl; - dw_die_ref context_die; +gen_entry_point_die (tree decl, dw_die_ref context_die) { tree origin = decl_ultimate_origin (decl); dw_die_ref decl_die = new_die (DW_TAG_entry_point, context_die, decl); @@ -10293,7 +10467,7 @@ gen_entry_point_die (decl, context_die) emit full debugging info for them. */ static void -retry_incomplete_types () +retry_incomplete_types (void) { int i; @@ -10304,9 +10478,7 @@ retry_incomplete_types () /* Generate a DIE to represent an inlined instance of an enumeration type. */ static void -gen_inlined_enumeration_type_die (type, context_die) - tree type; - dw_die_ref context_die; +gen_inlined_enumeration_type_die (tree type, dw_die_ref context_die) { dw_die_ref type_die = new_die (DW_TAG_enumeration_type, context_die, type); @@ -10318,9 +10490,7 @@ gen_inlined_enumeration_type_die (type, context_die) /* Generate a DIE to represent an inlined instance of a structure type. */ static void -gen_inlined_structure_type_die (type, context_die) - tree type; - dw_die_ref context_die; +gen_inlined_structure_type_die (tree type, dw_die_ref context_die) { dw_die_ref type_die = new_die (DW_TAG_structure_type, context_die, type); @@ -10332,9 +10502,7 @@ gen_inlined_structure_type_die (type, context_die) /* Generate a DIE to represent an inlined instance of a union type. */ static void -gen_inlined_union_type_die (type, context_die) - tree type; - dw_die_ref context_die; +gen_inlined_union_type_die (tree type, dw_die_ref context_die) { dw_die_ref type_die = new_die (DW_TAG_union_type, context_die, type); @@ -10348,10 +10516,8 @@ gen_inlined_union_type_die (type, context_die) enumerated type name/value is listed as a child of the enumerated type DIE. */ -static void -gen_enumeration_type_die (type, context_die) - tree type; - dw_die_ref context_die; +static dw_die_ref +gen_enumeration_type_die (tree type, dw_die_ref context_die) { dw_die_ref type_die = lookup_type_die (type); @@ -10363,7 +10529,7 @@ gen_enumeration_type_die (type, context_die) add_name_attribute (type_die, type_tag (type)); } else if (! TYPE_SIZE (type)) - return; + return type_die; else remove_AT (type_die, DW_AT_declaration); @@ -10388,24 +10554,26 @@ gen_enumeration_type_die (type, context_die) link != NULL; link = TREE_CHAIN (link)) { dw_die_ref enum_die = new_die (DW_TAG_enumerator, type_die, link); + tree value = TREE_VALUE (link); add_name_attribute (enum_die, IDENTIFIER_POINTER (TREE_PURPOSE (link))); - if (host_integerp (TREE_VALUE (link), - TREE_UNSIGNED (TREE_TYPE (TREE_VALUE (link))))) - { - if (tree_int_cst_sgn (TREE_VALUE (link)) < 0) - add_AT_int (enum_die, DW_AT_const_value, - tree_low_cst (TREE_VALUE (link), 0)); - else - add_AT_unsigned (enum_die, DW_AT_const_value, - tree_low_cst (TREE_VALUE (link), 1)); - } + if (host_integerp (value, TREE_UNSIGNED (TREE_TYPE (value)))) + /* DWARF2 does not provide a way of indicating whether or + not enumeration constants are signed or unsigned. GDB + always assumes the values are signed, so we output all + values as if they were signed. That means that + enumeration constants with very large unsigned values + will appear to have negative values in the debugger. */ + add_AT_int (enum_die, DW_AT_const_value, + tree_low_cst (value, tree_int_cst_sgn (value) > 0)); } } else add_AT_flag (type_die, DW_AT_declaration, 1); + + return type_die; } /* Generate a DIE to represent either a real live formal parameter decl or to @@ -10422,9 +10590,7 @@ gen_enumeration_type_die (type, context_die) argument type of some subprogram type. */ static dw_die_ref -gen_formal_parameter_die (node, context_die) - tree node; - dw_die_ref context_die; +gen_formal_parameter_die (tree node, dw_die_ref context_die) { dw_die_ref parm_die = new_die (DW_TAG_formal_parameter, context_die, node); @@ -10469,9 +10635,7 @@ gen_formal_parameter_die (node, context_die) at the end of an (ANSI prototyped) formal parameters list. */ static void -gen_unspecified_parameters_die (decl_or_type, context_die) - tree decl_or_type; - dw_die_ref context_die; +gen_unspecified_parameters_die (tree decl_or_type, dw_die_ref context_die) { new_die (DW_TAG_unspecified_parameters, context_die, decl_or_type); } @@ -10482,9 +10646,7 @@ gen_unspecified_parameters_die (decl_or_type, context_die) those which appear as part of a function *definition*). */ static void -gen_formal_types_die (function_or_method_type, context_die) - tree function_or_method_type; - dw_die_ref context_die; +gen_formal_types_die (tree function_or_method_type, dw_die_ref context_die) { tree link; tree formal_type = NULL; @@ -10543,9 +10705,7 @@ gen_formal_types_die (function_or_method_type, context_die) trick; we need to attach the member declaration by hand. */ static void -gen_type_die_for_member (type, member, context_die) - tree type, member; - dw_die_ref context_die; +gen_type_die_for_member (tree type, tree member, dw_die_ref context_die) { gen_type_die (type, context_die); @@ -10571,8 +10731,7 @@ gen_type_die_for_member (type, member, context_die) may later generate inlined and/or out-of-line instances of. */ static void -dwarf2out_abstract_function (decl) - tree decl; +dwarf2out_abstract_function (tree decl) { dw_die_ref old_die; tree save_fn; @@ -10583,7 +10742,7 @@ dwarf2out_abstract_function (decl) decl = DECL_ORIGIN (decl); old_die = lookup_decl_die (decl); - if (old_die && get_AT_unsigned (old_die, DW_AT_inline)) + if (old_die && get_AT (old_die, DW_AT_inline)) /* We've already generated the abstract instance. */ return; @@ -10613,9 +10772,7 @@ dwarf2out_abstract_function (decl) block-local). */ static void -gen_subprogram_die (decl, context_die) - tree decl; - dw_die_ref context_die; +gen_subprogram_die (tree decl, dw_die_ref context_die) { char label_id[MAX_ARTIFICIAL_LABEL_BYTES]; tree origin = decl_ultimate_origin (decl); @@ -10625,7 +10782,7 @@ gen_subprogram_die (decl, context_die) tree outer_scope; dw_die_ref old_die = lookup_decl_die (decl); int declaration = (current_function_decl != decl - || class_scope_p (context_die)); + || class_or_namespace_scope_p (context_die)); /* It is possible to have both DECL_ABSTRACT and DECLARATION be true if we started to generate the abstract instance of an inline, decided to output @@ -10634,7 +10791,7 @@ gen_subprogram_die (decl, context_die) we'll get back to the abstract instance when done with the class. */ /* The class-scope declaration DIE must be the primary DIE. */ - if (origin && declaration && class_scope_p (context_die)) + if (origin && declaration && class_or_namespace_scope_p (context_die)) { origin = NULL; if (old_die) @@ -10662,7 +10819,7 @@ gen_subprogram_die (decl, context_die) /* We can have a normal definition following an inline one in the case of redefinition of GNU C extern inlines. It seems reasonable to use AT_specification in this case. */ - && !get_AT_unsigned (old_die, DW_AT_inline)) + && !get_AT (old_die, DW_AT_inline)) { /* ??? This can happen if there is a bug in the program, for instance, if it has duplicate function definitions. Ideally, @@ -10696,7 +10853,7 @@ gen_subprogram_die (decl, context_die) else { subr_die = new_die (DW_TAG_subprogram, context_die, decl); - add_AT_die_ref (subr_die, DW_AT_specification, old_die); + add_AT_specification (subr_die, old_die); if (get_AT_unsigned (old_die, DW_AT_decl_file) != file_index) add_AT_unsigned (subr_die, DW_AT_decl_file, file_index); if (get_AT_unsigned (old_die, DW_AT_decl_line) @@ -10732,7 +10889,7 @@ gen_subprogram_die (decl, context_die) if (declaration) { - if (!old_die || !get_AT_unsigned (old_die, DW_AT_inline)) + if (!old_die || !get_AT (old_die, DW_AT_inline)) { add_AT_flag (subr_die, DW_AT_declaration, 1); @@ -10746,26 +10903,26 @@ gen_subprogram_die (decl, context_die) } else if (DECL_ABSTRACT (decl)) { - if (DECL_INLINE (decl) && !flag_no_inline) + if (DECL_DECLARED_INLINE_P (decl)) { - /* ??? Checking DECL_DEFER_OUTPUT is correct for static - inline functions, but not for extern inline functions. - We can't get this completely correct because information - about whether the function was declared inline is not - saved anywhere. */ - if (DECL_DEFER_OUTPUT (decl)) + if (cgraph_function_possibly_inlined_p (decl)) add_AT_unsigned (subr_die, DW_AT_inline, DW_INL_declared_inlined); else - add_AT_unsigned (subr_die, DW_AT_inline, DW_INL_inlined); + add_AT_unsigned (subr_die, DW_AT_inline, DW_INL_declared_not_inlined); } else - add_AT_unsigned (subr_die, DW_AT_inline, DW_INL_declared_not_inlined); + { + if (cgraph_function_possibly_inlined_p (decl)) + add_AT_unsigned (subr_die, DW_AT_inline, DW_INL_inlined); + else + add_AT_unsigned (subr_die, DW_AT_inline, DW_INL_not_inlined); + } equate_decl_number_to_die (decl, subr_die); } else if (!DECL_EXTERNAL (decl)) { - if (!old_die || !get_AT_unsigned (old_die, DW_AT_inline)) + if (!old_die || !get_AT (old_die, DW_AT_inline)) equate_decl_number_to_die (decl, subr_die); ASM_GENERATE_INTERNAL_LABEL (label_id, FUNC_BEGIN_LABEL, @@ -10784,8 +10941,8 @@ gen_subprogram_die (decl, context_die) #endif /* Define the "frame base" location for this routine. We use the - frame pointer or stack pointer registers, since the RTL for local - variables is relative to one of them. */ + frame pointer or stack pointer registers, since the RTL for local + variables is relative to one of them. */ fp_reg = frame_pointer_needed ? hard_frame_pointer_rtx : stack_pointer_rtx; add_AT_loc (subr_die, DW_AT_frame_base, reg_loc_descriptor (fp_reg)); @@ -10818,12 +10975,12 @@ gen_subprogram_die (decl, context_die) gen_formal_types_die (decl, subr_die); else { - /* Generate DIEs to represent all known formal parameters */ + /* Generate DIEs to represent all known formal parameters. */ tree arg_decls = DECL_ARGUMENTS (decl); tree parm; /* When generating DIEs, generate the unspecified_parameters DIE - instead if we come across the arg "__builtin_va_alist" */ + instead if we come across the arg "__builtin_va_alist" */ for (parm = arg_decls; parm; parm = TREE_CHAIN (parm)) if (TREE_CODE (parm) == PARM_DECL) { @@ -10836,15 +10993,15 @@ gen_subprogram_die (decl, context_die) } /* Decide whether we need an unspecified_parameters DIE at the end. - There are 2 more cases to do this for: 1) the ansi ... declaration - - this is detectable when the end of the arg list is not a - void_type_node 2) an unprototyped function declaration (not a - definition). This just means that we have no info about the - parameters at all. */ + There are 2 more cases to do this for: 1) the ansi ... declaration - + this is detectable when the end of the arg list is not a + void_type_node 2) an unprototyped function declaration (not a + definition). This just means that we have no info about the + parameters at all. */ fn_arg_types = TYPE_ARG_TYPES (TREE_TYPE (decl)); if (fn_arg_types != NULL) { - /* this is the prototyped case, check for ... */ + /* This is the prototyped case, check for.... */ if (TREE_VALUE (tree_last (fn_arg_types)) != void_type_node) gen_unspecified_parameters_die (decl, subr_die); } @@ -10892,16 +11049,14 @@ gen_subprogram_die (decl, context_die) /* Generate a DIE to represent a declared data object. */ static void -gen_variable_die (decl, context_die) - tree decl; - dw_die_ref context_die; +gen_variable_die (tree decl, dw_die_ref context_die) { tree origin = decl_ultimate_origin (decl); dw_die_ref var_die = new_die (DW_TAG_variable, context_die, decl); dw_die_ref old_die = lookup_decl_die (decl); int declaration = (DECL_EXTERNAL (decl) - || class_scope_p (context_die)); + || class_or_namespace_scope_p (context_die)); if (origin != NULL) add_abstract_origin_attribute (var_die, origin); @@ -10918,7 +11073,7 @@ gen_variable_die (decl, context_die) && get_AT_flag (old_die, DW_AT_declaration) == 1) { /* This is a definition of a C++ class level static. */ - add_AT_die_ref (var_die, DW_AT_specification, old_die); + add_AT_specification (var_die, old_die); if (DECL_NAME (decl)) { unsigned file_index = lookup_filename (DECL_SOURCE_FILE (decl)); @@ -10954,7 +11109,7 @@ gen_variable_die (decl, context_die) if (declaration) add_AT_flag (var_die, DW_AT_declaration, 1); - if (class_scope_p (context_die) || DECL_ABSTRACT (decl)) + if (class_or_namespace_scope_p (context_die) || DECL_ABSTRACT (decl)) equate_decl_number_to_die (decl, var_die); if (! declaration && ! DECL_ABSTRACT (decl)) @@ -10969,9 +11124,7 @@ gen_variable_die (decl, context_die) /* Generate a DIE to represent a label identifier. */ static void -gen_label_die (decl, context_die) - tree decl; - dw_die_ref context_die; +gen_label_die (tree decl, dw_die_ref context_die) { tree origin = decl_ultimate_origin (decl); dw_die_ref lbl_die = new_die (DW_TAG_label, context_die, decl); @@ -10987,14 +11140,15 @@ gen_label_die (decl, context_die) equate_decl_number_to_die (decl, lbl_die); else { - insn = DECL_RTL (decl); + insn = DECL_RTL_IF_SET (decl); /* Deleted labels are programmer specified labels which have been - eliminated because of various optimisations. We still emit them + eliminated because of various optimizations. We still emit them here so that it is possible to put breakpoints on them. */ - if (GET_CODE (insn) == CODE_LABEL - || ((GET_CODE (insn) == NOTE - && NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED_LABEL))) + if (insn + && (GET_CODE (insn) == CODE_LABEL + || ((GET_CODE (insn) == NOTE + && NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED_LABEL)))) { /* When optimization is enabled (via -O) some parts of the compiler (e.g. jump.c and cse.c) may try to delete CODE_LABEL insns which @@ -11013,10 +11167,7 @@ gen_label_die (decl, context_die) /* Generate a DIE for a lexical block. */ static void -gen_lexical_block_die (stmt, context_die, depth) - tree stmt; - dw_die_ref context_die; - int depth; +gen_lexical_block_die (tree stmt, dw_die_ref context_die, int depth) { dw_die_ref stmt_die = new_die (DW_TAG_lexical_block, context_die, stmt); char label[MAX_ARTIFICIAL_LABEL_BYTES]; @@ -11055,10 +11206,7 @@ gen_lexical_block_die (stmt, context_die, depth) /* Generate a DIE for an inlined subprogram. */ static void -gen_inlined_subroutine_die (stmt, context_die, depth) - tree stmt; - dw_die_ref context_die; - int depth; +gen_inlined_subroutine_die (tree stmt, dw_die_ref context_die, int depth) { tree decl = block_ultimate_origin (stmt); @@ -11103,15 +11251,13 @@ gen_inlined_subroutine_die (stmt, context_die, depth) /* Generate a DIE for a field in a record, or structure. */ static void -gen_field_die (decl, context_die) - tree decl; - dw_die_ref context_die; +gen_field_die (tree decl, dw_die_ref context_die) { dw_die_ref decl_die; if (TREE_TYPE (decl) == error_mark_node) return; - + decl_die = new_die (DW_TAG_member, context_die, decl); add_name_and_src_coords_attributes (decl_die, decl); add_type_attribute (decl_die, member_declared_type (decl), @@ -11144,9 +11290,7 @@ gen_field_die (decl, context_die) represent certain things in other languages (e.g. Pascal) someday. */ static void -gen_pointer_type_die (type, context_die) - tree type; - dw_die_ref context_die; +gen_pointer_type_die (tree type, dw_die_ref context_die) { dw_die_ref ptr_die = new_die (DW_TAG_pointer_type, scope_die_for (type, context_die), type); @@ -11162,9 +11306,7 @@ gen_pointer_type_die (type, context_die) represent certain things in other languages (e.g. Pascal) someday. */ static void -gen_reference_type_die (type, context_die) - tree type; - dw_die_ref context_die; +gen_reference_type_die (tree type, dw_die_ref context_die) { dw_die_ref ref_die = new_die (DW_TAG_reference_type, scope_die_for (type, context_die), type); @@ -11178,9 +11320,7 @@ gen_reference_type_die (type, context_die) /* Generate a DIE for a pointer to a member type. */ static void -gen_ptr_to_mbr_type_die (type, context_die) - tree type; - dw_die_ref context_die; +gen_ptr_to_mbr_type_die (tree type, dw_die_ref context_die) { dw_die_ref ptr_die = new_die (DW_TAG_ptr_to_member_type, @@ -11195,20 +11335,22 @@ gen_ptr_to_mbr_type_die (type, context_die) /* Generate the DIE for the compilation unit. */ static dw_die_ref -gen_compile_unit_die (filename) - const char *filename; +gen_compile_unit_die (const char *filename) { dw_die_ref die; char producer[250]; - const char *wd = getpwd (); const char *language_string = lang_hooks.name; int language; die = new_die (DW_TAG_compile_unit, NULL, NULL); - add_name_attribute (die, filename); - if (wd != NULL && filename[0] != DIR_SEPARATOR) - add_AT_string (die, DW_AT_comp_dir, wd); + if (filename) + { + add_name_attribute (die, filename); + /* Don't add cwd for <built-in>. */ + if (filename[0] != DIR_SEPARATOR && filename[0] != '<') + add_comp_dir_attribute (die); + } sprintf (producer, "%s %s", language_string, version_string); @@ -11228,7 +11370,7 @@ gen_compile_unit_die (filename) if (strcmp (language_string, "GNU C++") == 0) language = DW_LANG_C_plus_plus; else if (strcmp (language_string, "GNU Ada") == 0) - language = DW_LANG_Ada83; + language = DW_LANG_Ada95; else if (strcmp (language_string, "GNU F77") == 0) language = DW_LANG_Fortran77; else if (strcmp (language_string, "GNU Pascal") == 0) @@ -11245,9 +11387,7 @@ gen_compile_unit_die (filename) /* Generate a DIE for a string type. */ static void -gen_string_type_die (type, context_die) - tree type; - dw_die_ref context_die; +gen_string_type_die (tree type, dw_die_ref context_die) { dw_die_ref type_die = new_die (DW_TAG_string_type, scope_die_for (type, context_die), type); @@ -11265,9 +11405,7 @@ gen_string_type_die (type, context_die) /* Generate the DIE for a base class. */ static void -gen_inheritance_die (binfo, context_die) - tree binfo; - dw_die_ref context_die; +gen_inheritance_die (tree binfo, tree access, dw_die_ref context_die) { dw_die_ref die = new_die (DW_TAG_inheritance, context_die, binfo); @@ -11277,20 +11415,19 @@ gen_inheritance_die (binfo, context_die) if (TREE_VIA_VIRTUAL (binfo)) add_AT_unsigned (die, DW_AT_virtuality, DW_VIRTUALITY_virtual); - if (TREE_VIA_PUBLIC (binfo)) + if (access == access_public_node) add_AT_unsigned (die, DW_AT_accessibility, DW_ACCESS_public); - else if (TREE_VIA_PROTECTED (binfo)) + else if (access == access_protected_node) add_AT_unsigned (die, DW_AT_accessibility, DW_ACCESS_protected); } /* Generate a DIE for a class member. */ static void -gen_member_die (type, context_die) - tree type; - dw_die_ref context_die; +gen_member_die (tree type, dw_die_ref context_die) { tree member; + tree binfo = TYPE_BINFO (type); dw_die_ref child; /* If this is not an incomplete type, output descriptions of each of its @@ -11306,14 +11443,17 @@ gen_member_die (type, context_die) the TREE node representing the appropriate (containing) type. */ /* First output info about the base classes. */ - if (TYPE_BINFO (type) && TYPE_BINFO_BASETYPES (type)) + if (binfo && BINFO_BASETYPES (binfo)) { - tree bases = TYPE_BINFO_BASETYPES (type); + tree bases = BINFO_BASETYPES (binfo); + tree accesses = BINFO_BASEACCESSES (binfo); int n_bases = TREE_VEC_LENGTH (bases); int i; for (i = 0; i < n_bases; i++) - gen_inheritance_die (TREE_VEC_ELT (bases, i), context_die); + gen_inheritance_die (TREE_VEC_ELT (bases, i), + (accesses ? TREE_VEC_ELT (accesses, i) + : access_public_node), context_die); } /* Now output info about the data members and type members. */ @@ -11351,9 +11491,7 @@ gen_member_die (type, context_die) member DIEs needed by later specification DIEs. */ static void -gen_struct_or_union_type_die (type, context_die) - tree type; - dw_die_ref context_die; +gen_struct_or_union_type_die (tree type, dw_die_ref context_die) { dw_die_ref type_die = lookup_type_die (type); dw_die_ref scope_die = 0; @@ -11361,12 +11499,14 @@ gen_struct_or_union_type_die (type, context_die) int complete = (TYPE_SIZE (type) && (! TYPE_STUB_DECL (type) || ! TYPE_DECL_SUPPRESS_DEBUG (TYPE_STUB_DECL (type)))); + int ns_decl = (context_die && context_die->die_tag == DW_TAG_namespace); if (type_die && ! complete) return; if (TYPE_CONTEXT (type) != NULL_TREE - && AGGREGATE_TYPE_P (TYPE_CONTEXT (type))) + && (AGGREGATE_TYPE_P (TYPE_CONTEXT (type)) + || TREE_CODE (TYPE_CONTEXT (type)) == NAMESPACE_DECL)) nested = 1; scope_die = scope_die_for (type, context_die); @@ -11381,7 +11521,7 @@ gen_struct_or_union_type_die (type, context_die) scope_die, type); equate_type_number_to_die (type, type_die); if (old_die) - add_AT_die_ref (type_die, DW_AT_specification, old_die); + add_AT_specification (type_die, old_die); else add_name_attribute (type_die, type_tag (type)); } @@ -11390,10 +11530,10 @@ gen_struct_or_union_type_die (type, context_die) /* If this type has been completed, then give it a byte_size attribute and then give a list of members. */ - if (complete) + if (complete && !ns_decl) { /* Prevent infinite recursion in cases where the type of some member of - this type is expressed in terms of this type itself. */ + this type is expressed in terms of this type itself. */ TREE_ASM_WRITTEN (type) = 1; add_byte_size_attribute (type_die, type); if (TYPE_STUB_DECL (type) != NULL_TREE) @@ -11432,9 +11572,7 @@ gen_struct_or_union_type_die (type, context_die) /* Generate a DIE for a subroutine _type_. */ static void -gen_subroutine_type_die (type, context_die) - tree type; - dw_die_ref context_die; +gen_subroutine_type_die (tree type, dw_die_ref context_die) { tree return_type = TREE_TYPE (type); dw_die_ref subr_die @@ -11447,12 +11585,10 @@ gen_subroutine_type_die (type, context_die) gen_formal_types_die (type, subr_die); } -/* Generate a DIE for a type definition */ +/* Generate a DIE for a type definition. */ static void -gen_typedef_die (decl, context_die) - tree decl; - dw_die_ref context_die; +gen_typedef_die (tree decl, dw_die_ref context_die) { dw_die_ref type_die; tree origin; @@ -11493,9 +11629,7 @@ gen_typedef_die (decl, context_die) /* Generate a type description DIE. */ static void -gen_type_die (type, context_die) - tree type; - dw_die_ref context_die; +gen_type_die (tree type, dw_die_ref context_die) { int need_pop; @@ -11543,7 +11677,7 @@ gen_type_die (type, context_die) TREE_ASM_WRITTEN (type) = 1; /* For these types, all that is required is that we output a DIE (or a - set of DIEs) to represent the "basis" type. */ + set of DIEs) to represent the "basis" type. */ gen_type_die (TREE_TYPE (type), context_die); break; @@ -11556,7 +11690,7 @@ gen_type_die (type, context_die) gen_type_die (TREE_TYPE (type), context_die); /* Now output a DIE to represent this pointer-to-data-member type - itself. */ + itself. */ gen_ptr_to_mbr_type_die (type, context_die); break; @@ -11601,11 +11735,11 @@ gen_type_die (type, context_die) case UNION_TYPE: case QUAL_UNION_TYPE: /* If this is a nested type whose containing class hasn't been written - out yet, writing it out will cover this one, too. This does not apply - to instantiations of member class templates; they need to be added to - the containing class as they are generated. FIXME: This hurts the - idea of combining type decls from multiple TUs, since we can't predict - what set of template instantiations we'll get. */ + out yet, writing it out will cover this one, too. This does not apply + to instantiations of member class templates; they need to be added to + the containing class as they are generated. FIXME: This hurts the + idea of combining type decls from multiple TUs, since we can't predict + what set of template instantiations we'll get. */ if (TYPE_CONTEXT (type) && AGGREGATE_TYPE_P (TYPE_CONTEXT (type)) && ! TREE_ASM_WRITTEN (TYPE_CONTEXT (type))) @@ -11621,7 +11755,10 @@ gen_type_die (type, context_die) need_pop = 1; } else - need_pop = 0; + { + declare_in_namespace (type, context_die); + need_pop = 0; + } if (TREE_CODE (type) == ENUMERAL_TYPE) gen_enumeration_type_die (type, context_die); @@ -11659,9 +11796,7 @@ gen_type_die (type, context_die) /* Generate a DIE for a tagged type instantiation. */ static void -gen_tagged_type_instantiation_die (type, context_die) - tree type; - dw_die_ref context_die; +gen_tagged_type_instantiation_die (tree type, dw_die_ref context_die) { if (type == NULL_TREE || type == error_mark_node) return; @@ -11703,10 +11838,7 @@ gen_tagged_type_instantiation_die (type, context_die) things which are local to the given block. */ static void -gen_block_die (stmt, context_die, depth) - tree stmt; - dw_die_ref context_die; - int depth; +gen_block_die (tree stmt, dw_die_ref context_die, int depth) { int must_output_die = 0; tree origin; @@ -11748,12 +11880,12 @@ gen_block_die (stmt, context_die, depth) else { /* In the case where the current block represents an inlining of the - "body block" of an inline function, we must *NOT* output any DIE for - this block because we have already output a DIE to represent the whole - inlined function scope and the "body block" of any function doesn't - really represent a different scope according to ANSI C rules. So we - check here to make sure that this block does not represent a "body - block inlining" before trying to set the MUST_OUTPUT_DIE flag. */ + "body block" of an inline function, we must *NOT* output any DIE for + this block because we have already output a DIE to represent the whole + inlined function scope and the "body block" of any function doesn't + really represent a different scope according to ANSI C rules. So we + check here to make sure that this block does not represent a "body + block inlining" before trying to set the MUST_OUTPUT_DIE flag. */ if (! is_body_block (origin ? origin : stmt)) { /* Determine if this block directly contains any "significant" @@ -11798,10 +11930,7 @@ gen_block_die (stmt, context_die, depth) all of its sub-blocks. */ static void -decls_for_scope (stmt, context_die, depth) - tree stmt; - dw_die_ref context_die; - int depth; +decls_for_scope (tree stmt, dw_die_ref context_die, int depth) { tree decl; tree subblocks; @@ -11846,8 +11975,7 @@ decls_for_scope (stmt, context_die, depth) /* Is this a typedef we can avoid emitting? */ static inline int -is_redundant_typedef (decl) - tree decl; +is_redundant_typedef (tree decl) { if (TYPE_DECL_IS_STUB (decl)) return 1; @@ -11863,12 +11991,102 @@ is_redundant_typedef (decl) return 0; } +/* Returns the DIE for namespace NS or aborts. + + Note that namespaces don't really have a lexical context, so there's no + need to pass in a context_die. They always go inside their containing + namespace, or comp_unit_die if none. */ + +static dw_die_ref +force_namespace_die (tree ns) +{ + dw_die_ref ns_die; + + dwarf2out_decl (ns); + ns_die = lookup_decl_die (ns); + if (!ns_die) + abort(); + + return ns_die; +} + +/* Force out any required namespaces to be able to output DECL, + and return the new context_die for it, if it's changed. */ + +static dw_die_ref +setup_namespace_context (tree thing, dw_die_ref context_die) +{ + tree context = DECL_P (thing) ? DECL_CONTEXT (thing) : TYPE_CONTEXT (thing); + if (context && TREE_CODE (context) == NAMESPACE_DECL) + /* Force out the namespace. */ + context_die = force_namespace_die (context); + + return context_die; +} + +/* Emit a declaration DIE for THING (which is either a DECL or a tagged + type) within its namespace, if appropriate. + + For compatibility with older debuggers, namespace DIEs only contain + declarations; all definitions are emitted at CU scope. */ + +static void +declare_in_namespace (tree thing, dw_die_ref context_die) +{ + dw_die_ref ns_context; + + if (debug_info_level <= DINFO_LEVEL_TERSE) + return; + + ns_context = setup_namespace_context (thing, context_die); + + if (ns_context != context_die) + { + if (DECL_P (thing)) + gen_decl_die (thing, ns_context); + else + gen_type_die (thing, ns_context); + } +} + +/* Generate a DIE for a namespace or namespace alias. */ + +static void +gen_namespace_die (tree decl) +{ + dw_die_ref context_die = setup_namespace_context (decl, comp_unit_die); + + /* Namespace aliases have a DECL_ABSTRACT_ORIGIN of the namespace + they are an alias of. */ + if (DECL_ABSTRACT_ORIGIN (decl) == NULL) + { + /* Output a real namespace. */ + dw_die_ref namespace_die + = new_die (DW_TAG_namespace, context_die, decl); + add_name_and_src_coords_attributes (namespace_die, decl); + equate_decl_number_to_die (decl, namespace_die); + } + else + { + /* Output a namespace alias. */ + + /* Force out the namespace we are an alias of, if necessary. */ + dw_die_ref origin_die + = force_namespace_die (DECL_ABSTRACT_ORIGIN (decl)); + + /* Now create the namespace alias DIE. */ + dw_die_ref namespace_die + = new_die (DW_TAG_imported_declaration, context_die, decl); + add_name_and_src_coords_attributes (namespace_die, decl); + add_AT_die_ref (namespace_die, DW_AT_import, origin_die); + equate_decl_number_to_die (decl, namespace_die); + } +} + /* Generate Dwarf debug information for a decl described by DECL. */ static void -gen_decl_die (decl, context_die) - tree decl; - dw_die_ref context_die; +gen_decl_die (tree decl, dw_die_ref context_die) { tree origin; @@ -11882,7 +12100,7 @@ gen_decl_die (decl, context_die) case CONST_DECL: /* The individual enumerators of an enum type get output when we output - the Dwarf representation of the relevant enum type itself. */ + the Dwarf representation of the relevant enum type itself. */ break; case FUNCTION_DECL: @@ -11898,8 +12116,9 @@ gen_decl_die (decl, context_die) /* If we're emitting an out-of-line copy of an inline function, emit info for the abstract instance and set up to refer to it. */ - else if (DECL_INLINE (decl) && ! DECL_ABSTRACT (decl) - && ! class_scope_p (context_die) + else if (cgraph_function_possibly_inlined_p (decl) + && ! DECL_ABSTRACT (decl) + && ! class_or_namespace_scope_p (context_die) /* dwarf2out_abstract_function won't emit a die if this is just a declaration. We must avoid setting DECL_ABSTRACT_ORIGIN in that case, because that works only if we have a die. */ @@ -11924,6 +12143,9 @@ gen_decl_die (decl, context_die) origin = decl_class_context (decl); if (origin != NULL_TREE) gen_type_die_for_member (origin, decl, context_die); + + /* And its containing namespace. */ + declare_in_namespace (decl, context_die); } /* Now output a DIE to represent the function itself. */ @@ -11932,16 +12154,16 @@ gen_decl_die (decl, context_die) case TYPE_DECL: /* If we are in terse mode, don't generate any DIEs to represent any - actual typedefs. */ + actual typedefs. */ if (debug_info_level <= DINFO_LEVEL_TERSE) break; /* 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) DW_TAG_structure_type, - DW_TAG_union_type, or DW_TAG_enumeration_type DIE here. */ + 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) DW_TAG_structure_type, + DW_TAG_union_type, or DW_TAG_enumeration_type DIE here. */ if (TYPE_DECL_IS_STUB (decl) && decl_ultimate_origin (decl) != NULL_TREE) { gen_tagged_type_instantiation_die (TREE_TYPE (decl), context_die); @@ -11962,12 +12184,12 @@ gen_decl_die (decl, context_die) case VAR_DECL: /* If we are in terse mode, don't generate any DIEs to represent any - variable declarations or definitions. */ + variable declarations or definitions. */ if (debug_info_level <= DINFO_LEVEL_TERSE) break; /* Output any DIEs that are needed to specify the type of this data - object. */ + object. */ gen_type_die (TREE_TYPE (decl), context_die); /* And its containing type. */ @@ -11975,10 +12197,13 @@ gen_decl_die (decl, context_die) if (origin != NULL_TREE) gen_type_die_for_member (origin, decl, context_die); + /* And its containing namespace. */ + declare_in_namespace (decl, 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 - function. */ + complicated because of the possibility that the VAR_DECL really + represents an inlined instance of a formal parameter for an inline + function. */ origin = decl_ultimate_origin (decl); if (origin != NULL_TREE && TREE_CODE (origin) == PARM_DECL) gen_formal_parameter_die (decl, context_die); @@ -12003,29 +12228,21 @@ gen_decl_die (decl, context_die) break; case NAMESPACE_DECL: - /* Ignore for now. */ + gen_namespace_die (decl); break; default: + if ((int)TREE_CODE (decl) > NUM_TREE_CODES) + /* Probably some frontend-internal decl. Assume we don't care. */ + break; abort (); } } - -static void -mark_limbo_die_list (ptr) - void *ptr ATTRIBUTE_UNUSED; -{ - limbo_die_node *node; - for (node = limbo_die_list; node; node = node->next) - ggc_mark_tree (node->created_for); -} /* Add Ada "use" clause information for SGI Workshop debugger. */ void -dwarf2out_add_library_unit_info (filename, context_list) - const char *filename; - const char *context_list; +dwarf2out_add_library_unit_info (const char *filename, const char *context_list) { unsigned int file_index; @@ -12048,8 +12265,7 @@ dwarf2out_add_library_unit_info (filename, context_list) compilation proper has finished. */ static void -dwarf2out_global_decl (decl) - tree decl; +dwarf2out_global_decl (tree decl) { /* Output DWARF2 information for file-scope tentative data object declarations, file-scope (extern) function declarations (which had no @@ -12062,8 +12278,7 @@ dwarf2out_global_decl (decl) /* Write the debugging output for DECL. */ void -dwarf2out_decl (decl) - tree decl; +dwarf2out_decl (tree decl) { dw_die_ref context_die = comp_unit_die; @@ -12073,33 +12288,27 @@ dwarf2out_decl (decl) return; case FUNCTION_DECL: - /* Ignore this FUNCTION_DECL if it refers to a builtin declaration of a - builtin function. Explicit programmer-supplied declarations of - these same functions should NOT be ignored however. */ - if (DECL_EXTERNAL (decl) && DECL_BUILT_IN (decl)) - return; - /* What we would really like to do here is to filter out all mere - file-scope declarations of file-scope functions which are never - referenced later within this translation unit (and keep all of ones - that *are* referenced later on) but we aren't clairvoyant, so we have - no idea which functions will be referenced in the future (i.e. later - on within the current translation unit). So here we just ignore all - file-scope function declarations which are not also definitions. If - and when the debugger needs to know something about these functions, - it will have to hunt around and find the DWARF information associated - with the definition of the function. + file-scope declarations of file-scope functions which are never + referenced later within this translation unit (and keep all of ones + that *are* referenced later on) but we aren't clairvoyant, so we have + no idea which functions will be referenced in the future (i.e. later + on within the current translation unit). So here we just ignore all + file-scope function declarations which are not also definitions. If + and when the debugger needs to know something about these functions, + it will have to hunt around and find the DWARF information associated + with the definition of the function. We can't just check DECL_EXTERNAL to find out which FUNCTION_DECL - nodes represent definitions and which ones represent mere - declarations. We have to check DECL_INITIAL instead. That's because - the C front-end supports some weird semantics for "extern inline" - function definitions. These can get inlined within the current - translation unit (an thus, we need to generate Dwarf info for their - abstract instances so that the Dwarf info for the concrete inlined - instances can have something to refer to) but the compiler never - generates any out-of-lines instances of such things (despite the fact - that they *are* definitions). + nodes represent definitions and which ones represent mere + declarations. We have to check DECL_INITIAL instead. That's because + the C front-end supports some weird semantics for "extern inline" + function definitions. These can get inlined within the current + translation unit (an thus, we need to generate Dwarf info for their + abstract instances so that the Dwarf info for the concrete inlined + instances can have something to refer to) but the compiler never + generates any out-of-lines instances of such things (despite the fact + that they *are* definitions). The important point is that the C front-end marks these "extern inline" functions as DECL_EXTERNAL, but we need to generate DWARF for @@ -12120,33 +12329,40 @@ dwarf2out_decl (decl) case VAR_DECL: /* Ignore this VAR_DECL if it refers to a file-scope extern data object - declaration and if the declaration was never even referenced from - within this entire compilation unit. We suppress these DIEs in - order to save space in the .debug section (by eliminating entries - which are probably useless). Note that we must not suppress - block-local extern declarations (whether used or not) because that - would screw-up the debugger's name lookup mechanism and cause it to - miss things which really ought to be in scope at a given point. */ + declaration and if the declaration was never even referenced from + within this entire compilation unit. We suppress these DIEs in + order to save space in the .debug section (by eliminating entries + which are probably useless). Note that we must not suppress + block-local extern declarations (whether used or not) because that + would screw-up the debugger's name lookup mechanism and cause it to + miss things which really ought to be in scope at a given point. */ if (DECL_EXTERNAL (decl) && !TREE_USED (decl)) return; /* If we are in terse mode, don't generate any DIEs to represent any - variable declarations or definitions. */ + variable declarations or definitions. */ if (debug_info_level <= DINFO_LEVEL_TERSE) return; break; + case NAMESPACE_DECL: + if (debug_info_level <= DINFO_LEVEL_TERSE) + return; + if (lookup_decl_die (decl) != NULL) + return; + break; + case TYPE_DECL: /* Don't emit stubs for types unless they are needed by other DIEs. */ if (TYPE_DECL_SUPPRESS_DEBUG (decl)) return; /* Don't bother trying to generate any DIEs to represent any of the - normal built-in types for the language we are compiling. */ + normal built-in types for the language we are compiling. */ if (DECL_SOURCE_LINE (decl) == 0) { /* OK, we need to generate one for `bool' so GDB knows what type - comparisons have. */ + comparisons have. */ if ((get_AT_unsigned (comp_unit_die, DW_AT_language) == DW_LANG_C_plus_plus) && TREE_CODE (TREE_TYPE (decl)) == BOOLEAN_TYPE @@ -12178,9 +12394,8 @@ dwarf2out_decl (decl) a lexical block. */ static void -dwarf2out_begin_block (line, blocknum) - unsigned int line ATTRIBUTE_UNUSED; - unsigned int blocknum; +dwarf2out_begin_block (unsigned int line ATTRIBUTE_UNUSED, + unsigned int blocknum) { function_section (current_function_decl); ASM_OUTPUT_DEBUG_LABEL (asm_out_file, BLOCK_BEGIN_LABEL, blocknum); @@ -12190,9 +12405,7 @@ dwarf2out_begin_block (line, blocknum) lexical block. */ static void -dwarf2out_end_block (line, blocknum) - unsigned int line ATTRIBUTE_UNUSED; - unsigned int blocknum; +dwarf2out_end_block (unsigned int line ATTRIBUTE_UNUSED, unsigned int blocknum) { function_section (current_function_decl); ASM_OUTPUT_DEBUG_LABEL (asm_out_file, BLOCK_END_LABEL, blocknum); @@ -12206,8 +12419,7 @@ dwarf2out_end_block (line, blocknum) we may end up calling them anyway. */ static bool -dwarf2out_ignore_block (block) - tree block; +dwarf2out_ignore_block (tree block) { tree decl; @@ -12231,65 +12443,70 @@ dwarf2out_ignore_block (block) all searches. */ static unsigned -lookup_filename (file_name) - const char *file_name; +lookup_filename (const char *file_name) { - unsigned i; - - /* ??? Why isn't DECL_SOURCE_FILE left null instead. */ - if (strcmp (file_name, "<internal>") == 0 - || strcmp (file_name, "<built-in>") == 0) - return 0; + size_t i, n; + char *save_file_name; /* Check to see if the file name that was searched on the previous call matches this file name. If so, return the index. */ - if (file_table.last_lookup_index != 0) - if (0 == strcmp (file_name, - file_table.table[file_table.last_lookup_index])) - return file_table.last_lookup_index; + if (file_table_last_lookup_index != 0) + { + const char *last + = VARRAY_CHAR_PTR (file_table, file_table_last_lookup_index); + if (strcmp (file_name, last) == 0) + return file_table_last_lookup_index; + } /* Didn't match the previous lookup, search the table */ - for (i = 1; i < file_table.in_use; i++) - if (strcmp (file_name, file_table.table[i]) == 0) + n = VARRAY_ACTIVE_SIZE (file_table); + for (i = 1; i < n; i++) + if (strcmp (file_name, VARRAY_CHAR_PTR (file_table, i)) == 0) { - file_table.last_lookup_index = i; + file_table_last_lookup_index = i; return i; } - /* Prepare to add a new table entry by making sure there is enough space in - the table to do so. If not, expand the current table. */ - if (i == file_table.allocated) - { - file_table.allocated = i + FILE_TABLE_INCREMENT; - file_table.table = (char **) - xrealloc (file_table.table, file_table.allocated * sizeof (char *)); - } - /* Add the new entry to the end of the filename table. */ - file_table.table[i] = xstrdup (file_name); - file_table.in_use = i + 1; - file_table.last_lookup_index = i; + file_table_last_lookup_index = n; + save_file_name = (char *) ggc_strdup (file_name); + VARRAY_PUSH_CHAR_PTR (file_table, save_file_name); + VARRAY_PUSH_UINT (file_table_emitted, 0); - if (DWARF2_ASM_LINE_DEBUG_INFO) + return i; +} + +static int +maybe_emit_file (int fileno) +{ + if (DWARF2_ASM_LINE_DEBUG_INFO && fileno > 0) { - fprintf (asm_out_file, "\t.file %u ", i); - output_quoted_string (asm_out_file, file_name); - fputc ('\n', asm_out_file); + if (!VARRAY_UINT (file_table_emitted, fileno)) + { + VARRAY_UINT (file_table_emitted, fileno) = ++emitcount; + fprintf (asm_out_file, "\t.file %u ", + VARRAY_UINT (file_table_emitted, fileno)); + output_quoted_string (asm_out_file, + VARRAY_CHAR_PTR (file_table, fileno)); + fputc ('\n', asm_out_file); + } + return VARRAY_UINT (file_table_emitted, fileno); } - - return i; + else + return fileno; } static void -init_file_table () +init_file_table (void) { /* Allocate the initial hunk of the file_table. */ - file_table.table = (char **) xcalloc (FILE_TABLE_INCREMENT, sizeof (char *)); - file_table.allocated = FILE_TABLE_INCREMENT; + VARRAY_CHAR_PTR_INIT (file_table, 64, "file_table"); + VARRAY_UINT_INIT (file_table_emitted, 64, "file_table_emitted"); /* Skip the first entry - file numbers begin at 1. */ - file_table.in_use = 1; - file_table.last_lookup_index = 0; + VARRAY_PUSH_CHAR_PTR (file_table, NULL); + VARRAY_PUSH_UINT (file_table_emitted, 0); + file_table_last_lookup_index = 0; } /* Output a label to mark the beginning of a source code line entry @@ -12297,11 +12514,10 @@ init_file_table () 'line_info_table' for later output of the .debug_line section. */ static void -dwarf2out_source_line (line, filename) - unsigned int line; - const char *filename; +dwarf2out_source_line (unsigned int line, const char *filename) { - if (debug_info_level >= DINFO_LEVEL_NORMAL) + if (debug_info_level >= DINFO_LEVEL_NORMAL + && line != 0) { function_section (current_function_decl); @@ -12314,6 +12530,8 @@ dwarf2out_source_line (line, filename) { unsigned file_num = lookup_filename (filename); + file_num = maybe_emit_file (file_num); + /* Emit the .loc directive understood by GNU as. */ fprintf (asm_out_file, "\t.loc %d %d 0\n", file_num, line); @@ -12327,7 +12545,7 @@ dwarf2out_source_line (line, filename) else if (DECL_SECTION_NAME (current_function_decl)) { dw_separate_line_info_ref line_info; - ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, SEPARATE_LINE_CODE_LABEL, + (*targetm.asm_out.internal_label) (asm_out_file, SEPARATE_LINE_CODE_LABEL, separate_line_info_table_in_use); /* expand the line info table if necessary */ @@ -12336,10 +12554,14 @@ dwarf2out_source_line (line, filename) { separate_line_info_table_allocated += LINE_INFO_TABLE_INCREMENT; separate_line_info_table - = (dw_separate_line_info_ref) - xrealloc (separate_line_info_table, - separate_line_info_table_allocated - * sizeof (dw_separate_line_info_entry)); + = ggc_realloc (separate_line_info_table, + separate_line_info_table_allocated + * sizeof (dw_separate_line_info_entry)); + memset (separate_line_info_table + + separate_line_info_table_in_use, + 0, + (LINE_INFO_TABLE_INCREMENT + * sizeof (dw_separate_line_info_entry))); } /* Add the new entry at the end of the line_info_table. */ @@ -12353,7 +12575,7 @@ dwarf2out_source_line (line, filename) { dw_line_info_ref line_info; - ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, LINE_CODE_LABEL, + (*targetm.asm_out.internal_label) (asm_out_file, LINE_CODE_LABEL, line_info_table_in_use); /* Expand the line info table if necessary. */ @@ -12361,10 +12583,11 @@ dwarf2out_source_line (line, filename) { line_info_table_allocated += LINE_INFO_TABLE_INCREMENT; line_info_table - = (dw_line_info_ref) - xrealloc (line_info_table, - (line_info_table_allocated - * sizeof (dw_line_info_entry))); + = ggc_realloc (line_info_table, + (line_info_table_allocated + * sizeof (dw_line_info_entry))); + memset (line_info_table + line_info_table_in_use, 0, + LINE_INFO_TABLE_INCREMENT * sizeof (dw_line_info_entry)); } /* Add the new entry at the end of the line_info_table. */ @@ -12378,11 +12601,9 @@ dwarf2out_source_line (line, filename) /* Record the beginning of a new source file. */ static void -dwarf2out_start_source_file (lineno, filename) - unsigned int lineno; - const char *filename; +dwarf2out_start_source_file (unsigned int lineno, const char *filename) { - if (flag_eliminate_dwarf2_dups && !is_main_source) + if (flag_eliminate_dwarf2_dups) { /* Record the beginning of the file for break_out_includes. */ dw_die_ref bincl_die; @@ -12391,14 +12612,13 @@ dwarf2out_start_source_file (lineno, filename) add_AT_string (bincl_die, DW_AT_name, filename); } - is_main_source = 0; - if (debug_info_level >= DINFO_LEVEL_VERBOSE) { named_section_flags (DEBUG_MACINFO_SECTION, SECTION_DEBUG); dw2_asm_output_data (1, DW_MACINFO_start_file, "Start new file"); dw2_asm_output_data_uleb128 (lineno, "Included from line number %d", lineno); + maybe_emit_file (lookup_filename (filename)); dw2_asm_output_data_uleb128 (lookup_filename (filename), "Filename we just started"); } @@ -12407,8 +12627,7 @@ dwarf2out_start_source_file (lineno, filename) /* Record the end of a source file. */ static void -dwarf2out_end_source_file (lineno) - unsigned int lineno ATTRIBUTE_UNUSED; +dwarf2out_end_source_file (unsigned int lineno ATTRIBUTE_UNUSED) { if (flag_eliminate_dwarf2_dups) /* Record the end of the file for break_out_includes. */ @@ -12426,9 +12645,8 @@ dwarf2out_end_source_file (lineno) initial whitespace, #, whitespace, directive-name, whitespace part. */ static void -dwarf2out_define (lineno, buffer) - unsigned lineno ATTRIBUTE_UNUSED; - const char *buffer ATTRIBUTE_UNUSED; +dwarf2out_define (unsigned int lineno ATTRIBUTE_UNUSED, + const char *buffer ATTRIBUTE_UNUSED) { if (debug_info_level >= DINFO_LEVEL_VERBOSE) { @@ -12444,9 +12662,8 @@ dwarf2out_define (lineno, buffer) initial whitespace, #, whitespace, directive-name, whitespace part. */ static void -dwarf2out_undef (lineno, buffer) - unsigned lineno ATTRIBUTE_UNUSED; - const char *buffer ATTRIBUTE_UNUSED; +dwarf2out_undef (unsigned int lineno ATTRIBUTE_UNUSED, + const char *buffer ATTRIBUTE_UNUSED) { if (debug_info_level >= DINFO_LEVEL_VERBOSE) { @@ -12460,22 +12677,13 @@ dwarf2out_undef (lineno, buffer) /* Set up for Dwarf output at the start of compilation. */ static void -dwarf2out_init (main_input_filename) - const char *main_input_filename; +dwarf2out_init (const char *filename ATTRIBUTE_UNUSED) { init_file_table (); - /* Remember the name of the primary input file. */ - primary_filename = main_input_filename; - - /* Add it to the file table first, under the assumption that we'll - be emitting line number data for it first, which avoids having - to add an initial DW_LNS_set_file. */ - lookup_filename (main_input_filename); - /* Allocate the initial hunk of the decl_die_table. */ - decl_die_table - = (dw_die_ref *) xcalloc (DECL_DIE_TABLE_INCREMENT, sizeof (dw_die_ref)); + decl_die_table = ggc_alloc_cleared (DECL_DIE_TABLE_INCREMENT + * sizeof (dw_die_ref)); decl_die_table_allocated = DECL_DIE_TABLE_INCREMENT; decl_die_table_in_use = 0; @@ -12483,17 +12691,15 @@ dwarf2out_init (main_input_filename) VARRAY_TREE_INIT (decl_scope_table, 256, "decl_scope_table"); /* Allocate the initial hunk of the abbrev_die_table. */ - abbrev_die_table - = (dw_die_ref *) xcalloc (ABBREV_DIE_TABLE_INCREMENT, - sizeof (dw_die_ref)); + abbrev_die_table = ggc_alloc_cleared (ABBREV_DIE_TABLE_INCREMENT + * sizeof (dw_die_ref)); abbrev_die_table_allocated = ABBREV_DIE_TABLE_INCREMENT; /* Zero-th entry is allocated, but unused */ abbrev_die_table_in_use = 1; /* Allocate the initial hunk of the line_info_table. */ - line_info_table - = (dw_line_info_ref) xcalloc (LINE_INFO_TABLE_INCREMENT, - sizeof (dw_line_info_entry)); + line_info_table = ggc_alloc_cleared (LINE_INFO_TABLE_INCREMENT + * sizeof (dw_line_info_entry)); line_info_table_allocated = LINE_INFO_TABLE_INCREMENT; /* Zero-th entry is allocated, but unused */ @@ -12503,16 +12709,14 @@ dwarf2out_init (main_input_filename) value given in the DW_AT_name attribute of the DW_TAG_compile_unit DIE will (typically) be a relative pathname and that this pathname should be taken as being relative to the directory from which the compiler was - invoked when the given (base) source file was compiled. */ - comp_unit_die = gen_compile_unit_die (main_input_filename); - is_main_source = 1; + invoked when the given (base) source file was compiled. We will fill + in this value in dwarf2out_finish. */ + comp_unit_die = gen_compile_unit_die (NULL); VARRAY_TREE_INIT (incomplete_types, 64, "incomplete_types"); VARRAY_RTX_INIT (used_rtx_varray, 32, "used_rtx_varray"); - ggc_add_root (&limbo_die_list, 1, 1, mark_limbo_die_list); - ASM_GENERATE_INTERNAL_LABEL (text_end_label, TEXT_END_LABEL, 0); ASM_GENERATE_INTERNAL_LABEL (abbrev_section_label, DEBUG_ABBREV_SECTION_LABEL, 0); @@ -12549,54 +12753,255 @@ dwarf2out_init (main_input_filename) } } -/* Allocate a string in .debug_str hash table. */ - -static hashnode -indirect_string_alloc (tab) - hash_table *tab ATTRIBUTE_UNUSED; -{ - struct indirect_string_node *node; - - node = xmalloc (sizeof (struct indirect_string_node)); - node->refcount = 0; - node->form = 0; - node->label = NULL; - - return (hashnode) node; -} - /* A helper function for dwarf2out_finish called through ht_forall. Emit one queued .debug_str string. */ static int -output_indirect_string (pfile, h, v) - struct cpp_reader *pfile ATTRIBUTE_UNUSED; - hashnode h; - const PTR v ATTRIBUTE_UNUSED; +output_indirect_string (void **h, void *v ATTRIBUTE_UNUSED) { - struct indirect_string_node *node = (struct indirect_string_node *) h; + struct indirect_string_node *node = (struct indirect_string_node *) *h; if (node->form == DW_FORM_strp) { named_section_flags (DEBUG_STR_SECTION, DEBUG_STR_SECTION_FLAGS); ASM_OUTPUT_LABEL (asm_out_file, node->label); - assemble_string ((const char *) HT_STR (&node->id), - HT_LEN (&node->id) + 1); + assemble_string (node->str, strlen (node->str) + 1); } return 1; } + + +/* Clear the marks for a die and its children. + Be cool if the mark isn't set. */ + +static void +prune_unmark_dies (dw_die_ref die) +{ + dw_die_ref c; + die->die_mark = 0; + for (c = die->die_child; c; c = c->die_sib) + prune_unmark_dies (c); +} + + +/* Given DIE that we're marking as used, find any other dies + it references as attributes and mark them as used. */ + +static void +prune_unused_types_walk_attribs (dw_die_ref die) +{ + dw_attr_ref a; + + for (a = die->die_attr; a != NULL; a = a->dw_attr_next) + { + if (a->dw_attr_val.val_class == dw_val_class_die_ref) + { + /* A reference to another DIE. + Make sure that it will get emitted. */ + prune_unused_types_mark (a->dw_attr_val.v.val_die_ref.die, 1); + } + else if (a->dw_attr == DW_AT_decl_file) + { + /* A reference to a file. Make sure the file name is emitted. */ + a->dw_attr_val.v.val_unsigned = + maybe_emit_file (a->dw_attr_val.v.val_unsigned); + } + } +} + + +/* Mark DIE as being used. If DOKIDS is true, then walk down + to DIE's children. */ + +static void +prune_unused_types_mark (dw_die_ref die, int dokids) +{ + dw_die_ref c; + + if (die->die_mark == 0) + { + /* We haven't done this node yet. Mark it as used. */ + die->die_mark = 1; + + /* We also have to mark its parents as used. + (But we don't want to mark our parents' kids due to this.) */ + if (die->die_parent) + prune_unused_types_mark (die->die_parent, 0); + + /* Mark any referenced nodes. */ + prune_unused_types_walk_attribs (die); + + /* If this node is a specification, + also mark the definition, if it exists. */ + if (get_AT_flag (die, DW_AT_declaration) && die->die_definition) + prune_unused_types_mark (die->die_definition, 1); + } + + if (dokids && die->die_mark != 2) + { + /* We need to walk the children, but haven't done so yet. + Remember that we've walked the kids. */ + die->die_mark = 2; + + /* Walk them. */ + for (c = die->die_child; c; c = c->die_sib) + { + /* If this is an array type, we need to make sure our + kids get marked, even if they're types. */ + if (die->die_tag == DW_TAG_array_type) + prune_unused_types_mark (c, 1); + else + prune_unused_types_walk (c); + } + } +} + + +/* Walk the tree DIE and mark types that we actually use. */ + +static void +prune_unused_types_walk (dw_die_ref die) +{ + dw_die_ref c; + + /* Don't do anything if this node is already marked. */ + if (die->die_mark) + return; + + switch (die->die_tag) { + case DW_TAG_const_type: + case DW_TAG_packed_type: + case DW_TAG_pointer_type: + case DW_TAG_reference_type: + case DW_TAG_volatile_type: + case DW_TAG_typedef: + case DW_TAG_array_type: + case DW_TAG_structure_type: + case DW_TAG_union_type: + case DW_TAG_class_type: + case DW_TAG_friend: + case DW_TAG_variant_part: + case DW_TAG_enumeration_type: + case DW_TAG_subroutine_type: + case DW_TAG_string_type: + case DW_TAG_set_type: + case DW_TAG_subrange_type: + case DW_TAG_ptr_to_member_type: + case DW_TAG_file_type: + /* It's a type node --- don't mark it. */ + return; + + default: + /* Mark everything else. */ + break; + } + + die->die_mark = 1; + + /* Now, mark any dies referenced from here. */ + prune_unused_types_walk_attribs (die); + + /* Mark children. */ + for (c = die->die_child; c; c = c->die_sib) + prune_unused_types_walk (c); +} + + +/* Remove from the tree DIE any dies that aren't marked. */ + +static void +prune_unused_types_prune (dw_die_ref die) +{ + dw_die_ref c, p, n; + if (!die->die_mark) + abort(); + + p = NULL; + for (c = die->die_child; c; c = n) + { + n = c->die_sib; + if (c->die_mark) + { + prune_unused_types_prune (c); + p = c; + } + else + { + if (p) + p->die_sib = n; + else + die->die_child = n; + free_die (c); + } + } +} + + +/* Remove dies representing declarations that we never use. */ + +static void +prune_unused_types (void) +{ + unsigned int i; + limbo_die_node *node; + + /* Clear all the marks. */ + prune_unmark_dies (comp_unit_die); + for (node = limbo_die_list; node; node = node->next) + prune_unmark_dies (node->die); + + /* Set the mark on nodes that are actually used. */ + prune_unused_types_walk (comp_unit_die); + for (node = limbo_die_list; node; node = node->next) + prune_unused_types_walk (node->die); + + /* Also set the mark on nodes referenced from the + pubname_table or arange_table. */ + for (i = 0; i < pubname_table_in_use; i++) + prune_unused_types_mark (pubname_table[i].die, 1); + for (i = 0; i < arange_table_in_use; i++) + prune_unused_types_mark (arange_table[i], 1); + + /* Get rid of nodes that aren't marked. */ + prune_unused_types_prune (comp_unit_die); + for (node = limbo_die_list; node; node = node->next) + prune_unused_types_prune (node->die); + + /* Leave the marks clear. */ + prune_unmark_dies (comp_unit_die); + for (node = limbo_die_list; node; node = node->next) + prune_unmark_dies (node->die); +} + /* Output stuff that dwarf requires at the end of every file, and generate the DWARF-2 debugging info. */ static void -dwarf2out_finish (input_filename) - const char *input_filename ATTRIBUTE_UNUSED; +dwarf2out_finish (const char *filename) { limbo_die_node *node, *next_node; dw_die_ref die = 0; + /* Add the name for the main input file now. We delayed this from + dwarf2out_init to avoid complications with PCH. */ + add_name_attribute (comp_unit_die, filename); + if (filename[0] != DIR_SEPARATOR) + add_comp_dir_attribute (comp_unit_die); + else if (get_AT (comp_unit_die, DW_AT_comp_dir) == NULL) + { + size_t i; + for (i = 1; i < VARRAY_ACTIVE_SIZE (file_table); i++) + if (VARRAY_CHAR_PTR (file_table, i)[0] != DIR_SEPARATOR + /* Don't add cwd for <built-in>. */ + && VARRAY_CHAR_PTR (file_table, i)[0] != '<') + { + add_comp_dir_attribute (comp_unit_die); + break; + } + } + /* Traverse the limbo die list, and add parent/child links. The only dies without parents that should be here are concrete instances of inline functions, and the comp_unit_die. We can ignore the comp_unit_die. @@ -12648,8 +13053,6 @@ dwarf2out_finish (input_filename) else abort (); } - - free (node); } limbo_die_list = NULL; @@ -12662,6 +13065,9 @@ dwarf2out_finish (input_filename) we'll see the end of an include file before the beginning. */ reverse_all_dies (comp_unit_die); + if (flag_eliminate_unused_debug_types) + prune_unused_types (); + /* Generate separate CUs for each of the include files we've seen. They will go into limbo_die_list. */ if (flag_eliminate_dwarf2_dups) @@ -12675,7 +13081,7 @@ dwarf2out_finish (input_filename) /* Output a terminator label for the .text section. */ text_section (); - ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, TEXT_END_LABEL, 0); + (*targetm.asm_out.internal_label) (asm_out_file, TEXT_END_LABEL, 0); /* Output the source line correspondence table. We must do this even if there is no line information. Otherwise, on an empty @@ -12765,7 +13171,7 @@ dwarf2out_finish (input_filename) /* If we emitted any DW_FORM_strp form attribute, output the string table too. */ if (debug_str_hash) - ht_forall (debug_str_hash, output_indirect_string, NULL); + htab_traverse (debug_str_hash, output_indirect_string, NULL); } #else |