X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fdwarf2out.c;h=13a7e57c81ee6d02c65693f2c2c571634fa7a95b;hb=6ed35e790fcd76db061d707ba16320d9f2647f65;hp=f791538aa5f72a2c2f4e885aabf9a184a2530d6e;hpb=b0d72d6814c87010fbd7d55194dff65375a1bd2a;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index f791538aa5f..13a7e57c81e 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -44,6 +44,7 @@ Boston, MA 02111-1307, USA. */ #include "regs.h" #include "insn-config.h" #include "reload.h" +#include "function.h" #include "output.h" #include "expr.h" #include "except.h" @@ -55,6 +56,12 @@ Boston, MA 02111-1307, USA. */ #include "ggc.h" #include "md5.h" #include "tm_p.h" +#include "diagnostic.h" +#include "debug.h" + +#ifdef DWARF2_DEBUGGING_INFO +static void dwarf2out_source_line PARAMS ((unsigned int, const char *)); +#endif /* DWARF2 Abbreviation Glossary: CFA = Canonical Frame Address @@ -86,11 +93,18 @@ dwarf2out_do_frame () #endif #ifdef DWARF2_UNWIND_INFO || flag_unwind_tables - || (flag_exceptions && ! exceptions_via_longjmp) + || (flag_exceptions && ! USING_SJLJ_EXCEPTIONS) #endif ); } +/* The number of the current function definition for which debugging + information is being generated. These numbers range from 1 up to the + maximum number of function definitions contained within the current + compilation unit. These numbers are used to create unique label id's + unique to each function definition. */ +unsigned current_funcdef_number = 0; + #if defined (DWARF2_DEBUGGING_INFO) || defined (DWARF2_UNWIND_INFO) /* How to start an assembler comment. */ @@ -150,7 +164,9 @@ typedef struct dw_fde_struct const char *dw_fde_current_label; const char *dw_fde_end; dw_cfi_ref dw_fde_cfi; - int nothrow; + unsigned funcdef_number; + unsigned nothrow : 1; + unsigned uses_eh_lsda : 1; } dw_fde_node; @@ -212,13 +228,6 @@ static unsigned fde_table_in_use; /* A list of call frame insns for the CIE. */ static dw_cfi_ref cie_cfi_head; -/* The number of the current function definition for which debugging - information is being generated. These numbers range from 1 up to the - maximum number of function definitions contained within the current - compilation unit. These numbers are used to create unique label id's - unique to each function definition. */ -static unsigned current_funcdef_number = 0; - /* 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 @@ -238,7 +247,7 @@ 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)); +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)); @@ -280,8 +289,8 @@ static void def_cfa_1 PARAMS ((const char *, dw_cfa_location *)); #endif #endif -#ifndef FRAME_SECTION -#define FRAME_SECTION ".debug_frame" +#ifndef DEBUG_FRAME_SECTION +#define DEBUG_FRAME_SECTION ".debug_frame" #endif #ifndef FUNC_BEGIN_LABEL @@ -356,7 +365,7 @@ expand_builtin_dwarf_fp_regnum () #ifndef INCOMING_FRAME_SP_OFFSET #define INCOMING_FRAME_SP_OFFSET 0 #endif - + /* Return a pointer to a copy of the section string name S with all attributes stripped off, and an asterisk prepended (for assemble_name). */ @@ -395,9 +404,7 @@ expand_builtin_init_dwarf_reg_sizes (address) if (offset < 0) continue; - emit_move_insn (change_address (mem, mode, - plus_constant (addr, offset)), - GEN_INT (size)); + emit_move_insn (adjust_address (mem, mode, offset), GEN_INT (size)); } } @@ -951,7 +958,7 @@ dwarf2out_stack_adjust (insn) long offset; const char *label; - if (! asynchronous_exceptions && GET_CODE (insn) == CALL_INSN) + if (! flag_non_call_exceptions && GET_CODE (insn) == CALL_INSN) { /* Extract the size of the args from the CALL rtx itself. */ @@ -968,7 +975,7 @@ dwarf2out_stack_adjust (insn) /* If only calls can throw, and we have a frame pointer, save up adjustments until we see the CALL_INSN. */ - else if (! asynchronous_exceptions + else if (! flag_non_call_exceptions && cfa.reg != STACK_POINTER_REGNUM) return; @@ -1130,11 +1137,13 @@ static dw_cfa_location cfa_temp; cfa_store.reg to the actual CFA cfa_temp register holding an integral value. cfa_temp.offset stores the value, which will be used to adjust the - stack pointer. + stack pointer. cfa_temp is also used like cfa_store, + to track stores to the stack via fp or a temp reg. Rules 1- 4: Setting a register's value to cfa.reg or an expression with cfa.reg as the first operand changes the cfa.reg and its - cfa.offset. + cfa.offset. Rule 1 and 4 also set cfa_temp.reg and + cfa_temp.offset. Rules 6- 9: Set a non-cfa.reg register value to a constant or an expression yielding a constant. This sets cfa_temp.reg @@ -1143,9 +1152,9 @@ static dw_cfa_location cfa_temp; Rule 5: Create a new register cfa_store used to save items to the stack. - Rules 10-13: Save a register to the stack. Define offset as the + Rules 10-14: Save a register to the stack. Define offset as the difference of the original location and cfa_store's - location. + location (or cfa_temp's location if cfa_temp is used). The Rules @@ -1154,26 +1163,30 @@ static dw_cfa_location cfa_temp; Rule 1: (set :cfa.reg) - effects: cfa.reg = + effects: cfa.reg = cfa.offset unchanged + cfa_temp.reg = + cfa_temp.offset = cfa.offset Rule 2: - (set sp ({minus,plus} {sp,fp}:cfa.reg {,:cfa_temp.reg})) + (set sp ({minus,plus,losum} {sp,fp}:cfa.reg {,:cfa_temp.reg})) effects: cfa.reg = sp if fp used cfa.offset += {+/- , cfa_temp.offset} if cfa.reg==sp cfa_store.offset += {+/- , cfa_temp.offset} if cfa_store.reg==sp Rule 3: - (set fp ({minus,plus} :cfa.reg )) + (set fp ({minus,plus,losum} :cfa.reg )) effects: cfa.reg = fp cfa_offset += +/- Rule 4: - (set (plus :cfa.reg )) + (set ({plus,losum} :cfa.reg )) constraints: != fp != sp effects: cfa.reg = + cfa_temp.reg = + cfa_temp.offset = cfa.offset Rule 5: (set (plus :cfa_temp.reg sp:cfa.reg)) @@ -1205,30 +1218,31 @@ static dw_cfa_location cfa_temp; (set (mem (pre_modify sp:cfa_store (???? ))) ) effects: cfa_store.offset -= cfa.offset = cfa_store.offset if cfa.reg == sp - offset = -cfa_store.offset cfa.reg = sp - cfa.base_offset = offset + cfa.base_offset = -cfa_store.offset Rule 11: (set (mem ({pre_inc,pre_dec} sp:cfa_store.reg)) ) effects: cfa_store.offset += -/+ mode_size(mem) cfa.offset = cfa_store.offset if cfa.reg == sp - offset = -cfa_store.offset cfa.reg = sp - cfa.base_offset = offset + cfa.base_offset = -cfa_store.offset Rule 12: - (set (mem ({minus,plus} :cfa_store )) ) - effects: cfa_store.offset += -/+ - offset = -cfa_store.offset - cfa.reg = :{cfa_store,cfa_temp} )) ) + effects: cfa.reg = + cfa.base_offset = -/+ - {cfa_store,cfa_temp}.offset Rule 13: - (set (mem :cfa_store) ) - effects: offset = -cfa_store.offset - cfa.reg = - cfa.base_offset = offset */ + (set (mem :{cfa_store,cfa_temp}) ) + effects: cfa.reg = + cfa.base_offset = -{cfa_store,cfa_temp}.offset + + Rule 14: + (set (mem (postinc :cfa_temp )) ) + effects: cfa.reg = + cfa.base_offset = -cfa_temp.offset + cfa_temp.offset -= mode_size(mem) */ static void dwarf2out_frame_debug_expr (expr, label) @@ -1288,10 +1302,13 @@ dwarf2out_frame_debug_expr (expr, label) FP. So we just rely on the backends to only set RTX_FRAME_RELATED_P on appropriate insns. */ cfa.reg = REGNO (dest); + cfa_temp.reg = cfa.reg; + cfa_temp.offset = cfa.offset; break; case PLUS: case MINUS: + case LO_SUM: if (dest == stack_pointer_rtx) { /* Rule 2 */ @@ -1317,10 +1334,13 @@ dwarf2out_frame_debug_expr (expr, label) abort (); cfa.reg = STACK_POINTER_REGNUM; } + else if (GET_CODE (src) == LO_SUM) + /* Assume we've set the source reg of the LO_SUM from sp. */ + ; else if (XEXP (src, 0) != stack_pointer_rtx) abort (); - if (GET_CODE (src) == PLUS) + if (GET_CODE (src) != MINUS) offset = -offset; if (cfa.reg == STACK_POINTER_REGNUM) cfa.offset += offset; @@ -1340,7 +1360,7 @@ dwarf2out_frame_debug_expr (expr, label) && GET_CODE (XEXP (src, 1)) == CONST_INT) { offset = INTVAL (XEXP (src, 1)); - if (GET_CODE (src) == PLUS) + if (GET_CODE (src) != MINUS) offset = -offset; cfa.offset += offset; cfa.reg = HARD_FRAME_POINTER_REGNUM; @@ -1350,7 +1370,7 @@ dwarf2out_frame_debug_expr (expr, label) } else { - if (GET_CODE (src) != PLUS) + if (GET_CODE (src) == MINUS) abort (); /* Rule 4 */ @@ -1360,27 +1380,34 @@ dwarf2out_frame_debug_expr (expr, label) { /* Setting a temporary CFA register that will be copied into the FP later on. */ - offset = INTVAL (XEXP (src, 1)); - if (GET_CODE (src) == PLUS) - offset = -offset; + offset = - INTVAL (XEXP (src, 1)); cfa.offset += offset; cfa.reg = REGNO (dest); + /* Or used to save regs to the stack. */ + cfa_temp.reg = cfa.reg; + cfa_temp.offset = cfa.offset; } /* Rule 5 */ - else + else if (GET_CODE (XEXP (src, 0)) == REG + && REGNO (XEXP (src, 0)) == cfa_temp.reg + && XEXP (src, 1) == stack_pointer_rtx) { /* Setting a scratch register that we will use instead of SP for saving registers to the stack. */ - if (XEXP (src, 1) != stack_pointer_rtx) - abort (); - if (GET_CODE (XEXP (src, 0)) != REG - || (unsigned) REGNO (XEXP (src, 0)) != cfa_temp.reg) - abort (); if (cfa.reg != STACK_POINTER_REGNUM) abort (); cfa_store.reg = REGNO (dest); cfa_store.offset = cfa.offset - cfa_temp.offset; } + /* Rule 9 */ + else if (GET_CODE (src) == LO_SUM + && GET_CODE (XEXP (src, 1)) == CONST_INT) + { + cfa_temp.reg = REGNO (dest); + cfa_temp.offset = INTVAL (XEXP (src, 1)); + } + else + abort (); } break; @@ -1401,26 +1428,18 @@ dwarf2out_frame_debug_expr (expr, label) cfa_temp.offset |= INTVAL (XEXP (src, 1)); break; + /* Skip over HIGH, assuming it will be followed by a LO_SUM, + which will fill in all of the bits. */ + /* Rule 8 */ + case HIGH: + break; + default: abort (); } def_cfa_1 (label, &cfa); break; - /* Skip over HIGH, assuming it will be followed by a LO_SUM, which - will fill in all of the bits. */ - /* Rule 8 */ - case HIGH: - break; - - /* Rule 9 */ - case LO_SUM: - if (GET_CODE (XEXP (src, 1)) != CONST_INT) - abort (); - cfa_temp.reg = REGNO (dest); - cfa_temp.offset = INTVAL (XEXP (src, 1)); - break; - case MEM: if (GET_CODE (src) != REG) abort (); @@ -1467,23 +1486,38 @@ dwarf2out_frame_debug_expr (expr, label) /* With an offset. */ case PLUS: case MINUS: + case LO_SUM: if (GET_CODE (XEXP (XEXP (dest, 0), 1)) != CONST_INT) abort (); offset = INTVAL (XEXP (XEXP (dest, 0), 1)); if (GET_CODE (XEXP (dest, 0)) == MINUS) offset = -offset; - if (cfa_store.reg != (unsigned) REGNO (XEXP (XEXP (dest, 0), 0))) + if (cfa_store.reg == (unsigned) REGNO (XEXP (XEXP (dest, 0), 0))) + offset -= cfa_store.offset; + else if (cfa_temp.reg == (unsigned) REGNO (XEXP (XEXP (dest, 0), 0))) + offset -= cfa_temp.offset; + else abort (); - offset -= cfa_store.offset; break; /* Rule 13 */ /* Without an offset. */ case REG: - if (cfa_store.reg != (unsigned) REGNO (XEXP (dest, 0))) + if (cfa_store.reg == (unsigned) REGNO (XEXP (dest, 0))) + offset = -cfa_store.offset; + else if (cfa_temp.reg == (unsigned) REGNO (XEXP (dest, 0))) + offset = -cfa_temp.offset; + else abort (); - offset = -cfa_store.offset; + break; + + /* Rule 14 */ + case POST_INC: + if (cfa_temp.reg != (unsigned) REGNO (XEXP (XEXP (dest, 0), 0))) + abort (); + offset = -cfa_temp.offset; + cfa_temp.offset -= GET_MODE_SIZE (GET_MODE (dest)); break; default: @@ -1584,9 +1618,10 @@ dwarf2out_frame_debug (insn) /* Output a Call Frame Information opcode and its operand(s). */ static void -output_cfi (cfi, fde) +output_cfi (cfi, fde, for_eh) register dw_cfi_ref cfi; register dw_fde_ref fde; + int for_eh; { if (cfi->dw_cfi_opc == DW_CFA_advance_loc) { @@ -1618,8 +1653,14 @@ output_cfi (cfi, fde) switch (cfi->dw_cfi_opc) { case DW_CFA_set_loc: - dw2_asm_output_addr (DWARF2_ADDR_SIZE, - cfi->dw_cfi_oprnd1.dw_cfi_addr, NULL); + if (for_eh) + dw2_asm_output_encoded_addr_rtx ( + ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/1, /*global=*/0), + gen_rtx_SYMBOL_REF (Pmode, cfi->dw_cfi_oprnd1.dw_cfi_addr), + NULL); + else + dw2_asm_output_addr (DWARF2_ADDR_SIZE, + cfi->dw_cfi_oprnd1.dw_cfi_addr, NULL); break; case DW_CFA_advance_loc1: dw2_asm_output_delta (1, cfi->dw_cfi_oprnd1.dw_cfi_addr, @@ -1680,26 +1721,30 @@ static void output_call_frame_info (for_eh) int for_eh; { - register unsigned long i; + register unsigned int i; register dw_fde_ref fde; register dw_cfi_ref cfi; char l1[20], l2[20]; -#ifdef ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL - char ld[20]; -#endif - - /* Do we want to include a pointer to the exception table? */ - int eh_ptr = for_eh && exception_table_p (); + int any_lsda_needed = 0; + char augmentation[6]; + int augmentation_size; + int fde_encoding = DW_EH_PE_absptr; + int per_encoding = DW_EH_PE_absptr; + int lsda_encoding = DW_EH_PE_absptr; /* If we don't have any functions we'll want to unwind out of, don't emit any EH unwind information. */ if (for_eh) { + int any_eh_needed = 0; for (i = 0; i < fde_table_in_use; ++i) - if (! fde_table[i].nothrow) - goto found; - return; - found:; + if (fde_table[i].uses_eh_lsda) + any_eh_needed = any_lsda_needed = 1; + else if (! fde_table[i].nothrow) + any_eh_needed = 1; + + if (! any_eh_needed) + return; } /* We're going to be generating comments, so turn on app. */ @@ -1714,26 +1759,20 @@ output_call_frame_info (for_eh) tree label = get_file_function_name ('F'); force_data_section (); - ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (DWARF2_ADDR_SIZE)); + ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (PTR_SIZE)); ASM_GLOBALIZE_LABEL (asm_out_file, IDENTIFIER_POINTER (label)); ASM_OUTPUT_LABEL (asm_out_file, IDENTIFIER_POINTER (label)); #endif assemble_label ("__FRAME_BEGIN__"); } else - ASM_OUTPUT_SECTION (asm_out_file, FRAME_SECTION); + ASM_OUTPUT_SECTION (asm_out_file, DEBUG_FRAME_SECTION); /* Output the CIE. */ ASM_GENERATE_INTERNAL_LABEL (l1, CIE_AFTER_SIZE_LABEL, for_eh); ASM_GENERATE_INTERNAL_LABEL (l2, CIE_END_LABEL, for_eh); -#ifdef ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL - ASM_GENERATE_INTERNAL_LABEL (ld, CIE_LENGTH_LABEL, for_eh); - dw2_asm_output_offset (for_eh ? 4 : DWARF_OFFSET_SIZE, ld, - "Length of Common Information Entry"); -#else dw2_asm_output_delta (for_eh ? 4 : DWARF_OFFSET_SIZE, l2, l1, "Length of Common Information Entry"); -#endif ASM_OUTPUT_LABEL (asm_out_file, l1); /* Now that the CIE pointer is PC-relative for EH, @@ -1744,20 +1783,71 @@ output_call_frame_info (for_eh) dw2_asm_output_data (1, DW_CIE_VERSION, "CIE Version"); - if (eh_ptr) - { - /* The CIE contains a pointer to the exception region info for the - frame. Make the augmentation string three bytes (including the - trailing null) so the pointer is 4-byte aligned. The Solaris ld - can't handle unaligned relocs. */ - dw2_asm_output_nstring ("eh", -1, "CIE Augmentation"); - dw2_asm_output_addr (DWARF2_ADDR_SIZE, "__EXCEPTION_TABLE__", - "pointer to exception region info"); - } - else + augmentation[0] = 0; + augmentation_size = 0; + if (for_eh) { - dw2_asm_output_data (1, 0, "CIE Augmentation (none)"); + char *p; + + /* Augmentation: + z Indicates that a uleb128 is present to size the + 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 + FDE code pointers. + P Indicates the presence of an encoding + language + personality routine in the CIE augmentation. */ + + fde_encoding = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/1, /*global=*/0); + per_encoding = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/2, /*global=*/1); + lsda_encoding = ASM_PREFERRED_EH_DATA_FORMAT (/*code=*/0, /*global=*/0); + + p = augmentation + 1; + if (eh_personality_libfunc) + { + *p++ = 'P'; + augmentation_size += 1 + size_of_encoded_value (per_encoding); + } + if (any_lsda_needed) + { + *p++ = 'L'; + augmentation_size += 1; + } + if (fde_encoding != DW_EH_PE_absptr) + { + *p++ = 'R'; + augmentation_size += 1; + } + if (p > augmentation + 1) + { + augmentation[0] = 'z'; + *p = '\0'; + } + + /* Ug. Some platforms can't do unaligned dynamic relocations at all. */ + if (eh_personality_libfunc && per_encoding == DW_EH_PE_aligned) + { + int offset = ( 4 /* Length */ + + 4 /* CIE Id */ + + 1 /* CIE version */ + + strlen (augmentation) + 1 /* Augmentation */ + + size_of_uleb128 (1) /* Code alignment */ + + size_of_sleb128 (DWARF_CIE_DATA_ALIGNMENT) + + 1 /* RA column */ + + 1 /* Augmentation size */ + + 1 /* Personality encoding */ ); + int pad = -offset & (PTR_SIZE - 1); + + augmentation_size += pad; + + /* Augmentations should be small, so there's scarce need to + iterate for a solution. Die if we exceed one uleb128 byte. */ + if (size_of_uleb128 (augmentation_size) != 1) + abort (); + } } + dw2_asm_output_nstring (augmentation, -1, "CIE Augmentation"); dw2_asm_output_data_uleb128 (1, "CIE Code Alignment Factor"); @@ -1766,38 +1856,46 @@ output_call_frame_info (for_eh) dw2_asm_output_data (1, DWARF_FRAME_RETURN_COLUMN, "CIE RA Column"); + if (augmentation[0]) + { + dw2_asm_output_data_uleb128 (augmentation_size, "Augmentation size"); + if (eh_personality_libfunc) + { + dw2_asm_output_data (1, per_encoding, "Personality (%s)", + eh_data_format_name (per_encoding)); + dw2_asm_output_encoded_addr_rtx (per_encoding, + eh_personality_libfunc, NULL); + } + if (any_lsda_needed) + dw2_asm_output_data (1, lsda_encoding, "LSDA Encoding (%s)", + eh_data_format_name (lsda_encoding)); + if (fde_encoding != DW_EH_PE_absptr) + dw2_asm_output_data (1, fde_encoding, "FDE Encoding (%s)", + eh_data_format_name (fde_encoding)); + } + for (cfi = cie_cfi_head; cfi != NULL; cfi = cfi->dw_cfi_next) - output_cfi (cfi, NULL); + output_cfi (cfi, NULL, for_eh); /* Pad the CIE out to an address sized boundary. */ - ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (DWARF2_ADDR_SIZE)); + ASM_OUTPUT_ALIGN (asm_out_file, + floor_log2 (for_eh ? PTR_SIZE : DWARF2_ADDR_SIZE)); ASM_OUTPUT_LABEL (asm_out_file, l2); -#ifdef ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL - ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL (asm_out_file, ld, l2, l1); - if (flag_debug_asm) - fprintf (asm_out_file, "\t%s CIE Length Symbol", ASM_COMMENT_START); - fputc ('\n', asm_out_file); -#endif /* Loop through all of the FDE's. */ for (i = 0; i < fde_table_in_use; ++i) { fde = &fde_table[i]; - /* Don't emit EH unwind info for leaf functions. */ - if (for_eh && fde->nothrow) + /* Don't emit EH unwind info for leaf functions that don't need it. */ + if (for_eh && fde->nothrow && ! fde->uses_eh_lsda) continue; ASM_OUTPUT_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); -#ifdef ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL - ASM_GENERATE_INTERNAL_LABEL (ld, FDE_LENGTH_LABEL, for_eh + i * 2); - dw2_asm_output_offset (for_eh ? 4 : DWARF_OFFSET_SIZE, ld, "FDE Length"); -#else dw2_asm_output_delta (for_eh ? 4 : DWARF_OFFSET_SIZE, l2, l1, "FDE Length"); -#endif ASM_OUTPUT_LABEL (asm_out_file, l1); /* ??? This always emits a 4 byte offset when for_eh is true, but it @@ -1812,30 +1910,78 @@ output_call_frame_info (for_eh) dw2_asm_output_delta (4, l1, "__FRAME_BEGIN__", "FDE CIE offset"); else dw2_asm_output_offset (DWARF_OFFSET_SIZE, - stripattributes (FRAME_SECTION), + stripattributes (DEBUG_FRAME_SECTION), "FDE CIE offset"); - dw2_asm_output_addr (DWARF2_ADDR_SIZE, fde->dw_fde_begin, - "FDE initial location"); + if (for_eh) + { + dw2_asm_output_encoded_addr_rtx (fde_encoding, + gen_rtx_SYMBOL_REF (Pmode, fde->dw_fde_begin), + "FDE initial location"); + dw2_asm_output_delta (size_of_encoded_value (fde_encoding), + fde->dw_fde_end, fde->dw_fde_begin, + "FDE address range"); + } + else + { + dw2_asm_output_addr (DWARF2_ADDR_SIZE, fde->dw_fde_begin, + "FDE initial location"); + dw2_asm_output_delta (DWARF2_ADDR_SIZE, + fde->dw_fde_end, fde->dw_fde_begin, + "FDE address range"); + } + + if (augmentation[0]) + { + if (any_lsda_needed) + { + int size = size_of_encoded_value (lsda_encoding); - dw2_asm_output_delta (DWARF2_ADDR_SIZE, fde->dw_fde_end, - fde->dw_fde_begin, "FDE address range"); + if (lsda_encoding == DW_EH_PE_aligned) + { + int offset = ( 4 /* Length */ + + 4 /* CIE offset */ + + 2 * size_of_encoded_value (fde_encoding) + + 1 /* Augmentation size */ ); + int pad = -offset & (PTR_SIZE - 1); + + size += pad; + if (size_of_uleb128 (size) != 1) + abort (); + } + + dw2_asm_output_data_uleb128 (size, "Augmentation size"); + + if (fde->uses_eh_lsda) + { + ASM_GENERATE_INTERNAL_LABEL (l1, "LLSDA", + fde->funcdef_number); + dw2_asm_output_encoded_addr_rtx ( + lsda_encoding, gen_rtx_SYMBOL_REF (Pmode, l1), + "Language Specific Data Area"); + } + else + { + if (lsda_encoding == DW_EH_PE_aligned) + ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (PTR_SIZE)); + dw2_asm_output_data (size_of_encoded_value (lsda_encoding), + 0, "Language Specific Data Area (none)"); + } + } + else + dw2_asm_output_data_uleb128 (0, "Augmentation size"); + } /* Loop through the Call Frame Instructions associated with this FDE. */ fde->dw_fde_current_label = fde->dw_fde_begin; for (cfi = fde->dw_fde_cfi; cfi != NULL; cfi = cfi->dw_cfi_next) - output_cfi (cfi, fde); + output_cfi (cfi, fde, for_eh); /* Pad the FDE out to an address sized boundary. */ - ASM_OUTPUT_ALIGN (asm_out_file, floor_log2 (DWARF2_ADDR_SIZE)); + ASM_OUTPUT_ALIGN (asm_out_file, + floor_log2 ((for_eh ? PTR_SIZE : DWARF2_ADDR_SIZE))); ASM_OUTPUT_LABEL (asm_out_file, l2); -#ifdef ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL - ASM_OUTPUT_DEFINE_LABEL_DIFFERENCE_SYMBOL (asm_out_file, ld, l2, l1); - if (flag_debug_asm) - fprintf (asm_out_file, "\t%s FDE Length Symbol", ASM_COMMENT_START); - fputc ('\n', asm_out_file); -#endif } #ifndef EH_FRAME_SECTION @@ -1857,19 +2003,42 @@ output_call_frame_info (for_eh) the prologue. */ void -dwarf2out_begin_prologue () +dwarf2out_begin_prologue (line, file) + unsigned int line ATTRIBUTE_UNUSED; + const char *file ATTRIBUTE_UNUSED; { char label[MAX_ARTIFICIAL_LABEL_BYTES]; register dw_fde_ref fde; + current_function_func_begin_label = 0; + +#ifdef IA64_UNWIND_INFO + /* ??? current_function_func_begin_label is also used by except.c + for call-site information. We must emit this label if it might + be used. */ + if ((! flag_exceptions || USING_SJLJ_EXCEPTIONS) + && ! dwarf2out_do_frame ()) + return; +#else + if (! dwarf2out_do_frame ()) + return; +#endif + ++current_funcdef_number; function_section (current_function_decl); ASM_GENERATE_INTERNAL_LABEL (label, FUNC_BEGIN_LABEL, current_funcdef_number); - ASM_OUTPUT_LABEL (asm_out_file, label); + ASM_OUTPUT_DEBUG_LABEL (asm_out_file, FUNC_BEGIN_LABEL, + current_funcdef_number); current_function_func_begin_label = get_identifier (label); +#ifdef IA64_UNWIND_INFO + /* We can elide the fde allocation if we're not emitting debug info. */ + if (! dwarf2out_do_frame ()) + return; +#endif + /* Expand the fde table if necessary. */ if (fde_table_in_use == fde_table_allocated) { @@ -1888,9 +2057,18 @@ dwarf2out_begin_prologue () fde->dw_fde_current_label = NULL; fde->dw_fde_end = NULL; fde->dw_fde_cfi = NULL; + fde->funcdef_number = current_funcdef_number; fde->nothrow = current_function_nothrow; + fde->uses_eh_lsda = cfun->uses_eh_lsda; args_size = old_args_size = 0; + + /* We only want to output line number information for the genuine + dwarf2 prologue case, not the eh frame case. */ +#ifdef DWARF2_DEBUGGING_INFO + if (file) + dwarf2out_source_line (line, file); +#endif } /* Output a marker (i.e. a label) for the absolute end of the generated code @@ -1936,11 +2114,11 @@ dwarf2out_frame_finish () #ifdef MIPS_DEBUGGING_INFO if (write_symbols == DWARF2_DEBUG) output_call_frame_info (0); - if (flag_unwind_tables || (flag_exceptions && ! exceptions_via_longjmp)) + if (flag_unwind_tables || (flag_exceptions && ! USING_SJLJ_EXCEPTIONS)) output_call_frame_info (1); #else if (write_symbols == DWARF2_DEBUG - || flag_unwind_tables || (flag_exceptions && ! exceptions_via_longjmp)) + || flag_unwind_tables || (flag_exceptions && ! USING_SJLJ_EXCEPTIONS)) output_call_frame_info (1); #endif } @@ -1951,6 +2129,7 @@ dwarf2out_frame_finish () typedef struct dw_val_struct *dw_val_ref; typedef struct die_struct *dw_die_ref; typedef struct dw_loc_descr_struct *dw_loc_descr_ref; +typedef struct dw_loc_list_struct *dw_loc_list_ref; /* Each DIE may have a series of attribute/value pairs. Values can take on several forms. The forms that are used in this @@ -1960,6 +2139,7 @@ typedef enum { dw_val_class_addr, dw_val_class_loc, + dw_val_class_loc_list, dw_val_class_const, dw_val_class_unsigned_const, dw_val_class_long_long, @@ -2001,6 +2181,7 @@ typedef struct dw_val_struct union { rtx val_addr; + dw_loc_list_ref val_loc_list; dw_loc_descr_ref val_loc; long int val_int; long unsigned val_unsigned; @@ -2032,6 +2213,19 @@ typedef struct dw_loc_descr_struct } 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 +{ + dw_loc_list_ref dw_loc_next; + const char *begin; /* Label for begin address of range */ + const char *end; /* Label for end address of range */ + char *ll_symbol; /* Label for beginning of location list. Only on head of list */ + const char *section; /* Section this loclist is relative to */ + 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, @@ -2370,6 +2564,7 @@ new_loc_descr (op, oprnd1, oprnd2) return descr; } + /* Add a location description term to a location description expression. */ static inline void @@ -2819,6 +3014,47 @@ get_cfa_from_loc_descr (cfa, loc) /* And now, the support for symbolic debugging information. */ #ifdef DWARF2_DEBUGGING_INFO +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)); + +/* The debug hooks structure. */ + +struct gcc_debug_hooks dwarf2_debug_hooks = +{ + dwarf2out_init, + dwarf2out_finish, + dwarf2out_define, + dwarf2out_undef, + dwarf2out_start_source_file, + dwarf2out_end_source_file, + dwarf2out_begin_block, + dwarf2out_end_block, + dwarf2out_ignore_block, + dwarf2out_source_line, + dwarf2out_begin_prologue, + debug_nothing_int, /* end_prologue */ + dwarf2out_end_epilogue, + debug_nothing_tree, /* begin_function */ + debug_nothing_int, /* end_function */ + dwarf2out_decl, /* function_decl */ + dwarf2out_global_decl, + debug_nothing_tree, /* deferred_inline_function */ + /* The DWARF 2 backend tries to reduce debugging bloat by not + emitting the abstract description of inline functions until + something tries to reference them. */ + dwarf2out_abstract_function, /* outlining_inline_function */ + debug_nothing_rtx /* label */ +}; + /* NOTE: In the comments in this file, many references are made to "Debugging Information Entries". This term is abbreviated as `DIE' throughout the remainder of this file. */ @@ -3124,6 +3360,9 @@ static unsigned arange_table_in_use; arange_table. */ #define ARANGE_TABLE_INCREMENT 64 +/* Whether we have location lists that need outputting */ +static unsigned have_location_lists; + /* A pointer to the base of a list of incomplete types which might be completed at some later time. */ @@ -3194,6 +3433,9 @@ static void add_AT_fde_ref PARAMS ((dw_die_ref, static void add_AT_loc PARAMS ((dw_die_ref, enum dwarf_attribute, dw_loc_descr_ref)); +static void add_AT_loc_list PARAMS ((dw_die_ref, + enum dwarf_attribute, + dw_loc_list_ref)); static void add_AT_addr PARAMS ((dw_die_ref, enum dwarf_attribute, rtx)); @@ -3241,11 +3483,11 @@ 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 char *gen_internal_sym PARAMS ((void)); static void assign_symbol_names PARAMS ((dw_die_ref)); static void break_out_includes PARAMS ((dw_die_ref)); 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 unsigned long size_of_string PARAMS ((const char *)); static int constant_size PARAMS ((long unsigned)); static unsigned long size_of_die PARAMS ((dw_die_ref)); @@ -3357,31 +3599,39 @@ static void gen_type_die_for_member PARAMS ((tree, tree, dw_die_ref)); static rtx save_rtx PARAMS ((rtx)); 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 *)); /* Section names used to hold DWARF debugging information. */ #ifndef DEBUG_INFO_SECTION #define DEBUG_INFO_SECTION ".debug_info" #endif -#ifndef ABBREV_SECTION -#define ABBREV_SECTION ".debug_abbrev" +#ifndef DEBUG_ABBREV_SECTION +#define DEBUG_ABBREV_SECTION ".debug_abbrev" #endif -#ifndef ARANGES_SECTION -#define ARANGES_SECTION ".debug_aranges" +#ifndef DEBUG_ARANGES_SECTION +#define DEBUG_ARANGES_SECTION ".debug_aranges" #endif -#ifndef DW_MACINFO_SECTION -#define DW_MACINFO_SECTION ".debug_macinfo" +#ifndef DEBUG_MACINFO_SECTION +#define DEBUG_MACINFO_SECTION ".debug_macinfo" #endif #ifndef DEBUG_LINE_SECTION #define DEBUG_LINE_SECTION ".debug_line" #endif -#ifndef LOC_SECTION -#define LOC_SECTION ".debug_loc" +#ifndef DEBUG_LOC_SECTION +#define DEBUG_LOC_SECTION ".debug_loc" #endif -#ifndef PUBNAMES_SECTION -#define PUBNAMES_SECTION ".debug_pubnames" +#ifndef DEBUG_PUBNAMES_SECTION +#define DEBUG_PUBNAMES_SECTION ".debug_pubnames" #endif -#ifndef STR_SECTION -#define STR_SECTION ".debug_str" +#ifndef DEBUG_STR_SECTION +#define DEBUG_STR_SECTION ".debug_str" #endif /* Standard ELF section names for compiled code and data. */ @@ -3399,18 +3649,23 @@ static int file_info_cmp PARAMS ((const void *, const void *)); the section names themselves. */ #ifndef TEXT_SECTION_LABEL -#define TEXT_SECTION_LABEL "Ltext" +#define TEXT_SECTION_LABEL "Ltext" #endif #ifndef DEBUG_LINE_SECTION_LABEL -#define DEBUG_LINE_SECTION_LABEL "Ldebug_line" +#define DEBUG_LINE_SECTION_LABEL "Ldebug_line" #endif #ifndef DEBUG_INFO_SECTION_LABEL -#define DEBUG_INFO_SECTION_LABEL "Ldebug_info" +#define DEBUG_INFO_SECTION_LABEL "Ldebug_info" #endif -#ifndef ABBREV_SECTION_LABEL -#define ABBREV_SECTION_LABEL "Ldebug_abbrev" +#ifndef DEBUG_ABBREV_SECTION_LABEL +#define DEBUG_ABBREV_SECTION_LABEL "Ldebug_abbrev" +#endif +#ifndef DEBUG_LOC_SECTION_LABEL +#define DEBUG_LOC_SECTION_LABEL "Ldebug_loc" +#endif +#ifndef DEBUG_MACINFO_SECTION_LABEL +#define DEBUG_MACINFO_SECTION_LABEL "Ldebug_macinfo" #endif - /* 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. @@ -3422,7 +3677,8 @@ static char text_section_label[MAX_ARTIFICIAL_LABEL_BYTES]; static char abbrev_section_label[MAX_ARTIFICIAL_LABEL_BYTES]; static char debug_info_section_label[MAX_ARTIFICIAL_LABEL_BYTES]; static char debug_line_section_label[MAX_ARTIFICIAL_LABEL_BYTES]; - +static char macinfo_section_label[MAX_ARTIFICIAL_LABEL_BYTES]; +static char loc_section_label[MAX_ARTIFICIAL_LABEL_BYTES]; #ifndef TEXT_END_LABEL #define TEXT_END_LABEL "Letext" #endif @@ -3484,7 +3740,7 @@ is_pseudo_reg (rtl) { return ((GET_CODE (rtl) == REG && REGNO (rtl) >= FIRST_PSEUDO_REGISTER) || (GET_CODE (rtl) == SUBREG - && REGNO (XEXP (rtl, 0)) >= FIRST_PSEUDO_REGISTER)); + && REGNO (SUBREG_REG (rtl)) >= FIRST_PSEUDO_REGISTER)); } /* Return a reference to a type, with its const and volatile qualifiers @@ -4256,6 +4512,34 @@ AT_loc (a) abort (); } +static inline void +add_AT_loc_list (die, attr_kind, loc_list) + register dw_die_ref die; + register enum dwarf_attribute attr_kind; + register dw_loc_list_ref loc_list; +{ + register dw_attr_ref attr = (dw_attr_ref) xmalloc (sizeof (dw_attr_node)); + + attr->dw_attr_next = NULL; + attr->dw_attr = attr_kind; + attr->dw_attr_val.val_class = dw_val_class_loc_list; + attr->dw_attr_val.v.val_loc_list = loc_list; + add_dwarf_attr (die, attr); + have_location_lists = 1; +} + +static inline dw_loc_list_ref AT_loc_list PARAMS ((dw_attr_ref)); + +static inline dw_loc_list_ref +AT_loc_list (a) + register dw_attr_ref a; +{ + if (a && AT_class (a) == dw_val_class_loc_list) + return a->dw_attr_val.v.val_loc_list; + + abort (); +} + /* Add an address constant attribute value to a DIE. */ static inline void @@ -4733,6 +5017,9 @@ print_die (die, outfile) case dw_val_class_loc: fprintf (outfile, "location descriptor"); break; + case dw_val_class_loc_list: + fprintf (outfile, "location list -> label:%s", AT_loc_list (a)->ll_symbol); + break; case dw_val_class_const: fprintf (outfile, "%ld", AT_int (a)); break; @@ -5127,18 +5414,19 @@ is_symbol_die (c) { if (is_type_die (c)) return 1; - if (get_AT (c, DW_AT_declaration) + if (get_AT (c, DW_AT_declaration) && ! get_AT (c, DW_AT_specification)) return 1; return 0; } static char * -gen_internal_sym () +gen_internal_sym (prefix) + const char *prefix; { char buf[256]; static int label_num; - ASM_GENERATE_INTERNAL_LABEL (buf, "LDIE", label_num++); + ASM_GENERATE_INTERNAL_LABEL (buf, prefix, label_num++); return xstrdup (buf); } @@ -5160,7 +5448,7 @@ assign_symbol_names (die) die->die_symbol = xstrdup (p); } else - die->die_symbol = gen_internal_sym (); + die->die_symbol = gen_internal_sym ("LDIE"); } for (c = die->die_child; c != NULL; c = c->die_sib) @@ -5245,6 +5533,24 @@ add_sibling_attributes (die) add_sibling_attributes (c); } +/* Output all location lists for the DIE and it's children */ +static void +output_location_lists (die) + register dw_die_ref die; +{ + dw_die_ref c; + dw_attr_ref d_attr; + for (d_attr = die->die_attr; d_attr; d_attr = d_attr->dw_attr_next) + { + if (AT_class (d_attr) == dw_val_class_loc_list) + { + output_loc_list (AT_loc_list (d_attr)); + } + } + for (c = die->die_child; c != NULL; c = c->die_sib) + output_location_lists (c); + +} /* The format of each DIE (and its attribute value pairs) is encoded in an abbreviation table. This routine builds the abbreviation table and assigns a unique abbreviation id for @@ -5256,7 +5562,7 @@ build_abbrev_table (die) register dw_die_ref die; { register unsigned long abbrev_id; - register unsigned long n_alloc; + register unsigned int n_alloc; register dw_die_ref c; register dw_attr_ref d_attr, a_attr; @@ -5383,6 +5689,9 @@ size_of_die (die) size += lsize; } break; + case dw_val_class_loc_list: + size += DWARF_OFFSET_SIZE; + break; case dw_val_class_const: size += size_of_sleb128 (AT_int (a)); break; @@ -5518,6 +5827,10 @@ value_format (a) { case dw_val_class_addr: return DW_FORM_addr; + case dw_val_class_loc_list: + /* FIXME: Could be DW_FORM_data8, with a > 32 bit size + .debug_loc section */ + return DW_FORM_data4; case dw_val_class_loc: switch (constant_size (size_of_locs (AT_loc (a)))) { @@ -5636,6 +5949,88 @@ output_die_symbol (die) ASM_OUTPUT_LABEL (asm_out_file, sym); } +/* Return a new location list, given the begin and end range, and the + expression. gensym tells us whether to generate a new internal + symbol for 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) + register dw_loc_descr_ref expr; + register const char *begin; + register const char *end; + register const char *section; + register unsigned gensym; +{ + register dw_loc_list_ref retlist + = (dw_loc_list_ref) xcalloc (1, sizeof (dw_loc_list_node)); + retlist->begin = begin; + retlist->end = end; + retlist->expr = expr; + retlist->section = section; + if (gensym) + retlist->ll_symbol = gen_internal_sym ("LLST"); + return retlist; +} + +/* Add a location description expression to a location list */ +static inline void +add_loc_descr_to_loc_list (list_head, descr, begin, end, section) + register dw_loc_list_ref *list_head; + register dw_loc_descr_ref descr; + register const char *begin; + register const char *end; + register const char *section; +{ + register dw_loc_list_ref *d; + + /* Find the end of the chain. */ + for (d = list_head; (*d) != NULL; d = &(*d)->dw_loc_next) + ; + /* 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 */ +static void +output_loc_list (list_head) + register dw_loc_list_ref list_head; +{ + register dw_loc_list_ref curr=list_head; + ASM_OUTPUT_LABEL (asm_out_file, list_head->ll_symbol); + if (strcmp (curr->section, ".text") == 0) + { + /* dw2_asm_output_data will mask off any extra bits in the ~0. */ + dw2_asm_output_data (DWARF2_ADDR_SIZE, ~(unsigned HOST_WIDE_INT)0, + "Location list base address specifier fake entry"); + dw2_asm_output_offset (DWARF2_ADDR_SIZE, curr->section, + "Location list base address specifier base"); + } + for (curr = list_head; curr != NULL; curr=curr->dw_loc_next) + { + int size; + dw2_asm_output_delta (DWARF2_ADDR_SIZE, curr->begin, curr->section, + "Location list begin address (%s)", + list_head->ll_symbol); + dw2_asm_output_delta (DWARF2_ADDR_SIZE, curr->end, curr->section, + "Location list end address (%s)", + list_head->ll_symbol); + size = size_of_locs (curr->expr); + + /* Output the block length for this list of location operations. */ + dw2_asm_output_data (constant_size (size), size, "%s", + "Location expression size"); + + output_loc_sequence (curr->expr); + } + dw2_asm_output_data (DWARF_OFFSET_SIZE, 0, + "Location list terminator begin (%s)", + list_head->ll_symbol); + dw2_asm_output_data (DWARF_OFFSET_SIZE, 0, + "Location list terminator end (%s)", + list_head->ll_symbol); +} /* Output the DIE and its attributes. Called recursively to generate the definitions of each child DIE. */ @@ -5726,7 +6121,14 @@ output_die (die) case dw_val_class_flag: dw2_asm_output_data (1, AT_flag (a), "%s", name); break; - + case dw_val_class_loc_list: + { + char *sym = AT_loc_list (a)->ll_symbol; + if (sym == 0) + abort(); + dw2_asm_output_delta (DWARF_OFFSET_SIZE, sym, loc_section_label, name); + } + break; case dw_val_class_die_ref: if (AT_ref_external (a)) { @@ -5804,10 +6206,13 @@ output_comp_unit (die) { const char *secname; - if (die->die_child == 0) - return; - - /* Mark all the DIEs in this CU so we know which get local refs. */ + /* Even if there are no children of this DIE, we must output the + information about the compilation unit. Otherwise, on an empty + translation unit, we will generate a present, but empty, + .debug_info section. IRIX 6.5 `nm' will then complain when + examining the file. + + Mark all the DIEs in this CU so we know which get local refs. */ mark_dies (die); build_abbrev_table (die); @@ -6768,22 +7173,35 @@ modified_type_die (type, is_const_type, is_volatile_type, context_die) if (code != ERROR_MARK) { - type = build_type_variant (type, is_const_type, is_volatile_type); - - mod_type_die = lookup_type_die (type); - if (mod_type_die) - return mod_type_die; + tree qualified_type; + + /* See if we already have the appropriately qualified variant of + this type. */ + qualified_type + = get_qualified_type (type, + ((is_const_type ? TYPE_QUAL_CONST : 0) + | (is_volatile_type + ? TYPE_QUAL_VOLATILE : 0))); + /* If we do, then we can just use its DIE, if it exists. */ + if (qualified_type) + { + mod_type_die = lookup_type_die (qualified_type); + if (mod_type_die) + return mod_type_die; + } /* Handle C typedef types. */ - if (TYPE_NAME (type) && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL - && DECL_ORIGINAL_TYPE (TYPE_NAME (type))) + if (qualified_type && TYPE_NAME (qualified_type) + && TREE_CODE (TYPE_NAME (qualified_type)) == TYPE_DECL + && DECL_ORIGINAL_TYPE (TYPE_NAME (qualified_type))) { - tree dtype = TREE_TYPE (TYPE_NAME (type)); - if (type == dtype) + tree type_name = TYPE_NAME (qualified_type); + tree dtype = TREE_TYPE (type_name); + if (qualified_type == dtype) { /* For a named type, use the typedef. */ - gen_type_die (type, context_die); - mod_type_die = lookup_type_die (type); + gen_type_die (qualified_type, context_die); + mod_type_die = lookup_type_die (qualified_type); } else if (is_const_type < TYPE_READONLY (dtype) @@ -6791,7 +7209,7 @@ modified_type_die (type, is_const_type, is_volatile_type, context_die) /* cv-unqualified version of named type. Just use the unnamed type to which it refers. */ mod_type_die - = modified_type_die (DECL_ORIGINAL_TYPE (TYPE_NAME (type)), + = modified_type_die (DECL_ORIGINAL_TYPE (type_name), is_const_type, is_volatile_type, context_die); /* Else cv-qualified version of named type; fall through. */ @@ -6844,6 +7262,10 @@ modified_type_die (type, is_const_type, is_volatile_type, context_die) if (mod_type_die == NULL) abort (); } + + /* We want to equate the qualified type to the die below. */ + if (qualified_type) + type = qualified_type; } equate_type_number_to_die (type, mod_type_die); @@ -7028,7 +7450,7 @@ mem_loc_descriptor (rtl, mode) 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 = XEXP (rtl, 0); + rtl = SUBREG_REG (rtl); /* Fall through. */ @@ -7060,6 +7482,16 @@ mem_loc_descriptor (rtl, mode) pool. */ case CONST: case SYMBOL_REF: + /* Alternatively, the symbol in the constant pool might be referenced + by a different symbol. */ + if (GET_CODE (rtl) == SYMBOL_REF + && CONSTANT_POOL_ADDRESS_P (rtl)) + { + rtx tmp = get_pool_constant (rtl); + if (GET_CODE (tmp) == SYMBOL_REF) + rtl = tmp; + } + mem_loc_result = new_loc_descr (DW_OP_addr, 0, 0); mem_loc_result->dw_loc_oprnd1.val_class = dw_val_class_addr; mem_loc_result->dw_loc_oprnd1.v.val_addr = save_rtx (rtl); @@ -7067,7 +7499,7 @@ mem_loc_descriptor (rtl, mode) case PRE_MODIFY: /* Extract the PLUS expression nested inside and fall into - PLUS code bellow. */ + PLUS code below. */ rtl = XEXP (rtl, 1); goto plus; @@ -7172,7 +7604,7 @@ loc_descriptor (rtl) 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 = XEXP (rtl, 0); + rtl = SUBREG_REG (rtl); /* Fall through. */ @@ -7265,6 +7697,7 @@ loc_descriptor_from_tree (loc, addressp) case COMPONENT_REF: case BIT_FIELD_REF: case ARRAY_REF: + case ARRAY_RANGE_REF: { tree obj, offset; HOST_WIDE_INT bitsize, bitpos, bytepos; @@ -9194,7 +9627,7 @@ gen_type_die_for_member (type, member, context_die) of a function which we may later generate inlined and/or out-of-line instances of. */ -void +static void dwarf2out_abstract_function (decl) tree decl; { @@ -9213,10 +9646,13 @@ dwarf2out_abstract_function (decl) /* Be sure we've emitted the in-class declaration DIE (if any) first, so we don't get confused by DECL_ABSTRACT. */ - context = decl_class_context (decl); - if (context) - gen_type_die_for_member - (context, decl, decl_function_context (decl) ? NULL : comp_unit_die); + if (debug_info_level > DINFO_LEVEL_TERSE) + { + context = decl_class_context (decl); + if (context) + gen_type_die_for_member + (context, decl, decl_function_context (decl) ? NULL : comp_unit_die); + } /* Pretend we've just finished compiling this function. */ save_fn = current_function_decl; @@ -10587,6 +11023,21 @@ dwarf2out_add_library_unit_info (filename, context_list) } } +/* Debug information for a global DECL. Called from toplev.c after + compilation proper has finished. */ +static void +dwarf2out_global_decl (decl) + tree decl; +{ + /* Output DWARF2 information for file-scope tentative data object + declarations, file-scope (extern) function declarations (which + had no corresponding body) and file-scope tagged type + declarations and definitions which have not yet been forced out. */ + + if (TREE_CODE (decl) != FUNCTION_DECL || !DECL_INITIAL (decl)) + dwarf2out_decl (decl); +} + /* Write the debugging output for DECL. */ void @@ -10705,9 +11156,10 @@ dwarf2out_decl (decl) /* Output a marker (i.e. a label) for the beginning of the generated code for a lexical block. */ -void -dwarf2out_begin_block (blocknum) - register unsigned blocknum; +static void +dwarf2out_begin_block (line, blocknum) + unsigned int line ATTRIBUTE_UNUSED; + unsigned int blocknum; { function_section (current_function_decl); ASM_OUTPUT_DEBUG_LABEL (asm_out_file, BLOCK_BEGIN_LABEL, blocknum); @@ -10716,9 +11168,10 @@ dwarf2out_begin_block (blocknum) /* Output a marker (i.e. a label) for the end of the generated code for a lexical block. */ -void -dwarf2out_end_block (blocknum) - register unsigned blocknum; +static void +dwarf2out_end_block (line, blocknum) + unsigned int line ATTRIBUTE_UNUSED; + unsigned int blocknum; { function_section (current_function_decl); ASM_OUTPUT_DEBUG_LABEL (asm_out_file, BLOCK_END_LABEL, blocknum); @@ -10731,7 +11184,7 @@ dwarf2out_end_block (blocknum) as we would end up with orphans, and in the presence of scheduling we may end up calling them anyway. */ -int +static bool dwarf2out_ignore_block (block) tree block; { @@ -10815,15 +11268,20 @@ init_file_table () and record information relating to this source line, in 'line_info_table' for later output of the .debug_line section. */ -void -dwarf2out_line (filename, line) +static void +dwarf2out_source_line (line, filename) + unsigned int line; register const char *filename; - register unsigned line; { if (debug_info_level >= DINFO_LEVEL_NORMAL) { function_section (current_function_decl); + /* If requested, emit something human-readable. */ + if (flag_debug_asm) + fprintf (asm_out_file, "\t%s %s:%d\n", ASM_COMMENT_START, + filename, line); + if (DWARF2_ASM_LINE_DEBUG_INFO) { unsigned file_num = lookup_filename (filename); @@ -10843,9 +11301,6 @@ dwarf2out_line (filename, line) register dw_separate_line_info_ref line_info; ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, SEPARATE_LINE_CODE_LABEL, separate_line_info_table_in_use); - if (flag_debug_asm) - fprintf (asm_out_file, "\t%s %s:%d\n", ASM_COMMENT_START, - filename, line); /* expand the line info table if necessary */ if (separate_line_info_table_in_use @@ -10872,9 +11327,6 @@ dwarf2out_line (filename, line) ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, LINE_CODE_LABEL, line_info_table_in_use); - if (flag_debug_asm) - fprintf (asm_out_file, "\t%s %s:%d\n", ASM_COMMENT_START, - filename, line); /* Expand the line info table if necessary. */ if (line_info_table_in_use == line_info_table_allocated) @@ -10895,12 +11347,12 @@ dwarf2out_line (filename, line) } } -/* Record the beginning of a new source file, for later output - of the .debug_macinfo section. At present, unimplemented. */ +/* Record the beginning of a new source file. */ -void -dwarf2out_start_source_file (filename) - register const char *filename ATTRIBUTE_UNUSED; +static void +dwarf2out_start_source_file (lineno, filename) + register unsigned int lineno; + register const char *filename; { if (flag_eliminate_dwarf2_dups) { @@ -10908,26 +11360,38 @@ dwarf2out_start_source_file (filename) dw_die_ref bincl_die = new_die (DW_TAG_GNU_BINCL, comp_unit_die); add_AT_string (bincl_die, DW_AT_name, filename); } + if (debug_info_level >= DINFO_LEVEL_VERBOSE) + { + ASM_OUTPUT_SECTION (asm_out_file, DEBUG_MACINFO_SECTION); + dw2_asm_output_data (1, DW_MACINFO_start_file, "Start new file"); + dw2_asm_output_data_uleb128 (lineno, "Included from line number %d", lineno); + dw2_asm_output_data_uleb128 (lookup_filename (filename), "Filename we just started"); + } } -/* Record the end of a source file, for later output - of the .debug_macinfo section. At present, unimplemented. */ +/* Record the end of a source file. */ -void -dwarf2out_end_source_file () +static void +dwarf2out_end_source_file (lineno) + unsigned int lineno ATTRIBUTE_UNUSED; { if (flag_eliminate_dwarf2_dups) { /* Record the end of the file for break_out_includes. */ new_die (DW_TAG_GNU_EINCL, comp_unit_die); } + if (debug_info_level >= DINFO_LEVEL_VERBOSE) + { + ASM_OUTPUT_SECTION (asm_out_file, DEBUG_MACINFO_SECTION); + dw2_asm_output_data (1, DW_MACINFO_end_file, "End file"); + } } -/* Called from check_newline in c-parse.y. The `buffer' parameter contains +/* Called from debug_define in toplev.c. The `buffer' parameter contains the tail part of the directive line, i.e. the part which is past the initial whitespace, #, whitespace, directive-name, whitespace part. */ -void +static void dwarf2out_define (lineno, buffer) register unsigned lineno ATTRIBUTE_UNUSED; register const char *buffer ATTRIBUTE_UNUSED; @@ -10935,27 +11399,40 @@ dwarf2out_define (lineno, buffer) static int initialized = 0; if (!initialized) { - dwarf2out_start_source_file (primary_filename); + dwarf2out_start_source_file (0, primary_filename); initialized = 1; } + if (debug_info_level >= DINFO_LEVEL_VERBOSE) + { + ASM_OUTPUT_SECTION (asm_out_file, DEBUG_MACINFO_SECTION); + dw2_asm_output_data (1, DW_MACINFO_define, "Define macro"); + dw2_asm_output_data_uleb128 (lineno, "At line number %d", lineno); + dw2_asm_output_nstring (buffer, -1, "The macro"); + } } -/* Called from check_newline in c-parse.y. The `buffer' parameter contains +/* Called from debug_undef in toplev.c. The `buffer' parameter contains the tail part of the directive line, i.e. the part which is past the initial whitespace, #, whitespace, directive-name, whitespace part. */ -void +static void dwarf2out_undef (lineno, buffer) register unsigned lineno ATTRIBUTE_UNUSED; register const char *buffer ATTRIBUTE_UNUSED; { + if (debug_info_level >= DINFO_LEVEL_VERBOSE) + { + ASM_OUTPUT_SECTION (asm_out_file, DEBUG_MACINFO_SECTION); + dw2_asm_output_data (1, DW_MACINFO_undef, "Undefine macro"); + dw2_asm_output_data_uleb128 (lineno, "At line number %d", lineno); + dw2_asm_output_nstring (buffer, -1, "The macro"); + } } /* Set up for Dwarf output at the start of compilation. */ -void -dwarf2out_init (asm_out_file, main_input_filename) - register FILE *asm_out_file; +static void +dwarf2out_init (main_input_filename) register const char *main_input_filename; { init_file_table (); @@ -11007,7 +11484,8 @@ dwarf2out_init (asm_out_file, main_input_filename) ggc_add_rtx_varray_root (&used_rtx_varray, 1); ASM_GENERATE_INTERNAL_LABEL (text_end_label, TEXT_END_LABEL, 0); - ASM_GENERATE_INTERNAL_LABEL (abbrev_section_label, ABBREV_SECTION_LABEL, 0); + ASM_GENERATE_INTERNAL_LABEL (abbrev_section_label, + DEBUG_ABBREV_SECTION_LABEL, 0); if (DWARF2_GENERATE_TEXT_SECTION_LABEL) ASM_GENERATE_INTERNAL_LABEL (text_section_label, TEXT_SECTION_LABEL, 0); else @@ -11016,8 +11494,10 @@ dwarf2out_init (asm_out_file, main_input_filename) DEBUG_INFO_SECTION_LABEL, 0); ASM_GENERATE_INTERNAL_LABEL (debug_line_section_label, DEBUG_LINE_SECTION_LABEL, 0); - - ASM_OUTPUT_SECTION (asm_out_file, ABBREV_SECTION); + ASM_GENERATE_INTERNAL_LABEL (loc_section_label, DEBUG_LOC_SECTION_LABEL, 0); + ASM_OUTPUT_SECTION (asm_out_file, DEBUG_LOC_SECTION); + ASM_OUTPUT_LABEL (asm_out_file, loc_section_label); + ASM_OUTPUT_SECTION (asm_out_file, DEBUG_ABBREV_SECTION); ASM_OUTPUT_LABEL (asm_out_file, abbrev_section_label); if (DWARF2_GENERATE_TEXT_SECTION_LABEL) { @@ -11028,16 +11508,24 @@ dwarf2out_init (asm_out_file, main_input_filename) ASM_OUTPUT_LABEL (asm_out_file, debug_info_section_label); ASM_OUTPUT_SECTION (asm_out_file, DEBUG_LINE_SECTION); ASM_OUTPUT_LABEL (asm_out_file, debug_line_section_label); + if (debug_info_level >= DINFO_LEVEL_VERBOSE) + { + ASM_OUTPUT_SECTION (asm_out_file, DEBUG_MACINFO_SECTION); + ASM_GENERATE_INTERNAL_LABEL (macinfo_section_label, + DEBUG_MACINFO_SECTION_LABEL, 0); + ASM_OUTPUT_LABEL (asm_out_file, macinfo_section_label); + } } /* Output stuff that dwarf requires at the end of every file, and generate the DWARF-2 debugging info. */ -void -dwarf2out_finish () +static void +dwarf2out_finish (input_filename) + register const char *input_filename ATTRIBUTE_UNUSED; { limbo_die_node *node, *next_node; - dw_die_ref die; + dw_die_ref die = 0; /* Traverse the limbo die list, and add parent/child links. The only dies without parents that should be here are concrete instances of @@ -11096,31 +11584,31 @@ dwarf2out_finish () ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, BSS_END_LABEL, 0); #endif - /* Output the source line correspondence table. */ - if (line_info_table_in_use > 1 || separate_line_info_table_in_use) + /* Output the source line correspondence table. We must do this + even if there is no line information. Otherwise, on an empty + translation unit, we will generate a present, but empty, + .debug_info section. IRIX 6.5 `nm' will then complain when + examining the file. */ + if (! DWARF2_ASM_LINE_DEBUG_INFO) { - if (! DWARF2_ASM_LINE_DEBUG_INFO) - { - ASM_OUTPUT_SECTION (asm_out_file, DEBUG_LINE_SECTION); - output_line_info (); - } - - /* We can only use the low/high_pc attributes if all of the code - was in .text. */ - if (separate_line_info_table_in_use == 0) - { - add_AT_lbl_id (comp_unit_die, DW_AT_low_pc, text_section_label); - add_AT_lbl_id (comp_unit_die, DW_AT_high_pc, text_end_label); - } + ASM_OUTPUT_SECTION (asm_out_file, DEBUG_LINE_SECTION); + output_line_info (); + } - add_AT_lbl_offset (comp_unit_die, DW_AT_stmt_list, - debug_line_section_label); + /* We can only use the low/high_pc attributes if all of the code was + in .text. */ + if (separate_line_info_table_in_use == 0) + { + add_AT_lbl_id (comp_unit_die, DW_AT_low_pc, text_section_label); + add_AT_lbl_id (comp_unit_die, DW_AT_high_pc, text_end_label); } -#if 0 /* unimplemented */ - if (debug_info_level >= DINFO_LEVEL_VERBOSE && primary) - add_AT_unsigned (die, DW_AT_macro_info, 0); -#endif + if (debug_info_level >= DINFO_LEVEL_NORMAL) + add_AT_lbl_offset (comp_unit_die, DW_AT_stmt_list, + debug_line_section_label); + + if (debug_info_level >= DINFO_LEVEL_VERBOSE) + add_AT_lbl_offset (comp_unit_die, DW_AT_macro_info, macinfo_section_label); /* Output all of the compilation units. We put the main one last so that the offsets are available to output_pubnames. */ @@ -11129,13 +11617,13 @@ dwarf2out_finish () output_comp_unit (comp_unit_die); /* Output the abbreviation table. */ - ASM_OUTPUT_SECTION (asm_out_file, ABBREV_SECTION); + ASM_OUTPUT_SECTION (asm_out_file, DEBUG_ABBREV_SECTION); output_abbrev_section (); if (pubname_table_in_use) { /* Output public names table. */ - ASM_OUTPUT_SECTION (asm_out_file, PUBNAMES_SECTION); + ASM_OUTPUT_SECTION (asm_out_file, DEBUG_PUBNAMES_SECTION); output_pubnames (); } @@ -11144,8 +11632,24 @@ dwarf2out_finish () if (fde_table_in_use) { /* Output the address range information. */ - ASM_OUTPUT_SECTION (asm_out_file, ARANGES_SECTION); + ASM_OUTPUT_SECTION (asm_out_file, DEBUG_ARANGES_SECTION); output_aranges (); } + /* Output location list section if necessary */ + if (have_location_lists) + { + /* Output the location lists info. */ + ASM_OUTPUT_SECTION (asm_out_file, DEBUG_LOC_SECTION); + output_location_lists (die); + have_location_lists = 0; + } + + /* Have to end the primary source file. */ + if (debug_info_level >= DINFO_LEVEL_VERBOSE) + { + ASM_OUTPUT_SECTION (asm_out_file, DEBUG_MACINFO_SECTION); + dw2_asm_output_data (1, DW_MACINFO_end_file, "End file"); + } + } #endif /* DWARF2_DEBUGGING_INFO */